TerminalColorExtras.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, PagesForMode, Show, TurnOff, TurnOn, width],
ColorDisplayFaceExtras USING [Connect, SetDisplaySize],
Terminal USING [BitmapState, ChannelsVisible, ColorMode, Object, Virtual],
TerminalImpl USING [ColorFaceMode, ExpandColorCursorPattern,
LegalColorFaceMode, 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,
width, height: 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 width > 0
AND height > 0
THEN
TRUSTED{
-- set screen dimensions if not defaulted
ColorDisplayFaceExtras.SetDisplaySize[width, height];
};
TRUSTED { pages ← ColorDisplayFace.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;
IF (ColorDisplayFace.bplA
MOD Basics.bitsPerWord)=0
THEN
vt.colorWordsPerLineA ← ColorDisplayFace.bplA/Basics.bitsPerWord
ELSE ERROR TerminalColorExtrasError[$BitsPerLineABad];
IF (ColorDisplayFace.bplB
MOD Basics.bitsPerWord)=0
THEN
vt.colorWordsPerLineB ← ColorDisplayFace.bplB/Basics.bitsPerWord
ELSE ERROR TerminalColorExtrasError[$BitsPerLineBBad];
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 (width > 0 AND height > 0) OR (vMem # VM.nullInterval)
THEN {
fmode: ColorDisplayFace.Mode ~ TerminalImpl.ColorFaceMode[newMode];
IF TerminalImpl.LegalColorFaceMode[fmode]
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.