<> <> <> <> <> DIRECTORY Ascii USING [Lower], Buttons USING [Button, ButtonProc, Create, SetDisplayStyle], ColorDisplay USING [CDNotifyProc, CDRegistration, CDState], ColorDisplayDefs USING [colorMode24, ColorDisplayType, ColorMode], ColorDisplayFace USING [SetDisplayType], Commander USING [CommandProc, Register], Containers USING [Container, Create], Imager, ImagerDevice, ImagerTerminal, InterminalBackdoor, ImagerCache, ImagerRaster, ImagerColorMap, ImagerColor USING [ColorFromGray], ImagerForkContext USING [Create], ImagerGray USING [Create, LikeScreen], ImagerMaskContext USING [Create], ImagerPixelMap USING [PixelMap, PixelMapRep], Interminal USING [GetColorDisplaySide, SetColorDisplaySide], IO USING [card, EndOfStream, GetTokenRope, IDProc, PutF, RIS, rope, STREAM], MessageWindow USING [Append, Blink], Process USING [Detach, Pause, SetTimeout, Ticks], Rope USING [Equal, Fetch, Length, ROPE, Translate, TranslatorType], SafeStorage USING [ReclaimCollectibleObjects], Terminal USING [BitmapState, CantDoIt, ChannelsVisible, ColorMode, Current, FrameBuffer, GetColorBitmapState, GetColorMode, GetColorFrameBufferA, GetColorFrameBufferB, GetVisibility, SetColorBitmapState, SetColorCursorPresentation, SetColorMode, Virtual], UserProfile USING [Boolean, Number, Token], ViewerClasses USING [Viewer], ViewerOps USING [ChangeColumn, CloseViewer, ComputeColumn, EnumerateViewers, EnumProc, OpenIcon, PaintEverything, SetOpenHeight], ViewerPrivate USING [Screen, SetCreator], WindowManager USING [colorDisplayOn, ScreenPos, StartColorViewers, StopColorViewers]; ColorDisplayImpl: CEDAR MONITOR IMPORTS Ascii, Buttons, ColorDisplayFace, Commander, Containers, ImagerCache, ImagerColor, ImagerColorMap, ImagerForkContext, ImagerGray, ImagerMaskContext, ImagerRaster, ImagerTerminal, Interminal, InterminalBackdoor, IO, MessageWindow, Process, Rope, SafeStorage, Terminal, UserProfile, ViewerOps, ViewerPrivate, WindowManager EXPORTS ColorDisplay ~ BEGIN OPEN ColorDisplay; <> bppLast: PUBLIC CARDINAL _ 8; bppBLast: PUBLIC CARDINAL _ 0; onLeftLast: PUBLIC BOOLEAN _ TRUE; grayLast: PUBLIC BOOLEAN _ FALSE; monitorTypeLast: PUBLIC Rope.ROPE _ "640x480"; DefaultBpp, Bpp: PUBLIC PROC RETURNS [bpp: CARDINAL] ~ { -- remembers 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 }; DefaultBppB, BppB: PUBLIC PROC RETURNS [bpp: CARDINAL] ~ { -- remembers bpp IF WindowManager.colorDisplayOn THEN { OPEN Terminal; colorMode: ColorMode _ GetColorMode[Current[]]; bpp _ (IF colorMode.full THEN 0 ELSE colorMode.bitsPerPixelChannelB); } ELSE bpp _ bppBLast; bppBLast _ 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; }; DefaultGray, Gray: PUBLIC PROC RETURNS [onLeft: BOOLEAN] ~ { RETURN[grayLast]; }; DefaultOn: PUBLIC PROC RETURNS [BOOLEAN] ~ { RETURN[WindowManager.colorDisplayOn]; }; DefaultMonitorType: PUBLIC PROC RETURNS [Rope.ROPE] ~ { RETURN[monitorTypeLast]; }; MessageBlink: PROC [message: Rope.ROPE] ~ { MessageWindow.Append[message, TRUE]; MessageWindow.Blink[]; }; SetColorDisplayStatus: PUBLIC ENTRY PROC [on: BOOLEAN _ DefaultOn[], onLeft: BOOLEAN _ DefaultOnLeft[], gray: BOOL _ DefaultGray[], bpp: CARDINAL _ DefaultBpp[], bppB: CARDINAL _ DefaultBppB[], monitorType: Rope.ROPE _ DefaultMonitorType[]] = { ENABLE UNWIND => NULL; NOTIFY forCDChanges; --Let the informant know... IF NOT InterminalBackdoor.terminal.hasColorDisplay THEN RETURN; -- No color display. SELECT bpp FROM 1, 2, 4, 8, 24 => NULL; ENDCASE => {MessageBlink["Invalid bits per pixel."]; RETURN}; SELECT bppB FROM 0, 1, 2 => NULL; ENDCASE => {MessageBlink["Invalid bits per pixel on chan B."]; RETURN}; IF NOT (Rope.Equal[s1: monitorType, s2: "640x480", case: FALSE] OR Rope.Equal[s1: monitorType, s2: "1024x768", case: FALSE]) THEN { MessageBlink["Invalid monitor type."]; RETURN}; SELECT TRUE FROM <> (on = WindowManager.colorDisplayOn AND bpp = Bpp[] AND bppB = BppB[] AND Rope.Equal[monitorType, monitorTypeLast, FALSE] AND onLeft=OnLeft[] AND gray=Gray[]) => RETURN; <<>> <> (on = WindowManager.colorDisplayOn AND Rope.Equal[monitorType, monitorTypeLast, FALSE] AND Bpp[] = bpp AND gray # Gray[] AND on) => {IF Gray[] THEN DefaultViewers[] ELSE GrayViewers[]; grayLast _ NOT grayLast; RETURN}; <<>> <> (on = WindowManager.colorDisplayOn AND Rope.Equal[monitorType, monitorTypeLast, FALSE] AND Bpp[] # 8 AND gray # Gray[] AND on) => {RETURN}; <> (on = WindowManager.colorDisplayOn AND bpp = Bpp[] AND bppB = BppB[] AND Rope.Equal[monitorType, monitorTypeLast, FALSE] AND gray=Gray[] AND on) => { IF Interminal.GetColorDisplaySide[] = left THEN Interminal.SetColorDisplaySide[right] ELSE Interminal.SetColorDisplaySide[left]}; <<>> <> 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]; <<>> <> 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: BOOL _ FALSE; onLeftLast _ onLeft; bppLast _ bpp; bppBLast _ bppB; grayLast _ gray; monitorTypeLast _ monitorType; --Back up the given parameters ListColorViewers[]; -- Make a list of all the viewers on the color display (if any) WindowManager.StopColorViewers[]; -- Turn off display IF on THEN { SELECT TRUE FROM Rope.Equal[s1: monitorType, s2: "640x480", case: FALSE] => ok _ Start640Monitor[bitsPerPixel: bpp, bitsPerPixelB: bppB, pos: side]; Rope.Equal[s1: monitorType, s2: "1024x768", case: FALSE] => ok _ Start1024Monitor[bitsPerPixel: bpp, bitsPerPixelB: bppB, pos: side]; ENDCASE => MessageBlink["Invalid monitor type!!"]; IF NOT ok THEN {MessageBlink["Can't turn on color!"]; RETURN}; IF bpp = 8 THEN {IF grayLast THEN GrayViewers[] ELSE DefaultViewers[]}; ReopenColorViewers[]; }; }; }; StartMonitor: PROC [type: ColorDisplayDefs.ColorDisplayType, bitsPerPixel, bitsPerPixelB: CARDINAL, pos: WindowManager.ScreenPos] ~ { mode: ColorDisplayDefs.ColorMode ~ IF bitsPerPixel = 24 THEN ColorDisplayDefs.colorMode24 ELSE [FALSE, bitsPerPixel, bitsPerPixelB]; []_ ColorDisplayFace.SetDisplayType[type]; FOR try: CARDINAL IN [1..3] DO []_ Terminal.SetColorMode[InterminalBackdoor.terminal, 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, bitsPerPixelB:CARDINAL _ 0, pos: WindowManager.ScreenPos _ left] RETURNS [ok: BOOL _ TRUE] = { StartMonitor[standard, bitsPerPixel, bitsPerPixelB, pos]; }; Start1024Monitor: PUBLIC PROCEDURE [bitsPerPixel: CARDINAL _ 8, bitsPerPixelB:CARDINAL _ 0, pos: WindowManager.ScreenPos _ left] RETURNS [ok: BOOL _ TRUE] = { IF bitsPerPixel = 24 THEN RETURN [FALSE]; StartMonitor[highResolution, bitsPerPixel, bitsPerPixelB, pos]; }; GetColorDisplayStatus: PUBLIC ENTRY PROC RETURNS [on, onLeft, gray: BOOLEAN, bpp, bppB: CARDINAL, monitorType: Rope.ROPE] ~ { ENABLE UNWIND => NULL; [on, onLeft, gray, bpp, bppB, monitorType] _ GetColorDisplayStatusInternal[]; }; GetCDState: INTERNAL PROC RETURNS [state: CDState] ~ INLINE { [state.on, state.onLeft, state.gray, state.bpp, state.bppB, state.monitorType] _ GetColorDisplayStatusInternal[]; }; GetColorDisplayStatusInternal: INTERNAL PROC RETURNS [on, onLeft, gray: BOOLEAN, bpp, bppB: CARDINAL, monitorType: Rope.ROPE] ~ { on _ WindowManager.colorDisplayOn; onLeft _ OnLeft[]; bpp _ Bpp[]; bppB _ BppB[]; monitorType _ monitorTypeLast; gray _ grayLast; }; GetColorDisplayProfile: PUBLIC PROC RETURNS [on, onLeft, gray: BOOLEAN, bpp, bppB: CARDINAL, monitorType: Rope.ROPE] ~ { RightOrLeft: PROC RETURNS[rl: Rope.ROPE] ~ INLINE {rl _ IF onLeftLast THEN "left" ELSE "right"}; tBpp, tBppB: 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[]; SELECT tBppB _ UserProfile.Number["ColorDisplay.BitsPerPointB", BppB[]] FROM 0, 1, 2 => bppB _ tBppB; ENDCASE => bppB _ Bpp[]; onLeft _ Rope.Equal[UserProfile.Token["ColorDisplay.Side", RightOrLeft[]], "left", FALSE]; monitorType _ UserProfile.Token["ColorDisplay.Type", monitorTypeLast]; gray _ UserProfile.Boolean["ColorDisplay.Gray", grayLast]; }; 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] ~ { ENABLE UNWIND => NULL; vt: Terminal.Virtual _ InterminalBackdoor.terminal; state: Terminal.BitmapState _ Terminal.GetColorBitmapState[vt]; mode: Terminal.ColorMode _ Terminal.GetColorMode[vt]; visible: Terminal.ChannelsVisible _ Terminal.GetVisibility[vt]; IF state # displayed THEN RETURN; [] _ Terminal.SetColorBitmapState[vt, allocated, mode, none]; Process.Pause[ticks]; [] _ Terminal.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 => { contextB, contextM: Imager.Context; fb: Terminal.FrameBuffer _ Terminal.GetColorFrameBufferB[terminal]; context _ GrayContext[vt: terminal, pixelUnits: TRUE]; <<-- this should probably get its context from ImagerGray instead of>> <<-- ImagerRaster.NewGrayDevice. However while it works don't fix it>> <<-- Mik >> IF fb#NIL AND ~Terminal.GetColorMode[terminal].full THEN { frame: ImagerPixelMap.PixelMap ~ PixelMapFromFrameBuffer[fb]; contextB _ ImagerGray.Create[frame, $Intensity, ImagerGray.LikeScreen[frame.sSize], 1, NIL, NIL, TRUE]; contextM _ ImagerMaskContext.Create[contextB, ImagerColor.ColorFromGray[1]]; context _ ImagerForkContext.Create[context, contextM]; }; } ENDCASE => ERROR; }; DitherCreateContext: 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 => { contextB, contextM: Imager.Context; fb: Terminal.FrameBuffer _ Terminal.GetColorFrameBufferB[terminal]; context _ ImagerTerminal.ColorContext[vt: terminal, pixelUnits: TRUE]; IF fb#NIL AND ~Terminal.GetColorMode[terminal].full THEN { frame: ImagerPixelMap.PixelMap ~ PixelMapFromFrameBuffer[fb]; contextB _ ImagerGray.Create[frame, $Intensity, ImagerGray.LikeScreen[frame.sSize], 1, NIL, NIL, TRUE]; contextM _ ImagerMaskContext.Create[contextB, ImagerColor.ColorFromGray[1]]; context _ ImagerForkContext.Create[context, contextM]; }; }; ENDCASE => ERROR; }; PixelMapFromFrameBuffer: PROC [frameBuffer: Terminal.FrameBuffer] RETURNS [ImagerPixelMap.PixelMap] ~ { Lg: PROC [n: NAT] RETURNS [NAT] ~ { RETURN[SELECT n FROM 1 => 0, 2 => 1, 4 => 2, 8 => 3, 16 => 4, ENDCASE => ERROR] }; refRep: REF ImagerPixelMap.PixelMapRep ~ NEW[ImagerPixelMap.PixelMapRep _ [ ref: frameBuffer, pointer: frameBuffer.base, words: INT[frameBuffer.wordsPerLine]*INT[frameBuffer.height], lgBitsPerPixel: Lg[frameBuffer.bitsPerPixel], rast: frameBuffer.wordsPerLine, lines: frameBuffer.height ]]; frame: ImagerPixelMap.PixelMap ~ [ sOrigin: 0, fOrigin: 0, sMin: 0, fMin: 0, sSize: frameBuffer.height, fSize: frameBuffer.width, refRep: refRep ]; RETURN[frame]; }; gamma: REAL _ 2.2; fontCacheID: ATOM ~ $ColorDisplay; fontCacheSize: NAT _ 10000; 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[DitherCreateContext]; ImagerColorMap.SetStandardColorMap[vt: InterminalBackdoor.terminal, gamma: gamma]; ViewerOps.PaintEverything[]; }; Init: PROC[] RETURNS[] ~ { <> -- DefaultViewers[]; [ , onLeftLast, grayLast, bppLast, bppBLast, monitorTypeLast] _ GetColorDisplayProfile[]; TRUSTED { Process.SetTimeout[@forCDChanges, 300]; Process.Detach[FORK WatchForChanges[]]; }; <> Commander.Register[key:"ColorDisplay", proc: FiddleWithDisplay, doc: "Configure color monitor"]; <> [] _ Buttons.Create[ info: [name: "Color"], proc: BugColor, fork: FALSE ]; }; <> FiddleWithDisplay: Commander.CommandProc ~ { MyLower: Rope.TranslatorType = BEGIN RETURN[Ascii.Lower[old]]; END; myOn, myGray: BOOLEAN; myBpp, myBppB: CARDINAL; myOnLeft: BOOLEAN; myMonType: Rope.ROPE; noParams: BOOLEAN _ TRUE; s: IO.STREAM _ IO.RIS[Rope.Translate[base: cmd.commandLine, translator: MyLower]]; [myOn, myOnLeft, myGray, myBpp, myBppB, myMonType] _ GetColorDisplayStatus[]; DO f: Rope.ROPE _ IO.GetTokenRope[s, IO.IDProc ! IO.EndOfStream => EXIT].token; noParams _ FALSE; SELECT Rope.Fetch[f, 0] FROM '0 => myOn _ FALSE; '1 => IF Rope.Equal[f, "1024x768"] THEN { myMonType _ "1024x768"; myOn _ TRUE } ELSE IF Rope.Length[f]=1 THEN {myBpp _ 1; myOn _ TRUE; } ELSE { IO.PutF[cmd.err, "Option %g that begins with a 1 has to be 1024x768 or 1 exactly.\n", IO.rope[f]]; RETURN; }; '2 => IF Rope.Equal[f, "24"] THEN { myOn _ TRUE; myBpp _ 24 } ELSE IF Rope.Length[f]=1 THEN { myBpp _ 2; myOn _ TRUE } ELSE { IO.PutF[cmd.err, "Can't do %g bpp\n", IO.rope[f]]; RETURN; }; '4 => { myBpp _ 4; myOn _ TRUE }; '6 => { IF Rope.Equal[f, "640x480"] THEN { myMonType _ "640x480"; myOn _ TRUE } ELSE { IO.PutF[cmd.err, "%g is an invalid key\n", IO.rope[f]]; RETURN; }; }; '8 => { myBpp _ 8; myOn _ TRUE }; 'l => { myOnLeft _ TRUE; myOn _ TRUE }; 'r => { myOnLeft _ FALSE; myOn _ TRUE }; 'd => { IF Rope.Equal[f, "default"] THEN [myOn, myOnLeft, myGray, myBpp, myBppB, myMonType] _ GetColorDisplayProfile[] ELSE {myGray _ FALSE; myOn _ TRUE }; }; '+ => { SELECT TRUE FROM Rope.Equal[f, "+2"] => { myBppB _ 2; myOn _ TRUE }; Rope.Equal[f, "+1"] => { myBppB _ 1; myOn _ TRUE }; Rope.Equal[f, "+0"] => { myBppB _ 0; myOn _ TRUE }; ENDCASE => { IO.PutF[cmd.err, "valid B channel values are 0,1,2\n"]; RETURN; }; }; 'o => IF Rope.Equal[f, "on"] THEN myOn _ TRUE ELSE IF Rope.Equal[f, "off"] THEN myOn _ FALSE ELSE { IO.PutF[cmd.err, "%g is an invalid key\n", IO.rope[f]]; RETURN; }; 'g => { myGray _ TRUE; myOn _ TRUE }; '? => IO.PutF[cmd.err, "%g, %g bpp, %g, %g, %g\n", IO.rope[IF myOn THEN "on" ELSE "off"], IO.card[myBpp], IO.rope[IF myOnLeft THEN "left" ELSE "right"], IO.rope[myMonType], IO.rope[(IF myGray THEN "Gray" ELSE "Dither")]]; ENDCASE => { IO.PutF[cmd.err, "%g is an invalid key\n", IO.rope[f]]; RETURN[]; }; ENDLOOP; IF noParams THEN myOn _ ~myOn; SetColorDisplayStatus[myOn, myOnLeft, myGray, myBpp, myBppB, myMonType]; }; ButtonSet: TYPE ~ RECORD [ on, off, left, right, lowres, highres, c1, c2, c4, c8, c24, gray, dither: Buttons.Button _ NIL, reg: CDRegistration _ NIL, cdt: Containers.Container _ NIL ]; CreateColorDisplayTool: PROC ~ { bs: REF ButtonSet ~ NEW[ButtonSet]; prev: Buttons.Button; hMargin: INT ~ -1; hSeparator: INT ~ 10; vMargin: INT ~ 5; vHeight: INT ~ 10; thisX, thisY: INT; CreateCDTButton: PROC [name: Rope.ROPE, proc: Buttons.ButtonProc, extraOffset: INT _ 0] RETURNS [button: Buttons.Button] ~ { button _ prev _ Buttons.Create[ info: [ name: name, wx: thisX, wy: thisY, parent: bs.cdt, border: TRUE ], proc: proc ]; thisX _ thisX + prev.ww + hMargin + extraOffset; }; bs.cdt _ Containers.Create[ info: [ name: "ColorDisplayTool", column: right, scrollable: FALSE ] ]; thisX _ hMargin+hSeparator; thisY _ vMargin; <> bs.on _ CreateCDTButton["On", CDTOn]; --On Button bs.off _ CreateCDTButton["Off", CDTOff, hSeparator]; --Off Button bs.c1 _ CreateCDTButton["1 ", CDT1]; --1 Button bs.c2 _ CreateCDTButton["2 ", CDT2]; --2 Button bs.c4 _ CreateCDTButton["4 ", CDT4]; --4 Button bs.c8 _ CreateCDTButton["8 ", CDT8]; --8 Button bs.c24 _ CreateCDTButton["24 ", CDT24, hSeparator]; --24 Button bs.left _ CreateCDTButton["Left", CDTLeft]; --Left Button bs.right _ CreateCDTButton["Right", CDTRight, hSeparator]; --Right Button bs.lowres _ CreateCDTButton["640x480", CDTLowRes]; --640x480 Button bs.highres _ CreateCDTButton["1024x768", CDTHighRes, hSeparator]; --1024x768 Button bs.gray _ CreateCDTButton["Gray", CDTGray]; bs.dither _ CreateCDTButton["Dither", CDTDither, hSeparator]; <<>> bs.reg _ RegisterCDNotifyProc[MonitorButtons, bs]; <> ViewerOps.SetOpenHeight[bs.cdt, thisY + vHeight + 2*vMargin]; ViewerOps.OpenIcon[icon: bs.cdt, bottom: FALSE]; }; shouldBeLit: ARRAY BOOLEAN OF ATOM ~ [$BlackOnWhite, $WhiteOnBlack]; MonitorButtons: CDNotifyProc ~ { Repaint: PROC [button: Buttons.Button, condition: BOOLEAN] ~ INLINE { OPEN Buttons; Buttons.SetDisplayStyle[button, shouldBeLit[condition]]; }; <> bs: REF ButtonSet ~ NARROW[clientData]; IF bs.cdt=NIL OR bs.cdt.destroyed THEN { --No point blowing ourselves to smithereens. UnregisterCDNotifyProc[bs.reg]; RETURN; }; Repaint[bs.on, new.on]; Repaint[bs.off, ~ new.on]; Repaint[bs.c1, new.bpp = 1]; Repaint[bs.c2, new.bpp = 2]; Repaint[bs.c4, new.bpp = 4]; Repaint[bs.c8, new.bpp = 8]; Repaint[bs.c24, new.bpp = 24]; Repaint[bs.left, new.onLeft]; Repaint[bs.right, ~ new.onLeft]; Repaint[bs.lowres, new.monitorType.Equal["640x480"]]; Repaint[bs.highres, ~ new.monitorType.Equal["640x480"]]; Repaint[bs.gray, new.gray]; Repaint[bs.dither, ~ new.gray]; }; CDTOn: Buttons.ButtonProc ~ {SetColorDisplayStatus[on: TRUE]}; CDTOff: Buttons.ButtonProc ~ {SetColorDisplayStatus[on: FALSE]}; CDTLeft: Buttons.ButtonProc ~ {SetColorDisplayStatus[onLeft: TRUE]}; CDTRight: Buttons.ButtonProc ~ {SetColorDisplayStatus[onLeft: FALSE]}; CDTLowRes: Buttons.ButtonProc ~ {SetColorDisplayStatus[monitorType: "640x480"]}; CDTHighRes: Buttons.ButtonProc ~ {SetColorDisplayStatus[monitorType: "1024x768"]}; CDT1: Buttons.ButtonProc ~ {SetColorDisplayStatus[on: FALSE, bpp: 1]}; CDT2: Buttons.ButtonProc ~ {SetColorDisplayStatus[on: FALSE, bpp: 2]}; CDT4: Buttons.ButtonProc ~ {SetColorDisplayStatus[on: FALSE, bpp: 4]}; CDT8: Buttons.ButtonProc ~ {SetColorDisplayStatus[on: FALSE, bpp: 8]}; CDT24: Buttons.ButtonProc ~ { IF grayLast THEN MessageBlink["Can't be gray and 24bpp."] ELSE SetColorDisplayStatus[on: FALSE, bpp: 24, gray: FALSE, monitorType: "640x480"]; }; CDTGray: Buttons.ButtonProc ~ { IF bppLast = 24 THEN MessageBlink["Can't be gray and 24bpp."] ELSE SetColorDisplayStatus[gray: TRUE]; }; CDTDither: Buttons.ButtonProc ~ {SetColorDisplayStatus[gray: FALSE]}; BugColor: Buttons.ButtonProc ~ { SELECT mouseButton FROM red => SetColorDisplayStatus[on: ~GetColorDisplayStatus[].on]; yellow => TRUSTED {SleepColorDisplay[300]}; blue => CreateColorDisplayTool[]; ENDCASE; }; Init[]; END. <<>>