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
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 = {
[cmd: Handle] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL]
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["<<RootNode"];
[] ¬ NodeProps.MapProps[rootNode, AnnotateProps];
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["<<NodeLevel: %d", [integer[level]]]];
[] ¬ NodeProps.MapProps[thisNode, AnnotateProps];
AppendRope[">>"];
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"];
}.
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.