TerminalColorExtrasImpl.mesa
Cribbed from TerminalImpl, October 8, 1984 12:53:00 pm PDT
Last Edited by: Birrell, November 16, 1983 11:24 am
Last Edited by: Wyatt, December 21, 1983 1:19 pm
implement color display
Last Edited by: Russ Atkinson, December 21, 1983 5:17 pm
fix problems with ShowColorCursor & HideColorCursor
Last Edited by: Frank Crow, October 8, 1984 12:53:47 pm PDT
DIRECTORY
Basics       USING [bitsPerWord],
ColorDisplayFace    USING [baseA, baseB, bplA, bplB, Disconnect, height,
           Mode, Show, TurnOff, TurnOn, width],
ColorDisplayFaceExtras  USING [Connect, SetDisplaySize, PagesForMode],
Terminal      USING [BitmapState, ChannelsVisible, ColorMode, Object, Virtual],
TerminalImpl     USING [ColorFaceMode, ExpandColorCursorPattern,
           VirtualImpl, current],
TerminalColorExtras   USING [],
VM        USING [AddressForPageNumber, Allocate, CantAllocate, Free,
           Interval, nullInterval, Pin, Unpin];
TerminalColorExtrasImpl: CEDAR MONITOR
IMPORTS
ColorDisplayFace, ColorDisplayFaceExtras, TerminalImpl, VM
EXPORTS TerminalColorExtras
SHARES Terminal, TerminalImpl =
BEGIN
Types
Virtual: TYPE = Terminal.Virtual;
VirtualImpl: TYPE = TerminalImpl.VirtualImpl;
TerminalColorExtrasError: PUBLIC SIGNAL [reason: ATOM] ~ CODE;
Color Display
Set color display up: Height, Width and Bitmap may be provided if desired
SetColorBitmapState: PUBLIC PROC [vt: Virtual,
newState: Terminal.BitmapState,
newMode: Terminal.ColorMode,
newVisibility: Terminal.ChannelsVisible,
widthA, heightA, widthB, heightB: NAT ← 0,
vMem: VM.Interval ← VM.nullInterval
]
RETURNS [
oldState: Terminal.BitmapState,
oldMode: Terminal.ColorMode, oldVisibility: Terminal.ChannelsVisible
] = {
impl: VirtualImpl = NARROW[vt.impl];
SetColorBitmapStateInner: ENTRY PROC = {
ENABLE UNWIND => NULL;
AllocateColorVM: PROC[fmode: ColorDisplayFace.Mode] RETURNS [interval: VM.Interval] = {
pages: INT;
IF widthA+heightA+widthB+heightB > 0 THEN TRUSTED{ -- set size if not defaulted
ColorDisplayFaceExtras.SetDisplaySize[widthA, heightA, widthB, heightB];
};
TRUSTED { pages ← ColorDisplayFaceExtras.PagesForMode[fmode] };
IF vMem = VM.nullInterval THEN {
interval ← VM.Allocate[
count: pages ! VM.CantAllocate => ERROR TerminalColorExtrasError[$CantGetVM] ];
}
ELSE IF pages <= vMem.count THEN interval ← vMem
         ELSE ERROR TerminalColorExtrasError[$BadDimensions];
};
Connect: INTERNAL PROC[fmode: ColorDisplayFace.Mode] = TRUSTED {
impl.colorVM ← AllocateColorVM[fmode];
ColorDisplayFaceExtras.Connect[mode: fmode,
firstPage: impl.colorVM.page, nPages: impl.colorVM.count];
vt.colorWidth ← ColorDisplayFace.width;
vt.colorHeight ← ColorDisplayFace.height;
vt.colorBitmapA ← ColorDisplayFace.baseA;
vt.colorBitmapB ← ColorDisplayFace.baseB;
vt.colorWordsPerLineA ← ColorDisplayFace.bplA/Basics.bitsPerWord;
IF (ColorDisplayFace.bplA MOD Basics.bitsPerWord) # 0
THEN vt.colorWordsPerLineA ← vt.colorWordsPerLineA + 1;
vt.colorWordsPerLineB ← ColorDisplayFace.bplB/Basics.bitsPerWord;
IF (ColorDisplayFace.bplB MOD Basics.bitsPerWord) # 0
THEN vt.colorWordsPerLineB ← vt.colorWordsPerLineB + 1;
impl.colorCursorVM ← VM.Allocate[3];
VM.Pin[impl.colorCursorVM];
impl.colorCursorSourceA ← VM.AddressForPageNumber[impl.colorCursorVM.page]; --page 1
impl.colorCursorBackupA ← impl.colorCursorSourceA+256; --page 2
impl.colorCursorSourceB ← impl.colorCursorBackupA+256; --first half of page 3
impl.colorCursorBackupB ← impl.colorCursorSourceB+128; --second half of page 3
TerminalImpl.ExpandColorCursorPattern[vt, impl];
};
Disconnect: INTERNAL PROC = TRUSTED {
vt.colorBitmapA ← vt.colorBitmapB ← NIL;
vt.colorWordsPerLineA ← vt.colorWordsPerLineB ← 0;
ColorDisplayFace.Disconnect[];
VM.Free[impl.colorVM];    -- Don't throw this away, somebody else may own it!
impl.colorVM ← VM.nullInterval;   -- Garbage collector will get it if not
impl.colorBitmapState ← none;
impl.colorCursorSourceA ← impl.colorCursorBackupA ← NIL;
impl.colorCursorSourceB ← impl.colorCursorBackupB ← NIL;
VM.Free[impl.colorCursorVM];
impl.colorCursorVM ← VM.nullInterval;
};
TurnOn: INTERNAL PROC = {
IF TerminalImpl.current=vt THEN {
VM.Pin[impl.colorVM];
TRUSTED{ColorDisplayFace.TurnOn[]};
};
};
TurnOff: INTERNAL PROC = {
IF TerminalImpl.current=vt THEN {
TRUSTED{ColorDisplayFace.TurnOff[]};
VM.Unpin[impl.colorVM];
};
};
oldMode ← vt.colorMode;
oldState ← impl.colorBitmapState;
oldVisibility ← impl.colorVisibility;
IF (newMode#oldMode) OR (widthA+heightA+widthB+heightB > 0) OR (vMem # VM.nullInterval)
THEN {
fmode: ColorDisplayFace.Mode ~ TerminalImpl.ColorFaceMode[newMode];
IF TRUE    -- TerminalImpl.LegalColorFaceMode[fmode] (fix sometime!!)
THEN vt.colorMode ← newMode
ELSE ERROR TerminalColorExtrasError[$BadColorMode];
IF oldState#none THEN {
IF oldState=displayed THEN TurnOff[];
Disconnect[];
};
IF newState#none THEN {
Connect[fmode];
IF newState=displayed THEN TurnOn[];
};
}
ELSE IF newState#oldState THEN {
IF oldState=displayed THEN TurnOff[];
IF newState=none THEN Disconnect[];
IF oldState=none THEN Connect[TerminalImpl.ColorFaceMode[vt.colorMode]];
IF newState=displayed THEN TurnOn[];
};
impl.colorBitmapState ← newState;
IF newVisibility#oldVisibility THEN {
impl.colorVisibility ← newVisibility;
IF vt=TerminalImpl.current THEN SELECT newVisibility FROM
none => TRUSTED{ColorDisplayFace.Show[a: FALSE, b: FALSE]};
aOnly => TRUSTED{ColorDisplayFace.Show[a: TRUE, b: FALSE]};
bOnly => TRUSTED{ColorDisplayFace.Show[a: FALSE, b: TRUE]};
all => TRUSTED{ColorDisplayFace.Show[a: TRUE, b: TRUE]};
ENDCASE => ERROR TerminalColorExtrasError[$BadVisibility];
};
};
Acquire/Release replaced by ENTRY on inner proc to prevent deadlock in notifier stuff. This is probably not a good fix, since it may keep the monitor locked for a long time while allocating the bitmap
--AcquireAndMarkTerminalUnstable[];
SetColorBitmapStateInner[];
--MarkTerminalStable[];
};
END.