ColorMapsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, December 23, 1985 12:52:29 pm PST
last edited by Christian Jacobi, February 12, 1986 10:16:42 am PST
Last edited by: Christian Jacobi, September 18, 1986 2:29:59 pm PDT
DIRECTORY
Buttons,
Commander,
CommandTool,
ColorMaps,
FS,
FileNames,
Imager,
ImagerColorMap,
ImagerDitherContext,
ImagerTerminal,
InterminalBackdoor,
IO,
List,
MessageWindow,
PopUpSelection,
Rope,
SymTab,
Terminal,
TerminalIO,
UserProfile,
ViewerPrivate,
WindowManager;
ColorMapsImpl: CEDAR MONITOR
IMPORTS Buttons, Commander, CommandTool, FS, FileNames, ImagerColorMap, ImagerDitherContext, ImagerTerminal, InterminalBackdoor, IO, List, MessageWindow, PopUpSelection, Rope, SymTab, Terminal, TerminalIO, UserProfile, ViewerPrivate, WindowManager
EXPORTS ColorMaps =
BEGIN OPEN ColorMaps;
last: Rope.ROPENIL;
terminal: Terminal.Virtual ← InterminalBackdoor.terminal;
useMapEntries: ImagerDitherContext.MapEntries ← NIL;
useCursor: Terminal.ColorCursorPresentation ← onesAreWhite;
regTab: SymTab.Ref ← SymTab.Create[5];
callBackList: LIST OF PROCNIL;
ContextCreator: ViewerPrivate.ContextCreatorProc =
BEGIN
context: Imager.Context;
SELECT screen FROM
bw => context ← ImagerTerminal.BWContext[vt: terminal, pixelUnits: TRUE];
color => {
context ← ImagerTerminal.ColorContext[vt: terminal, pixelUnits: TRUE];
IF useMapEntries#NIL THEN
ImagerDitherContext.SetDitherMap[context, useMapEntries];
--experimenting showed that the following line was necessary....
[] ← Terminal.SetColorCursorPresentation[terminal, useCursor];
}
ENDCASE => ERROR;
RETURN [context]
END;
ForceColors: PROC [mapEntries: ImagerDitherContext.MapEntries, allBitsCursor: BOOLTRUE] =
BEGIN
ImagerColorMap.LoadEntries[vt: terminal, mapEntries: mapEntries, gamma: 1, shared: FALSE];
useCursor ← IF allBitsCursor THEN onesAreWhite ELSE onesAreBlack;
[] ← Terminal.SetColorCursorPresentation[terminal, useCursor];
[] ← ViewerPrivate.SetCreator[ContextCreator];
END;
Last: PUBLIC PROC [] RETURNS [fileName: Rope.ROPE] =
BEGIN
RETURN [last];
END;
On8Bits: PUBLIC PROC [forceOn: BOOLTRUE, force8bit: BOOLTRUE] RETURNS [BOOLFALSE] =
BEGIN
StartWindowManager: PROC [] = {
WindowManager.StartColorViewers[
screenPos: (IF Rope.Equal["right", UserProfile.Token[key: "ColorDisplay.Side"], FALSE] THEN right ELSE left),
bitsPerPixel: 8
];
};
Is8: PROC [] RETURNS [BOOL] = {
m: Terminal.ColorMode = Terminal.GetColorMode[terminal];
RETURN [~m.full AND m.bitsPerPixelChannelA=8];
};
IF terminal.hasColorDisplay THEN {
IF ~WindowManager.colorDisplayOn AND forceOn THEN StartWindowManager[];
IF WindowManager.colorDisplayOn AND ~Is8[] AND force8bit THEN {
WindowManager.StopColorViewers[];
StartWindowManager[];
};
RETURN [ WindowManager.colorDisplayOn AND Is8[] ];
}
END;
SetUpFile: PROC [fileName: Rope.ROPE, forceOn: BOOLTRUE, force8bit: BOOLTRUE, msgs: IO.STREAMNIL] =
BEGIN
fastList: LIST OF ImagerColorMap.MapEntry←NIL;
slowList: LIST OF ImagerColorMap.MapEntry←NIL;
cdCursor: BOOLTRUE;
OneLine: PROC [line: Rope.ROPE] =
BEGIN
Range: PROC [i: INT] RETURNS [c: [0..256)] = {
i ← MAX[0, MIN[i, 255]];
c ← i
};
stream: IO.STREAMIO.RIS[line];
i, index, r, g, b: INT;
mapEntrie: ImagerColorMap.MapEntry;
i ← IO.GetInt[stream];
r ← IO.GetInt[stream];
g ← IO.GetInt[stream];
b ← IO.GetInt[stream];
index ← ABS[i] MOD 256;
mapEntrie ← [Range[index], Range[r], Range[g], Range[b]];
fastList ← CONS[mapEntrie, fastList];
IF index=i THEN slowList ← CONS[mapEntrie, slowList];
END;
IF On8Bits[forceOn, force8bit] THEN {
file: IO.STREAMNIL; line: Rope.ROPE;
IF msgs=NIL THEN msgs ← TerminalIO.CreateStream[];
fileName ← ExtendName[fileName];
file ← FS.StreamOpen[fileName ! FS.Error => {
IO.PutF[msgs, "not done: %g\n", IO.rope[error.explanation]];
GOTO thatsIt
}];
line ← IO.GetTokenRope[file ! IO.EndOfStream => GOTO thatsIt].token;
IF ~Rope.Equal[line, "ColorMap", FALSE] THEN {
IO.PutRope[msgs, "not a ColorMap file\n"]
};
line ← IO.GetTokenRope[file ! IO.EndOfStream => GOTO thatsIt].token;
IF Rope.Equal[line, "onesAreBlack", FALSE] THEN cdCursor ← FALSE;
BEGIN
DO
line ← IO.GetLineRope[file ! IO.EndOfStream => {GOTO eof}];
IF ~Rope.IsEmpty[line] THEN OneLine[line];
ENDLOOP;
EXITS eof => NULL
END;
useMapEntries ← slowList;
ForceColors[fastList, cdCursor];
last ← fileName;
IO.Close[file];
};
EXITS thatsIt => NULL
END;
SetUpOff: PROC [] =
BEGIN
last ← NIL;
IF terminal.hasColorDisplay THEN WindowManager.StopColorViewers[];
END;
SetUpCedar: PROC[] =
BEGIN
last ← NIL;
IF terminal.hasColorDisplay THEN {
[] ← ViewerPrivate.SetCreator[NIL];
[] ← On8Bits[];
ImagerTerminal.SetStandardColorMap[terminal];
WindowManager.RestoreCursor[];
[] ← Terminal.SetColorCursorPresentation[terminal, onesAreBlack];
};
END;
SetUp: PUBLIC PROC [fileName: Rope.ROPE, forceOn: BOOLTRUE, forceBits: BOOLTRUE, msgs: IO.STREAMNIL] =
BEGIN
WHILE Rope.Equal[fileName, "type filename", FALSE] DO
fileName ← TerminalIO.RequestRope["filename for colormap file (///) >"];
ENDLOOP;
IF Rope.Equal[fileName, "cedar-8-bit", FALSE] THEN SetUpCedar[]
ELSE IF Rope.Equal[fileName, "off", FALSE] THEN SetUpOff[]
ELSE IF Rope.Equal[fileName, "?", FALSE] THEN {
msgs.PutRope["current color map from: "]; msgs.PutRope[last]; msgs.PutRope["\n"];
RETURN
}
ELSE IF ~Rope.IsEmpty[fileName] THEN
--IF ~Rope.Equal[fileName, Last[], FALSE] THEN
--bad optimiztion: disables reset after other tool
SetUpFile[fileName, forceOn, forceBits, msgs];
CallList[];
END;
ExtendName: PROC [name: Rope.ROPE] RETURNS [fn: Rope.ROPE] =
BEGIN
fn ← name;
IF Rope.Find[fn, "."]<1 THEN fn ← Rope.Concat[fn, ".ColorMap"];
END;
RegisterMenu: PUBLIC PROC [entryName: Rope.ROPE, fileName: Rope.ROPENIL] =
BEGIN
IF Rope.IsEmpty[fileName] THEN [] ← regTab.Delete[entryName]
ELSE [] ← regTab.Store[entryName, fileName]
END;
CallBack: PUBLIC ENTRY PROC [p: PROC] =
BEGIN
IF p#NIL THEN callBackList ← CONS [p, callBackList];
END;
CallList: PROC [] =
BEGIN
FOR l: LIST OF PROC ← callBackList, l.rest WHILE l#NIL DO
l.first[]
ENDLOOP
END;
Create: PUBLIC PROC [fileName: Rope.ROPE, special: REFNIL, msgs: IO.STREAMNIL] =
BEGIN
file: IO.STREAM;
IF msgs=NIL THEN msgs ← TerminalIO.CreateStream[];
IF ~On8Bits[FALSE, FALSE] THEN {
msgs.PutRope["not done; not in 8 bit mode\n"];
GOTO thatsIt
};
file ← FS.StreamOpen[ExtendName[fileName], create ! FS.Error => {
msgs.PutRope["not done:"]; msgs.PutRope[error.explanation]; msgs.PutRope["\n"];
GOTO thatsIt
}];
IO.PutRope[file, "ColorMap\n"];
IF Terminal.GetColorCursorPresentation[terminal]=onesAreBlack THEN
IO.PutRope[file, "onesAreBlack\n"]
ELSE
IO.PutRope[file, "onesAreWhite\n"];
FOR i: Terminal.ChannelValue IN Terminal.ChannelValue DO
red, green, blue: Terminal.ColorValue;
index: INT ← i;
[red, green, blue] ← Terminal.GetColor[terminal, i];
IF special=$i THEN index ← -index;
IO.PutF[file, " %g %g %g %g\n", IO.int[index], IO.card[red], IO.card[green], IO.card[blue]];
ENDLOOP;
IO.Close[file];
EXITS thatsIt => NULL
END;
ButtonHit: Buttons.ButtonProc =
BEGIN
ENABLE TerminalIO.UserAbort => GOTO aborted;
choice: INT ← 0;
lor: LIST OF Rope.ROPENIL;
Each: SymTab.EachPairAction = {
lor ← CONS[key, lor]; quit ← FALSE
};
[] ← regTab.Pairs[Each];
IF lor#NIL THEN choice ← PopUpSelection.Request["color", lor];
IF choice>0 THEN TRUSTED {
entry: Rope.ROPENARROW[List.NthElement[LOOPHOLE[lor], choice]];
name: Rope.ROPENARROW[regTab.Fetch[entry].val];
SetUp[name];
};
Message[];
EXITS aborted => NULL;
END;
Message: PROC [] =
BEGIN
r: Rope.ROPE ← Last[];
IF r=NIL THEN r ← "not loaded from a file";
MessageWindow.Append[Rope.Concat["color map: ", r], TRUE];
END;
ColorMapCommand: Commander.CommandProc =
BEGIN
argv: CommandTool.ArgumentVector
← CommandTool.Parse[cmd ! CommandTool.Failed => {msg ← errorMsg; GO TO oops}];
IF argv.argc<=1 OR argv[1].IsEmpty[] THEN GO TO oops;
IF argv[1].Fetch[0]#'- THEN SetUp[argv[1], TRUE, TRUE, cmd.out]
ELSE { --switches..
SELECT TRUE FROM
Rope.Equal[argv[1], "-n", FALSE] => { --read without forcing display
IF argv.argc<=2 THEN {msg ← "needs filename"; GO TO oops};
SetUp[argv[2], FALSE, FALSE, cmd.out];
};
Rope.Equal[argv[1], "-register", FALSE] => { --register menu command
fn: Rope.ROPE;
IF argv.argc<=3 THEN {msg ← "needs key and filename"; GO TO oops};
fn ← FileNames.FileWithSearchRules[root: argv[3], defaultExtension: ".ColorMap", searchRules: NIL].fullPath;
IF Rope.IsEmpty[fn] THEN {msg ← "file not found"; GO TO oops};
RegisterMenu[argv[2], fn];
};
Rope.Equal[argv[1], "-create", FALSE] => {--create file
IF argv.argc<=2 THEN {msg ← "needs filename"; GO TO oops};
Create[argv[2], NIL, cmd.out];
};
ENDCASE => {msg ← "only known switches: -n, -register, -create"; GO TO oops};
};
EXITS oops => result ← $Failure;
END;
IF terminal.hasColorDisplay THEN
[] ← Buttons.Create[info: [name: "8-bit colors"], proc: ButtonHit, fork: TRUE];
RegisterMenu["cedar-8-bit", "cedar-8-bit"];
RegisterMenu["off", "off"];
Commander.Register[key: "///Commands/ColorMaps", proc: ColorMapCommand, doc: "reads 8 bit colormap from file [-n, -register, -create]"];
END.