DIRECTORY Abutters, Buttons USING [ButtonProc, Create], Convert USING [RealFromRope], Imager USING [MaskVector, SetStrokeWidth], ImagerBackdoor USING [GetReal], IO, Real USING [CompareREAL], RedBlackTree, --using lots... Rope USING [Equal, ROPE], Trc, Vector2 USING [InlineAdd, Length, Sub, VEC], ViewerClasses USING [Viewer, ViewerRec], ViewerOps, ViewerTools; TrcManualImpl: CEDAR PROGRAM IMPORTS Abutters, Buttons, Convert, Imager, ImagerBackdoor, IO, Real, RedBlackTree, Rope, Trc, Vector2, ViewerOps, ViewerTools ~ BEGIN ROPE: TYPE ~ Rope.ROPE; VEC: TYPE ~ Vector2.VEC; margin: NAT ~ 10; ManualInstance: TYPE ~ REF ManualInstanceRep; ManualInstanceRep: TYPE ~ RECORD [ xScale, yScale: REAL _ 1.0, pins: RedBlackTree.Table _ RedBlackTree.Create[getKey: TrcManualGet, compare: TrcManualCompare] ]; Pin: TYPE ~ REF PinRep; PinRep: TYPE ~ RECORD [ vec: Vector2.VEC ]; ManualControlData: TYPE ~ REF ManualControlDataRep; ManualControlDataRep: TYPE ~ RECORD [ container, childControl: ViewerClasses.Viewer _ NIL, trc: Trc.TRC _ NIL, y: INTEGER ]; ManualFcn: Trc.Fcn = { VecFromRef: PROC [ref: REF] RETURNS [vec: VEC] ~ { WITH ref SELECT FROM p: Pin => RETURN [p^]; --This will return NIL as well ENDCASE => ERROR; }; instance: ManualInstance ~ NARROW[trc.instance]; left, equal, right: REF; [left, equal, right] _ RedBlackTree.Lookup3[self: instance.pins, lookupKey: RealToRef[a]]; SELECT TRUE FROM equal#NIL => RETURN [VecFromRef[equal].y]; left=NIL AND right=NIL => RETURN [a]; left=NIL => RETURN [NARROW[right, Pin].y]; right=NIL => RETURN [NARROW[left, Pin].y] ENDCASE => { --We're between two pins, at least one of which is a fixed Pin. vLeft: VEC ~ VecFromRef[left]; vRight: VEC ~ VecFromRef[right]; alpha: REAL ~ (a-vLeft.x)/(vRight.x-vLeft.x); RETURN [(alpha*(vRight.y) + (1.0-alpha)*(vLeft.y))] }; }; ManualBackground: Trc.BackgroundProc = { Mark: PROC [vec: VEC] ~ INLINE { Imager.MaskVector[context: context, p1: vec.InlineAdd[[-d,-d]], p2: vec.InlineAdd[[d,d]]]; Imager.MaskVector[context: context, p1: vec.InlineAdd[[d,-d]], p2: vec.InlineAdd[[-d,d]]]; }; instance: ManualInstance ~ NARROW[trc.instance]; w: REAL ~ ImagerBackdoor.GetReal[context: context, key: strokeWidth]; d: REAL ~ 3*w; Imager.SetStrokeWidth[context: context, strokeWidth: w/2]; IF whatChanged=NIL THEN { XMarksTheSpot: RedBlackTree.EachNode = { WITH data SELECT FROM pin: Pin => Mark[pin^]; ENDCASE => ERROR; }; RedBlackTree.EnumerateIncreasing[self: instance.pins, procToApply: XMarksTheSpot]; } ELSE { WITH whatChanged SELECT FROM atom: ATOM => NULL; --Somebody has us layered ENDCASE => ERROR; }; }; ManualPickle: Trc.PickleProc = { instance: ManualInstance ~ NARROW[trc.instance]; IO.PutRope[self: stream, r: " {"]; PutValuesToStream[instance, stream, indentation]; IO.PutF[stream: stream, format: "\n%g}", v1: [rope[indentation]]]; }; ManualDepickle: Trc.DepickleProc = { instance: ManualInstance ~ NEW[ManualInstanceRep]; token: ROPE; trc _ NEW[Trc.TRCRep _ [class: class, instance: instance, listener: NIL]]; IF ~IO.GetCedarTokenRope[stream: stream].token.Equal["{"] THEN ERROR; token _ ParseManualInstance[instance, stream]; IF ~Rope.Equal[token, "}"] THEN ERROR; }; ManualControl: Trc.BuildControlViewerProc = { text, button: ViewerClasses.Viewer; instance: ManualInstance; IF trc.instance=NIL THEN { --Need to instantiate viewer trc.instance _ instance _ NEW[ManualInstanceRep]; } ELSE instance _ NARROW[trc.instance]; viewer _ Abutters.Create[viewerFlavor: Abutters.vanilla, info: info, paint: paint].QuaViewer; text _ ViewerTools.MakeNewTextViewer[info: [parent: viewer, wx: 5, wy: 25, wh: 200, ww: 200], paint: FALSE]; { contents: IO.STREAM ~ IO.ROS[]; PutValuesToStream[instance, contents]; ViewerTools.SetContents[viewer: text, contents: IO.RopeFromROS[self: contents], paint: FALSE]; }; ViewerOps.AddProp[viewer: text, prop: $Trc, val: trc]; button _ Buttons.Create[info: [parent: viewer, wx: 5, wy: 5, name: "Read"], proc: ReadViewer, clientData: text, paint: FALSE]; ViewerOps.MoveViewer[viewer: viewer, x: viewer.wx, y: viewer.wy, w: text.wx+text.ww+5, h: text.wy+text.wh+5, paint: paint]; }; ManualCopy: Trc.CopyProc = { CopyEachPin: RedBlackTree.EachNode = { RedBlackTree.Insert[self: newInstance.pins, dataToInsert: data, insertKey: data]; }; instance: ManualInstance ~ NARROW[trc.instance]; newInstance: ManualInstance ~ NEW[ManualInstanceRep]; new _ NEW[Trc.TRCRep _ [class: trc.class, instance: newInstance, listener: NIL]]; RedBlackTree.EnumerateIncreasing[self: instance.pins, procToApply: CopyEachPin]; }; manualClass: Trc.Class ~ NEW[Trc.ClassRep _ [ flavor: $Manual, fcn: ManualFcn, blockFcn: Trc.DefaultBlockFcn, copy: ManualCopy, pickle: ManualPickle, depickle: ManualDepickle, notify: NIL, background: ManualBackground, control: ManualControl, classData: NIL ]]; ReadViewer: Buttons.ButtonProc = { text: ViewerClasses.Viewer ~ NARROW[clientData]; trc: Trc.TRC ~ NARROW[ViewerOps.FetchProp[viewer: text, prop: $Trc]]; instance: ManualInstance ~ NARROW[trc.instance]; stream: IO.STREAM ~ IO.RIS[rope: ViewerTools.GetContents[viewer: text]]; [] _ ParseManualInstance[instance, stream]; Trc.NotifyListeners[trc: trc, fork: TRUE]; }; ParseManualInstance: PROC [instance: ManualInstance, stream: IO.STREAM] RETURNS [token: ROPE _ NIL] ~ { tokenKind: IO.TokenKind; { ENABLE IO.EndOfStream => {token _ NIL; tokenKind _ tokenEOF; CONTINUE}; instance.pins _ RedBlackTree.Create[getKey: TrcManualGet, compare: TrcManualCompare]; instance.xScale _ instance.yScale _ 1.0; DO --Get any scale factors [token: token, tokenKind: tokenKind] _ IO.GetCedarTokenRope[stream: stream]; SELECT tokenKind FROM tokenID => SELECT TRUE FROM Rope.Equal[s1: token, s2: "xScale", case: FALSE] => instance.xScale _ Convert.RealFromRope[IO.GetCedarTokenRope[stream: stream].token]; Rope.Equal[s1: token, s2: "yScale", case: FALSE] => instance.yScale _ Convert.RealFromRope[IO.GetCedarTokenRope[stream: stream].token]; ENDCASE => ERROR; ENDCASE => EXIT; ENDLOOP; DO SELECT tokenKind FROM tokenDECIMAL, tokenREAL => { x: REAL ~ Convert.RealFromRope[token]/instance.xScale; y: REAL ~ Convert.RealFromRope[IO.GetCedarTokenRope[stream: stream].token]/instance.yScale; [] _ RedBlackTree.Insert[self: instance.pins, dataToInsert: NEW[PinRep _ [[x, y]]], insertKey: NEW[REAL _ x]]; [token: token, tokenKind: tokenKind] _ IO.GetCedarTokenRope[stream: stream]; }; ENDCASE => EXIT; ENDLOOP; }; }; PutValuesToStream: PROC [instance: ManualInstance, stream: IO.STREAM, indentation: ROPE _ NIL] ~ { WriteEachPin: RedBlackTree.EachNode = { WITH data SELECT FROM pin: Pin => IO.PutF[stream: stream, format: "\n%g\t%g\t%g", v1: [rope[indentation]], v2: [real[pin.x*instance.xScale]], v3: [real[pin.y*instance.yScale]]]; ENDCASE => ERROR; }; IF instance.xScale#1.0 THEN IO.PutF[stream: stream, format: "\n%g\txScale %g", v1: [rope[indentation]], v2: [real[instance.xScale]]]; IF instance.yScale#1.0 THEN IO.PutF[stream: stream, format: "\n%g\tyScale %g", v1: [rope[indentation]], v2: [real[instance.yScale]]]; RedBlackTree.EnumerateIncreasing[self: instance.pins, procToApply: WriteEachPin]; }; RealToRef: PROC [real: REAL] RETURNS [ref: REF] ~ INLINE { RETURN [NEW[REAL _ real]]; }; RefToReal: PROC [ref: REF] RETURNS [real: REAL] ~ INLINE { WITH ref SELECT FROM refReal: REF REAL => RETURN [refReal^]; pin: Pin => RETURN [pin.x] ENDCASE => ERROR; }; TrcManualGet: RedBlackTree.GetKey = { RETURN [data]; }; TrcManualCompare: RedBlackTree.Compare = { RETURN [Real.CompareREAL[RefToReal[data], RefToReal[k]]]; }; NoPins: SIGNAL ~ CODE; FindNearestPin: PROC [pins: RedBlackTree.Table, loc: VEC, trc: Trc.TRC] RETURNS [closest: VEC, joinPin: BOOL] ~ { PinFromRef: PROC [ref: REF] RETURNS [pin: Pin] ~ { IF ref=NIL THEN RETURN [NIL]; WITH ref SELECT FROM p: Pin => RETURN [p]; --This will return NIL as well real: REF REAL => RETURN [NEW[PinRep _ [[x: real^, y: Trc.ApplyFcn[trc, real^]]]]]; ENDCASE => ERROR; }; left, equal, right: REF; [left, equal, right] _ RedBlackTree.Lookup3[self: pins, lookupKey: RealToRef[loc.x]]; IF equal=NIL THEN { pin1: Pin ~ PinFromRef[left]; pin2: Pin ~ PinFromRef[right]; pickLeft: BOOL ~ SELECT TRUE FROM pin1=NIL AND pin2=NIL => ERROR NoPins[], pin1=NIL => FALSE, pin2=NIL => TRUE, ENDCASE => pin1^.Sub[loc].Length[] < pin2^.Sub[loc].Length[]; IF pickLeft THEN RETURN [pin1^, ISTYPE[left, REF REAL]] ELSE RETURN [pin2^, ISTYPE[right, REF REAL]]; } ELSE { pin1: Pin ~ PinFromRef[equal]; RETURN [pin1^, ISTYPE[equal, REF REAL]]; }; }; Trc.RegisterClass[manualClass]; END.  TrcManualImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Eric Nickell, September 22, 1986 8:40:31 pm PDT [trc: TRC, a: REAL] RETURNS [b: REAL] [trc: TRC, context: Imager.Context, rectangle: ImagerTransformation.Rectangle, whatChanged: REF _ NIL] [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] [trc: TRC, stream: STREAM, indentation: ROPE _ NIL] [class: Trc.Class, stream: STREAM] RETURNS [trc: TRC] tokenKind: IO.TokenKind; [tokenKind: tokenKind, token: token] _ IO.GetCedarTokenRope[stream: stream]; WHILE tokenKind=tokenREAL DO x: REAL ~ Convert.RealFromRope[token]; [tokenKind: tokenKind, token: token] _ IO.GetCedarTokenRope[stream: stream]; SELECT tokenKind FROM tokenREAL => RedBlackTree.Insert[self: instance.pins, dataToInsert: NEW[PinRep _ [[x: x, y: Convert.RealFromRope[token]]]], insertKey: RealToRef[x]]; ENDCASE => ERROR; [tokenKind: tokenKind, token: token] _ IO.GetCedarTokenRope[stream: stream]; ENDLOOP; [tokenKind: tokenKind, token: token] _ IO.GetCedarTokenRope[stream: stream]; [trc: TRC, info: ViewerClasses.ViewerRec, paint: BOOL] RETURNS [viewer: ViewerClasses.Viewer] [trc: TRC] RETURNS [new: TRC] [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] [data: RedBlackTree.UserData] RETURNS [RedBlackTree.Key] [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison] Κ2˜™Icodešœ Οmœ1™˜EKšœžœ˜K–0[context: Imager.Context, strokeWidth: REAL]˜:šžœ žœžœ˜–> -- [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE]˜(Kš‘:™:šžœžœž˜K˜Kšžœžœ˜—K˜—K–B[self: RedBlackTree.Table, procToApply: RedBlackTree.EachNode]˜RKšœ˜—šžœ˜šžœ žœž˜KšœžœžœŸ˜.Kšžœžœ˜—Kšœ˜—K˜—šœ ˜ Kš‘3™3Kšœžœ˜0Kšžœ ˜"K–―[stream: STREAM, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]˜1Kšžœ@˜BK˜—–9 -- [class: Trc.Class, stream: STREAM] RETURNS [trc: TRC]šœ$˜$Kš‘5™5Kšœžœ˜2Kšœžœ˜ Kšœ žœ ™K–0[stream: STREAM, flushComments: BOOL _ TRUE]šœžœ;žœ˜JKšžœžœ4žœžœ˜EKšΠos'Ρkos£#™Lš€£€™K–[stream: STREAM]š£€£™&Kš£'€£#™Lš€£ €™Kš£D€£N™•Kš€£€£™—Kš£'€£#™LKš€£™—Kš£'€£#™LK˜.K–-[s1: ROPE, s2: ROPE, case: BOOL _ TRUE]šžœžœžœ˜&K˜—–T -- [trc: TRC, info: ViewerClasses.ViewerRec] RETURNS [viewer: ViewerClasses.Viewer]š’ œ ˜-Kš‘]™]K–³ -- [proc: ChoiceButtons.SelectionNotifierProc, permission: ChoiceButtons.EnumPermissionProc, namesOfButtons: ChoiceButtons.ButtonList _ NIL, nextx: CARDINAL, nexty: CARDINAL, type: ChoiceButtons.DisplayStyle, buttonOn: Buttons.Button _ NIL, flipLabel: ViewerClasses.Viewer _ NIL, clientdata: REF ANY _ NIL]˜#Kšœ˜K˜šžœžœžœŸ˜7Kšœžœ˜1Kšœ˜—Kšžœ žœ˜%K–Ϊ[viewerFlavor: ATOM, 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, spare0: FALSE, spare1: FALSE, spare2: FALSE, spare3: FALSE, spare4: FALSE, spare5: FALSE, spare6: FALSE, position: 0, openHeight: 0, link: NIL, parent: NIL, sibling: NIL, child: NIL, props: NIL, data: NIL], paint: BOOL _ TRUE]˜]K–Δ[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, spare0: FALSE, spare1: FALSE, spare2: FALSE, spare3: FALSE, spare4: FALSE, spare5: FALSE, spare6: FALSE, position: 0, openHeight: 0, link: NIL, parent: NIL, sibling: NIL, child: NIL, props: NIL, data: NIL], paint: BOOL _ TRUE]šœežœ˜l–>[viewer: ViewerClasses.Viewer, prop: ATOM, val: REF ANY]šœ˜K–ldStream: STREAM _ NIL]š œ žœžœžœžœ˜K˜&K–&[self: STREAM, close: BOOL _ TRUE]šœ0žœ%žœ˜^Kšœ˜—K˜6Kšœwžœ˜~K–n[viewer: ViewerClasses.Viewer, x: INTEGER, y: INTEGER, w: INTEGER, h: INTEGER, paint: BOOL _ TRUE]˜{K˜—˜Kš‘™–> -- [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE]˜&Kš‘:™:K–b[self: RedBlackTree.Table, dataToInsert: RedBlackTree.UserData, insertKey: RedBlackTree.Key]šœQ˜QK˜—Kšœžœ˜0Kšœžœ˜5KšœžœBžœ˜QK–B[self: RedBlackTree.Table, procToApply: RedBlackTree.EachNode]˜PK˜—K˜šœžœ˜-KšœΟtœ˜K˜Kšœ˜K˜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šœžœ ˜0K–.[viewer: ViewerClasses.Viewer, prop: ATOM]šœ žœžœ0˜EKšœžœ˜0K–)[rope: ROPE, oldStream: STREAM _ NIL]š œžœžœžœžœ.˜HK˜+Kšœ$žœ˜*K˜—–y -- [trc: TRC, info: ViewerClasses.ViewerRec, propList: Properties.PropList _ NIL] RETURNS [viewer: ViewerClasses.Viewer]š’œžœ$žœžœžœ žœžœ˜gKšœ žœ ˜šœ˜Kšžœžœžœžœ˜GK˜KšœU˜UK˜(K˜šžœŸ˜K–0[stream: STREAM, flushComments: BOOL _ TRUE]šœ'žœ#˜Lšžœ ž˜šœ žœžœž˜K–0[stream: STREAM, flushComments: BOOL _ TRUE]šœ*žœX˜‡K– [r: ROPE]šœ*žœX˜‡Kšžœžœ˜—Kšžœžœ˜—Kšžœ˜—šž˜šžœ ž˜šœ˜K– [r: ROPE]šœžœ/˜6K–0[stream: STREAM, flushComments: BOOL _ TRUE]šœžœžœ:˜[K–b[self: RedBlackTree.Table, dataToInsert: RedBlackTree.UserData, insertKey: RedBlackTree.Key]šœ<žœ žœžœ˜nK–0[stream: STREAM, flushComments: BOOL _ TRUE]šœ'žœ#˜LKšœ˜—Kšžœžœ˜—Kšžœ˜—Kšœ˜—K˜—–7 -- [trc: TRC, stream: STREAM, indentation: ROPE _ NIL]š ’œžœ$žœžœžœžœ˜b–> -- [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE]˜'Kš‘:™:šžœžœž˜Kšœ žœ˜›Kšžœžœ˜—K˜—K–―[stream: STREAM, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šžœžœžœg˜…K–―[stream: STREAM, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šžœžœžœg˜…K˜QK˜—š ’ œžœžœžœžœžœ˜:Kšžœžœžœ ˜K˜—š ’ œžœžœžœžœžœ˜:šžœžœž˜Kšœ žœžœžœ ˜'Kšœ žœ˜Kšžœžœ˜—K˜—šœ%˜%Kš‘8™8Kšžœ˜K˜—–R -- [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison]šœ*˜*Kš‘N™NKšžœ3˜9K˜—Lšœžœžœ˜š’œžœ!žœ žœžœ žœ žœ˜qš’ œžœžœžœ˜2Kš žœžœžœžœžœ˜šžœžœž˜Kšœ žœŸ‘Ÿ˜5Kš œžœžœžœžœ6˜SKšžœžœ˜—K˜—Kšœžœ˜K–;[self: RedBlackTree.Table, lookupKey: RedBlackTree.Key]šœU˜Ušžœžœžœ˜Kšœ˜Kšœ˜šœ žœžœžœž˜!Kš œžœžœžœžœ ˜(Kšœžœžœ˜Kšœžœžœ˜Kšžœ6˜=—Kšžœ žœžœ žœžœžœžœžœ žœžœžœ˜eKšœ˜—šžœ˜K˜Kšžœ žœžœžœ˜(Kšœ˜—K˜—K˜Kšœ˜K˜—K˜Kšžœ˜—…—!$D`