-- AnnotateProperties.mesa
-- written by Beach, May 1982
-- last written by Paxton July 9, 1982 1:52 pm

DIRECTORY
 Atom USING [GetPName],
 CIFS USING [Error],
 EditSpan USING [CannotDoEdit, Delete, InsertTextNode],
 IO,
 NodeProps USING [GetProp, GetSpecs, MapProps, MapPropsAction, PutProp, true],
 PutGet USING [FromFile, ToFile],
 Rope USING [Cat, Equal, Find, ROPE, Size],
 TextEdit USING [AppendRope],
 TextNode USING [FirstChild, Forward, MakeNodeSpan, Ref, RefTextNode],
 UserExec USING [CommandProc, ExecHandle, RegisterCommand],
 WindowManager USING [UnWaitCursor, WaitCursor];

AnnotateProperties: PROGRAM
 IMPORTS Atom, CIFS, EditSpan, IO, NodeProps, PutGet, Rope, TextEdit, TextNode, UserExec, WindowManager = {

rootNode: TextNode.Ref;
annotationNode: TextNode.RefTextNode;
commentAtom: ATOM = $Comment;
propertyAnnotationAtom: ATOM = $PropertyAnnotation;
trueRope: Rope.ROPE = "TRUE";

AnnotatePropertiesCommand: UserExec.CommandProc = TRUSTED {
 RETURN[DoAnnotations[exec, TRUE]] };

PruneAnnotationsCommand: UserExec.CommandProc = TRUSTED {
 RETURN[DoAnnotations[exec, FALSE]] };

DoAnnotations: PROC [exec: UserExec.ExecHandle, annotate: BOOLEAN ← TRUE]
 RETURNS[ok: BOOLEAN ← TRUE] = {
 ENABLE UNWIND => WindowManager.UnWaitCursor[];
 filename: Rope.ROPE;
 tabIndent: NAT ← 8;
 WindowManager.WaitCursor[];
DO-- process each file in command line
  filename ← IO.GetRope[exec.commandLineStream];
  IF Rope.Size[filename]=0 THEN EXIT;
  IF Rope.Find[filename,"."] = -1 THEN -- add .mesa extension
   filename ← Rope.Cat[filename,".mesa"];
  { ENABLE CIFS.Error => {
   exec.out.PutRope[filename];
   exec.out.PutRope[" not found.\n"];
   ok ← FALSE;
   LOOP };
  rootNode ← PutGet.FromFile[filename];
  };
  IF annotate THEN
   AddAnnotationNodes[]
  ELSE
   PruneAnnotationNodes[];
  [] ← PutGet.ToFile[filename, rootNode];
  ENDLOOP;
 WindowManager.UnWaitCursor[];
 exec.out.PutRope[" Done."];
 RETURN[ok];
 };

AddAnnotationNodes: PROCEDURE = {
 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 = {
 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];
 };

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[rootNode, thisNode, before];
 [] ← TextEdit.AppendRope[rootNode, annotationNode, IO.PutFToRope["<<NodeLevel: %d", IO.int[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]};

UserExec.RegisterCommand["AnnotateProperties", AnnotatePropertiesCommand, "Annotate a Tioga document by inserting nodes identifying properties and styles of each node"];

UserExec.RegisterCommand["PruneAnnotations", PruneAnnotationsCommand, "Prune the nodes created by the AnnotateProperties command"];

}.