<> <> <> <> <> <> <> <> 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 <> <<>> Virtual: TYPE = Terminal.Virtual; VirtualImpl: TYPE = TerminalImpl.VirtualImpl; <<>> TerminalColorExtrasError: PUBLIC SIGNAL [reason: ATOM] ~ CODE; <> <<>> <> 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[]; <> 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]; }; }; <> --AcquireAndMarkTerminalUnstable[]; SetColorBitmapStateInner[]; --MarkTerminalStable[]; }; END.