AdjustColorImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Created Saturday, September 8, 1984 7:32 pm PDT
Last edited by Eric Nickell, December 19, 1985 12:37:55 pm PST
Implements the arbitration for having several types of tools trying to control the color maps simultaneously so that everyone can know who has the ball, etc.
DIRECTORY
ColorDisplay USING [CDNotifyProc, RegisterCDNotifyProc],
Gammas USING [gamma, BuildGammaTable, GammaCorrect, InstallGammaTable],
Terminal USING [ChannelValue, ColorValue, Current, SetRedMap, SetGreenMap, SetBlueMap, Virtual],
AdjustColor
;
AdjustColorImpl: CEDAR MONITOR
IMPORTS ColorDisplay, Gammas, Terminal
EXPORTS AdjustColor
= BEGIN
OPEN AdjustColor;
ToolList: TYPE ~ LIST OF AdjustColorTool;
NoSuchFlavor: PUBLIC ERROR ~ CODE;
AlreadyExists: PUBLIC ERROR ~ CODE;
term: Terminal.Virtual ~ Terminal.Current[];
inControl: AdjustColorTool ← NIL; --Tool currently able to adjust colors
registeredTools: ToolList ← NIL;--All registered tools. NOTE that a NIL flavor implies an unregistered tool.
redTab: PUBLIC TRC;
grnTab: PUBLIC TRC;
bluTab: PUBLIC TRC;
RegisterAdjustColorTool: PUBLIC ENTRY PROC [tool: AdjustColorToolRec] ~ {
ENABLE UNWIND => NULL;
IF tool.flavor = NIL THEN ERROR; --C'mon! No messing around here...
Check for duplication
FOR tools: ToolList ← registeredTools, tools.rest UNTIL tools=NIL DO
IF tools.first.flavor = tool.flavor THEN {
tools.first^ ← tool;
RETURN;
};
ENDLOOP;
Add tool to the list of those registered
registeredTools ← CONS[NEW[AdjustColorToolRec ← tool], registeredTools];
};
UnRegisterAdjustColorTool: PUBLIC PROC [flavor: Flavor] ~ {
FOR tools: ToolList ← registeredTools, tools.rest UNTIL tools=NIL DO
IF tools.first.flavor = flavor THEN {
IF inControl#NIL AND inControl.flavor=flavor THEN inControl ← NIL;
tools.first.flavor ← NIL;
RETURN
};
ENDLOOP;
ERROR NoSuchFlavor;
};
InControl: PUBLIC ENTRY PROC RETURNS [flavor: Flavor] ~ {
ENABLE UNWIND => NULL;
RETURN [IF inControl=NIL THEN NIL ELSE inControl.flavor]
};
RequestControl: PUBLIC ENTRY PROC [flavor: Flavor] RETURNS [granted: BOOLEAN] ~ {
ENABLE UNWIND => NULL;
FOR tools: ToolList ← registeredTools, tools.rest UNTIL tools=NIL DO
IF tools.first.flavor = flavor THEN {
IF inControl#NIL AND inControl.byebye#NIL THEN {
The call-back procedure is forked off, so that our clients may monitor such information, and properly set up WAIT's, etc. If we were to use this process, the MONITOR mechanism could deadlock.
p: PROCESSFORK inControl.byebye[inControl.flavor, flavor]; --Warn tool losing control
};
inControl ← tools.first; --Turn over control
RETURN [TRUE];
};
ENDLOOP;
ERROR NoSuchFlavor;
};
ClientDataForFlavor: PUBLIC ENTRY PROC [flavor: Flavor] RETURNS [REF] ~ {
ENABLE UNWIND => NULL;
FOR tools: ToolList ← registeredTools, tools.rest UNTIL tools=NIL DO
IF tools.first.flavor = flavor THEN {
RETURN [tools.first.clientData];
};
ENDLOOP;
ERROR NoSuchFlavor;
};
AdjustColors: PUBLIC ENTRY PROC [flavor: Flavor, red, green, blue: REF TRC] RETURNS [done: BOOL] ~ {
ENABLE UNWIND => NULL;
IF inControl = NIL OR flavor # inControl.flavor THEN RETURN [FALSE]; --If our caller is not in control, ignore him.
IF red=NIL OR green=NIL OR blue=NIL THEN TRUSTED {
IF red#NIL THEN FOR index: Color IN Color DO
SetRedMap[index, red[index]];
ENDLOOP;
IF green#NIL THEN FOR index: Color IN Color DO
SetGreenMap[index, green[index]];
ENDLOOP;
IF blue#NIL THEN FOR index: Color IN Color DO
SetBlueMap[index, blue[index]];
ENDLOOP;
}
ELSE TRUSTED {
FOR index: Color IN Color DO
SetRedMap[index, red[index]];
SetGreenMap[index, green[index]];
SetBlueMap[index, blue[index]];
ENDLOOP;
};
};
NewGamma: PUBLIC PROC [gammaValue: REAL ← 2.2] ~ TRUSTED {
Gammas.InstallGammaTable[Gammas.BuildGammaTable[gammaValue]];
FOR index: Color IN Color DO
Terminal.SetRedMap[term, index, Gammas.GammaCorrect[redTab[index]]];
Terminal.SetGreenMap[term, index, Gammas.GammaCorrect[grnTab[index]]];
Terminal.SetBlueMap[term, index, Gammas.GammaCorrect[bluTab[index]]];
ENDLOOP;
};
SetRedMap: PROC [index: CARDINAL, c: Color] ~ TRUSTED INLINE {
IF redTab[index]#c THEN Terminal.SetRedMap[term, index, Gammas.GammaCorrect[redTab[index] ← c]];
};
SetGreenMap: PROC [index: CARDINAL, c: Color] ~ TRUSTED INLINE {
IF grnTab[index]#c THEN Terminal.SetGreenMap[term, index, Gammas.GammaCorrect[grnTab[index] ← c]];
};
SetBlueMap: PROC [index: CARDINAL, c: Color] ~ TRUSTED INLINE {
IF bluTab[index]#c THEN Terminal.SetBlueMap[term, index, Gammas.GammaCorrect[bluTab[index] ← c]];
};
RespecifyMaps: ENTRY ColorDisplay.CDNotifyProc ~ TRUSTED {
IF new.on AND new.bpp=24 AND (new.on#old.on OR new.bpp#old.bpp) THEN {
FOR index: Color IN Color DO
Terminal.SetRedMap[term, index, Gammas.GammaCorrect[redTab[index]]];
Terminal.SetGreenMap[term, index, Gammas.GammaCorrect[grnTab[index]]];
Terminal.SetBlueMap[term, index, Gammas.GammaCorrect[bluTab[index]]];
ENDLOOP;
};
};
Init: PROC ~ TRUSTED {
[] ← ColorDisplay.RegisterCDNotifyProc[RespecifyMaps, NIL];
FOR index: Color IN Color DO
redTab[index] ← grnTab[index] ← bluTab[index] ← index;
Terminal.SetRedMap[term, index, Gammas.GammaCorrect[index]];
Terminal.SetGreenMap[term, index, Gammas.GammaCorrect[index]];
Terminal.SetBlueMap[term, index, Gammas.GammaCorrect[index]];
ENDLOOP;
};
Init[];
END.