AnnotateProperties.mesa
Copyright © 1984 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
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],
ProcessExtras 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, ProcessExtras, PutGet, 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.Cat[".mesa"];
{ ENABLE
FS.Error => {
execOut.PutRope[filename];
execOut.PutRope[" not found.\n"];
result ← $Warning;
msg ← "Some files not found";
LOOP };
ProcessExtras.CheckForAbort[];
rootNode ← PutGet.FromFile[filename];
ProcessExtras.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: PROCEDURE [rootNode: TextNode.Ref] = {
annotationNode: TextNode.RefTextNode;
CreateRootAnnotationNode: PROCEDURE = {
annotationNode ← EditSpan.InsertTextNode[rootNode, rootNode, child];
[] ← TextEdit.AppendRope[rootNode, annotationNode, "<<RootNode"];
[] ← NodeProps.MapProps[rootNode, AnnotateProps];
[] ← TextEdit.AppendRope[rootNode, annotationNode, ">>"];
NodeProps.PutProp[annotationNode, propertyAnnotationAtom, trueRope];
NodeProps.PutProp[annotationNode, commentAtom, NodeProps.true];
};
CreateAnnotationNode: PROCEDURE [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["<<NodeLevel: %d", [integer[level]]]];
[] ← NodeProps.MapProps[thisNode, AnnotateProps];
[] ← TextEdit.AppendRope[rootNode, annotationNode, ">>"];
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: PROCEDURE [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[BOOLEAN] = {
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.