DIRECTORY Atom, Buttons, PFS, Commander, EditSpan, InputFocus, IO, MessageWindow, NodeProps, Process, TiogaIO, Rope, TextEdit, TextNode, TiogaOps, ViewerClasses; AnnotateProperties: CEDAR PROGRAM IMPORTS Atom, Buttons, PFS, Commander, EditSpan, InputFocus, IO, MessageWindow, NodeProps, Process, TiogaIO, 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.Concat[".mesa"]; { ENABLE PFS.Error => { execOut.PutRope[filename]; execOut.PutRope[" not found.\n"]; result ¬ $Warning; msg ¬ "Some files not found"; LOOP }; Process.CheckForAbort[]; rootNode ¬ TiogaIO.FromFile[PFS.PathFromRope[filename]].root; Process.CheckForAbort[]; }; TRUSTED { TiogaOps.Lock[LOOPHOLE[rootNode]]; }; IF annotate THEN AddAnnotationNodes[rootNode] ELSE PruneAnnotationNodes[rootNode]; [] ¬ TiogaIO.ToFile[PFS.PathFromRope[filename], rootNode]; TRUSTED { TiogaOps.Unlock[LOOPHOLE[rootNode]]; }; ENDLOOP; }; AddAnnotationNodes: PROC [rootNode: TextNode.Ref] = { annotationNode: TextNode.RefTextNode; AppendRope: PROC [rope: Rope.ROPE] ~ { [] ¬ TextEdit.ReplaceByRope[root: rootNode, dest: annotationNode, start: annotationNode.rope.Size, len: 0, rope: rope]; }; CreateRootAnnotationNode: PROC = { annotationNode ¬ EditSpan.InsertTextNode[rootNode, rootNode, child]; AppendRope["<>"]; NodeProps.PutProp[annotationNode, propertyAnnotationAtom, trueRope]; annotationNode.comment ¬ 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]]; }; AppendRope[IO.PutFR1["<>"]; NodeProps.PutProp[annotationNode, propertyAnnotationAtom, trueRope]; annotationNode.comment ¬ TRUE; }; AnnotateProps: NodeProps.MapPropsAction = { nodeRope: Rope.ROPE ¬ Rope.Cat[", ", Atom.GetPName[name], ": ", NodeProps.GetSpecs[name, value]]; AppendRope[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 Σ 1984, 1985, 1991 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, January 30, 1992 1:53 pm PST Russ Atkinson, September 29, 1983 11:51 am Last Edited by: Beach, October 24, 1984 8:20:16 pm PDT JKF February 27, 1989 10:25:39 am PST 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. Κ•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ<™HKšœ™Kšœ™Kšœ#™#K™!K™#K™*K™6K™%K™)K™—šΟk œžœ#žœ`˜‘K˜—KšΡblnœžœž˜!šžœžžœ#žœT˜“K˜Kšœ žœ ˜Kšœžœ˜3Kšœžœ ˜K˜—šΟn œ˜(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˜—š œžœ˜5Kšœ%˜%š  œžœ žœ˜&K˜wKšœ˜—š œžœ˜"K˜DK˜K˜1K˜K˜DKšœžœ˜K˜—š œžœ!žœ˜GK˜Tšžœ;žœ˜Cšœ˜Kšœ˜Kšœ;˜;K˜@—Kšœ˜—Kšœ žœ.˜;K˜1K˜K˜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šžœžœ˜