DIRECTORY Trc, TrcViewers, Abutters USING [Create, QuaViewer, vanilla], Allocator USING [bsiEscape, EHeaderP, ExtendedHeader, NHeaderP, NormalHeader], AllocatorOps USING [bsiToSize, NewObject, REFToNHP], Atom USING [GetPName], Draw2d USING [Line], Imager USING [DoSaveAll, --MaskVector,-- Rectangle, Scale2T, SetStrokeEnd, SetStrokeJoint, SetStrokeWidth, TranslateT], IO USING [GetAtom, PutF, STREAM], PrincOpsUtils USING [LongCopy], Process USING [Detach, priorityBackground, SetPriority, Yield], Real USING [RoundC], RedBlackTree, RefTab USING [Create, Delete, EachPairAction, GetSize, Pairs, Ref, Store], Rope USING [Compare, Concat], RTTypesBasicPrivate USING [MapRefOffsets], SafeStorage USING [GetReferentType], TIPUser USING [TIPScreenCoords], Vector2 USING [VEC], ViewerClasses USING [DestroyProc, ModifyProc, NotifyProc, PaintProc, SaveProc, Viewer, ViewerClass, ViewerClassRec], ViewerOps USING [AddProp, CreateViewer, FetchProp, PaintViewer, RegisterViewerClass], VM USING [WordsForPages]; TrcImpl: CEDAR MONITOR IMPORTS Abutters, AllocatorOps, Atom, Draw2d, Imager, IO, PrincOpsUtils, Process, Real, RedBlackTree, RefTab, Rope, RTTypesBasicPrivate, SafeStorage, Trc, ViewerOps, VM EXPORTS Trc, TrcViewers ~ BEGIN OPEN Trc; STREAM: TYPE ~ IO.STREAM; GetClass: RedBlackTree.GetKey = { RETURN [NARROW[data, Class].flavor]; }; CompareClasses: RedBlackTree.Compare = { RETURN [Rope.Compare[ s1: Atom.GetPName[NARROW[k, ATOM]], s2: Atom.GetPName[NARROW[data, Class].flavor], case: FALSE ]]; }; classes: RedBlackTree.Table ~ RedBlackTree.Create[getKey: GetClass, compare: CompareClasses]; RegisterClass: PUBLIC PROC [class: Class] ~ { RedBlackTree.Insert[self: classes, dataToInsert: class, insertKey: class.flavor]; }; EnumerateRegisteredClasses: PUBLIC PROC [proc: ClassEnumProc] ~ { EachClass: RedBlackTree.EachNode = { stop _ proc[NARROW[data]]; }; RedBlackTree.EnumerateIncreasing[self: classes, procToApply: EachClass] }; PickleArbitraryTrc: PUBLIC PROC [trc: TRC, stream: STREAM, indentation: ROPE _ NIL] ~ { IO.PutF[stream: stream, format: "\n%g%g\t", v1: [rope[indentation]], v2: [atom[trc.class.flavor]]]; Trc.Pickle[trc: trc, stream: stream, indentation: Rope.Concat[indentation, "\t"]]; }; DepickleArbitraryTrc: PUBLIC PROC [stream: STREAM] RETURNS [trc: TRC] ~ { flavor: ATOM ~ IO.GetAtom[stream: stream]; class: Trc.Class ~ Trc.ClassFromFlavor[flavor: flavor]; trc _ Trc.Depickle[class: class, stream: stream]; }; DefaultBlockFcn: PUBLIC BlockFcn ~ UNCHECKED { FOR k: NAT IN [0..count) DO to[k] _ trc.class.fcn[trc, from[k]]; ENDLOOP; }; DefaultCopy: PUBLIC CopyProc = { new _ NEW[TRCRep _ [class: trc.class, instance: NewRef[trc.instance], listener: NIL]]; }; DefaultPickle: PUBLIC PickleProc ~ {}; DefaultDepickle: PUBLIC DepickleProc ~ { RETURN [NEW[TRCRep _ [class: class, instance: NIL]]] }; DefaultNotify: PUBLIC NotifyProc ~ {}; DefaultBackground: PUBLIC BackgroundProc ~ {}; DefaultControl: PUBLIC BuildControlViewerProc = { viewer _ Abutters.Create[viewerFlavor: Abutters.vanilla, info: info, paint: paint].QuaViewer[]; }; NewRef: PROC [old: REF] RETURNS [new: REF] ~ TRUSTED { UsableWords: UNSAFE PROC [ref: REF] RETURNS [size: INT] ~ UNCHECKED { OPEN Allocator; ExtendedBlockSize: UNSAFE PROC [ehp: EHeaderP] RETURNS [words: INT _ 0] = UNCHECKED INLINE { SELECT ehp.sizeTag FROM words => words _ ehp.extendedSize; pages => words _ VM.WordsForPages[ehp.extendedSize]; ENDCASE => ERROR; }; NHPToEHP: UNSAFE PROC [nhp: NHeaderP] RETURNS [EHeaderP] = INLINE { RETURN [LOOPHOLE[nhp - (SIZE[ExtendedHeader] - SIZE[NormalHeader]), EHeaderP]]; }; nhp: NHeaderP ~ AllocatorOps.REFToNHP[ref]; IF nhp.blockSizeIndex # Allocator.bsiEscape THEN RETURN [AllocatorOps.bsiToSize[nhp.blockSizeIndex] - SIZE[NormalHeader]] ELSE RETURN [ExtendedBlockSize[NHPToEHP[nhp]] - SIZE[ExtendedHeader]]; }; EachContainedRef: UNSAFE PROC [offset: LONG CARDINAL] ~ { newP: LONG POINTER = LOOPHOLE[new, LONG POINTER] + offset; oldP: LONG POINTER TO REF = LOOPHOLE[old, LONG POINTER] + offset; r: REF = oldP^; LOOPHOLE[newP, LONG POINTER TO LONG POINTER]^ _ NIL; LOOPHOLE[newP, REF REF ANY]^ _ r; }; IF old=NIL THEN RETURN [NIL] ELSE { count: CARDINAL ~ UsableWords[old]; new _ AllocatorOps.NewObject[type: SafeStorage.GetReferentType[old], size: count]; PrincOpsUtils.LongCopy[from: LOOPHOLE[old], nwords: count, to: LOOPHOLE[new]]; RTTypesBasicPrivate.MapRefOffsets[ref: old, procLeaf: EachContainedRef]; --Copy the contained REFs by hand to maintain proper reference counts }; }; ClassFromFlavor: PUBLIC PROC [flavor: ATOM] RETURNS [class: Class] ~ { RETURN [NARROW[RedBlackTree.Lookup[self: classes, lookupKey: flavor]]]; }; Registration: TYPE ~ RECORD [trc: TRC, listener: Listener]; InstallListener: PUBLIC PROC [trc: TRC, listener: Listener] RETURNS [registration: REF] ~ { trc.listener _ CONS[listener, trc.listener]; RETURN [NEW[Registration _ [trc, listener]]]; }; DeinstallListener: PUBLIC PROC [registration: REF] ~ { reg: REF Registration ~ NARROW[registration]; new: LIST OF Listener _ NIL; FOR each: LIST OF Listener _ reg.trc.listener, each.rest UNTIL each=NIL DO IF each.first#reg.listener THEN new _ CONS[each.first, new]; ENDLOOP; reg.trc.listener _ new; }; NotifyListeners: PUBLIC PROC [trc: TRC, fork: BOOL _ FALSE] ~ { FOR each: LIST OF Listener _ trc.listener, each.rest UNTIL each=NIL DO IF fork THEN TRUSTED { Process.Detach[FORK each.first.proc[trc: trc, listenerData: each.first.listenerData]]; } ELSE { each.first.proc[trc: trc, listenerData: each.first.listenerData]; }; ENDLOOP; }; BuildTable: PUBLIC PROC [nElements: NAT, first, delta: REAL] RETURNS [table: Table] ~ { table _ NEW[TableRep[nElements]]; FOR k: NAT IN [0..nElements) DO table[k] _ first + delta*k; ENDLOOP; }; UnsafeTableFromTable: PUBLIC PROC [table: Table, start, count: NAT _ 0] RETURNS [unsafeTable: UnsafeTable] ~ TRUSTED { IF count=0 THEN count _ table.n-start; IF start+count > table.n THEN ERROR; RETURN [LOOPHOLE[@table[start]]]; }; Display: TYPE ~ REF DisplayRep; DisplayRep: TYPE ~ RECORD [ trc: TRC, rectangle: Imager.Rectangle, dx: REAL, listenerRegistration: REF, clientData: REF ]; CreateTRCViewer: PUBLIC PROC [trc: TRC, rectangle: Rectangle, dx: REAL, info: ViewerRec, paint: BOOL _ TRUE] RETURNS [viewer: Viewer] ~ { display: Display ~ NEW[DisplayRep _ [ trc: trc, rectangle: rectangle, dx: dx, clientData: info.data ]]; info.data _ display; info.scrollable _ info.hscrollable _ FALSE; IF info.tipTable=NIL THEN info.tipTable _ trc.class.tipTable; viewer _ ViewerOps.CreateViewer[flavor: $Trc, info: info, paint: paint]; ViewerOps.AddProp[viewer: viewer, prop: $DeferIfCPUAbove, val: Trc.FetchProp[viewer: viewer, prop: $DeferIfCPUAbove]]; --If some ancestor viewer of ours (obviously not a trc viewer itself, has a $DeferIfCPUAbove hanging on it, we want to hang it here, so that at paint time, we don't have to go looking all over for it... IF trc.class.tipTable#NIL THEN viewer.tipTable _ trc.class.tipTable; display.listenerRegistration _ InstallListener[trc: trc, listener: [proc: TrcViewerListener, listenerData: viewer]]; IF paint THEN ViewerOps.PaintViewer[viewer: viewer, hint: all]; }; NewTrc: PUBLIC PROC [viewer: Viewer, trc: TRC, paint: BOOL _ TRUE] ~ { display: Display ~ NARROW[viewer.data]; Trc.DeinstallListener[display.listenerRegistration]; display.trc _ trc; display.listenerRegistration _ InstallListener[trc: trc, listener: [proc: TrcViewerListener, listenerData: viewer]]; IF paint THEN ViewerOps.PaintViewer[viewer: viewer, hint: all]; viewer.tipTable _ trc.class.tipTable; }; InfoFromTRCViewer: PUBLIC PROC [viewer: Viewer] RETURNS [trc: TRC, rectangle: Rectangle, dx: REAL, clientData: REF] ~ { display: Display ~ NARROW[viewer.data]; RETURN [trc: display.trc, rectangle: display.rectangle, dx: display.dx, clientData: display.clientData] }; ResetTRCViewer: PUBLIC PROC [viewer: Viewer, rectangle: Rectangle, dx: REAL, clientData: REF] ~ { display: Display ~ NARROW[viewer.data]; display^ _ [trc: display.trc, rectangle: rectangle, dx: dx, clientData: clientData]; }; VecFromTIPCoords: PUBLIC PROC [viewer: Viewer, coords: TIPUser.TIPScreenCoords] RETURNS [vec: Vector2.VEC] ~ { display: Display ~ NARROW[viewer.data]; RETURN [ Vector2.VEC [x: display.rectangle.x+display.rectangle.w*coords.mouseX/viewer.cw, y: display.rectangle.y+display.rectangle.h*coords.mouseY/viewer.ch]]; }; FetchProp: PUBLIC PROC [viewer: Viewer, prop: ATOM] RETURNS [val: REF ANY] ~ { FOR v: Viewer _ viewer, v.parent UNTIL v=NIL DO val _ ViewerOps.FetchProp[viewer: v, prop: prop]; IF val#NIL THEN WITH val SELECT FROM eval: PropEvaluator => RETURN [eval.proc[viewer, prop, eval.data]]; ENDCASE => RETURN [val]; ENDLOOP; RETURN [NIL]; }; TrcViewerListener: ENTRY ListenerProc = { ENABLE UNWIND => NULL; [] _ RefTab.Store[x: toPaint, key: listenerData, val: NIL]; NOTIFY timeToPaint; }; toPaint: RefTab.Ref ~ RefTab.Create[]; timeToPaint: CONDITION; PaintTrcViewers: ENTRY PROC ~ TRUSTED { --A process runs this proc in background ENABLE UNWIND => NULL; Process.SetPriority[Process.priorityBackground]; DO PaintAndRemoveFromTable: RefTab.EachPairAction = TRUSTED { Process.Yield[]; [] _ RefTab.Delete[x: toPaint, key: key]; ViewerOps.PaintViewer[viewer: NARROW[key, Viewer], hint: client]; RETURN [FALSE]; }; UNTIL RefTab.GetSize[x: toPaint] > 0 DO WAIT timeToPaint; ENDLOOP; [] _ RefTab.Pairs[x: toPaint, action: PaintAndRemoveFromTable]; ENDLOOP; }; TrcNotify: ViewerClasses.NotifyProc = { display: Display ~ NARROW[self.data]; display.trc.class.notify[viewer: self, trc: display.trc, input: input]; }; TrcPaint: ViewerClasses.PaintProc = { PaintBackground: PROC ~ { Trc.PaintBackground[trc: display.trc, context: context, rectangle: display.rectangle, whatChanged: whatChanged]; }; display: Display ~ NARROW[self.data]; Imager.Scale2T[context: context, s: [x: self.cw/display.rectangle.w, y: self.ch/display.rectangle.h]]; Imager.TranslateT[context: context, t: [x: display.rectangle.x, y: display.rectangle.y]]; Imager.SetStrokeEnd[context: context, strokeEnd: butt]; Imager.SetStrokeJoint[context: context, strokeJoint: mitered]; Imager.SetStrokeWidth[context: context, strokeWidth: 2*display.rectangle.w/self.cw]; Imager.DoSaveAll[context: context, action: PaintBackground]; Imager.SetStrokeWidth[context: context, strokeWidth: --2*display.rectangle.w/self.cw-- 0.0]; IF whatChanged=NIL THEN TRUSTED { --Actually paint the trc itself... nElements: NAT ~ 1+MIN[self.cw, Real.RoundC[display.rectangle.w/display.dx]]; delta: REAL ~ display.rectangle.w/nElements; from: Table ~ BuildTable[nElements: nElements, first: display.rectangle.x, delta: delta]; to: Table ~ NEW[TableRep[nElements]]; last, this: VEC; from[nElements-1] _ display.rectangle.x + display.rectangle.w; ApplyBlockFcn[trc: display.trc, from: UnsafeTableFromTable[from], to: UnsafeTableFromTable[to], count: nElements]; last _ [x: from[0], y: to[0]]; FOR k: NAT IN [1..nElements) DO Draw2d.Line[context: context, vec0: last, vec1: this _ [x: from[k], y: to[k]]]; last _ this; ENDLOOP; }; }; TrcModify: ViewerClasses.ModifyProc = { }; TrcDestroy: ViewerClasses.DestroyProc = { display: Display ~ NARROW[self.data]; DeinstallListener[registration: display.listenerRegistration]; display.trc _ NIL }; TrcSave: ViewerClasses.SaveProc = { }; trcViewerClass: ViewerClasses.ViewerClass ~ NEW[ViewerClasses.ViewerClassRec _ [ flavor: $Trc, notify: TrcNotify, paint: TrcPaint, modify: TrcModify, destroy: TrcDestroy, save: TrcSave, cursor: crossHairsCircle, icon: private ]]; ViewerOps.RegisterViewerClass[flavor: $Trc, class: trcViewerClass]; TRUSTED {Process.Detach[FORK PaintTrcViewers[]]}; END. ΖTrcImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Eric Nickell, January 14, 1987 8:27:37 am PST [data: RedBlackTree.UserData] RETURNS [RedBlackTree.Key] [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison] [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] classes: RefTab.Ref ~ RefTab.Create[]; RegisterClass: PUBLIC PROC [class: Class] ~ { [] _ RefTab.Store[x: classes, key: class.flavor, val: class]; }; EnumerateRegisteredClasses: PUBLIC PROC [proc: ClassEnumProc] ~ { EnumClasses: RefTab.EachPairAction = { [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] RETURN [proc[NARROW[val, Class]]]; }; [] _ RefTab.Pairs[x: classes, action: EnumClasses]; }; [trc: TRC] RETURNS [new: TRC] [trc: TRC, info: ViewerClasses.ViewerRec] RETURNS [viewer: ViewerClasses.Viewer] this ref will be in both newP^ and oldP^ NIL the destination to force the following AssignRef to increment the ref force AssignRef by faking out the compiler ClassFromFlavor: PUBLIC PROC [flavor: ATOM] RETURNS [class: Class] ~ { RETURN [NARROW[RefTab.Fetch[x: classes, key: flavor].val]]; }; Blechh!!! [trc: TRC, listenerData: REF ANY] [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] Process.Detach[FORK ViewerOps.PaintViewer[viewer: NARROW[key, Viewer], hint: client]]; [self: ViewerClasses.Viewer, input: LIST OF REF ANY] [self: ViewerClasses.Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL] RETURNS [quit: BOOL _ FALSE] Imager.MaskVector[context: context, p1: last, p2: this _ [x: from[k], y: to[k]]]; [self: ViewerClasses.Viewer, change: ViewerClasses.ModifyAction] Body [self: ViewerClasses.Viewer] [self: ViewerClasses.Viewer, force: BOOL _ FALSE] Body ΚJ˜™ Icodešœ Οmœ1™˜JKšœžœ˜Kšœžœ˜*Kšœ žœ˜$Kšœžœ˜ Kšœžœžœ˜Kšœžœa˜tKšœ žœF˜UKšžœžœ˜K˜—K˜KšΠlnœž ˜Kšžœ/žœnž˜¨Kšžœ˜Kšœž˜šžœ˜ K˜Icode2•StartOfExpansion#[mod: RefTab.SeqIndex _ 21B (17)]šžœžœžœžœ˜–< -- [data: RedBlackTree.UserData] RETURNS [RedBlackTree.Key]˜!LšΠck8™8Kšžœžœ˜$L˜—–R -- [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison]˜(Lš‘N™N–-[s1: ROPE, s2: ROPE, case: BOOL _ TRUE]šžœ˜Kšœžœžœ˜#Kšœžœ˜.Kšœž˜ Kšœ˜—L˜—L˜]šΟn œž œ˜-K–b[self: RedBlackTree.Table, dataToInsert: RedBlackTree.UserData, insertKey: RedBlackTree.Key]šœQ˜QK˜—š’œž œ˜A–> -- [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE]˜$Kš‘:™:Kšœ žœ˜K˜—K˜GK˜—L™&š’ œž œ™-K–7[x: RefTab.Ref, key: RefTab.Key, val: RefTab.Val]™=K™—š’œž œ™A–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœ&™&Kš‘:™:Kšžœžœ™"K™—K™3K™—š’œžœžœžœ žœžœžœ˜WKšžœa˜cKšœR˜RK˜—š ’œž œ žœžœžœ˜IKšœžœžœ˜*K–[flavor: ATOM]˜7K˜1K˜—š’œžœ ž œ˜.šžœžœžœ ž˜K˜$Kšžœ˜—Kšœ˜—–! -- [trc: TRC] RETURNS [new: TRC]š’ œžœ ˜ Kš‘™KšœžœGžœ˜VK˜—Kš’ œžœ˜&š’œžœ˜(Kšžœžœ#žœ˜4Kšœ˜—Kš’ œžœ˜&Kš’œžœ˜.–T -- [trc: TRC, info: ViewerClasses.ViewerRec] RETURNS [viewer: ViewerClasses.Viewer]š’œžœ˜1Kš‘P™PK–™[info: ViewerClasses.ViewerRec _ [class: NIL, wx: 0, wy: 0, ww: 0, wh: 0, cx: 0, cy: 0, cw: 0, ch: 0, lock: [process: PROCESS#0B, count: 0B (0)], tipTable: NIL, name: NIL, file: NIL, label: NIL, menu: NIL, icon: 177777B?, column: left, caption: FALSE, scrollable: TRUE, hscrollable: FALSE, iconic: TRUE, border: TRUE, newVersion: FALSE, newFile: FALSE, visible: TRUE, offDeskTop: FALSE, destroyed: FALSE, init: FALSE, saveInProgress: FALSE, inhibitDestroy: FALSE, guardDestroy: FALSE, paintingWedged: FALSE, ...], paint: BOOL _ TRUE]šœ_˜_K˜—š ’œžœžœžœžœžœ˜6š’ œžœžœžœžœžœž œ˜EKšžœ ˜š’œžœžœžœ žœž œžœ˜\šžœ ž˜Kšœ#˜#Kšœžœ!˜4Kšžœžœ˜—Kšœ˜—š ’œžœžœžœžœ˜CKšžœžœžœžœ˜OK˜—K˜+šžœ)˜+Kšžœžœ/žœ˜MKšžœžœ%žœ˜F—K˜—š ’œžœžœ žœžœ˜9Kš œžœžœžœžœžœ ˜:Kšœžœžœžœžœžœžœžœ ˜Ašœžœ ˜K™(—šžœžœžœžœžœžœžœ˜4K™I—šžœžœžœžœ˜!K™*—K˜—š žœžœžœžœžœžœ˜#Kšœžœ˜#K–[ref: REF ANY]˜RKšœžœžœ˜NK–([ref: REF ANY, procLeaf: PROC [...]]šœIŸE˜ŽKšœ˜—K˜—š’œž œ žœžœ™FK–$[x: RefTab.Ref, key: RefTab.Key]šžœžœ-™;K™—š’œž œ žœžœ˜FK–;[self: RedBlackTree.Table, lookupKey: RedBlackTree.Key]šžœžœ9˜GK˜—Lšœžœžœžœ˜;š ’œž œžœžœžœ˜[Kšœžœ˜,Kšžœžœ"˜-K˜—š’œž œžœ˜6K™ Kšœžœžœ˜-Kšœžœžœ žœ˜š žœžœžœ(žœžœž˜JKšžœžœžœ˜[viewer: ViewerClasses.Viewer, prop: ATOM, val: REF ANY]šœwŸΚ˜ΑKšžœžœžœ&˜DK–&[trc: TRC, listener: Trc.Listener]šœt˜tK–w[viewer: ViewerClasses.Viewer, hint: ViewerOps.PaintHint, clearClient: BOOL _ TRUE, whatChanged: REF ANY _ NIL]šžœžœ2˜?K˜—š ’œž œžœ žœžœ˜FKšœžœ˜'Kšœ4˜4K˜Kšœt˜tK–w[viewer: ViewerClasses.Viewer, hint: ViewerOps.PaintHint, clearClient: BOOL _ TRUE, whatChanged: REF ANY _ NIL]šžœžœ2˜?K˜%K˜—–% -- [trc: TRC, listenerData: REF ANY]š’œžœžœžœžœžœžœ˜wKšœžœ˜'Kšžœa˜gK˜—š ’œžœžœ,žœžœ˜aKšœžœ˜'KšœT˜TK˜—š’œž œ3žœžœ˜nKšœžœ˜'Kšžœ žœ‹˜ŸK˜—K˜š ’ œž œžœžœžœžœ˜Nšžœžœžœž˜/K–.[viewer: ViewerClasses.Viewer, prop: ATOM]˜1š žœžœžœžœžœž˜$Kšœžœ&˜CKšžœžœ˜—Kšžœ˜—Kšžœžœ˜ K˜—š’œžœ˜)Lš‘!™!L–w[viewer: ViewerClasses.Viewer, hint: ViewerOps.PaintHint, clearClient: BOOL _ TRUE, whatChanged: REF ANY _ NIL]šžœžœžœ˜L–7[x: RefTab.Ref, key: RefTab.Key, val: RefTab.Val]šœ6žœ˜;Lšžœ ˜L˜—Kšœ&˜&Kšœ ž œ˜š ’œžœžœžœŸ(˜PKšžœžœžœ˜K˜0–[x: RefTab.Ref]šž˜–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]š’œžœ˜:Kš‘:™:K–$[x: RefTab.Ref, key: RefTab.Key]˜K˜)K–w[viewer: ViewerClasses.Viewer, hint: ViewerOps.PaintHint, clearClient: BOOL _ TRUE, whatChanged: REF ANY _ NIL]šœžœžœ™VKšœžœ˜AKšžœžœ˜K˜—šžœ ž˜'Kšžœ ˜Kšžœ˜—K–2[x: RefTab.Ref, action: RefTab.EachPairAction]˜?Kšžœ˜—K˜—˜'Kš‘4™4Kšœžœ ˜%K˜GK˜—K–#[mod: RefTab.SeqIndex _ 21B (17)]˜˜%Kš‘u™u–%[context: Imager.Context, s: VEC]š’œžœ˜K˜pK˜—Kšœžœ ˜%Kšœf˜fK–%[context: Imager.Context, t: VEC]šœY˜YK–:[context: Imager.Context, strokeEnd: Imager.StrokeEnd]˜7K–>[context: Imager.Context, strokeJoint: Imager.StrokeJoint]˜>K–0[context: Imager.Context, strokeWidth: REAL]šœT˜TK–+[context: Imager.Context, action: PROC]˜K˜rK˜šžœžœžœž˜K–1[context: Imager.Context, p1: VEC, p2: VEC]šœQ™QK–Z[context: Imager.Context, vec0: VEC, vec1: VEC, drawType: Draw2d.DrawType _ solid]šœO˜OK˜ Kšžœ˜—K˜Kšœ˜—K˜—–D -- [self: ViewerClasses.Viewer, change: ViewerClasses.ModifyAction]˜'Kš‘@™@K™K˜—– -- [self: ViewerClasses.Viewer]˜)Kš‘™Kšœžœ ˜%K–[registration: REF ANY]šœ>˜>Kšœž˜K˜—–5 -- [self: ViewerClasses.Viewer, force: BOOL _ FALSE]˜#Kš‘1™1K™K˜—šœ,žœ!˜PK˜ K˜K˜K˜K˜K˜K˜K˜ K˜—K˜K–J[flavor: ViewerClasses.ViewerFlavor, class: ViewerClasses.ViewerClass]˜CKšžœžœΟtœ˜1—K˜Kšžœ˜—…—-BOR