DIRECTORY Atom USING [GetPName], Buttons USING [ButtonProc, Create], FS USING [Error], Commander USING [CommandProc, Handle, Register], EditSpan USING [CannotDoEdit, ChangeNesting, Delete, InsertTextNode], InputFocus USING [GetInputFocus], IO USING [EndOfStream, GetTokenRope, PutFR, PutRope, RIS, STREAM], MessageWindow USING [Append, Blink], NodeProps USING [GetProp, GetSpecs, MapProps, MapPropsAction, PutProp, true], Process USING [CheckForAbort], PutGet USING [FromFile, ToFile], Rope USING [Cat, Equal, Find, IsEmpty, ROPE], TextEdit USING [AppendRope], TextNode USING [FirstChild, Forward, Level, MakeNodeSpan, Ref, RefTextNode], TiogaOps USING [CancelSelection, Jump, Lock, Unlock, ViewerDoc], ViewerClasses USING [Viewer]; AnnotateProperties: CEDAR PROGRAM IMPORTS Atom, Buttons, FS, Commander, EditSpan, InputFocus, IO, MessageWindow, NodeProps, Process, PutGet, Rope, TextEdit, TextNode, TiogaOps = { commentAtom: ATOM ~ $Comment; propertyAnnotationAtom: ATOM ~ $PropertyAnnotation; trueRope: Rope.ROPE ~ "TRUE"; DoAnnotations: Commander.CommandProc = { execOut: IO.STREAM = cmd.out; filename: Rope.ROPE; commandLineStream: IO.STREAM = IO.RIS[cmd.commandLine]; annotate: BOOL _ cmd.procData.clientData = $Annotate; rootNode: TextNode.Ref; DO -- process each file in command line filename _ IO.GetTokenRope[commandLineStream ! IO.EndOfStream => {filename _ NIL; CONTINUE}].token; IF filename.IsEmpty THEN EXIT; IF filename.Find["."] = -1 THEN -- add .mesa extension filename _ filename.Cat[".mesa"]; { ENABLE FS.Error => { execOut.PutRope[filename]; execOut.PutRope[" not found.\n"]; result _ $Warning; msg _ "Some files not found"; LOOP }; Process.CheckForAbort[]; rootNode _ PutGet.FromFile[filename]; Process.CheckForAbort[]; }; TRUSTED { TiogaOps.Lock[LOOPHOLE[rootNode]]; }; IF annotate THEN AddAnnotationNodes[rootNode] ELSE PruneAnnotationNodes[rootNode]; [] _ PutGet.ToFile[filename, rootNode]; TRUSTED { TiogaOps.Unlock[LOOPHOLE[rootNode]]; }; ENDLOOP; }; AddAnnotationNodes: PROC [rootNode: TextNode.Ref] = { annotationNode: TextNode.RefTextNode; CreateRootAnnotationNode: PROC = { annotationNode _ EditSpan.InsertTextNode[rootNode, rootNode, child]; [] _ TextEdit.AppendRope[rootNode, annotationNode, "<>"]; NodeProps.PutProp[annotationNode, propertyAnnotationAtom, trueRope]; NodeProps.PutProp[annotationNode, commentAtom, NodeProps.true]; }; CreateAnnotationNode: PROC [thisNode: TextNode.Ref, level: INTEGER] = { annotationNode _ EditSpan.InsertTextNode[root~rootNode, old~thisNode, where~before]; IF TextNode.Level[annotationNode] > TextNode.Level[thisNode] THEN [] _ EditSpan.ChangeNesting[ root~rootNode, span~TextNode.MakeNodeSpan[annotationNode, annotationNode], change~TextNode.Level[thisNode]-TextNode.Level[annotationNode]]; [] _ TextEdit.AppendRope[ rootNode, annotationNode, IO.PutFR["<>"]; NodeProps.PutProp[annotationNode, propertyAnnotationAtom, trueRope]; NodeProps.PutProp[annotationNode, commentAtom, NodeProps.true]; }; AnnotateProps: NodeProps.MapPropsAction = { nodeRope: Rope.ROPE _ Rope.Cat[", ", Atom.GetPName[name], ": ", NodeProps.GetSpecs[name, value]]; [] _ TextEdit.AppendRope[rootNode, annotationNode, nodeRope]; RETURN[FALSE]}; next: TextNode.Ref; level, levelDelta: INTEGER _ 1; IF AnAnnotationNode[TextNode.FirstChild[rootNode]] THEN RETURN; CreateRootAnnotationNode[]; [next, levelDelta] _ TextNode.Forward[TextNode.FirstChild[rootNode]]; WHILE next#NIL DO level _ level+levelDelta; CreateAnnotationNode[next, level]; [next, levelDelta] _ TextNode.Forward[next]; ENDLOOP; }; PruneAnnotationNodes: PROC [rootNode: TextNode.Ref] = { next, prev: TextNode.Ref; [next, ] _ TextNode.Forward[rootNode]; WHILE next#NIL DO IF AnAnnotationNode[next] THEN { prev _ next; [next, ] _ TextNode.Forward[next]; EditSpan.Delete[ root: rootNode, del: TextNode.MakeNodeSpan[prev, prev], saveForPaste: FALSE ! EditSpan.CannotDoEdit => CONTINUE]} ELSE [next, ] _ TextNode.Forward[next]; ENDLOOP; }; AnAnnotationNode: PROC [node: TextNode.Ref] RETURNS[BOOL] = { propValue: REF; IF node#NIL THEN IF (propValue _ NodeProps.GetProp[node, propertyAnnotationAtom])#NIL THEN IF Rope.Equal[trueRope, NodeProps.GetSpecs[propertyAnnotationAtom, propValue]] THEN RETURN[TRUE]; RETURN[FALSE]; }; TiogaPropsButton: Buttons.ButtonProc ~ { viewer: ViewerClasses.Viewer ~ InputFocus.GetInputFocus[].owner; rootNode: TextNode.Ref; IF viewer = NIL THEN { MessageWindow.Append[message: "Please select a viewer first.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN; }; IF viewer.class.flavor # $Text THEN { MessageWindow.Append[message: "Selected viewer is not a Tioga viewer.", clearFirst: TRUE]; MessageWindow.Blink[]; RETURN; }; TiogaOps.CancelSelection[primary]; TRUSTED { rootNode _ LOOPHOLE[TiogaOps.ViewerDoc[viewer]] }; TRUSTED { TiogaOps.Lock[LOOPHOLE[rootNode]]; }; IF mouseButton = red THEN AddAnnotationNodes[rootNode] ELSE PruneAnnotationNodes[rootNode]; TRUSTED { TiogaOps.Unlock[LOOPHOLE[rootNode]]; }; TRUSTED { TiogaOps.Jump[viewer, [LOOPHOLE[rootNode], 0]]; }; }; Commander.Register[ "AnnotateProperties", DoAnnotations, "Annotate a Tioga document by inserting nodes identifying properties and styles of each node", $Annotate]; Commander.Register[ "PruneAnnotations", DoAnnotations, "Prune the nodes created by the AnnotateProperties command", $Prune]; [] _ Buttons.Create[ info: [name: "TiogaProps"], proc: TiogaPropsButton, documentation: "Annotate a Tioga viewer; right-click to remove annotations"]; }. ”AnnotateProperties.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Beach, May 1982 Paxton July 9, 1982 1:52 pm McGregor September 10, 1982 2:18 pm Maxwell, January 14, 1983 8:44 am Plass, April 21, 1983 10:59 am Russ Atkinson, September 29, 1983 11:51 am Last Edited by: Beach, October 24, 1984 8:20:16 pm PDT Doug Wyatt, March 6, 1985 11:44:04 am PST [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] Edited on October 24, 1984 7:38:46 pm PDT, by Beach Added locking to prevent Tioga disasters if someone messed with the document, like trying to scroll it! CreateAnnotationNode (local of AddAnnotationNodes) correctly sets the nesting level of created annotation nodes Edited on October 24, 1984 8:18:38 pm PDT, by Beach Cancelled the selection to avoid PruneAnnotations deleting the node that was selected and hence wedging the selection machinery after the scroll. Κε˜codešœ™Kšœ Οmœ7™BKšœ™Kšœ™Kšœ#™#K™!K™K™*K™6K™)K™—šΟk ˜ Kšœžœ ˜Kšœžœ˜#Kšžœžœ ˜Kšœ žœ!˜0Kšœ žœ7˜EKšœ žœ˜!Kšžœžœ-žœžœ˜BKšœžœ˜$Kšœ žœ>˜MKšœžœ˜Kšœžœ˜ Kšœžœžœ˜-Kšœ žœ˜Kšœ žœ>˜LKšœ žœ2˜@Kšœžœ ˜K˜—KšΠblœžœž˜!šžœžœ#žœS˜‘K˜Kšœ žœ ˜Kšœžœ˜3Kšœžœ ˜K˜—šœ(˜(Kšœ?™?Kšœ žœžœ ˜Kšœžœ˜Kš œžœžœžœžœ˜7Kšœ žœ'˜5K˜šžœΟc$˜'šœ žœ˜,Kšœžœžœžœ ˜6—Kšžœžœžœ˜šžœžœ ˜8K˜!—šœž˜šžœ ˜ K˜K˜!Kšœ˜K˜Kšžœ˜—Kšœ˜K˜%Kšœ˜K˜—Kšžœžœ˜/šžœ ˜ Kšžœ˜!Kšžœ ˜$—K˜'Kšžœžœ˜1Kšžœ˜—K˜K˜—šΟnœžœ˜5Kšœ%˜%š‘œžœ˜"K˜DK˜AK˜1K˜9K˜DK˜?K˜—š‘œžœ!žœ˜GK˜Tšžœ;žœ˜Bšœ˜Kšœ˜Kšœ;˜;Kšœ@˜@——šœ˜Kšœ ˜ Kšœ˜Kšžœ-˜/—K˜1K˜9K˜DK˜?K˜—šœ+˜+KšœžœN˜aK˜=Kšžœžœ˜—K˜Kšœžœ˜Kšžœ1žœžœ˜?Kšœ˜K˜Ešžœžœž˜K˜Kšœ"˜"K˜,Kšžœ˜—K˜K˜—š‘œžœ˜7K˜K˜&šžœžœž˜šžœžœ˜ K˜ K˜"šœ˜KšœFž˜KKšœžœ˜%——šž˜K˜"—Kšžœ˜—K˜K˜—š‘œžœžœžœ˜=Kšœ žœ˜šžœžœž˜šžœ?žœž˜IšžœMž˜SKšžœžœ˜ ———Kšžœžœ˜K˜K˜—šœ(˜(Kšœ@˜@Kšœ˜šžœ žœžœ˜KšœKžœ˜QK˜Kšžœ˜Kšœ˜—šžœžœ˜%KšœTžœ˜ZK˜Kšžœ˜Kšœ˜K˜—K˜"Kšžœžœ˜