<> <> <> <> <> DIRECTORY Imager USING [black, Color, Context, DoSave, IntegerClipRectangle, IntegerMaskRectangle, IntegerSetXY, MakeStipple, SetColor, ShowCharacters, white], Menus, MenusPrivate, MessageWindow USING [Append], Process USING [Detach, Milliseconds, MsecToTicks, priorityNormal, SetPriority, SetTimeout], Real USING [RoundC], Rope USING [Equal, FromRefText, ROPE], TIPUser USING [TIPScreenCoords], UserProfile USING [Boolean, CallWhenProfileChanges, Number, ProfileChangedProc], VFonts USING [defaultFont, FONT, FontAscent, FontHeight, RopeWidth], ViewerBLT USING [ChangeMenuHeight], ViewerClasses, ViewerOps USING [EnumProc, EnumerateViewers, InvertForMenus, PaintViewer], ViewerSpecs USING [captionHeight, guardOffset, guardHeight, menuHeight, windowBorderSize], WindowManager USING [RestoreCursor], WindowManagerPrivate USING [closePos, DrawCaptionMenu, growPos, windowMenus]; MenusImpl: CEDAR MONITOR LOCKS entry USING entry: EntryState IMPORTS Imager, MessageWindow, Process, Real, Rope, UserProfile, VFonts, ViewerBLT, ViewerOps, WindowManager, WindowManagerPrivate EXPORTS Menus, MenusPrivate SHARES ViewerOps = BEGIN OPEN Menus, MenusPrivate; ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; menuFont: VFonts.FONT _ VFonts.defaultFont; fontHeight: INTEGER; baselineOffset: INTEGER; registeredMenus: LIST OF Menu _ NIL; widthFudge: INTEGER = 3; targetNotFound: PUBLIC SIGNAL = CODE; MenuNameEqual: PROC[a, b: ATOM] RETURNS[BOOL] = INLINE { RETURN[a=b] }; MarkMenu: PUBLIC PROC [menus: ViewerMenus, parent: Viewer, mousePos: TIPUser.TIPScreenCoords] = { entry: EntryState _ ResolveEntry[menus, mousePos]; IF menus.inverted # entry THEN { IF menus.inverted # NIL THEN InvertEntry[menus,parent]; menus.inverted _ entry; IF menus.inverted # NIL THEN InvertEntry[menus,parent]; }; }; HitMenu: PUBLIC PROC[menus: ViewerMenus, parent: Viewer, mousePos: TIPUser.TIPScreenCoords, trigger: Trigger] = { entry: EntryState _ ResolveEntry[menus, mousePos]; hit: BOOL _ menus.inverted#NIL AND entry=menus.inverted; IF menus.inverted#NIL THEN InvertEntry[menus, parent]; -- take down menus.inverted _ NIL; IF hit THEN ProcessMenuHit[entry, menus, parent, trigger]; }; ProcessMenuHit: ENTRY PROC [entry: EntryState, menus: ViewerMenus, parent: Viewer, trigger: Trigger] = { SELECT entry.guardState FROM guarded => { response: REF ANY _ NIL; entry.guardState _ arming; TRUSTED {Process.Detach[FORK ArmMenuProc[entry, menus, parent]]}; response _ FindAction[entry, trigger].guardResponse; IF response#NIL THEN TRUSTED {Process.Detach[FORK GuardResponse[response]]}; }; arming=> NULL; -- no action armed => { IF entry.commonData.guarded THEN entry.guardState _ guarded; MenuPusher[entry, menus, parent, trigger, FALSE]; }; ENDCASE; }; ArmMenuProc: ENTRY PROC [entry: EntryState, menus: ViewerMenus, parent: Viewer] = BEGIN menuWaitCondition: CONDITION; <> TRUSTED {Process.SetTimeout[@menuWaitCondition, Process.MsecToTicks[armingTime]]}; WAIT menuWaitCondition; IF entry.guardState = arming THEN BEGIN entry.guardState _ armed; RedrawMenu[parent, menus, entry]; TRUSTED {Process.SetTimeout[@menuWaitCondition, Process.MsecToTicks[armedTime]]}; WAIT menuWaitCondition; END; IF entry.guardState#guarded THEN BEGIN entry.guardState _ guarded; RedrawMenu[parent, menus, entry]; END; END; MenuPusher: PROC[entry: EntryState, menus: ViewerMenus, parent: Viewer, trigger: Trigger, normalPriority: BOOL _ TRUE] = BEGIN changeOccurred: BOOLEAN _ FALSE; action: Action = FindAction[entry, trigger]; notifyProc: ViewerClasses.NotifyProc _ FindViewerMenu[menus,entry].commonData.notify; IF notifyProc = NIL THEN { notifyProc _ parent.class.notify; <> <> } ELSE { <> }; entry.greyed _ TRUE; RedrawMenu[parent, menus, entry]; IF normalPriority THEN TRUSTED {Process.SetPriority[Process.priorityNormal]}; <> IF notifyProc # NIL THEN notifyProc[parent, action.input]; entry.greyed _ FALSE; RedrawMenu[parent, menus, entry]; changeOccurred _ FALSE; FOR m: LIST OF MenuName _ action.makeActive, m.rest UNTIL m = NIL DO MakeActive[viewer: parent, menu: m.first, paint: FALSE]; changeOccurred _ TRUE; ENDLOOP; FOR m: LIST OF MenuName _ action.makeInactive, m.rest UNTIL m = NIL DO MakeInactive[viewer: parent, menu: m.first, paint: FALSE]; changeOccurred _ TRUE; ENDLOOP; FOR m: LIST OF MenuName _ action.toggle, m.rest UNTIL m = NIL DO Toggle[viewer: parent, menu: m.first, paint: FALSE]; changeOccurred _ TRUE; ENDLOOP; IF changeOccurred THEN RePaintBecauseOfMenuChange[parent]; WindowManager.RestoreCursor[]; END; RedrawMenu: PROC [viewer: Viewer, menus: ViewerMenus, entry: EntryState] = BEGIN IF menus = WindowManagerPrivate.windowMenus THEN WindowManagerPrivate.DrawCaptionMenu[viewer, FALSE] ELSE ViewerOps.PaintViewer[viewer: viewer, hint: menu, whatChanged: entry]; END; GuardResponse: PROC [response: REF ANY] = BEGIN WITH response SELECT FROM response: ROPE => MessageWindow.Append[response, TRUE]; response: REF UnGuardRec => response.proc[response.data]; ENDCASE => ERROR; -- not valid response END; ClearMenu: PUBLIC PROC [menus: ViewerMenus, parent: Viewer, paint: BOOL _ TRUE] = BEGIN IF menus.inverted#NIL THEN BEGIN IF paint THEN InvertEntry[menus, parent]; menus.inverted _ NIL; END; END; DrawSingleEntry: PROC [viewer: Viewer, context: Imager.Context, entry: EntryState, clearFirst: BOOLEAN _ TRUE] = { myGrey: Imager.Color = Imager.MakeStipple[001010B]; lowerLeftX: INTEGER _ viewer.wx + entry.xPos; lowerLeftY: INTEGER _ viewer.wy + entry.yPos; IF clearFirst THEN { Imager.SetColor[context, Imager.white]; Imager.IntegerMaskRectangle[context, lowerLeftX - widthFudge, lowerLeftY, entry.width + (2*widthFudge), fontHeight-1]; Imager.SetColor[context, Imager.black]; }; IF entry.greyed THEN { Imager.SetColor[context, myGrey]; Imager.IntegerMaskRectangle[context, lowerLeftX - widthFudge, lowerLeftY, entry.width + (2*widthFudge), fontHeight-1]; Imager.SetColor[context, Imager.black]; }; WITH entry.commonData.displayData SELECT FROM r: ROPE => { Imager.IntegerSetXY[context, lowerLeftX, lowerLeftY + baselineOffset]; Imager.ShowCharacters[context, r, VFonts.defaultFont]; }; user: REF DrawingRec => { CallUserDrawProc: PROC = { <> Imager.IntegerClipRectangle[context, lowerLeftX-widthFudge, lowerLeftY, entry.width+(2*widthFudge), fontHeight-1]; [] _ user.proc[op: draw, context: context, clientData: user.data]; }; Imager.IntegerSetXY[context, lowerLeftX, lowerLeftY]; Imager.DoSave[context, CallUserDrawProc]; }; ENDCASE => ERROR; IF entry.commonData.guarded AND entry.guardState # armed THEN { OPEN ViewerSpecs; Imager.IntegerMaskRectangle[context, lowerLeftX - 1, lowerLeftY + baselineOffset+guardOffset, entry.width + 2, guardHeight]; }; }; DrawMenu: PUBLIC PROC [v: Viewer, menus: ViewerMenus, context: Imager.Context, whatChanged: REF ANY _ NIL] = { <> <> WITH whatChanged SELECT FROM entry: EntryState => DrawSingleEntry[v, context, entry]; ENDCASE => { FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF m.first.active THEN FOR e: LIST OF EntryState _ m.first.entries, e.rest UNTIL e = NIL DO DrawSingleEntry[v, context, e.first, FALSE]; ENDLOOP; ENDLOOP; menus.inverted _ NIL; }; }; resolveCacheMenus: ViewerMenus _ NIL; resolveCacheMenu: ViewerMenu _ NIL; rce: EntryState _ NIL; -- stands for ResolveCacheEntry ResolveEntry: PROC [menus: ViewerMenus, mousePos: TIPUser.TIPScreenCoords] RETURNS [entry: EntryState] = { <> <> IF resolveCacheMenus = menus THEN IF resolveCacheMenu.active THEN { IF mousePos.mouseX IN [rce.xPos..(rce.xPos + rce.width)] AND mousePos.mouseY IN [rce.yPos..(rce.yPos+(fontHeight-1))] THEN RETURN[rce]; }; <> FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF NOT m.first.active THEN LOOP; FOR e: LIST OF EntryState _ m.first.entries, e.rest UNTIL e = NIL DO IF mousePos.mouseX IN [e.first.xPos..(e.first.xPos + e.first.width)] AND mousePos.mouseY IN [e.first.yPos..(e.first.yPos+(fontHeight-1))] THEN { <> resolveCacheMenus _ menus; resolveCacheMenu _ m.first; rce _ e.first; RETURN[e.first]; }; ENDLOOP; ENDLOOP; RETURN[NIL]; }; InvertEntry: PROC [menus: ViewerMenus, parent: Viewer] = { IF ~parent.destroyed AND ~parent.iconic THEN { entry: EntryState _ menus.inverted; ViewerOps.InvertForMenus[parent, (parent.wx+entry.xPos)-widthFudge, parent.wy+entry.yPos, entry.width+(2*widthFudge), fontHeight-1]; }; }; ComputeFontInfo: PROC = BEGIN ascent: INTEGER = VFonts.FontAscent[menuFont]; fontHeight _ VFonts.FontHeight[menuFont]; baselineOffset _ Real.RoundC[fontHeight-ascent]; END; FindAction: PROC[entry: EntryState, trigger: Trigger] RETURNS [Action] = { FOR list: LIST OF Action _ entry.commonData.actions, list.rest UNTIL list=NIL DO action: Action = list.first; IF action.triggers[trigger] THEN RETURN[action]; ENDLOOP; ERROR; }; FindViewerMenu: PROC [menus: ViewerMenus, entry: EntryState] RETURNS [menu: ViewerMenu] = { FOR l: LIST OF ViewerMenu _ menus.list, l.rest UNTIL l = NIL DO FOR e: LIST OF EntryState _ l.first.entries, e.rest UNTIL e = NIL DO IF e.first = entry THEN RETURN[l.first]; ENDLOOP; ENDLOOP; RETURN[NIL]; }; ValidateMenu: PROC[menu: Menu] = { FOR entries: LIST OF Entry _ menu.entries, entries.rest UNTIL entries=NIL DO entry: Entry = entries.first; IF entry.displayData=NIL THEN entry.displayData _ entry.name ELSE { <> WITH entry.displayData SELECT FROM dispData: REF TEXT => entry.displayData _ Rope.FromRefText[dispData]; okRope: ROPE => NULL; okProc: REF DrawingRec => NULL; ENDCASE => ERROR; -- invalid data type for DisplayData field. }; FOR actions: LIST OF Action _ entry.actions, actions.rest UNTIL actions=NIL DO action: Action = actions.first; IF action.guardResponse=NIL THEN NULL ELSE { <> WITH action.guardResponse SELECT FROM textRef: REF TEXT => action.guardResponse _ Rope.FromRefText[textRef]; okRope: ROPE => NULL; okRec: REF UnGuardRec => NULL; ENDCASE => ERROR; -- invalid data type for guardResponse field. }; ENDLOOP; ENDLOOP; }; RegisterMenu: PUBLIC PROC [menu: Menu] = { ValidateMenu[menu]; registeredMenus _ CONS[menu, registeredMenus]; }; AlreadyRegistered: PUBLIC PROC [name: MenuName] RETURNS [registered: BOOLEAN] = { FOR m: LIST OF Menu _ registeredMenus, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.name, name] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; ReRegisterMenu: PUBLIC PROC [menu: Menu, paint: BOOL _ TRUE] = { newMenu: ViewerMenuRec; MenuDefinitonChanged: ViewerOps.EnumProc = { <<[v: Viewer] RETURNS [BOOL _ TRUE] >> menus: ViewerMenus = NARROW[v.menus]; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF MenuNameEqual[menu.name, m.first.commonData.name] THEN m.first _ NEW[ViewerMenuRec _ newMenu]; ENDLOOP; IF paint THEN RePaintBecauseOfMenuChange[v]; }; ValidateMenu[menu]; FOR m: LIST OF Menu _ registeredMenus, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.name, menu.name] THEN { m.first _ menu; newMenu _ MakeNewViewerMenuRec[m.first]; ViewerOps.EnumerateViewers[MenuDefinitonChanged]; RETURN; }; ENDLOOP; ERROR targetNotFound; }; GetRegisteredMenu: PUBLIC PROC [name: MenuName] RETURNS [Menu] = { FOR m: LIST OF Menu _ registeredMenus, m.rest UNTIL m = NIL DO menu: Menu = m.first; IF MenuNameEqual[menu.name, name] THEN RETURN[menu]; ENDLOOP; ERROR targetNotFound; }; ClearMenus: PUBLIC PROC [viewer: Viewer, paint: BOOL _ TRUE] = { viewer.menus _ NIL; IF paint THEN RePaintBecauseOfMenuChange[viewer]; }; AddMenu: PUBLIC PROC [viewer: Viewer, name: MenuName, paint: BOOL _ TRUE, addBefore: MenuName _ NIL] = { menus: ViewerMenus = NARROW[viewer.menus]; IF menus = NIL THEN { IF addBefore # NIL THEN SIGNAL targetNotFound; viewer.menus _ NEW[ViewerMenusRec _ [list: LIST[MakeNewViewerMenu[name]]]]; } ELSE IF addBefore # NIL THEN { <> prev: LIST OF ViewerMenu _ NIL; foundIt: BOOLEAN _ FALSE; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.commonData.name, name] THEN { prev.rest _ CONS[MakeNewViewerMenu[name], m]; foundIt _ TRUE; }; prev _ m; ENDLOOP; IF NOT foundIt THEN SIGNAL targetNotFound; } ELSE IF GetRegisteredMenu[name].breakBefore THEN { <> prev: LIST OF ViewerMenu _ NIL; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO prev _ m; ENDLOOP; prev.rest _ LIST[MakeNewViewerMenu[name]]; } ELSE { <> prev: LIST OF ViewerMenu _ NIL; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL OR ((prev # NIL AND prev.first.commonData.breakAfter = FALSE) AND m.first.commonData.breakBefore) DO prev _ m; ENDLOOP; prev.rest _ CONS[MakeNewViewerMenu[name],prev.rest]; }; IF paint THEN RePaintBecauseOfMenuChange[viewer]; }; ViewerlessAddMenu: PUBLIC PROC [name: MenuName, addBefore: MenuName _ NIL, paint: BOOL _ TRUE] = { <> IF WindowManagerPrivate.windowMenus = NIL THEN { IF addBefore # NIL THEN SIGNAL targetNotFound; WindowManagerPrivate.windowMenus _ NEW[ViewerMenusRec]; WindowManagerPrivate.windowMenus.list _ LIST[MakeNewViewerMenu[name]]; } ELSE IF addBefore # NIL THEN { <> prev: LIST OF ViewerMenu _ NIL; foundIt: BOOLEAN _ FALSE; FOR m: LIST OF ViewerMenu _ WindowManagerPrivate.windowMenus.list, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.commonData.name, name] THEN { prev.rest _ CONS[MakeNewViewerMenu[name], m]; foundIt _ TRUE; }; prev _ m; ENDLOOP; IF NOT foundIt THEN SIGNAL targetNotFound; } ELSE IF GetRegisteredMenu[name].breakBefore THEN { <> prev: LIST OF ViewerMenu _ NIL; FOR m: LIST OF ViewerMenu _ WindowManagerPrivate.windowMenus.list, m.rest UNTIL m = NIL DO prev _ m; ENDLOOP; prev.rest _ LIST[MakeNewViewerMenu[name]]; } ELSE { <> prev: LIST OF ViewerMenu _ NIL; FOR m: LIST OF ViewerMenu _ WindowManagerPrivate.windowMenus.list, m.rest UNTIL m = NIL OR ((prev # NIL AND prev.first.commonData.breakAfter = FALSE) AND m.first.commonData.breakBefore) DO prev _ m; ENDLOOP; prev.rest _ CONS[MakeNewViewerMenu[name],prev.rest]; }; }; MakeNewViewerMenu: PROC[name: MenuName] RETURNS[ViewerMenu] = { FOR m: LIST OF Menu _ registeredMenus, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.name, name] THEN RETURN[NEW[ViewerMenuRec _ MakeNewViewerMenuRec[m.first]]]; ENDLOOP; ERROR targetNotFound; }; MakeNewViewerMenuRec: PROC[menu: Menu] RETURNS[ViewerMenuRec] = { RETURN[[commonData: menu, active: menu.beginsActive, entries: MakeNewViewerMenuEntries[menu]]]; }; MakeNewViewerMenuEntries: PROC[menu: Menu] RETURNS[LIST OF EntryState] = { reversedList: LIST OF EntryState _ NIL; answer: LIST OF EntryState _ NIL; FOR e: LIST OF Entry _ menu.entries, e.rest UNTIL e = NIL DO reversedList _ CONS[NEW[EntryStateRec _ [commonData: e.first]], reversedList]; ENDLOOP; FOR e: LIST OF EntryState _ reversedList, e.rest UNTIL e = NIL DO IF e.first.commonData.guarded THEN e.first.guardState _ guarded; answer _ CONS[e.first, answer]; ENDLOOP; RETURN[answer]; }; MakeActive: PUBLIC PROC [viewer: Viewer, menu: MenuName, paint: BOOL _ TRUE] = { menus: ViewerMenus = NARROW[viewer.menus]; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.commonData.name, menu] THEN { IF NOT m.first.active THEN { m.first.active _ TRUE; IF paint THEN RePaintBecauseOfMenuChange[viewer]; }; RETURN; }; ENDLOOP; SIGNAL targetNotFound; }; MakeInactive: PUBLIC PROC [viewer: Viewer, menu: MenuName, paint: BOOL _ TRUE] = { menus: ViewerMenus = NARROW[viewer.menus]; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.commonData.name, menu] THEN { IF m.first.active THEN { m.first.active _ FALSE; IF paint THEN RePaintBecauseOfMenuChange[viewer]; }; RETURN; }; ENDLOOP; SIGNAL targetNotFound; }; Toggle: PUBLIC PROC [viewer: Viewer, menu: MenuName, paint: BOOL _ TRUE] = { menus: ViewerMenus = NARROW[viewer.menus]; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.commonData.name, menu] THEN { m.first.active _ NOT m.first.active; IF paint THEN RePaintBecauseOfMenuChange[viewer]; RETURN; }; ENDLOOP; SIGNAL targetNotFound; }; MenuInViewer: PUBLIC PROC[viewer: Viewer, menu: MenuName] RETURNS[exists: BOOLEAN] = { menus: ViewerMenus = NARROW[viewer.menus]; FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF MenuNameEqual[m.first.commonData.name, menu] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; <> wrap: BOOLEAN _ TRUE; -- TRUE iff user wants menu entries ALWAYS to be displayed wrapIndent: INTEGER _ (menuHLeading*4); -- indention on non-first lines of wrapped menu tooNarrowToWrapMenus: INTEGER _ 150; -- don't wrap if the window is ridiculously narrow <> ReEstablishUserProfileParameters: PUBLIC UserProfile.ProfileChangedProc = { wrap _ UserProfile.Boolean[key: "ViewerMenusWrap", default: TRUE]; wrapIndent _ UserProfile.Number[key: "ViewerMenusWrapIndent", default: (menuHLeading*4)]; tooNarrowToWrapMenus _ UserProfile.Number["ViewerMenusTooNarrowToWrap", 150]; }; RecomputeMenus: PUBLIC PROC [v: Viewer] RETURNS[heightDelta: INTEGER] = { OPEN ViewerSpecs; <> <> menus: ViewerMenus = NARROW[v.menus]; originalHeight: INTEGER; prevLineHadBreakafter: BOOLEAN _ TRUE; -- starting true forces first line to move down wbs: INTEGER _ IF v.border THEN windowBorderSize ELSE 0; TopLeftCornerX: INTEGER _ wbs; TopLeftCornerY: INTEGER _ v.wh-captionHeight; CurrentX: INTEGER _ TopLeftCornerX + menuHLeading; CurrentY: INTEGER _ TopLeftCornerY; IF menus=NIL OR v.iconic THEN RETURN[0]; originalHeight _ menus.h; < wrap is true", IO.rope[ menus.list.first.commonData.name]], level: 2]>> < wrap is false", IO.rope[menus.list.first.commonData.name]], level: 2];>> FOR m: LIST OF ViewerMenu _ menus.list, m.rest UNTIL m = NIL DO IF NOT m.first.active THEN LOOP; IF prevLineHadBreakafter OR m.first.commonData.breakBefore THEN { CurrentX _ TopLeftCornerX + menuHLeading; CurrentY _ CurrentY - menuHeight; }; prevLineHadBreakafter _ m.first.commonData.breakAfter; FOR e: LIST OF EntryState _ m.first.entries, e.rest UNTIL e = NIL DO e.first.width _ WITH e.first.commonData.displayData SELECT FROM r: ROPE => VFonts.RopeWidth[r], user: REF DrawingRec => user.proc[op: query, clientData: user.data] ENDCASE => ERROR; IF wrap AND (v.ww > tooNarrowToWrapMenus) THEN IF (CurrentX + e.first.width) > (v.ww - wbs) THEN { <> <> CurrentX _ TopLeftCornerX + wrapIndent; CurrentY _ CurrentY - menuHeight; }; e.first.xPos _ CurrentX; e.first.yPos _ CurrentY; CurrentX _ CurrentX + e.first.width + menuHSpace; ENDLOOP; ENDLOOP; menus.x _ TopLeftCornerX; menus.y _ CurrentY; menus.w _ v.ww - (2 * wbs); menus.h _ TopLeftCornerY - CurrentY; <> RETURN[menus.h - originalHeight]; }; ReComputeWindowMenus: PUBLIC PROC [v: Viewer, guard: BOOL, color: BOOL] = { OPEN ViewerSpecs; <> CurrentX: INTEGER _ menuHLeading + windowBorderSize; CurrentY: INTEGER ~ v.wh - captionHeight; -- all have same Y coordinate WindowManagerPrivate.windowMenus.x _ windowBorderSize; WindowManagerPrivate.windowMenus.y _ v.wh - captionHeight; WindowManagerPrivate.windowMenus.w _ v.ww - (2 * windowBorderSize); WindowManagerPrivate.windowMenus.h _ captionHeight; <> IF guard THEN { <> SetDisplay[$windowDestroyMenu, FALSE]; SetDisplay[$windowGuardedDestroyMenu, TRUE]; } ELSE { <> SetDisplay[$windowDestroyMenu, TRUE]; SetDisplay[$windowGuardedDestroyMenu, FALSE]; }; IF color THEN SetDisplay[$windowColorMenu, TRUE] ELSE SetDisplay[$windowColorMenu, FALSE]; FOR m: LIST OF ViewerMenu _ WindowManagerPrivate.windowMenus.list, m.rest UNTIL m = NIL DO IF NOT m.first.active THEN LOOP; FOR e: LIST OF EntryState _ m.first.entries, e.rest UNTIL e = NIL DO e.first.width _ WITH e.first.commonData.displayData SELECT FROM r: ROPE => VFonts.RopeWidth[r], user: REF DrawingRec => user.proc[op: query, clientData: user.data] ENDCASE => ERROR; e.first.xPos _ CurrentX; e.first.yPos _ CurrentY; <> IF Rope.Equal[e.first.commonData.name, "Grow"] THEN { WindowManagerPrivate.growPos.mouseX _ e.first.xPos+1; WindowManagerPrivate.growPos.color _ FALSE; WindowManagerPrivate.growPos.mouseY _ e.first.yPos+1; }; IF Rope.Equal[e.first.commonData.name, "Close"] THEN { WindowManagerPrivate.closePos.mouseX _ e.first.xPos+1; WindowManagerPrivate.closePos.color _ FALSE; WindowManagerPrivate.closePos.mouseY _ e.first.yPos+1; }; CurrentX _ CurrentX + e.first.width + menuHSpace; ENDLOOP; ENDLOOP; }; SetDisplay: PROC [name: MenuName, setting: BOOL] = { FOR l: LIST OF ViewerMenu _ WindowManagerPrivate.windowMenus.list, l.rest UNTIL l = NIL DO IF MenuNameEqual[l.first.commonData.name, name] THEN { l.first.active _ setting; RETURN; }; ENDLOOP; ERROR; }; RePaintBecauseOfMenuChange: PROC[v: Viewer] = { ViewerBLT.ChangeMenuHeight[v, RecomputeMenus[v]]; <> }; ComputeFontInfo[]; UserProfile.CallWhenProfileChanges[ReEstablishUserProfileParameters]; END. <> <<>> <> <> <> <> <> <> <<};>> <<>> <> <> <= level THEN {>> <> <> <> <> <> <> <> <> <<};>> <<};>> <<}; -- Debug>>