DIRECTORY Basics USING [bitsPerWord, LongMult, RawWords], ColorDisplayFace, CountedVM USING [Allocate, Free, Handle, SimpleAllocate], PrincOps USING [BBTable, BBTableSpace, BitAddress, BitBltTablePtr], PrincOpsUtils USING [AlignedBBTable, AllocateNakedCondition, BITBLT], Process USING [Detach, EnableAborts, GetPriority, MsecToTicks, Pause, Priority, priorityForeground, SetPriority, Ticks], SystemVersion USING [machineType], Terminal USING [BitmapState, BWBackground, BWBorder, ChannelsVisible, ChannelValue, ColorCursorBitmapState, ColorCursorPresentation, ColorMode, ColorValue, FrameBuffer, FrameBufferRep, SwapAction, SwapNotifier, Virtual, VirtualRep], TerminalDefs USING [Cursor, KeyBits, KeyState, Position], TerminalFace USING [Beep, Connect, Disconnect, GetCursorPosition, GetKeyboard, GetMousePosition, globalStateSize, hasBorder, hasBuffer, hasSoundGenerator, height, Initialize, InitializeCleanup, pixelsPerInch, SetBackground, SetBorderPattern, SetCursorPattern, SetCursorPosition, SetMousePosition, TurnOff, TurnOn, width, wordsPerLine], TerminalPrivate USING [Notifier, NotifierItem, VirtualImpl, VirtualImplRep], VM USING [CantAllocate, lowCore, Pin, Unpin], VMSideDoor USING [AssignSpecialRealMemory, ReleaseSpecialRealMemory]; TerminalImpl: CEDAR MONITOR IMPORTS Basics, ColorDisplayFace, CountedVM, PrincOpsUtils, Process, SystemVersion, TerminalFace, VM, VMSideDoor EXPORTS Terminal ~ BEGIN OPEN TerminalPrivate, Terminal, TerminalDefs; VirtualImpl: TYPE ~ TerminalPrivate.VirtualImpl; VirtualImplRep: PUBLIC TYPE ~ TerminalPrivate.VirtualImplRep; Notifier: TYPE ~ TerminalPrivate.Notifier; NotifierItem: TYPE ~ TerminalPrivate.NotifierItem; priorityDuringSelect: Process.Priority = Process.priorityForeground; blinkTime: Process.Ticks = Process.MsecToTicks[100]; TerminalList: TYPE ~ LIST OF Virtual; terminals: TerminalList _ NIL; current: Virtual _ NIL; watcherDisableCount: NAT _ 0; terminalChanging: BOOL _ FALSE; terminalStable: CONDITION _ [timeout: 0]; bwRetrace: LONG POINTER TO CONDITION; meFirst: BOOL _ TRUE; verticalRetrace: CONDITION _ [timeout: 0]; WaitUntilSelected: INTERNAL PROC[vt: Virtual] = { UNTIL current=vt DO WAIT terminalStable; ENDLOOP; }; AcquireAndMarkTerminalUnstable: ENTRY PROC = { ENABLE UNWIND => NULL; WHILE terminalChanging DO WAIT terminalStable; ENDLOOP; terminalChanging _ TRUE; }; MarkTerminalStable: ENTRY PROC = { ENABLE UNWIND => NULL; terminalChanging _ FALSE; BROADCAST terminalStable; }; AcquireColorDisplay: ENTRY PROC [vt: Virtual] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; impl.colorDisplayChanging _ TRUE; }; ReleaseColorDisplay: ENTRY PROC [vt: Virtual] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; impl.colorDisplayChanging _ FALSE; BROADCAST impl.colorDisplayStable; }; InternalWaitForBWVerticalRetrace: INTERNAL PROC = { ENABLE UNWIND => NULL; IF meFirst THEN { meFirst _ FALSE; TRUSTED {WAIT bwRetrace^}; BROADCAST verticalRetrace; meFirst _ TRUE; } ELSE WAIT verticalRetrace; }; bitsPerWord: NAT ~ Basics.bitsPerWord; need64K: BOOL _ SystemVersion.machineType # dolphin; cachedBuffer: FrameBuffer _ NewFrameBuffer[ width: TerminalFace.width, height: TerminalFace.height, bitsPerPixel: 1, in64K: need64K]; NewFrameBuffer: PROC [width, height, bitsPerPixel: NAT, in64K: BOOL _ FALSE] RETURNS [FrameBuffer] ~ { wordsPerLine: NAT ~ (bitsPerPixel*width)/bitsPerWord; words: INT ~ INT[wordsPerLine]*INT[height]; vm: CountedVM.Handle ~ CountedVM.Allocate[words: words, in64K: in64K ! VM.CantAllocate => GO TO cant]; RETURN[NEW[FrameBufferRep _ [vm: vm, base: vm.pointer, wordsPerLine: wordsPerLine, bitsPerPixel: bitsPerPixel, width: width, height: height]]]; EXITS cant => ERROR CantDoIt; }; BWAllocate: INTERNAL PROC [impl: VirtualImpl] ~ { width: NAT ~ TerminalFace.width; height: NAT ~ TerminalFace.height; wordsPerLine: NAT ~ TerminalFace.wordsPerLine; IF (wordsPerLine*bitsPerWord)#width THEN ERROR; IF cachedBuffer # NIL THEN { impl.bwFrameBuffer _ cachedBuffer; cachedBuffer _ NIL; RETURN; }; impl.bwFrameBuffer _ NewFrameBuffer[ width: width, height: height, bitsPerPixel: 1, in64K: need64K]; }; BWFree: INTERNAL PROC [impl: VirtualImpl] ~ { IF cachedBuffer = NIL THEN cachedBuffer _ impl.bwFrameBuffer; impl.bwFrameBuffer _ NIL; }; BWConnect: INTERNAL PROC [impl: VirtualImpl] ~ { IF TerminalFace.hasBuffer THEN VMSideDoor.AssignSpecialRealMemory[impl.bwFrameBuffer.vm.interval]; TRUSTED { TerminalFace.Connect[impl.bwFrameBuffer.base] }; }; BWDisconnect: INTERNAL PROC [impl: VirtualImpl] ~ { TerminalFace.Disconnect[]; IF TerminalFace.hasBuffer THEN VMSideDoor.ReleaseSpecialRealMemory[impl.bwFrameBuffer.vm.interval]; }; BWTurnOn: INTERNAL PROC [impl: VirtualImpl] ~ TRUSTED { IF NOT TerminalFace.hasBuffer THEN VM.Pin[impl.bwFrameBuffer.vm.interval]; TerminalFace.TurnOn[]; }; BWTurnOff: INTERNAL PROC [impl: VirtualImpl] ~ { TerminalFace.TurnOff[]; InternalWaitForBWVerticalRetrace[]; InternalWaitForBWVerticalRetrace[]; IF NOT TerminalFace.hasBuffer THEN VM.Unpin[impl.bwFrameBuffer.vm.interval]; }; ColorAllocate: PROC [impl: VirtualImpl] ~ { mode: ColorMode ~ impl.colorMode; width: NAT ~ ColorDisplayFace.width; height: NAT ~ ColorDisplayFace.height; IF NOT ColorDisplayFace.HasMode[mode] THEN ERROR CantDoIt; IF mode.full THEN { impl.colorFrameBufferA _ NewFrameBuffer[ width: width, height: height, bitsPerPixel: 16]; impl.colorFrameBufferB _ NewFrameBuffer[ width: width, height: height, bitsPerPixel: 8]; } ELSE { IF mode.bitsPerPixelChannelA#0 THEN impl.colorFrameBufferA _ NewFrameBuffer[ width: width, height: height, bitsPerPixel: mode.bitsPerPixelChannelA]; IF mode.bitsPerPixelChannelB#0 THEN impl.colorFrameBufferB _ NewFrameBuffer[ width: width, height: height, bitsPerPixel: mode.bitsPerPixelChannelB]; }; impl.colorMapVM _ CountedVM.SimpleAllocate[ColorDisplayFace.wordsForColorMap]; TRUSTED { impl.colorMap _ ColorDisplayFace.InitializeColorMap[ mode: mode, pointer: impl.colorMapVM.pointer] }; IF impl.colorCursorVM=NIL THEN TRUSTED { vm: CountedVM.Handle ~ CountedVM.SimpleAllocate[words: 3*256]; impl.colorCursorVM _ vm; impl.colorCursorSourceA _ vm.pointer; --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 VM.Pin[vm.interval]; }; }; ColorFree: PROC [impl: VirtualImpl] ~ { impl.colorFrameBufferA _ NIL; impl.colorFrameBufferB _ NIL; TRUSTED { CountedVM.Free[impl.colorMapVM] }; impl.colorMap _ NIL; impl.colorMapVM _ NIL; }; ColorConnect: PROC [impl: VirtualImpl] ~ TRUSTED { mode: ColorMode ~ impl.colorMode; baseA, baseB: LONG POINTER _ NIL; IF impl.colorFrameBufferA#NIL THEN baseA _ impl.colorFrameBufferA.base; IF impl.colorFrameBufferB#NIL THEN baseB _ impl.colorFrameBufferB.base; ColorDisplayFace.Connect[mode: mode, baseA: baseA, baseB: baseB, map: impl.colorMap]; ExpandColorCursorPattern[impl]; }; ColorDisconnect: PROC [impl: VirtualImpl] ~ TRUSTED { ColorDisplayFace.Disconnect[]; }; ColorTurnOn: PROC [impl: VirtualImpl] ~ TRUSTED { mode: ColorMode ~ impl.colorMode; IF impl.colorFrameBufferA#NIL THEN VM.Pin[impl.colorFrameBufferA.vm.interval]; IF impl.colorFrameBufferB#NIL THEN VM.Pin[impl.colorFrameBufferB.vm.interval]; VM.Pin[impl.colorMapVM.interval]; ColorDisplayFace.TurnOn[]; }; ColorTurnOff: PROC [impl: VirtualImpl] ~ TRUSTED { mode: ColorMode ~ impl.colorMode; ColorDisplayFace.TurnOff[]; IF impl.colorFrameBufferA#NIL THEN VM.Unpin[impl.colorFrameBufferA.vm.interval]; IF impl.colorFrameBufferB#NIL THEN VM.Unpin[impl.colorFrameBufferB.vm.interval]; VM.Unpin[impl.colorMapVM.interval]; }; LoadTerminal: INTERNAL PROC[vt: Virtual] ~ { impl: VirtualImpl ~ vt.impl; TerminalFace.SetMousePosition[impl.mouse]; TerminalFace.SetCursorPosition[impl.bwCursorPosition]; TerminalFace.SetCursorPattern[impl.bwCursorPattern]; TerminalFace.SetBackground[impl.bwBackground]; TerminalFace.SetBorderPattern[oddPairs: impl.bwBorderOdd, evenPairs: impl.bwBorderEven]; IF impl.bwBitmapState#none THEN BWConnect[impl]; IF impl.bwBitmapState=displayed THEN BWTurnOn[impl]; ColorDisplayFace.SetVisibility[impl.colorVisibility]; IF impl.colorBitmapState#none THEN ColorConnect[impl]; IF impl.colorBitmapState=displayed THEN ColorTurnOn[impl]; }; UnloadTerminal: INTERNAL PROC[vt: Virtual] ~ { impl: VirtualImpl ~ vt.impl; impl.keyboard _ TerminalFace.GetKeyboard[]; impl.mouse _ TerminalFace.GetMousePosition[]; impl.bwCursorPosition _ TerminalFace.GetCursorPosition[]; IF impl.bwBitmapState=displayed THEN BWTurnOff[impl]; IF impl.bwBitmapState#none THEN BWDisconnect[impl]; IF impl.colorBitmapState=displayed THEN ColorTurnOff[impl]; IF impl.colorBitmapState#none THEN ColorDisconnect[impl]; }; NewVirtual: PROC RETURNS[vt: Virtual] = { impl: VirtualImpl = NEW[VirtualImplRep _ []]; vt _ NEW[Terminal.VirtualRep _ [ hasBlackAndWhiteDisplay: TRUE, bwWidth: TerminalFace.width, bwHeight: TerminalFace.height, bwHasBorder: TerminalFace.hasBorder, bwPixelsPerInch: TerminalFace.pixelsPerInch, hasColorDisplay: ColorDisplayFace.displayType#none, colorWidth: 0, colorHeight: 0, colorPixelsPerInch: ColorDisplayFace.pixelsPerInch, hasSoundGenerator: TerminalFace.hasSoundGenerator, impl: impl ]]; }; CantDoIt: PUBLIC ERROR = CODE; Create: PUBLIC PROC RETURNS [vt: Virtual] = { AddToList: ENTRY PROC [vt: Virtual] = INLINE { ENABLE UNWIND => NULL; terminals _ CONS[vt, terminals]; }; AddToList[vt _ NewVirtual[]]; }; Select: PUBLIC PROC [vt: Virtual _ NIL] = { old: Virtual; new: Virtual _ vt; DoNotifiers: PROC [vt: Virtual, action: Terminal.SwapAction] = { impl: VirtualImpl = vt.impl; head: Notifier = impl.notifiers; n: Notifier _ impl.notifiers; IF head = NIL THEN RETURN; DO n.proc[vt, action, n.clientData]; IF (n _ IF action = coming THEN n.next ELSE n.prev) = head THEN EXIT; ENDLOOP; }; FlipTerminal: ENTRY PROC [old, new: Virtual] = { ENABLE UNWIND => NULL; UnloadTerminal[old]; current _ new; LoadTerminal[new]; }; FindNextTerminal: ENTRY PROC [old: Virtual] RETURNS [new: Virtual] = { ENABLE UNWIND => NULL; FOR t: TerminalList _ terminals, t.rest UNTIL t = NIL DO IF t.first = old THEN RETURN[(IF t.rest = NIL THEN terminals ELSE t.rest).first]; REPEAT FINISHED => ERROR; ENDLOOP; }; AcquireAndMarkTerminalUnstable[]; old _ current; IF new = NIL THEN new _ FindNextTerminal[old]; IF old ~= new THEN { priority: Process.Priority = Process.GetPriority[]; IF priority < priorityDuringSelect THEN TRUSTED {Process.SetPriority[priorityDuringSelect]}; DoNotifiers[old, going]; DoNotifiers[new, coming]; AcquireColorDisplay[old]; AcquireColorDisplay[new]; FlipTerminal[old: old, new: new]; ReleaseColorDisplay[old]; ReleaseColorDisplay[new]; DoNotifiers[old, gone]; DoNotifiers[new, here]; IF priority < priorityDuringSelect THEN TRUSTED {Process.SetPriority[priority]}; }; MarkTerminalStable[]; }; Current: PUBLIC ENTRY PROC RETURNS[vt: Virtual] = { ENABLE UNWIND => NULL; WHILE terminalChanging DO WAIT terminalStable; ENDLOOP; vt _ current; }; DisableKeyboardWatcher: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; watcherDisableCount _ watcherDisableCount.SUCC; }; EnableKeyboardWatcher: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; IF watcherDisableCount > 0 THEN watcherDisableCount _ watcherDisableCount.PRED; }; RegisterNotifier: PUBLIC ENTRY PROC[vt: Virtual, notifier: Terminal.SwapNotifier, clientData: REF ANY _ NIL] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; n: Notifier = NEW[NotifierItem _ [next: NIL, prev: NIL, proc: notifier, clientData: clientData]]; head: Notifier = impl.notifiers; IF head = NIL THEN n.next _ n.prev _ n ELSE {n.next _ head; n.prev _ head.prev; head.prev.next _ n; head.prev _ n}; impl.notifiers _ n; }; UnregisterNotifier: PUBLIC ENTRY PROC[vt: Virtual, notifier: Terminal.SwapNotifier, clientData: REF ANY _ NIL] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; head: Notifier = impl.notifiers; n: Notifier _ impl.notifiers; IF head ~= NIL THEN DO IF n.proc = notifier AND n.clientData = clientData THEN { n.prev.next _ n.next; n.next.prev _ n.prev; IF n = head THEN impl.notifiers _ IF n.next = n THEN NIL ELSE n.next; EXIT }; IF (n _ n.next) = head THEN EXIT; ENDLOOP; }; GetKeys: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[KeyBits] ~ { ENABLE UNWIND => NULL; IF vt=current THEN RETURN[TerminalFace.GetKeyboard[]] ELSE { impl: VirtualImpl ~ vt.impl; RETURN[impl.keyboard] }; }; GetMousePosition: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[Position] ~ { ENABLE UNWIND => NULL; IF vt=current THEN RETURN[TerminalFace.GetMousePosition[]] ELSE { impl: VirtualImpl ~ vt.impl; RETURN[impl.mouse] }; }; SetMousePosition: PUBLIC ENTRY PROC[vt: Virtual, position: Position] ~ { ENABLE UNWIND => NULL; IF vt=current THEN TerminalFace.SetMousePosition[position] ELSE { impl: VirtualImpl ~ vt.impl; impl.mouse _ position }; }; SetBWCursorPosition: PUBLIC ENTRY PROC[vt: Virtual, position: Position] ~ { ENABLE UNWIND => NULL; IF vt=current THEN TerminalFace.SetCursorPosition[position] ELSE { impl: VirtualImpl ~ vt.impl; impl.bwCursorPosition _ position }; }; GetBWCursorPosition: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[Position] ~ { ENABLE UNWIND => NULL; IF vt=current THEN RETURN[TerminalFace.GetCursorPosition[]] ELSE { impl: VirtualImpl ~ vt.impl; RETURN[impl.bwCursorPosition] }; }; SetBWCursorPattern: PUBLIC ENTRY PROC[vt: Virtual, pattern: Cursor] = { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; impl.bwCursorPattern _ pattern; IF vt=current THEN TerminalFace.SetCursorPattern[pattern]; }; GetBWCursorPattern: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[pattern: Cursor] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; RETURN[impl.bwCursorPattern]; }; GetBWBitmapState: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[BitmapState] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; RETURN[impl.bwBitmapState] }; SetBWBitmapState: PUBLIC PROC[vt: Virtual, new: BitmapState] RETURNS[old: BitmapState] ~ { SetBWBitmapStateInner: ENTRY PROC ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; old _ impl.bwBitmapState; IF new=old THEN RETURN; IF old=none THEN BWAllocate[impl]; IF current=vt THEN { IF old=none THEN BWConnect[impl]; IF new=displayed THEN BWTurnOn[impl]; IF old=displayed THEN BWTurnOff[impl]; IF new=none THEN BWDisconnect[impl]; }; IF new=none THEN BWFree[impl]; impl.bwBitmapState _ new; }; SetBWBitmapStateInner[]; }; GetBWFrameBuffer: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[FrameBuffer] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; RETURN[impl.bwFrameBuffer]; }; GetBWBackground: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[BWBackground] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; RETURN[impl.bwBackground]; }; SetBWBackground: PUBLIC ENTRY PROC[vt: Virtual, new: BWBackground] RETURNS[old: BWBackground] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; old _ impl.bwBackground; IF old=new THEN RETURN; impl.bwBackground _ new; IF vt=current THEN TerminalFace.SetBackground[IF new=white THEN white ELSE black]; }; GetBWBorder: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[oddPairs, evenPairs: BWBorder] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; RETURN[impl.bwBorderOdd, impl.bwBorderEven]; }; SetBWBorder: PUBLIC ENTRY PROC[vt: Virtual, oddPairs, evenPairs: BWBorder] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; impl.bwBorderOdd _ oddPairs; impl.bwBorderEven _ evenPairs; IF vt=current AND TerminalFace.hasBorder THEN TerminalFace.SetBorderPattern[oddPairs: oddPairs, evenPairs: evenPairs]; }; WaitForBWVerticalRetrace: PUBLIC ENTRY PROC[vt: Virtual] = { ENABLE UNWIND => NULL; WaitUntilSelected[vt]; InternalWaitForBWVerticalRetrace[]; }; BlinkBWDisplay: PUBLIC PROC[vt: Virtual] = { impl: VirtualImpl ~ vt.impl; AcquireAndMarkTerminalUnstable[]; IF vt=current THEN { impl: VirtualImpl ~ vt.impl; background: BWBackground ~ impl.bwBackground; TerminalFace.SetBackground[IF background=white THEN black ELSE white]; Process.Pause[blinkTime]; TerminalFace.SetBackground[IF background=white THEN white ELSE black]; }; MarkTerminalStable[]; }; MinimumBitmapState: PROC [state1, state2: BitmapState] RETURNS [BitmapState] ~ { IF state1=none OR state2=none THEN RETURN[none]; IF state1=allocated OR state2=allocated THEN RETURN[allocated]; RETURN[displayed]; }; GetColorBitmapState: PUBLIC ENTRY PROC [vt: Virtual] RETURNS [BitmapState] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN [impl.colorBitmapState] }; SetColorBitmapState: PUBLIC PROC[vt: Virtual, newState: BitmapState, newMode: ColorMode, newVisibility: ChannelsVisible ] RETURNS [ oldState: BitmapState, oldMode: ColorMode, oldVisibility: ChannelsVisible ] ~ { SetColorBitmapStateInner: PROC ~ { impl: VirtualImpl ~ vt.impl; midState: BitmapState _ none; oldState _ impl.colorBitmapState; oldMode _ impl.colorMode; oldVisibility _ impl.colorVisibility; IF newMode=oldMode THEN midState _ MinimumBitmapState[oldState, newState]; IF current=vt AND oldState#midState THEN { IF oldState=displayed THEN ColorTurnOff[impl]; IF midState=none THEN ColorDisconnect[impl]; }; IF oldState#none AND midState=none THEN { vt.colorWidth _ 0; vt.colorHeight _ 0; ColorFree[impl]; }; impl.colorBitmapState _ midState; impl.colorMode _ newMode; impl.colorVisibility _ newVisibility; IF current=vt THEN ColorDisplayFace.SetVisibility[newVisibility]; IF midState=none AND newState#none THEN { ColorAllocate[impl]; -- may raise CantDoIt vt.colorWidth _ ColorDisplayFace.width; vt.colorHeight _ ColorDisplayFace.height; }; IF current=vt AND midState#newState THEN { IF midState=none THEN ColorConnect[impl]; IF newState=displayed THEN ColorTurnOn[impl]; }; impl.colorBitmapState _ newState; }; AcquireColorDisplay[vt]; SetColorBitmapStateInner[! UNWIND => ReleaseColorDisplay[vt]]; ReleaseColorDisplay[vt]; }; GetColorFrameBufferA: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[FrameBuffer] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorFrameBufferA]; }; GetColorFrameBufferB: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[FrameBuffer] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorFrameBufferB]; }; LegalColorMode: PUBLIC PROC[vt: Virtual, mode: ColorMode] RETURNS[BOOL] = { RETURN[ColorDisplayFace.HasMode[mode]]; }; GetColorMode: PUBLIC ENTRY PROC [vt: Virtual] RETURNS [ColorMode] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorMode]; }; SetColorMode: PUBLIC PROC [vt: Virtual, new: ColorMode] RETURNS [old: ColorMode] ~ { RETURN[SetColorBitmapState[vt, allocated, new, all].oldMode]; }; TurnOnColorDisplay: PUBLIC PROC [vt: Virtual] ~ { impl: VirtualImpl ~ vt.impl; [] _ SetColorBitmapState[vt, displayed, impl.colorMode, all]; }; TurnOffColorDisplay: PUBLIC PROC [vt: Virtual] ~ { impl: VirtualImpl ~ vt.impl; [] _ SetColorBitmapState[vt, allocated, impl.colorMode, all]; }; GetVisibility: PUBLIC ENTRY PROC[vt: Virtual] RETURNS[ChannelsVisible] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorVisibility]; }; SetVisibility: PUBLIC ENTRY PROC[vt: Virtual, visibility: ChannelsVisible] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; impl.colorVisibility _ visibility; IF vt=current THEN ColorDisplayFace.SetVisibility[visibility]; }; GetColor: PUBLIC ENTRY PROC [vt: Virtual, aChannelValue, bChannelValue: ChannelValue ] RETURNS [red, green, blue: ColorValue _ 0] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN [r: red, g: green, b: blue] _ ColorDisplayFace.GetColor[ map: impl.colorMap, pixelA: aChannelValue, pixelB: bChannelValue]; }; SetColor: PUBLIC ENTRY PROC [vt: Virtual, aChannelValue, bChannelValue: ChannelValue, red, green, blue: ColorValue] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN TRUSTED { ColorDisplayFace.SetColor[map: impl.colorMap, pixelA: aChannelValue, pixelB: bChannelValue, r: red, g: green, b: blue] }; }; GetRedMap: PUBLIC ENTRY PROC[vt: Virtual, in: ChannelValue] RETURNS [ColorValue] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN RETURN[ColorDisplayFace.GetR[map: impl.colorMap, in: in]] ELSE RETURN[0]; }; GetGreenMap: PUBLIC ENTRY PROC [vt: Virtual, in: ChannelValue] RETURNS [ColorValue] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN RETURN[ColorDisplayFace.GetG[map: impl.colorMap, in: in]] ELSE RETURN[0]; }; GetBlueMap: PUBLIC ENTRY PROC [vt: Virtual, in: ChannelValue] RETURNS [ColorValue] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN RETURN[ColorDisplayFace.GetB[map: impl.colorMap, in: in]] ELSE RETURN[0]; }; SetRedMap: PUBLIC ENTRY PROC [vt: Virtual, in: ChannelValue, out: ColorValue] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN TRUSTED { ColorDisplayFace.SetR[map: impl.colorMap, in: in, out: out] }; }; SetGreenMap: PUBLIC ENTRY PROC [vt: Virtual, in: ChannelValue, out: ColorValue] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN TRUSTED { ColorDisplayFace.SetG[map: impl.colorMap, in: in, out: out] }; }; SetBlueMap: PUBLIC ENTRY PROC [vt: Virtual, in: ChannelValue, out: ColorValue] ~ { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorMap#NIL THEN TRUSTED { ColorDisplayFace.SetB[map: impl.colorMap, in: in, out: out] }; }; GetColorCursorPosition: PUBLIC ENTRY PROC [vt: Virtual] RETURNS [Position] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorCursorPosition]; }; SetColorCursorPosition: PUBLIC ENTRY PROC [vt: Virtual, position: Position] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; IF NOT vt.hasColorDisplay THEN RETURN; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF impl.colorCursorPosition=position THEN RETURN; -- no change IF impl.colorCursorDisplayed THEN HideColorCursor[vt, impl]; impl.colorCursorPosition _ position; IF impl.colorCursorState=$visible AND NOT InhibitColorCursor[impl] THEN ShowColorCursor[vt, impl]; }; GetColorCursorPattern: PUBLIC ENTRY PROC [vt: Virtual] RETURNS [Cursor] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorCursorPattern]; }; SetColorCursorPattern: PUBLIC ENTRY PROC [vt: Virtual, pattern: Cursor] = { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; displayed: BOOL ~ impl.colorCursorDisplayed; IF NOT vt.hasColorDisplay THEN RETURN; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; IF displayed THEN HideColorCursor[vt, impl]; impl.colorCursorPattern _ pattern; IF impl.colorBitmapState#none THEN ExpandColorCursorPattern[impl]; IF displayed THEN ShowColorCursor[vt, impl]; }; GetColorCursorPresentation: PUBLIC ENTRY PROC [vt: Virtual] RETURNS [ColorCursorPresentation] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorCursorPresentation]; }; SetColorCursorPresentation: PUBLIC ENTRY PROC [vt: Virtual, new: ColorCursorPresentation] RETURNS [old: ColorCursorPresentation] = { ENABLE UNWIND => NULL; impl: VirtualImpl ~ vt.impl; displayed: BOOL ~ impl.colorCursorDisplayed; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; old _ impl.colorCursorPresentation; IF NOT vt.hasColorDisplay THEN RETURN; IF new=old THEN RETURN; -- no change IF displayed THEN HideColorCursor[vt, impl]; impl.colorCursorPresentation _ new; IF displayed THEN ShowColorCursor[vt, impl]; }; GetColorCursorState: PUBLIC ENTRY PROC [vt: Virtual] RETURNS [ColorCursorBitmapState] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; RETURN[impl.colorCursorState]; }; SetColorCursorState: PUBLIC ENTRY PROC [vt: Virtual, new: ColorCursorBitmapState] RETURNS [old: ColorCursorBitmapState] = { ENABLE UNWIND => NULL; impl: VirtualImpl = vt.impl; WHILE impl.colorDisplayChanging DO WAIT impl.colorDisplayStable ENDLOOP; old _ impl.colorCursorState; IF NOT vt.hasColorDisplay THEN RETURN; IF new=old THEN RETURN; IF impl.colorBitmapState#none THEN SELECT new FROM $invisible => IF impl.colorCursorDisplayed THEN HideColorCursor[vt, impl]; $visible => IF NOT InhibitColorCursor[impl] THEN ShowColorCursor[vt, impl]; ENDCASE; impl.colorCursorState _ new; }; LockColorFrame: PROC[vt: Virtual, xmin, ymin: NAT _ 0, xmax, ymax: NAT _ NAT.LAST] = { impl: VirtualImpl = vt.impl; AcquireColorDisplay[vt]; impl.xmin _ xmin; impl.ymin _ ymin; impl.xmax _ xmax; impl.ymax _ ymax; impl.colorFrameLocked _ TRUE; IF impl.colorCursorDisplayed AND InhibitColorCursor[impl] THEN HideColorCursor[vt, impl]; }; UnlockColorFrame: PROC[vt: Virtual] = { impl: VirtualImpl = vt.impl; impl.colorFrameLocked _ FALSE; IF impl.colorBitmapState#none AND impl.colorCursorState=$visible AND NOT impl.colorCursorDisplayed THEN ShowColorCursor[vt, impl]; ReleaseColorDisplay[vt]; }; ModifyColorFrame: PUBLIC PROC [vt: Virtual, action: PROC, xmin, ymin: NAT _ 0, xmax, ymax: NAT _ NAT.LAST] ~ { LockColorFrame[vt, xmin, ymin, xmax, ymax]; action[! UNWIND => UnlockColorFrame[vt]]; UnlockColorFrame[vt]; }; InhibitColorCursor: PROC[impl: VirtualImpl] RETURNS[BOOL] = INLINE { RETURN[impl.colorFrameLocked AND ColorCursorIntersectsFrame[impl]]; }; ColorCursorIntersectsFrame: PROC[impl: VirtualImpl] RETURNS[BOOL] = { x: INTEGER ~ impl.colorCursorPosition.x; y: INTEGER ~ impl.colorCursorPosition.y; w: INTEGER ~ 16; h: INTEGER ~ 16; RETURN[ximpl.xmin AND (y+h)>impl.ymin]; }; colorCursorWplSrcA: NAT ~ 16; colorCursorWplSrcB: NAT ~ 8; ExpandColorCursorPattern: PROC[impl: VirtualImpl] ~ { ExpandBitmap: PROC[buffer: LONG POINTER, wpl: CARDINAL, bpp: NAT] = TRUSTED { AddOne: PROC[address: PrincOps.BitAddress] RETURNS[PrincOps.BitAddress] = TRUSTED { IF address.bit<15 THEN address.bit _ address.bit+1 ELSE {address.bit _ 0; address.word _ address.word+1}; RETURN[address]; }; ppw: NAT ~ 16/bpp; bbSpace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbSpace]; bb^ _ [dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [disjoint: TRUE, gray: FALSE, srcFunc: null, dstFunc: null]]; bb.src.word _ @impl.colorCursorPattern; bb.srcDesc.srcBpl _ 16; bb.dst.word _ buffer; bb.dstBpl _ wpl*16; bb.width _ 1; bb.height _ 16; FOR i: NAT IN [0..16) DO FOR j: NAT IN [0..bpp) DO PrincOpsUtils.BITBLT[bb]; --write one column bb.dst _ AddOne[bb.dst]; ENDLOOP; bb.src _ AddOne[bb.src]; ENDLOOP; }; IF impl.colorBitmapState=none THEN RETURN; IF impl.colorMode.full THEN { ExpandBitmap[impl.colorCursorSourceA, colorCursorWplSrcA, 16]; ExpandBitmap[impl.colorCursorSourceB, colorCursorWplSrcB, 8]; } ELSE IF impl.colorMode.bitsPerPixelChannelA>0 THEN { ExpandBitmap[impl.colorCursorSourceA, colorCursorWplSrcA, impl.colorMode.bitsPerPixelChannelA]; }; }; HideColorCursor: PROC[vt: Virtual, impl: VirtualImpl] = TRUSTED { xMax: INTEGER ~ vt.colorWidth; yMax: INTEGER ~ vt.colorHeight; x: INTEGER ~ impl.colorCursorPosition.x; y: INTEGER ~ impl.colorCursorPosition.y; w: INTEGER ~ 16; h: INTEGER ~ 16; IF (x+w)>0 AND (y+h)>0 AND x0) THEN { bpp: NAT ~ IF impl.colorMode.full THEN 16 ELSE impl.colorMode.bitsPerPixelChannelA; ppw: NAT ~ 16/bpp; frameA: FrameBuffer ~ impl.colorFrameBufferA; frameB: FrameBuffer ~ impl.colorFrameBufferB; bltX, bltY, bltW, bltH: INTEGER; xoff, yoff: INTEGER _ 0; bbSpace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbSpace]; bb^ _ [dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [disjoint: TRUE, gray: FALSE, srcFunc: null, dstFunc: null]]; bltX _ x; bltY _ y; bltW _ w; bltH _ h; IF x<0 THEN {xoff _ ABS[x]; bltW _ w-xoff; bltX _ 0}; IF y<0 THEN {yoff _ ABS[y]; bltH _ h-yoff; bltY _ 0}; IF x>(xMax-w) THEN bltW _ xMax-x; IF y>(yMax-h) THEN bltH _ yMax-y; bb.dst.word _ frameA.base + Basics.LongMult[bltY, frameA.wordsPerLine] + bltX/ppw; bb.dst.bit _ (bltX MOD ppw)*bpp; bb.dstBpl _ frameA.wordsPerLine*16; bb.src.word _ impl.colorCursorBackupA; bb.src.bit _ 0; bb.srcDesc.srcBpl _ colorCursorWplSrcA*16; bb.width _ bltW*bpp; bb.height _ bltH; PrincOpsUtils.BITBLT[bb]; -- restore the bits under the cursor IF impl.colorMode.full THEN { bb.dst.word _ frameB.base + Basics.LongMult[bltY, frameB.wordsPerLine] + bltX/2; bb.dst.bit _ (bltX MOD 2)*8; bb.dstBpl _ frameB.wordsPerLine*16; bb.src.word _ impl.colorCursorBackupB; bb.src.bit _ 0; bb.srcDesc.srcBpl _ colorCursorWplSrcB*16; bb.width _ bltW*8; bb.height _ bltH; PrincOpsUtils.BITBLT[bb]; -- restore the rest of the bits under the cursor }; }; impl.colorCursorDisplayed _ FALSE; }; ShowColorCursor: PROC[vt: Virtual, impl: VirtualImpl] = TRUSTED { xMax: INTEGER ~ vt.colorWidth; yMax: INTEGER ~ vt.colorHeight; x: INTEGER ~ impl.colorCursorPosition.x; y: INTEGER ~ impl.colorCursorPosition.y; w: INTEGER ~ 16; h: INTEGER ~ 16; xoff, yoff: INTEGER _ 0; IF (x+w)>0 AND (y+h)>0 AND x0) THEN { bpp: NAT ~ IF impl.colorMode.full THEN 16 ELSE impl.colorMode.bitsPerPixelChannelA; ppw: NAT ~ 16/bpp; frameA: FrameBuffer ~ impl.colorFrameBufferA; frameB: FrameBuffer ~ impl.colorFrameBufferB; bltX, bltY, bltW, bltH: INTEGER; xoff, yoff: INTEGER _ 0; bbSpace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbSpace]; bb^ _ [dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [disjoint: TRUE, gray: FALSE, srcFunc: null, dstFunc: null]]; bltX _ x; bltY _ y; bltW _ w; bltH _ h; IF x<0 THEN {xoff _ ABS[x]; bltW _ w-xoff; bltX _ 0}; IF y<0 THEN {yoff _ ABS[y]; bltH _ h-yoff; bltY _ 0}; IF x>(xMax-w) THEN bltW _ xMax-x; IF y>(yMax-h) THEN bltH _ yMax-y; bb.dst _ [word: impl.colorCursorBackupA, bit: 0]; bb.dstBpl _ colorCursorWplSrcA*16; bb.src.word _ frameA.base + Basics.LongMult[bltY, frameA.wordsPerLine] + bltX/ppw; bb.src.bit _ (bltX MOD ppw)*bpp; bb.srcDesc.srcBpl _ frameA.wordsPerLine*16; bb.width _ bltW*bpp; bb.height _ bltH; PrincOpsUtils.BITBLT[bb]; -- save the bits under the cursor IF impl.colorMode.full THEN { bb.src.word _ frameB.base + Basics.LongMult[bltY, frameB.wordsPerLine] + bltX/2; bb.src.bit _ (bltX MOD 2)*8; bb.srcDesc.srcBpl _ frameB.wordsPerLine*16; bb.dst _ [word: impl.colorCursorBackupB, bit: 0]; bb.dstBpl _ colorCursorWplSrcB*16; bb.width _ bltW*8; bb.height _ bltH; PrincOpsUtils.BITBLT[bb]; -- save the rest of the bits under the cursor }; SELECT impl.colorCursorPresentation FROM $onesAreBlack => { bb.flags.srcFunc _ complement; bb.flags.dstFunc _ and }; $onesAreWhite => { bb.flags.srcFunc _ null; bb.flags.dstFunc _ or }; ENDCASE => ERROR; bb.dst.word _ frameA.base + Basics.LongMult[bltY, frameA.wordsPerLine] + bltX/ppw; bb.dst.bit _ (bltX MOD ppw)*bpp; bb.dstBpl _ frameA.wordsPerLine*16; bb.src.word _ impl.colorCursorSourceA + yoff*colorCursorWplSrcA + xoff/ppw; bb.src.bit _ (xoff MOD ppw)*bpp; bb.srcDesc.srcBpl _ colorCursorWplSrcA*16; bb.width _ bltW*bpp; bb.height _ bltH; PrincOpsUtils.BITBLT[bb]; -- Put the cursor in IF impl.colorMode.full THEN { bb.dst.word _ frameB.base + Basics.LongMult[bltY, frameB.wordsPerLine] + bltX/2; bb.dst.bit _ (bltX MOD 2)*8; bb.dstBpl _ frameB.wordsPerLine*16; bb.src.word _ impl.colorCursorSourceB + yoff*colorCursorWplSrcB + xoff/2; bb.src.bit _ (xoff MOD 2)*8; bb.srcDesc.srcBpl _ colorCursorWplSrcB*16; bb.width _ bltW*8; bb.height _ bltH; PrincOpsUtils.BITBLT[bb]; -- Put the rest of the cursor in }; }; impl.colorCursorDisplayed _ TRUE; }; Beep: PUBLIC PROC [vt: Virtual, frequency, duration: CARDINAL] ~ { IF vt.hasSoundGenerator AND vt=current THEN TerminalFace.Beep[frequency, duration]; }; WatcherEnabled: ENTRY PROC RETURNS [BOOL] = INLINE { ENABLE UNWIND => NULL; RETURN[watcherDisableCount = 0] }; KeyboardWatcher: PROC = TRUSTED { lastTime, thisTime, magicCombination: KeyState _ [bits[ALL[up]]]; waitTime: Process.Ticks = Process.MsecToTicks[300]; Process.SetPriority[Process.priorityForeground]; magicCombination.bits _ [Ctrl: down, LeftShift: down, RightShift: down]; lastTime.bits _ TerminalFace.GetKeyboard[]; DO Process.Pause[waitTime]; IF WatcherEnabled[] THEN { changed: BOOL _ FALSE; select: BOOL _ TRUE; thisTime.bits _ TerminalFace.GetKeyboard[]; FOR word: NAT IN[0..SIZE[KeyState]) DO thisWord: WORD ~ thisTime.words[word]; IF thisWord#lastTime.words[word] THEN changed _ TRUE; IF thisWord#magicCombination.words[word] THEN select _ FALSE; ENDLOOP; IF changed THEN { lastTime _ thisTime; IF select THEN Select[NIL]; }; }; ENDLOOP; }; AllocateGlobalState: PROC[size: NAT] RETURNS[LONG POINTER] ~ TRUSTED { RETURN[IF size=0 THEN NIL ELSE VM.lowCore.NEW[Basics.RawWords[size]]]; }; Initialize: ENTRY PROC ~ TRUSTED { vt: Virtual = NewVirtual[]; mask: WORD _ 0; initialPosition: Position; [bwRetrace, mask] _ PrincOpsUtils.AllocateNakedCondition[]; TerminalFace.Initialize[AllocateGlobalState[TerminalFace.globalStateSize], mask]; TerminalFace.InitializeCleanup[]; IF ColorDisplayFace.displayType#none THEN { ColorDisplayFace.Initialize[AllocateGlobalState[ColorDisplayFace.globalStateSize]]; ColorDisplayFace.InitializeCleanup[]; }; initialPosition _ [x: TerminalFace.width/2, y: TerminalFace.height/2]; TerminalFace.SetMousePosition[initialPosition]; TerminalFace.SetCursorPosition[initialPosition]; LoadTerminal[current _ vt]; terminals _ CONS[current, NIL]; Process.EnableAborts[@terminalStable]; Process.Detach[FORK KeyboardWatcher[]]; }; Initialize[]; END. ŒTerminalImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Levin on: December 15, 1983 4:31 pm Birrell, November 16, 1983 11:24 am Russ Atkinson (RRA) July 23, 1985 0:28:18 am PDT Doug Wyatt, May 2, 1985 3:26:52 pm PDT Global variables protected by the monitor lock 'terminalChanging' synchronizes 'Select' with long-running operations that can't afford to hold the monitor lock throughout (including 'Select' itself). Internal Procedures RRA: this goodie is here to cache the frame buffer for the B&W display. It is the only way for a small-memory Dolphin to get off the ground (I think). Exports to Terminal Keyboard and Mouse Black-and-White Cursor Black-and-White Display 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[]; MarkTerminalStable[]; Color Display Color maps Color Cursor GetColorCursorPosition returns the position of the virtual cursor associated with the color display on the specified virtual terminal. This position changes only as a result of calls on SetColorCursorPosition. SetColorCursorPosition sets the cursor position of the specified virtual terminal to the indicated value. This position will be reflected on the screen when the virtual terminal is next selected (or, if it is presently selected, immediately). It is the responsibility of the client to clip the position, if desired, to ensure that the cursor remains on the visible area of the display. Sound generator Keyboard watcher process Initialization Ê( ˜codešœ™Kšœ Ïmœ1™Kšœ˜Kšœ'Ïc˜/Kšœ8¡˜@Kšœ8¡˜NKšœ8¡˜OKšžœ˜K˜—K˜K˜—š  œžœ˜'Kšœžœ˜Kšœžœ˜Kšžœ%˜,Kšœžœ˜Kšœžœ˜K˜K˜—š  œžœžœ˜2K˜!Kšœžœžœžœ˜!Kšžœžœžœ%˜GKšžœžœžœ%˜GKšœU˜UK˜K˜K˜—š œžœžœ˜5Kšœ˜K˜K˜—š  œžœžœ˜1K˜!Kšžœžœžœžœ)˜NKšžœžœžœžœ)˜NKšžœ˜!Kšœ˜K˜K˜—š  œžœžœ˜2K˜!Kšœ˜Kšžœžœžœžœ+˜PKšžœžœžœžœ+˜PKšžœ!˜#K˜K˜—K˜š  œžœžœ˜,Kšœ˜Kšœ*˜*Kšœ6˜6Kšœ4˜4Kšœ.˜.KšœX˜XKšžœžœ˜0Kšžœžœ˜4Kšœ5˜5Kšžœžœ˜6Kšžœ!žœ˜:K˜K˜—š œžœžœ˜.Kšœ˜Kšœ+˜+Kšœ-˜-Kšœ9˜9Kšžœžœ˜5Kšžœžœ˜3Kšžœ!žœ˜;Kšžœžœ˜9K˜K˜—K˜š  œžœžœ˜)Kšœžœ˜-šœžœ˜ Kšœžœ˜Kšœ˜Kšœ˜Kšœ$˜$Kšœ,˜,Kšœ3˜3Kšœ˜Kšœ˜Kšœ3˜3Kšœ2˜2Kšœ ˜ K˜—K˜K˜—K™Kšœ™K™Kšœ žœžœžœ˜K˜š œžœžœžœ˜-š  œžœžœžœ˜.Kšžœžœžœ˜Kšœ žœ˜ Kšœ˜—Kšœ˜Kšœ˜K˜—š œž œžœ˜+K˜ K˜š  œžœ/˜@Kšœ˜K˜ K˜Kšžœžœžœžœ˜šž˜K˜!Kš žœžœžœžœžœžœ˜EKšžœ˜—K˜—š  œžœžœ˜0Kšžœžœžœ˜K˜K˜Kšœ˜K˜—š œžœžœžœ˜FKšžœžœžœ˜šžœ%žœžœž˜8Kš žœž œžœ žœžœ žœ˜Qšž˜Kšžœžœ˜—Kšžœ˜—K˜—K˜!K˜Kšžœžœžœ˜.šžœ žœ˜K˜3Kšžœ!ž œ,˜\Kšœ˜Kšœ˜K˜K˜K˜!K˜K˜Kšœ˜Kšœ˜Kšžœ!ž œ ˜PK˜—K˜K˜K˜—š  œžœžœžœžœ˜3Kšžœžœžœ˜Kšžœžœžœžœ˜7K˜ K˜K˜—š œžœžœžœ˜-Kšžœžœžœ˜Kšœ*žœ˜/Kšœ˜K˜—š œžœžœžœ˜,Kšžœžœžœ˜Kšžœžœ+žœ˜OK˜K˜—š œžœžœžœ<žœžœžœ˜qKšžœžœžœ˜Kšœ˜Kšœžœžœžœ+˜aK˜ Kšžœžœžœ˜&KšžœH˜LK˜K˜K˜—š œžœžœžœ<žœžœžœ˜sKšžœžœžœ˜Kšœ˜K˜ K˜šžœ žœž˜šž˜šžœžœžœ˜9K˜K˜Kš žœ žœžœ žœžœžœ˜EKšž˜K˜—Kšžœžœžœ˜!Kšžœ˜——K˜K˜—K˜K™K˜š  œžœžœžœžœ ˜K˜K˜K˜—K˜š  œžœžœžœžœ˜MKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœ˜K˜K˜—š  œžœžœžœžœ˜MKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœ˜K˜K˜—š  œžœžœžœžœ˜KKšžœ!˜'Kšœ˜K˜—š   œžœžœžœžœ˜EKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœ˜K˜K˜—š  œžœžœžœ˜TKšžœ7˜=K˜K˜—š œžœžœ˜1Kšœ˜Kšœ=˜=K˜K™—š œžœžœ˜2Kšœ˜Kšœ=˜=Kšœ˜K™—š   œžœžœžœžœ˜JKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœ˜K˜K˜—š  œžœžœžœ.˜NKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšœ"˜"Kšžœ žœ,˜>K˜K˜—K˜K™ K˜š  œžœžœžœ<žœ'˜…Kšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœ|˜•K˜K˜—š œžœžœžœ]˜xKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœžœ}˜žK˜K™—K˜š   œžœžœžœ žœ˜TKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœžœ3˜SKšžœžœ˜K˜K˜—š   œžœžœžœ!žœ˜WKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœžœ3˜SKšžœžœ˜K˜K˜—š   œžœžœžœ!žœ˜VKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœžœ3˜SKšžœžœ˜K˜K˜—š  œžœžœžœ5˜QKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœžœA˜bK˜K˜—š  œžœžœžœ5˜SKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœžœA˜bK˜K˜—š  œžœžœžœ5˜RKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœžœžœžœA˜bK˜K˜—K˜K™ ™KšœÒ™ÒKšœ‚™‚K™—š  œžœžœžœžœ˜NKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜HKšžœ˜!K˜K˜—š œžœžœžœ&˜OKšžœžœžœ˜Kšœ˜Kšžœžœžœžœ˜&Kšžœžœžœžœ˜HKšžœ#žœžœ¡ ˜>Kšžœžœ˜K˜=K˜—šžœžœ'žœ˜4šœ9˜9Kšœ%˜%—Kšœ˜—K˜K˜—š œžœ#žœ˜AKšœžœ˜Kšœžœ˜Kšœžœ˜(Kšœžœ˜(Kšœžœ˜Kšœžœ˜Kšžœ žœ žœžœ˜,šžœžœ(žœ˜IKš œžœžœžœžœ%˜SKšœžœ ˜Kšœ-˜-Kšœ-˜-Kšœžœ˜ Kšœ žœ˜Kšœ˜KšœE˜Ešœžœ"žœ ˜[Kšœ'žœžœ!˜Y—K˜K˜Kšžœžœ žœ˜6Kšžœžœ žœ˜5Kšžœ žœ˜!Kšžœ žœ˜!KšœR˜RKšœžœ ˜ Kšœ#˜#Kšœ&˜&Kšœ˜K˜*K˜K˜Kšœžœ¡%˜?šžœžœ˜KšœP˜PKšœžœ˜Kšœ#˜#Kšœ&˜&Kšœ˜K˜*K˜K˜Kšœžœ¡1˜KK˜—K˜—Kšœžœ˜"K˜K˜—š œžœ#žœ˜AKšœžœ˜Kšœžœ˜Kšœžœ˜(Kšœžœ˜(Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšžœ žœ žœžœ˜,šžœžœ(žœ˜IKš œžœžœžœžœ%˜SKšœžœ ˜Kšœ-˜-Kšœ-˜-Kšœžœ˜ Kšœ žœ˜Kšœ˜KšœE˜Ešœžœ"žœ ˜[Kšœ'žœžœ!˜Y—K˜K˜Kšžœžœ žœ˜5Kšžœžœ žœ˜5Kšžœ žœ˜!Kšžœ žœ˜!K˜K˜1K˜"KšœR˜RKšœžœ ˜ Kšœ+˜+K˜K˜Kšœžœ¡!˜;šžœžœ˜KšœP˜PKšœžœ˜Kšœ+˜+K˜1K˜"K˜K˜Kšœžœ¡-˜GK˜—K˜šžœž˜(K˜KK˜DKšžœžœ˜—KšœR˜RKšœžœ ˜ Kšœ#˜#KšœK˜KKšœžœ ˜ K˜*K˜K˜Kšœžœ¡˜/šžœžœ˜KšœP˜PKšœžœ˜Kšœ#˜#KšœI˜IKšœžœ˜K˜*K˜K˜Kšœžœ¡!˜;K˜—K˜—Kšœžœ˜!K˜K˜—K™K˜š œžœžœ$žœ˜BKšžœžœ žœ(˜SK˜—K™K™K™š  œžœžœžœžœžœ˜4Kšžœžœžœ˜Kšžœ˜Kšœ˜K˜—š œžœžœ˜!Kšœ7žœ˜AKšœ3˜3K˜0KšœH˜HKšœ+˜+šž˜Kšœ˜šžœžœ˜Kšœ žœžœ˜Kšœžœžœ˜Kšœ+˜+š žœžœžœžœ ž˜&Kšœ žœ˜&Kšžœžœ žœ˜5Kšžœ'žœ žœ˜=Kšžœ˜—šžœ žœ˜Kšœ˜Kšžœžœžœ˜K˜—K˜—Kšžœ˜—K˜—K™Kšœ™K™š œžœžœžœžœžœžœ˜FKšžœžœžœžœžœžœ žœ˜FK˜K˜—š  œžœžœžœ˜"Kšœ˜Kšœžœ˜K˜K˜;KšœQ˜QK˜!šžœ#žœ˜+KšœS˜SK˜%K˜—KšœF˜FK˜/K˜0K˜Kšœ žœ žœ˜K˜&Kšœžœ˜'K˜K˜—K˜ K˜Kšžœ˜—…—ˆr·