DIRECTORY Buttons USING [Button, ButtonProc, Create, SetDisplayStyle], CDebugDefs USING [Cmd, CmdIndex, DataRec, DoCommand, Handle, NumberCell], CodeDefs USING [CCInfoType], Commander USING [CommandProc, Handle, Register], Containers USING [ChildXBound, Create], Convert USING [CardFromWholeNumberLiteral, Error, RopeFromInt], IO USING [NUL, SP], Labels USING [Create], Menus USING [MouseButton], MessageWindow USING [Append], PrincOps USING [], RESOut USING [cancelAction, Complain], Rope USING [Concat, Fetch, Length, ROPE], Rules USING [Create, Rule], SafeStorage USING [NarrowFault], STDebugDefs USING [STDebugMisc, STDebugSymbols, STDebugTrees], VFonts USING [CharWidth, StringWidth], ViewerClasses USING [Viewer], ViewerEvents USING [EventProc, RegisterEventProc], ViewerIO USING [CreateViewerStreams, GetViewerFromStream], ViewerOps USING [AddProp, DestroyViewer, FetchProp, PaintViewer, SetOpenHeight], ViewerTools USING [GetContents, GetSelectionContents, MakeNewTextViewer, SetContents, SetSelection]; CDebugInterface: CEDAR PROGRAM IMPORTS Buttons, Commander, Containers, Convert, CDebugDefs, Labels, MessageWindow, RESOut, Rope, Rules, SafeStorage, STDebugDefs, VFonts, ViewerEvents, ViewerIO, ViewerOps, ViewerTools EXPORTS CDebugDefs = BEGIN OPEN CDebugDefs; entryHeight: CARDINAL = 15; -- how tall to make each line of items entryVSpace: CARDINAL = 2; -- vertical leading space between lines entryHSpace: CARDINAL = 5; -- min horizontal space between items in a line ROPE: TYPE = Rope.ROPE; PromptRec: TYPE = RECORD [handle: CDebugDefs.Handle, cell: ViewerClasses.Viewer, radix: INT _ 8]; PromptHandle: TYPE = REF PromptRec; CmdRec: TYPE = RECORD [handle: CDebugDefs.Handle, cmd: CDebugDefs.CmdIndex]; CmdHandle: TYPE = REF CmdRec; EnumItem: TYPE = RECORD [tag: ROPE, value: UNSPECIFIED]; ERef: TYPE = REF UNSPECIFIED; -- can't figure out how to make generic safely EnumItemSeqRec: TYPE = RECORD [SEQUENCE count: CARDINAL OF EnumItem]; EnumItemSeq: TYPE = REF EnumItemSeqRec; EnumRec: TYPE = RECORD [handle: CDebugDefs.Handle, choice: ViewerClasses.Viewer, choices: EnumItemSeq, showing: CARDINAL, eCell: ERef]; EnumHandle: TYPE = REF EnumRec; MakeTool: Commander.CommandProc = BEGIN rule: Rules.Rule; my: Handle _ NEW[DataRec]; my.en _ VFonts.CharWidth['0]; -- width of 'n was too wide my.outer _ Containers.Create[[-- construct the outer container name: "CDebug commands", -- name displayed in the caption iconic: FALSE, -- so tool will be open when first created column: left, -- initially in the left column guardDestroy: TRUE, scrollable: FALSE ]]; -- inhibit user from scrolling contents my.msg _ Labels.Create[ [ name: NIL, wx: 0, wy: my.height, wh: 2*entryHeight, parent: my.outer, border: FALSE]]; my.height _ my.height + 2*entryHeight + 2; -- interline spacing Containers.ChildXBound[my.outer, my.msg]; rule _ Rules.Create [[parent: my.outer, wy: my.height, ww: my.outer.cw, wh: 2]]; Containers.ChildXBound[my.outer, rule]; MakeCommands[my]; my.charsOnLine _ 0; ViewerOps.AddProp[my.outer, $cdebugHandle, my]; ViewerOps.SetOpenHeight[viewer: my.outer, clientHeight: my.height]; ViewerOps.PaintViewer[viewer: my.outer, hint: all]; [] _ ViewerEvents.RegisterEventProc[proc: DestroyTool, event: destroy, filter: my.outer]; MakeTypescript[my]; END; DestroyTool: ViewerEvents.EventProc = { IF before THEN { h: Handle _ NARROW[ViewerOps.FetchProp[viewer, $cdebugHandle]]; IF h = NIL OR h.outer # viewer THEN RETURN; h.dying _ TRUE; ViewerOps.DestroyViewer[h.ts]}; }; -- locations of the various fields Place: TYPE = RECORD [x, y: CARDINAL]; TreeCol: CARDINAL = 0; RepCol: CARDINAL = TreeCol + 7; MTCol: CARDINAL = RepCol + 6; TempCol: CARDINAL = MTCol + 9; FirstCol: CARDINAL = TempCol + 14; BodyCol: CARDINAL = FirstCol + 13; FopCol: CARDINAL = BodyCol + 7; treePlace: Place = [x: TreeCol+0, y: 0]; depthPlace: Place = [x: TreeCol+0, y: 1]; linksPlace: Place = [x: TreeCol+0, y: 2]; stopPlace: Place = [x: TreeCol+0, y: 3]; repPlace: Place = [x: RepCol+0, y: 0]; mdiPlace: Place = [x: MTCol+0, y: 0]; htiPlace: Place = [x: MTCol+4, y: 0]; ctiPlace: Place = [x: MTCol+0, y: 1]; btiPlace: Place = [x: MTCol+4, y: 1]; seiPlace: Place = [x: MTCol+0, y: 2]; nextsePlace: Place = [x: MTCol+4, y: 2]; sourcePlace: Place = [x: MTCol+0, y: 3]; varPlace: Place = [x: TempCol+0, y: 0]; vcompPlace: Place = [x: TempCol+5, y: 0]; tempPlace: Place = [x: TempCol+0, y: 1]; allStackPlace: Place = [x: TempCol+7, y: 1]; stackPlace: Place = [x: TempCol+0, y: 2]; tosPlace: Place = [x: TempCol+6, y: 2]; downPlace: Place = [x: TempCol+0, y: 3]; upPlace: Place = [x: TempCol+7, y: 3]; asCCPlace: Place = [x: FirstCol+0, y: 0]; curPlace: Place = [x: FirstCol+6, y: 0]; rcntPlace: Place = [x: FirstCol+0, y: 1]; fwdPlace: Place = [x: FirstCol+6, y: 1]; prevPlace: Place = [x: FirstCol+0, y: 2]; nextPlace: Place = [x: FirstCol+6, y: 2]; firstPlace: Place = [x: FirstCol+0, y: 3]; infoPlace: Place = [x: FirstCol+6, y: 3]; fopPlace: Place = [x: FopCol+0, y: 0]; mopPlace: Place = [x: FopCol+0, y: 1]; lblPlace: Place = [x: FopCol+0, y: 2]; liiPlace: Place = [x: FopCol+0, y: 3]; bodyPlace: Place = [x: BodyCol+0, y: 0]; stmtPlace: Place = [x: BodyCol+0, y: 1]; exprPlace: Place = [x: BodyCol+0, y: 2]; MakeCommands: PROC [handle: Handle] = BEGIN cmdy: INT = handle.height + entryVSpace; maxY: INT _ 0; MakeCmd: PROC [at: Place, name: ROPE, cmd: CDebugDefs.CmdIndex] = { b: Cmd _ Buttons.Create[ info: [ name: Rope.Concat[name, "!"], wx: at.x*handle.en, wy: cmdy + at.y * (entryHeight + entryVSpace), wh: entryHeight, -- specify rather than defaulting so line is uniform parent: handle.outer, border: FALSE], proc: OtherCmd, clientData: NEW [CmdRec _ [handle: handle, cmd: cmd]]]; maxY _ MAX[maxY, at.y]; }; MakeBool: PROC [at: Place, name: ROPE, initial: BOOL] RETURNS [flag: REF BOOL] = { b: Cmd; flag _ NEW[BOOL _ initial]; b _ Buttons.Create[ info: [ name: name, wx: at.x*handle.en, wy: cmdy + at.y * (entryHeight + entryVSpace), wh: entryHeight, -- specify rather than defaulting so line is uniform parent: handle.outer, border: FALSE], proc: ToggleBool, clientData: flag]; Buttons.SetDisplayStyle[ button: b, style: IF initial THEN $WhiteOnBlack ELSE $BlackOnWhite]; maxY _ MAX[maxY, at.y]; }; NamedCell: PROC [at: Place, name: ROPE, width: CARDINAL, initial: ROPE _ NIL, radix: INT _ 8] RETURNS [v: ViewerClasses.Viewer] = { ph: PromptHandle _ NEW[PromptRec _ [handle: handle, radix: radix, cell: NIL]]; cmdx: INT _ at.x*handle.en; b: Buttons.Button _ Buttons.Create[ info: [ name: Rope.Concat[name, ": "], wx: cmdx, wy: cmdy + at.y * (entryHeight + entryVSpace), wh: entryHeight, parent: handle.outer, border: FALSE], proc: SimplePrompt, clientData: ph]; cmdx _ cmdx + b.ww; v _ ViewerTools.MakeNewTextViewer[ info: [ wx: cmdx, wy: cmdy + at.y * (entryHeight + entryVSpace) + 1, ww: width*handle.en + 8, wh: entryHeight, parent: handle.outer, data: initial, scrollable: FALSE, border: FALSE]]; ph.cell _ v; maxY _ MAX[maxY, at.y]; }; MakeEnum: PROC [at: Place, name: ROPE, choices: EnumItemSeq, initial: CARDINAL _ 0] RETURNS [er: ERef] = { eh: EnumHandle _ NEW[EnumRec _ [handle: handle, choices: choices, showing: initial, eCell: (er _ NEW[UNSPECIFIED])]]; cmdx: INT _ at.x*handle.en; v: ViewerClasses.Viewer; width: INT _ 0; b: Buttons.Button _ Buttons.Create[ info: [ name: Rope.Concat[name, ": "], wx: cmdx, wy: cmdy + at.y * (entryHeight + entryVSpace), wh: entryHeight, parent: handle.outer, border: FALSE], proc: CycleOptions, clientData: eh]; FOR i: CARDINAL IN [0..choices.count) DO width _ MAX[width, VFonts.StringWidth[choices[i].tag]]; ENDLOOP; er^ _ choices[initial].value; cmdx _ cmdx + b.ww; v _ ViewerTools.MakeNewTextViewer[ info: [ wx: cmdx, wy: cmdy + at.y * (entryHeight + entryVSpace) + 1, ww: width + 12, wh: entryHeight, parent: handle.outer, data: choices[initial].tag, scrollable: FALSE, border: FALSE]]; eh.choice _ v; cmdx _ cmdx + v.ww + entryHSpace; maxY _ MAX[maxY, at.y]; }; infoEnum: EnumItemSeq _ NEW[EnumItemSeqRec[3]]; infoEnum[0] _ [tag: "gen", value: CodeDefs.CCInfoType[generating]]; infoEnum[1] _ [tag: "bind", value: CodeDefs.CCInfoType[binding]]; infoEnum[2] _ [tag: "code", value: CodeDefs.CCInfoType[coding]]; MakeCmd[at: treePlace, name: "Tree", cmd: tree]; MakeCmd[at: asCCPlace, name: "CC", cmd: asCC]; MakeCmd[at: varPlace, name: "Var", cmd: var]; MakeCmd[at: vcompPlace, name: "VComp", cmd: vcomp]; handle.showLinks _ MakeBool[at: linksPlace, name: "lnks", initial: FALSE]; handle.cmd.dVal _ NamedCell[at: depthPlace, name: "d", width: 3, initial: "2", radix: 10]; MakeCmd[at: stopPlace, name: "STOP", cmd: stop]; MakeCmd[at: firstPlace, name: "first", cmd: first]; MakeCmd[at: curPlace, name: "cur", cmd: cur]; MakeCmd[at: rcntPlace, name: "rcnt", cmd: rcnt]; MakeCmd[at: fwdPlace, name: "fwd", cmd: fwd]; MakeCmd[at: prevPlace, name: "prev", cmd: prev]; MakeCmd[at: nextPlace, name: "next", cmd: next]; handle.infoVar _ MakeEnum[at: infoPlace, name: "t", choices: infoEnum]; MakeCmd[at: tempPlace, name: "temp", cmd: temp]; MakeCmd[at: allStackPlace, name: "Stk", cmd: allStack]; MakeCmd[at: stackPlace, name: "sti", cmd: stack]; MakeCmd[at: tosPlace, name: "TOS", cmd: tos]; MakeCmd[at: downPlace, name: "down", cmd: down]; MakeCmd[at: upPlace, name: "up", cmd: up]; MakeCmd[at: lblPlace, name: "lbl", cmd: lbl]; MakeCmd[at: liiPlace, name: "lii", cmd: lii]; MakeCmd[at: mdiPlace, name: "mt", cmd: mdi]; MakeCmd[at: htiPlace, name: "ht", cmd: hti]; MakeCmd[at: ctiPlace, name: "ct", cmd: cti]; MakeCmd[at: btiPlace, name: "bt", cmd: bti]; MakeCmd[at: seiPlace, name: "se", cmd: sei]; MakeCmd[at: nextsePlace, name: "nx", cmd: nextse]; MakeCmd[at: fopPlace, name: "fop", cmd: fop]; MakeCmd[at: mopPlace, name: "mop", cmd: mop]; MakeCmd[at: repPlace, name: "rep", cmd: rep]; MakeCmd[at: bodyPlace, name: "Body", cmd: body]; MakeCmd[at: stmtPlace, name: "Stmt", cmd: stmt]; MakeCmd[at: exprPlace, name: "Expr", cmd: expr]; MakeCmd[at: sourcePlace, name: "Source", cmd: source]; handle.height _ cmdy + (maxY+1) * (entryHeight + entryVSpace) END; CellInt: PUBLIC PROC [handle: Handle, n: NumberCell] RETURNS [INT] = { contents: Rope.ROPE _ ViewerTools.GetContents[n]; RETURN [GetNumber[handle, contents]]}; CellCard: PUBLIC PROC [handle: Handle, n: NumberCell] RETURNS [CARDINAL] = { contents: Rope.ROPE _ ViewerTools.GetContents[n]; i: INT _ GetNumber[handle, contents]; IF ~ (i IN [0..CARDINAL.LAST]) THEN RESOut.Complain[h: handle, msg: "number out of range"]; RETURN [CARDINAL[i]]}; GetNumber: PUBLIC PROC [handle: Handle, contents: Rope.ROPE] RETURNS [v: INT _ 0] = { ENABLE SafeStorage.NarrowFault => GO TO bad; neg: BOOL _ FALSE; first: CARDINAL _ 0; IF Rope.Length[contents] = 0 THEN RETURN; FOR i: CARDINAL IN [0..CARDINAL[Rope.Length[contents]]) DO c: CHAR = Rope.Fetch[contents, i]; SELECT c FROM IN [IO.NUL..IO.SP] => NULL; '- => {neg _ TRUE; first _ i+1; EXIT}; ENDCASE => {first _ i; EXIT}; ENDLOOP; v _ Convert.CardFromWholeNumberLiteral[contents, first ! Convert.Error => { SELECT reason FROM $empty => RESOut.Complain[h: handle, msg: "number is blank."]; $syntax => RESOut.Complain[h: handle, msg: "number syntax error."]; $overflow => RESOut.Complain[h: handle, msg: "number overflowed."]; ENDCASE; -- above cases won't return (they raise cancelAction) GO TO bad}]; IF neg THEN v _ -v; EXITS bad => RETURN [0]; }; MakeTypescript: PROC [handle: Handle] = BEGIN v: ViewerClasses.Viewer; [handle.in, handle.out] _ ViewerIO.CreateViewerStreams [ name: "CDebug typescript", viewer: NIL, backingFile: NIL, editedStream: FALSE]; handle.ts _ ViewerIO.GetViewerFromStream[handle.out]; ViewerOps.AddProp[handle.ts, $cdebugHandle, handle]; handle.dying _ FALSE; [] _ ViewerEvents.RegisterEventProc[proc: DestroyTypescript, event: destroy, filter: v]; END; DestroyTypescript: ViewerEvents.EventProc = { h: Handle _ NARROW[ViewerOps.FetchProp[viewer, $cdebugHandle]]; IF before AND h # NIL AND h.ts = viewer AND ~h.dying THEN { MessageWindow.Append[message: "destroy command window instead", clearFirst: TRUE]; RETURN[TRUE]}; }; SetCell: PRIVATE PROC [handle: Handle, button: Menus.MouseButton, cell: ViewerClasses.Viewer, radix: CARDINAL] = { ENABLE RESOut.cancelAction => GO TO dont; SELECT button FROM blue => ViewerTools.SetSelection[cell]; red, yellow => { r: ROPE = ViewerTools.GetSelectionContents[]; i: INT = GetNumber[handle, r]; IF button = yellow THEN radix _ 8; ViewerTools.SetContents[cell, Convert.RopeFromInt[from: i, base: radix, showRadix: TRUE]]}; ENDCASE; EXITS dont => RETURN; }; SetTextCell: PRIVATE PROC [handle: Handle, button: Menus.MouseButton, cell: ViewerClasses.Viewer] = { ENABLE RESOut.cancelAction => GO TO dont; SELECT button FROM blue => ViewerTools.SetSelection[cell]; red => { r: ROPE = ViewerTools.GetSelectionContents[]; ViewerTools.SetContents[cell, r]}; ENDCASE; EXITS dont => RETURN; }; SimplePrompt: Buttons.ButtonProc = { ph: PromptHandle _ NARROW[clientData]; IF ph.radix = 0 THEN SetTextCell[ph.handle, mouseButton, ph.cell] ELSE SetCell[ph.handle, mouseButton, ph.cell, ph.radix]; }; GetSelectionValue: PUBLIC PROC [handle: Handle] RETURNS [UNSPECIFIED] = { r: ROPE = ViewerTools.GetSelectionContents[]; i: INT = GetNumber[handle, r]; IF ~(i IN [0..CARDINAL.LAST]) THEN RESOut.Complain[h: handle, msg: "Selected number too large"]; RETURN [CARDINAL[i]]}; GetLongSelectionValue: PUBLIC PROC [handle: Handle] RETURNS [INT] = { r: ROPE = ViewerTools.GetSelectionContents[]; RETURN [GetNumber[handle, r]]}; OtherCmd: Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { ENABLE RESOut.cancelAction, ABORTED => GO TO dont; ch: CmdHandle = NARROW[clientData]; IF ch.cmd = stop THEN ch.handle.stopFlag _ TRUE ELSE TRUSTED { ch.handle.stopFlag _ FALSE; CDebugDefs.DoCommand[ch.handle, ch.cmd, mouseButton]}; EXITS dont => RETURN; }; ToggleBool: Buttons.ButtonProc = { switch: REF BOOL _ NARROW [clientData]; switch^ _ ~switch^; Buttons.SetDisplayStyle[ button: NARROW[parent], style: IF switch^ THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; CycleOptions: Buttons.ButtonProc = { eh: EnumHandle _ NARROW [clientData]; next: CARDINAL; IF mouseButton = blue THEN { next _ IF eh.showing = 0 THEN eh.choices.count-1 ELSE eh.showing-1} ELSE { next _ IF eh.showing = eh.choices.count-1 THEN 0 ELSE eh.showing+1}; eh.eCell^ _ eh.choices[next].value; eh.showing _ next; ViewerTools.SetContents[eh.choice, eh.choices[next].tag]; }; TRUSTED { START STDebugDefs.STDebugMisc; START STDebugDefs.STDebugTrees; START STDebugDefs.STDebugSymbols}; Commander.Register[key: "CDebug", proc: MakeTool, doc: "Debugger for compiler internals"]; END. ®CDebugInterface.mesa Last Edited by: Sweet, February 11, 1986 11:25:16 am PST rule _ Rules.Create [[parent: my.outer, wy: my.height, ww: my.outer.cw, wh: 2]]; Containers.ChildXBound[my.outer, rule]; my.height _ my.height + 2; -- interline spacing [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE] gFramesPlace: Place = [x: BodyCol+0, y: 3]; -- default the width so that it will be computed for us -- default the width so that it will be computed for us MakeCmd[at: gFramesPlace, name: "GFrames", cmd: gFrames]; [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE] Ê©˜Icodešœ™K™8K˜šÏk ˜ Kšœœ/˜Kšœœ˜&Kšœœ ˜Kšœ œ ˜2Kšœ œ,˜:Kšœ œA˜PKšœ œS˜d—šœ œ˜šœ˜Kšœ²˜²—Kšœ ˜Kš˜Kšœ ˜K˜Kšœ œÏc&˜BKšœ œž'˜CKšœ œž/˜KKšœœœ˜K˜Kšœ œœ@œ˜aKšœœœ ˜#Kšœœœ7˜LKšœ œœ˜K˜Kš œ œœœ œ˜8Kšœœœ œž.˜LKš œœœœœœ ˜EKšœ œœ˜'Kšœ œœZœ˜‡Kšœ œœ ˜K˜šÏnœ˜'Kšœ˜Kšœ œ ˜Kšœž˜9šœžœ˜>Kšœž ˜9Kšœœž*˜9Kšœž˜-Kšœœ˜Kšœ œœž'˜=—˜Kšœœ˜ K˜K˜K˜Kšœœ˜—Kšœ+ž˜?Kšœ)˜)KšœP˜PKšœ'˜'Kšœ˜KšœP™PKšœ'™'Kšœž™/K˜K˜/K˜CKšœ3˜3KšœY˜YKšœ˜Kšœ˜K˜—•StartOfExpansiono -- [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE]šœ'˜'KšÐckk™kšœœ˜Kšœ œ-˜?Kš œœœœœ˜+Kšœ œ˜K˜—K˜K˜—˜"Kšœœœœ˜&Kšœ œ˜Kšœœ˜Kšœœ˜Kšœ œ ˜Kšœ œ˜"Kšœ œ˜"Kšœœ˜K˜K˜(K˜)K˜)K˜(K˜K˜&K˜K˜%K˜%K˜%K˜%K˜%K˜(K˜(K˜K˜'K˜)K˜(K˜,K˜)K˜'K˜(K˜&K˜K˜)K˜(K˜)K˜(K˜)K˜)K˜*K˜)K˜K˜K˜&K˜&Kšœ&˜&Kšœ&˜&K˜K˜(K˜(K˜(K™+K˜K˜—K˜šŸ œœœ˜,Kšœœ˜(Kšœœ˜K˜šŸœœœ˜Cšœ˜šœ˜Kšœ˜Kšœ˜Kšœ.˜.Kšœ7™7Kšœž4˜EKšœ˜Kšœœ˜—Kšœ˜Kšœ œ(˜7—Kšœœ ˜šœ˜K˜——šŸœœœ œœœœ˜RKšœ˜Kšœœœ ˜šœ˜šœ˜Kšœ ˜ Kšœ˜Kšœ.˜.Kšœ7™7Kšœž4˜EKšœ˜Kšœœ˜—Kšœ˜Kšœ˜—šœ˜Kšœ ˜ Kšœœ œœ˜9—Kšœœ ˜šœ˜K˜——šŸ œœœ œ œœ œ˜]Kšœ˜%Kšœœ2œ˜NKšœœ˜šœ#˜#šœ˜Kšœ˜Kšœ ˜ Kšœ.˜.Kšœ˜Kšœ˜Kšœœ˜—Kšœ˜Kšœ˜—Kšœ˜šœ"˜"šœ˜K˜ Kšœ2˜2Kšœ˜Kšœ˜Kšœ˜K˜Kšœ œ˜Kšœœ˜——K˜ Kšœœ ˜šœ˜K˜——šŸœœœ!œ˜SKšœ˜KšœœMœ œ˜uKšœœ˜Kšœ˜Kšœœ˜šœ#˜#šœ˜Kšœ˜Kšœ ˜ Kšœ.˜.Kšœ˜Kšœ˜Kšœœ˜—Kšœ˜Kšœ˜—šœœœ˜(Kšœœ,˜7Kšœ˜—Kšœ˜Kšœ˜šœ"˜"šœ˜K˜ Kšœ2˜2Kšœ˜Kšœ˜Kšœ˜K˜Kšœ œ˜Kšœœ˜——K˜Kšœ!˜!Kšœœ ˜Kšœ˜K˜—Kšœœ˜/K˜CK˜A˜@K˜—K˜0K˜.K˜-K˜3KšœCœ˜JK˜ZK˜0K˜K˜3K˜-K˜0K˜-K˜0K˜0KšœG˜GK˜K˜0K˜7K˜1K˜-K˜0K˜*K˜-K˜-K˜K˜,K˜,K˜,K˜,K˜,K˜2K˜K˜-K˜-K˜-K˜K˜0K˜0K˜0K™9K˜K˜6Kšœ=˜=Kšœ˜—K˜šŸœ œ!œœ˜FKšœœ˜1Kšœ ˜&K˜—šŸœ œ!œœ˜LKšœœ˜1Kšœœ˜%š œœœœœ˜$Kšœ7˜7—Kšœœ˜K˜—š Ÿ œ œ!œœœ ˜UKšœœœ˜,Kšœœœ˜Kšœœ˜Kšœœœ˜)š œœœœ˜:Kšœœ˜"šœ˜Kš œœœœœœ˜Kšœ œœ˜&Kšœœ˜—Kšœ˜—šœ8˜8šœ˜šœ˜Kšœ?˜?KšœC˜CKšœC˜CKšœž5˜>—Kšœœ˜ ——Kšœœ˜š˜Kšœœ˜—K˜K˜—šŸœœœ˜.K˜šœ8˜8Kšœ#œœœ˜O—Kšœ5˜5Kšœ4˜4Kšœœ˜KšœX˜XKšœ˜K˜—–o -- [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE]šœ-˜-Kš k™kKšœ œ-˜?š œœœœœ œ˜;KšœLœ˜RKšœœ˜—K˜K˜—šŸœœœPœ˜rKšœœœ˜)šœ˜K˜(˜Kšœœ&˜-Kšœœ˜Kšœœ ˜"KšœSœ˜[—Kšœ˜—š˜Kšœœ˜—Kšœ˜K˜—šŸ œœœL˜eKšœœœ˜)šœ˜K˜(˜Kšœœ&˜-Kšœ"˜"—Kšœ˜—š˜Kšœœ˜—Kšœ˜K˜—–† -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- šŸ œ œ˜%Kšœœ ˜&Kšœœ-˜AKšœ4˜8K˜K˜—šŸœ œœ œ˜IKšœœ&˜-Kšœœ˜š œœœœœ˜#Kšœ=˜=—Kšœœ˜K˜—šŸœ œœœ˜FKšœœ&˜-Kšœ˜K˜—–† -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- šŸœ †œ˜¦Kšœœœœ˜2Kšœœ ˜#Kšœœ˜/šœœ˜Kšœœ˜Kšœ6˜6—š˜Kšœœ˜—Kšœ˜K˜—šŸ œ œ˜#Kšœœœœ˜(K˜Kš œ"œœ œœ˜mK˜K˜—šŸ œ œ˜%Kšœœ˜&Kšœ ˜šœœ˜Kšœœœœ˜C—šœ˜Kšœœ!œœ˜D—K˜#K˜Kšœ9˜9K˜K˜—šœ˜ Kšœ˜Kšœ˜Kšœ˜"—K˜KšœZ˜ZKšœ˜K™——…—9bL¹