DIRECTORY PreDebug, Process, RuntimeError, ViewersWorld, ViewersWorldClasses, X11Viewers, Xl, XlBitmap, XlColorAccess, XTk, XTkNotification; X11ViewersColorImpl: CEDAR MONITOR IMPORTS PreDebug, Process, RuntimeError, X11Viewers, Xl, XlBitmap, XlColorAccess, XTk, XTkNotification, ViewersWorld SHARES X11Viewers = BEGIN OPEN X11Viewers; detailsForSynchronous: Xl.Details ~ NEW[Xl.DetailsRec ¬ [synchronous: TRUE]]; MapEntryRec: TYPE = PACKED RECORD [ isAnimationIndex: BOOL ¬ FALSE, --the real truth whether we own an index; client callbacks are delayed so we can't trust clients. r, g, b: BYTE ¬ 0, --so we can report the color back revokeClosure: REF RevokeColorMapClosure ¬ NIL ]; RevokeColorMapClosure: TYPE = RECORD [proc: ViewersWorld.RevokeColorMapIndexProc, data: REF, index: CARDINAL]; ColorMapData: TYPE = RECORD [ map: ARRAY [0..256) OF MapEntryRec ]; CheckBitsPerPixel: XTk.WidgetNotifyProc = { data: ScreenServerData ~ NARROW[callData]; cd: XlColorAccess.ColorData ~ XlColorAccess.Access[data.top.screenDepth.screen, data.possibleBitsPerPixel, Xl.VisualClass.pseudoColor]; IF cd#NIL AND cd.hasColors THEN { TRUSTED {XTk.PutWidgetProp[data.top, $ColorData, LOOPHOLE[cd --because readonly--]]}; X11Viewers.bitsPerPixelOk; }; }; ColorMapCreate: XTk.WidgetNotifyProc = { data: ScreenServerData ~ NARROW[callData]; WITH XTk.GetWidgetProp[data.top, $ColorData] SELECT FROM cd: XlColorAccess.ColorData => IF cd.hasColors AND data.useBitmap THEN { bitmap: XTk.Widget ~ data.bitmap; bitmap.attributes.colorMap ¬ cd.colormap; data.top.attributes.colorMap ¬ cd.colormap; }; ENDCASE => {}; }; RegisterRevokeColorMapEntries: XTk.WidgetNotifyProc = { data: ScreenServerData ~ NARROW[callData]; XTk.RegisterNotifier[data.top, XTk.preStopFastAccessKey, RevokeColorMapEntries, data]; }; ColorMapInstall: XTk.WidgetNotifyProc = { data: ScreenServerData ~ NARROW[callData]; bm: XlBitmap.Bitmap ¬ data.bm; WITH XTk.GetWidgetProp[data.top, $ColorData] SELECT FROM cd: XlColorAccess.ColorData => IF cd.hasColors AND data.useBitmap AND bm#NIL THEN { XlBitmap.SetColormap[data.bm, cd.entries]; }; ENDCASE => {}; }; RevokeColorMapEntries: XTk.WidgetNotifyProc = { WITH registerData SELECT FROM data: ScreenServerData => { XTk.PutWidgetProp[data.top, $ColorData, NIL]; WITH data.reservedForColorIndices SELECT FROM cm: REF ColorMapData => { closures: LIST OF RevokeColorMapClosure ¬ ClearAllAnimationIndices[cm]; TRUSTED {Process.Detach[FORK CallClientColorMapRevoke[data, closures] ]} }; ENDCASE => {}; }; ENDCASE => {}; }; CallClientColorMapRevoke: PROC [data: ScreenServerData, closures: LIST OF RevokeColorMapClosure] = { FOR l: LIST OF RevokeColorMapClosure ¬ closures, l.rest WHILE l#NIL DO l.first.proc[data.viewersWorld, l.first.index, l.first.data]; ENDLOOP }; SetAnimationIndex: ENTRY PROC [cm: REF ColorMapData, idx: [0..256), revokeClosure: REF RevokeColorMapClosure] RETURNS [fail: BOOL¬FALSE] = { IF cm=NIL OR cm.map[idx].isAnimationIndex THEN RETURN [fail¬TRUE]; cm.map[idx].isAnimationIndex ¬ TRUE; cm.map[idx].revokeClosure ¬ revokeClosure; }; ClearAnimationIndex: ENTRY PROC [cm: REF ColorMapData, idx: [0..256)] RETURNS [was: BOOL ¬ FALSE, revoke: REF RevokeColorMapClosure ¬ NIL] = { IF cm#NIL THEN { was ¬ cm.map[idx].isAnimationIndex; revoke ¬ cm.map[idx].revokeClosure; cm.map[idx].revokeClosure ¬ NIL; cm.map[idx].isAnimationIndex ¬ FALSE; }; }; ClearAllAnimationIndices: ENTRY PROC [cm: REF ColorMapData] RETURNS [closures: LIST OF RevokeColorMapClosure ¬ NIL] = { IF cm#NIL THEN { FOR i: [0..256) IN [0..256) DO closure: REF RevokeColorMapClosure ~ cm.map[i].revokeClosure; cm.map[i].revokeClosure ¬ NIL; cm.map[i].isAnimationIndex ¬ FALSE; IF closure#NIL THEN closures ¬ CONS[closure­, closures]; ENDLOOP; }; }; GetColorMapData: ENTRY PROC [data: ScreenServerData] RETURNS [REF ColorMapData] = { IF data=NIL THEN RETURN [NEW[ColorMapData]]; --never occurs, but never wedge monitor WITH data.reservedForColorIndices SELECT FROM cm: REF ColorMapData => RETURN [cm]; ENDCASE => { cm: REF ColorMapData ~ NEW[ColorMapData]; data.reservedForColorIndices ¬ cm; RETURN [cm]; }; }; AllocateColorMapIndex: PROC [screenServerData: REF, display: REF, revokeIndex: ViewersWorld.RevokeColorMapIndexProc, clientData: REF ¬ NIL] RETURNS [index: CARDINAL] = { data: ScreenServerData ~ NARROW[screenServerData]; cm: REF ColorMapData ~ GetColorMapData[data]; bitmap: XTk.Widget ~ data.bitmap; pixels: REF Xl.Card32Sequence; revokeClosure: REF RevokeColorMapClosure ¬ NIL; IF bitmap=NIL THEN ERROR ViewersWorld.outOfColormapEntries; IF data.actualBitsPerPixel#8 AND data.actualBitsPerPixel#4 THEN ERROR ViewersWorld.outOfColormapEntries; pixels ¬ Xl.AllocColorCells[c: bitmap.connection, colorMap: bitmap.attributes.colorMap, colors: 1, planes: 0, contiguos: FALSE ! Xl.XError => GOTO Oops].pixels; IF pixels=NIL OR pixels.leng#1 OR pixels[0]>256 THEN ERROR ViewersWorld.outOfColormapEntries; index ¬ pixels[0]; IF revokeIndex#NIL THEN revokeClosure ¬ NEW[RevokeColorMapClosure ¬ [revokeIndex, clientData, index]]; IF SetAnimationIndex[cm, index, revokeClosure].fail THEN ERROR ViewersWorld.outOfColormapEntries; EXITS Oops => ERROR ViewersWorld.outOfColormapEntries; }; FreeColorMapIndex: ViewersWorldClasses.FreeColorMapIndexProc = { ENABLE RuntimeError.UNCAUGHT, Xl.XError => {IF ~X11Viewers.debugging THEN GOTO oops}; IF index>255 THEN RETURN; WITH screenServerData SELECT FROM data: ScreenServerData => { bitmap: XTk.Widget ~ data.bitmap; cm: REF ColorMapData ~ GetColorMapData[data]; IF bitmap#NIL THEN { was: BOOL; revoke: REF RevokeColorMapClosure; [was, revoke] ¬ ClearAnimationIndex[cm, index]; IF was THEN { Xl.FreeColors[c: bitmap.connection, colorMap: bitmap.attributes.colorMap, pixels: LIST[index], planeMask: 0, details: detailsForSynchronous]; }; }; }; ENDCASE => {}; EXITS oops => {} }; SetColorMapEntry: ViewersWorldClasses.SetColorMapEntryProc = { ENABLE RuntimeError.UNCAUGHT, Xl.XError => {IF ~X11Viewers.debugging THEN GOTO oops}; IF index>255 THEN RETURN; WITH screenServerData SELECT FROM data: ScreenServerData => { cm: REF ColorMapData ~ GetColorMapData[data]; bitmap: XTk.Widget ~ data.bitmap; IF ~cm.map[index].isAnimationIndex THEN RETURN; cm.map[index].r ¬ red ¬ MIN[red, 255]; cm.map[index].g ¬ green ¬ MIN[green, 255]; cm.map[index].b ¬ blue ¬ MIN[blue, 255]; IF bitmap=NIL OR bitmap.fastAccessAllowed#ok THEN RETURN; Xl.StoreColors[c: bitmap.connection, colorMap: bitmap.attributes.colorMap, items: LIST[[pixel: index, rgb: [red: red*257, green: green*257, blue: blue*257] ]], details: detailsForSynchronous ]; }; ENDCASE => {}; EXITS oops => {} }; GetColorMapEntry: ViewersWorldClasses.GetColorMapEntryProc = { red ¬ green ¬ blue ¬ 0; IF index>255 THEN RETURN; WITH screenServerData SELECT FROM data: ScreenServerData => { WITH data.reservedForColorIndices SELECT FROM cm: REF ColorMapData => { red ¬ cm.map[index].r; green ¬ cm.map[index].g; blue ¬ cm.map[index].b; }; ENDCASE => {}; }; ENDCASE => {}; }; X11Viewers.baseClass.allocateColorMapIndex ¬ AllocateColorMapIndex; X11Viewers.baseClass.freeColorMapIndex ¬ FreeColorMapIndex; X11Viewers.baseClass.setColorMapEntry ¬ SetColorMapEntry; X11Viewers.baseClass.getColorMapEntry ¬ GetColorMapEntry; XTkNotification.RegisterGlobal[X11Viewers.beforeWindowCreation, ColorMapCreate]; XTkNotification.RegisterGlobal[X11Viewers.afterWidgetCreation, RegisterRevokeColorMapEntries]; XTkNotification.RegisterGlobal[X11Viewers.bitmapReplaced, ColorMapInstall]; XTkNotification.RegisterGlobal[X11Viewers.checkBitsPerPixel, CheckBitsPerPixel]; PreDebug.RegisterErrorExplainer[ViewersWorld.outOfColormapEntries, NIL, "Can't allocate a color map index"]; END. žX11ViewersColorImpl.mesa Copyright Σ 1988, 1989, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, August 9, 1990 4:18 pm PDT Christian Jacobi, August 20, 1993 1:40 pm PDT Willie-s, November 14, 1991 12:32 pm PST Michael Plass, February 25, 1992 4:09 pm PST Implements color displays for X11Viewers Initialization order matters: must be started after X11ViewersImpl must be started after X11ViewerProcsImpl Revoke color map indices, so client won't use them any more. Don't free color map indices because connection will/has crash anyway. --fork: we don't want to crash or hang with a silly client --no with select or luxury: never return a bad index <> --Returns correct color if it was defined using SetColorMapEntry; bogus color otherwise. Κ{–(cedarcode) style•NewlineDelimiter ˜™Icodešœ ΟeœH™TK™7K™-K™(K™,K™K™(K™šΟb™Kšž$™$Kšž(™(—K™—šΟk ˜ K˜‚—K˜šΟnœŸœŸ˜"KšŸœm˜tKšŸœ˜—KšŸœŸœ ˜K˜Kšœ$ŸœŸœ˜MK˜šœ ŸœŸœŸœ˜#KšœŸœŸœΟca˜Kšœ Ÿœ‘!˜4KšœŸœŸœ‘˜0K˜K˜—Kš œŸœŸœ4Ÿœ Ÿœ˜nK˜šœŸœŸœ˜KšœŸœ Ÿœ ˜"K˜—K˜š œ˜+KšœŸœ ˜*K˜‡šŸœŸœŸœŸœ˜!KšŸœ*Ÿœ‘œ˜UK˜K˜—K˜—K˜š œ˜(KšœŸœ ˜*šŸœ)ŸœŸ˜8šœŸœŸœŸœ˜HK˜!Kšœ)˜)Kšœ+˜+K˜—KšŸœ˜—K˜K˜—š œ˜7KšœŸœ ˜*KšœV˜VK˜K˜—š œ˜)KšœŸœ ˜*K˜šŸœ)ŸœŸ˜8š œŸœŸœŸœŸœŸœ˜SK˜*K˜—KšŸœ˜—K˜—K˜š œ˜/K™Kš ŸœŸœŸœŸœŸœ˜UKšŸœ ŸœŸœ˜šŸœŸœŸ˜!K™†˜KšœŸœ&˜-Kšœ!˜!KšŸœ!ŸœŸœ˜/KšœŸœ ˜&KšœŸœ ˜*KšœŸœ ˜(Kš ŸœŸœŸœŸœŸœ˜9šœK˜KšœŸœ˜Kšœ5˜5K˜—K˜K˜—K˜—KšŸœ˜—KšŸœ ˜K˜K˜—š œ.˜>K™XK˜KšŸœ ŸœŸœ˜šŸœŸœŸ˜!˜šŸœŸœŸ˜-šœŸœ˜K˜K˜K˜K˜—KšŸœ˜—K˜—KšŸœ˜—K˜—K™K˜CK˜;K˜9K˜9KšœP˜PKšœ^˜^KšœK˜KKšœP˜PKšœCŸœ&˜lKšŸœ˜K˜—…—μ*