ColorDisplayImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created from old ColorDisplay by Mik Lamming and Ken Pier
Last Edited by: Nickell, June 22, 1985 12:42:40 pm PDT
Last Edited by: Beach, August 17, 1984 5:24:14 pm PDT
Last Edited by: Pier, November 19, 1984 3:10:48 pm PST
Rick Beach, December 9, 1985 11:04:48 am PST
Tim Diebert: October 24, 1985 5:38:30 pm PDT
Tim Diebert May 17, 1985 4:50:03 pm PDT
DIRECTORY
ColorDisplay,
ColorDisplayDefs USING [colorMode24, ColorDisplayType, ColorMode],
ColorDisplayFace USING [SetDisplayType],
Imager, ImagerDevice, ImagerTerminal, InterminalBackdoor, ImagerCache, ImagerRaster, ImagerColorMap,
Interminal USING [GetColorDisplaySide, SetColorDisplaySide],
MessageWindow USING [Append, Blink],
Process USING [Detach, Pause, SetTimeout, Ticks],
Rope USING [Equal, ROPE],
SafeStorage USING [ReclaimCollectibleObjects],
Terminal USING [BitmapState, CantDoIt, ChannelsVisible, ColorMode, Current, FrameBuffer, GetColorBitmapState, GetColorMode, GetColorFrameBufferA, GetVisibility, SetColorBitmapState, SetColorCursorPresentation, SetColorMode, Virtual],
UserProfile USING [Number, Token],
ViewerClasses USING [Viewer],
ViewerPrivate,
ViewerOps USING [ChangeColumn, CloseViewer, ComputeColumn, EnumerateViewers, EnumProc, OpenIcon, PaintEverything],
WindowManager USING [colorDisplayOn, ScreenPos, StartColorViewers, StopColorViewers];
ColorDisplayImpl: CEDAR MONITOR
IMPORTS ColorDisplayFace, ImagerTerminal, InterminalBackdoor, ImagerCache, ImagerRaster, ImagerColorMap, Interminal, MessageWindow, Process, Rope, SafeStorage, Terminal, UserProfile, ViewerOps, ViewerPrivate, WindowManager
EXPORTS ColorDisplay
~ BEGIN OPEN ColorDisplay;
bppLast and sideLast are examined only when the color display is off. This lets the ColorDisplay package know where to default them to when the color display is turned on again. NOTE: Every call to the ColorDisplay package will cause these values to be updated with the actual state of the machine, if it is on.
bppLast: PUBLIC CARDINAL ← 8;
onLeftLast: PUBLIC BOOLEANTRUE;
nowGray: PUBLIC BOOLEANFALSE;
monitorTypeLast: PUBLIC Rope.ROPE ← "640x480";
DefaultBpp, Bpp: PUBLIC PROC RETURNS [bpp: CARDINAL] ~ { --Has side effect of remembering bpp
IF WindowManager.colorDisplayOn THEN {
OPEN Terminal;
colorMode: ColorMode ← GetColorMode[Current[]];
bpp ← (IF colorMode.full THEN 24 ELSE colorMode.bitsPerPixelChannelA);
}
ELSE bpp ← bppLast;
bppLast ← bpp;      --Remember the setting of the screen
};
DefaultOnLeft, OnLeft: PUBLIC PROC RETURNS [onLeft: BOOLEAN] ~ {
onLeft ← IF WindowManager.colorDisplayOn
THEN Interminal.GetColorDisplaySide[] = left ELSE onLeftLast;
onLeftLast ← onLeft;
};
DefaultOn: PUBLIC PROC RETURNS [BOOLEAN] ~ {
RETURN[WindowManager.colorDisplayOn];
};
DefaultMonitorType: PUBLIC PROC RETURNS [Rope.ROPE] ~ {
RETURN[monitorTypeLast];
};
SetColorDisplayStatus: PUBLIC ENTRY PROC [on: BOOLEAN ← DefaultOn[], onLeft: BOOLEAN ← DefaultOnLeft[], gray: BOOLFALSE, bpp: CARDINAL ← DefaultBpp[], monitorType: Rope.ROPE ← DefaultMonitorType[]] ~ {
ENABLE UNWIND => NULL;
NOTIFY forCDChanges;  --Let the informant know...
SELECT TRUE FROM
Check for nothing changed
(on=WindowManager.colorDisplayOn AND bpp=Bpp[] AND monitorType=monitorTypeLast AND onLeft=OnLeft[] AND gray=nowGray) => RETURN;
Check for change in gray
(on=WindowManager.colorDisplayOn AND gray#nowGray) => {IF nowGray THEN DefaultViewers[] ELSE GrayViewers[]; nowGray ← NOT nowGray; RETURN};
Check for just switching sides.
(on=WindowManager.colorDisplayOn AND bpp=Bpp[] AND monitorType=monitorTypeLast AND on) => {IF Interminal.GetColorDisplaySide[] = left
THEN Interminal.SetColorDisplaySide[right] ELSE Interminal.SetColorDisplaySide[left]};
Otherwise, we need to check the whole ball of wax
ENDCASE => TRUSTED {
colorViewerList, colorIconList: LIST OF ViewerClasses.Viewer ← NIL; --Really only viewers, tho
ListColorViewers: PROC ~ TRUSTED {   --Constructs a list of the color viewers
EnumColorViewers: ViewerOps.EnumProc ~ TRUSTED {
IF v.column=color THEN
IF v.iconic THEN colorIconList ← CONS[v,colorIconList] ELSE {
ViewerOps.CloseViewer[v, FALSE];
colorViewerList ← CONS[v,colorViewerList];
};
};
ViewerOps.EnumerateViewers[enum: EnumColorViewers];
ViewerOps.ComputeColumn[static];
};
ReopenColorViewers: PROC ~ TRUSTED {  --Reopen the listed color viewers
FOR each: LIST OF ViewerClasses.Viewer ← colorViewerList, each.rest UNTIL each=NIL DO
ViewerOps.ChangeColumn[each.first, color];
ViewerOps.OpenIcon[icon: each.first, paint: TRUE]; -- should be FALSE but call below to ComputeColumn doesn't repaint if no size change!
ENDLOOP;
ViewerOps.ComputeColumn[color];
Reset the icons that WOULD have been opened on the color display back there
FOR each: LIST OF ViewerClasses.Viewer ← colorIconList, each.rest UNTIL each=NIL DO
ViewerOps.ChangeColumn[each.first, color];
ENDLOOP;
};
side: WindowManager.ScreenPos ← IF onLeft THEN left ELSE right;
ok: BOOLFALSE;
onLeftLast ← onLeft;
bppLast ← bpp;
monitorTypeLast ← monitorType;  --Back up the given parameters
ListColorViewers[];
WindowManager.StopColorViewers[];
IF on THEN {
SELECT TRUE FROM
Rope.Equal[s1: monitorType, s2: "640x480", case: FALSE] => ok ← Start640Monitor[bitsPerPixel: bpp, pos: side];
Rope.Equal[s1: monitorType, s2: "1024x768", case: FALSE] => ok ← Start1024Monitor[bitsPerPixel: bpp, pos: side];
ENDCASE => {MessageWindow.Append["Invalid monitor type!!", TRUE];
MessageWindow.Blink[]};
IF NOT ok THEN
{MessageWindow.Append["Can't turn on color!"]; MessageWindow.Blink[];
RETURN};
IF nowGray#gray THEN {IF nowGray THEN DefaultViewers[] ELSE GrayViewers[]; nowGray ← NOT nowGray};
ReopenColorViewers[];
};
};
};
StartMonitor: PROC [type: ColorDisplayDefs.ColorDisplayType, bitsPerPixel: CARDINAL,
pos: WindowManager.ScreenPos] ~ {
mode: ColorDisplayDefs.ColorMode ~ IF bitsPerPixel = 24 THEN ColorDisplayDefs.colorMode24 ELSE [FALSE, 8, 0];
[]← ColorDisplayFace.SetDisplayType[type];
FOR try: CARDINAL IN [1..3] DO
[]← Terminal.SetColorMode[Terminal.Current[], mode
! Terminal.CantDoIt => {  --Try a bit of garbage collection
SELECT try FROM
1 => {
MessageWindow.Append["Couldn't allocate frame. Garbage collecting...", TRUE];
SafeStorage.ReclaimCollectibleObjects[];
LOOP;
};
2 => {
MessageWindow.Append[".....GARBAGE COLLECTING!!!"];
SafeStorage.ReclaimCollectibleObjects[traceAndSweep: TRUE];
LOOP;
};
3 => {
MessageWindow.Append["Couldn't do it. Sure you have a color display?", TRUE];
};
ENDCASE => ERROR;
};
];
ENDLOOP;
WindowManager.StartColorViewers[pos, bitsPerPixel];
};
Start640Monitor: PUBLIC PROCEDURE [bitsPerPixel: CARDINAL ← 8,
pos: WindowManager.ScreenPos ← left] RETURNS [ok: BOOLTRUE] = {
WindowManager.StopColorViewers[];
StartMonitor[standard, bitsPerPixel, pos];
};
Start1024Monitor: PUBLIC PROCEDURE [bitsPerPixel: CARDINAL ← 8,
pos: WindowManager.ScreenPos ← left] RETURNS [ok: BOOLTRUE] = {
WindowManager.StopColorViewers[];
IF bitsPerPixel = 24 THEN RETURN [FALSE];
StartMonitor[highResolution, bitsPerPixel, pos];
};
GetColorDisplayStatus: PUBLIC ENTRY PROC RETURNS [on, onLeft, gray: BOOLEAN, bpp: CARDINAL, monitorType: Rope.ROPE] ~ {
ENABLE UNWIND => NULL;
[on, onLeft, gray, bpp, monitorType] ← GetColorDisplayStatusInternal[];
};
GetCDState: INTERNAL PROC RETURNS [state: CDState] ~ INLINE {
[state.on, state.onLeft, state.gray, state.bpp, state.monitorType] ← GetColorDisplayStatusInternal[];
};
GetColorDisplayStatusInternal: INTERNAL PROC RETURNS [on, onLeft, gray: BOOLEAN, bpp: CARDINAL, monitorType: Rope.ROPE] ~ {
on ← WindowManager.colorDisplayOn;
onLeft ← OnLeft[];
bpp ← Bpp[];
monitorType ← monitorTypeLast;
gray ← nowGray;
};
GetColorDisplayProfile: PUBLIC PROC RETURNS [on, onLeft: BOOLEAN, bpp: CARDINAL, monitorType: Rope.ROPE] ~ {
RightOrLeft: PROC RETURNS[rl: Rope.ROPE] ~ INLINE {
rl ← IF onLeftLast THEN "left" ELSE "right"};
tBpp: INTEGER;   --Temporary bits per pixel
on ← WindowManager.colorDisplayOn;
SELECT tBpp ← UserProfile.Number["ColorDisplay.BitsPerPoint", Bpp[]] FROM
1,2,4,8,24 => bpp ← tBpp;
ENDCASE => bpp ← Bpp[];
onLeft ← Rope.Equal[UserProfile.Token["ColorDisplay.Side", RightOrLeft[]], "left", FALSE];
monitorType ← UserProfile.Token["ColorDisplay.Type", monitorTypeLast];
};
procList: LIST OF REF NotifyRecord ← NIL; --Dummy
NotifyRecord: TYPE ~ RECORD [
proc: CDNotifyProc,
clientData: REF
];
RegisterCDNotifyProc: PUBLIC ENTRY PROC [proc: CDNotifyProc, clientData: REF] RETURNS [reg: CDRegistration] ~ {
ENABLE UNWIND => NULL;
state: CDState ~ GetCDState[];
ref: REF NotifyRecord ~ NEW[NotifyRecord ← [proc: proc, clientData: clientData]];
procList ← CONS[ref, procList];
TRUSTED {Process.Detach[FORK proc[state, state, clientData]]};
RETURN [ref]
};
UnregisterCDNotifyProc: PUBLIC ENTRY PROC [reg: CDRegistration] ~ {
ENABLE UNWIND => NULL;
ref: REF NotifyRecord ~ NARROW[reg];
WHILE procList#NIL AND procList.first=ref DO--Eliminate if at beginning
procList ← procList.rest;
ENDLOOP;
FOR p: LIST OF REF NotifyRecord ← procList, p.rest UNTIL p=NIL DO
WHILE p.rest#NIL AND p.rest.first=reg DO
p.rest ← p.rest.rest;
ENDLOOP;
ENDLOOP;
};
forCDChanges: CONDITION;
WatchForChanges: ENTRY PROC ~ {
ENABLE UNWIND => NULL;
old, new: CDState ← GetCDState[];
DO
WHILE old = (new ← GetCDState[]) DO
WAIT forCDChanges;
ENDLOOP;
FOR each: LIST OF REF NotifyRecord ← procList, each.rest UNTIL each=NIL DO
TRUSTED {Process.Detach[FORK each.first.proc[old, new, each.first.clientData]];}
ENDLOOP;
old ← new;
ENDLOOP;
};
SleepColorDisplay: PUBLIC ENTRY UNSAFE PROC [ticks: Process.Ticks] ~ {
OPEN Terminal;
ENABLE UNWIND => NULL;
vt: Virtual ← Current[];
state: BitmapState ← GetColorBitmapState[vt];
mode: ColorMode ← GetColorMode[vt];
visible: ChannelsVisible ← GetVisibility[vt];
IF state#displayed THEN RETURN;
[] ← SetColorBitmapState[vt, allocated, mode, none];
Process.Pause[ticks];
[] ← SetColorBitmapState[vt, state, mode, visible];
};
Context: TYPE ~ Imager.Context;
GrayCreateContext: PROC [screen: ViewerPrivate.Screen] RETURNS [context: Imager.Context] ~ {
terminal: Terminal.Virtual ~ InterminalBackdoor.terminal;
SELECT screen FROM
bw => context ← ImagerTerminal.BWContext[vt: terminal, pixelUnits: TRUE];
color => context ← GrayContext[vt: terminal, pixelUnits: TRUE];
ENDCASE => ERROR;
};
gamma: REAL ← 2.2;
fontCacheID: ATOM ~ $ColorDisplay;
fontCacheSize: NAT ← 4000;
fontRastWeight: REAL ← 0.0;
GrayContext: PROC [vt: Terminal.Virtual, pixelUnits: BOOL] RETURNS [Context] ~ {
mode: Terminal.ColorMode ~ Terminal.GetColorMode[vt];
IF Terminal.GetColorBitmapState[vt]=none THEN RETURN[NIL]
ELSE {
frameBuffer: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferA[vt];
fontCache: ImagerCache.Ref ~ ImagerCache.GetNamedCache[
atom: fontCacheID, createSize: fontCacheSize];
device: ImagerDevice.Device ~ ImagerRaster.NewGrayDevice[vt];
[] ← Terminal.SetColorCursorPresentation[vt, onesAreBlack];
ImagerColorMap.SetStandardGrayMap[vt: vt, gamma: gamma];
RETURN[ImagerRaster.Create[device: device, pixelUnits: pixelUnits,
fontCache: fontCache, rastWeight: fontRastWeight]];
};
};
GrayViewers: PUBLIC PROC ~ {
[] ← ViewerPrivate.SetCreator[GrayCreateContext];
ViewerOps.PaintEverything[];
};
DefaultViewers: PUBLIC PROC ~ {
[] ← ViewerPrivate.SetCreator[NIL];
ImagerColorMap.SetStandardColorMap[vt: InterminalBackdoor.terminal, gamma: gamma];
ViewerOps.PaintEverything[];
};
Init: PROC[] RETURNS[] ~ {
Read the user profile to establish the initial back settings...
[,onLeftLast, bppLast, monitorTypeLast] ← GetColorDisplayProfile[];
TRUSTED {
Process.SetTimeout[@forCDChanges, 300];
Process.Detach[FORK WatchForChanges[]];
};
};
Init[];
END.
CHANGE LOG
Rick Beach, December 9, 1985 11:03:49 am PST
changes to: SetColorDisplayStatus, ReopenColorViewers (local of SetColorDisplayStatus) to force repaint of color viewer because ComputeColumn does not guarantee to paint all the viewers