TiogaRenumberImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by Teitelman, April 5, 1984 3:58:02 pm PST
Rick Beach, March 26, 1986 4:14:37 pm PST
DIRECTORY
Atom,
Buttons,
Commander,
CommandTool,
Convert,
IO,
Menus,
Process USING [CheckForAbort],
Rope,
TiogaOps,
ViewerClasses,
ViewerOps,
ViewerTools,
VFonts;
TiogaRenumberImpl: CEDAR PROGRAM
IMPORTS Buttons, Commander, CommandTool, Process, IO, Convert, Rope, TiogaOps, ViewerOps, ViewerTools
= BEGIN
Renumbering Tioga Documents
A hack to assist in renumbering figures, references, or footnotes. Registers the commands RenumberFootnotes, RenumberFigures, RenumberReferences, and the generic command Renumber. The first three commands search a document for a pattern and renumber following tokens, e.g. footnotes like ` 13', figures like `Figure 13', references like `[13]'. The generic command Renumber permits a user to specify all the search parameters.
FootNotes: PROCEDURE [name: Rope.ROPE, startingAfter: INT ← 0] RETURNS[last: INT ← 0] = {
last ← DocumentRenumbering[documentName: name, startingAfter: startingAfter, patternRope: " ", patternLooks: "m"];
};
References: PROCEDURE [name: Rope.ROPE, startingAfter: INT, delta: INT] = {
For use when a reference is added or dropped, references are of the form [nn]. For all nn > startingAfter, changes nn to nn + delta.
[] ← DocumentRenumbering[documentName: name, startingAfter: startingAfter, delta: delta, patternRope: "["];
};
Figures: PROCEDURE [name: Rope.ROPE, startingAfter: INT, delta: INT] = {
For use when a figure is added or dropped, figures are of the form Figure nn. For all nn > startingAfter, changes nn to nn + delta.
[] ← DocumentRenumbering[documentName: name, startingAfter: startingAfter, delta: delta, patternRope: "Figure "];
};
DocumentRenumbering: PROCEDURE [documentName: Rope.ROPE, startingAfter: INT, delta: INT ← 1, patternRope: Rope.ROPE, patternLooks: Rope.ROPENIL] RETURNS[last: INT ← 0] = {
For use when a reference is added or dropped, references are of the form [nn]. For all nn > startingAfter, changes nn to nn + delta.
viewer: ViewerClasses.Viewer;
IF (viewer ← ViewerOps.FindViewer[documentName]) = NIL THEN viewer ← ViewerOps.CreateViewer[flavor: $Text, info: [name: documentName, file: documentName]];
IF viewer.iconic THEN ViewerOps.OpenIcon[viewer];
IF viewer = NIL THEN RETURN[FIRST[INT]];
last ← GenericRenumbering[viewer~viewer, startSearch~[TiogaOps.ViewerDoc[viewer], 0], startAtNumber~startingAfter-1, becomesNumber~startingAfter+delta, delta~delta, patternRope~patternRope, patternLooks~patternLooks];
};
Viewer Interface
SeenNode: TYPE = RECORD[key: Rope.ROPE, val: INT];
SeenNodeList: TYPE = LIST OF REF SeenNode;
SeenNodeProp: TYPE = RECORD[seen: SeenNodeList, current: INT];
GenericRenumbering: PROC [viewer: ViewerClasses.Viewer, startSearch: TiogaOps.Location, startAtNumber, becomesNumber: INT, delta: INT ← 1, patternRope: Rope.ROPE, patternLooks: Rope.ROPENIL, singleStep: BOOLEANFALSE]
RETURNS [last: INTFIRST[INT]] ~ {
pattern: TiogaOps.Pattern ~ TiogaOps.CreateSimplePattern[patternRope]; -- creates a pattern for the search.
checkLooks: BOOLEAN ~ NOT patternLooks.IsEmpty;
seen: SeenNodeList ← NIL;
current: INT ← becomesNumber;
NumberProc: IO.BreakProc ~ {
RETURN [SELECT char FROM
IN ['0 .. '9] => other,
IN [IO.NUL .. IO.SP], ',, ':, '; => sepr,
ENDCASE => break]};
IF singleStep THEN {
ref: REF ← ViewerOps.FetchProp[viewer: viewer, prop: $SeenNodes];
WITH ref SELECT FROM
s: REF SeenNodeProp => { seen ← s.seen; current ← s.current; };
ENDCASE;
};
TiogaOps.SelectPoint[viewer: viewer, caret: startSearch];
DO
numberToken: Rope.ROPE;
stream: IO.STREAM;
begin, end: TiogaOps.Location;
looks: Rope.ROPE;
replacementNumber: INT;
found: BOOL ← TiogaOps.SelectionSearch[pattern: pattern];
IF NOT found THEN EXIT;
[, begin, end] ← TiogaOps.GetSelection[];
IF checkLooks THEN {
looks ← TiogaOps.FetchLooks[node: begin.node, index: begin.where];
IF Rope.Find[s1: looks, s2: patternLooks] = -1 THEN LOOP; -- this information should be specified in the pattern, but currently don't know how to create such a pattern
};
stream ← IO.RIS[TiogaOps.GetRope[begin.node], stream];
IO.SetIndex[stream, end.where + 1];
numberToken ← IO.GetTokenRope[stream, NumberProc ! IO.Error => LOOP].token;
FOR l: LIST OF REF SeenNode ← seen, l.rest UNTIL l = NIL DO
IF Rope.Equal[l.first.key, numberToken] THEN {
replacementNumber ← l.first.val;
EXIT;
};
REPEAT
FINISHED => {
replacementNumber ← current;
current ← current + delta;
seen ← CONS[NEW[SeenNode ← [key: numberToken, val: replacementNumber]], seen];
};
ENDLOOP;
IF replacementNumber < startAtNumber THEN LOOP;
TiogaOps.SetSelection[viewer: viewer, start: [end.node, end.where + 1], end: [end.node, IO.GetIndex[stream] - 1]];
looks ← TiogaOps.FetchLooks[node: end.node, index: end.where + 1];
TiogaOps.Delete[];
TiogaOps.SetLooks[looks, caret];
TiogaOps.InsertRope[Convert.RopeFromInt[replacementNumber]];
last ← replacementNumber;
IF singleStep THEN EXIT;
ENDLOOP;
IF singleStep THEN
ViewerOps.AddProp[viewer, $SeenNodes, NEW[SeenNodeProp ← [seen, current]]];
RETURN[last];
};
InitRenumberViewer: ViewerClasses.InitProc ~ {
PROC [self: Viewer]
t: ViewerClasses.Viewer;
b: Buttons.Button;
line1: INT ~ 0;
line2: INT ~ 14;
height: INT ~ 16;
patternWidth: INT ~ 70;
numberWidth: INT ~ 35;
openHeight: INT ~ 47; -- experimentally determined...
containerInitProc[self]; -- since I know its really a $Container, I need to init it for him
b ← Buttons.Create[proc: DoITProc,
info: [parent: self, name: "DoIT!", wx: 0, wy: line1, border: FALSE]];
b ← Buttons.Create[proc: StepProc,
info: [parent: self, name: "ForAll", wx: b.wx+b.ww, wy: line1, border: FALSE]];
ViewerOps.AddProp[viewer: self, prop: $SingleStep, val: b];
b ← Buttons.Create[proc: FiguresProc,
info: [parent: self, name: "Figures", wx: b.wx+b.ww, wy: line1, border: FALSE]];
b ← Buttons.Create[proc: FootnotesProc,
info: [parent: self, name: "Footnotes", wx: b.wx+b.ww, wy: line1, border: FALSE]];
b ← Buttons.Create[proc: ReferencesProc,
info: [parent: self, name: "References", wx: b.wx+b.ww, wy: line1, border: FALSE]];
b ← Buttons.Create[proc: PatternProc,
info: [parent: self, name: "Pattern:", wx: 0, wy: line2, border: FALSE]];
t ← ViewerTools.MakeNewTextViewer[info: [parent: self, wx: b.wx+b.ww, wy: line2+1, ww: patternWidth, wh: height, border: FALSE, scrollable: TRUE]];
ViewerOps.AddProp[viewer: self, prop: $Pattern, val: t];
b ← Buttons.Create[proc: StartAtProc,
info: [parent: self, name: "StartAt:", wx: t.wx+t.ww, wy: line2, border: FALSE]];
t ← ViewerTools.MakeNewTextViewer[info: [parent: self, wx: b.wx+b.ww, wy: line2+1, ww: numberWidth, wh: height, border: FALSE, scrollable: TRUE]];
ViewerOps.AddProp[viewer: self, prop: $StartAt, val: t];
ViewerTools.SetContents[t, "1"];
b ← Buttons.Create[proc: BecomesProc,
info: [parent: self, name: "Becomes:", wx: t.wx+t.ww, wy: line2, border: FALSE]];
t ← ViewerTools.MakeNewTextViewer[info: [parent: self, wx: b.wx+b.ww, wy: line2+1, ww: numberWidth, wh: height, border: FALSE, scrollable: TRUE]];
ViewerTools.SetContents[t, "1"];
ViewerOps.AddProp[viewer: self, prop: $Becomes, val: t];
b ← Buttons.Create[proc: DeltaProc,
info: [parent: self, name: "Delta:", wx: t.wx+t.ww, wy: line2, border: FALSE]];
t ← ViewerTools.MakeNewTextViewer[info: [parent: self, wx: b.wx+b.ww, wy: line2+1, ww: numberWidth, wh: height, border: FALSE, scrollable: TRUE]];
ViewerOps.AddProp[viewer: self, prop: $Delta, val: t];
ViewerTools.SetContents[t, "1"];
self.openHeight ← openHeight;
};
DoITProc: Buttons.ButtonProc ~ {
patternRope: Rope.ROPE;
patternLooks: Rope.ROPE;
startAtNumber: INT;
becomesNumber: INT;
delta: INT;
singleStep: BOOLEAN;
startSearch: TiogaOps.Location;
viewer: ViewerClasses.Viewer;
[viewer, startSearch, ] ← TiogaOps.GetSelection[primary];
single step or run through all variations
singleStep ← ViewerTools.GetContents[ViewerFromParent[parent, $SingleStep]].Equal["Single"];
IF NOT singleStep THEN
startSearch ← [TiogaOps.SelectionRoot[], 0];
IF NOT singleStep OR mouseButton = blue THEN
ViewerOps.AddProp[viewer, $SeenNodes, NIL];
get the pattern and looks from $Pattern viewer
patternRope ← ViewerTools.GetContents[ViewerFromParent[parent, $Pattern]];
IF patternRope.IsEmpty THEN ERROR;
patternLooks ← TiogaOps.FetchLooks[node: TiogaOps.FirstChild[TiogaOps.ViewerDoc[ViewerFromParent[parent, $Pattern]]], index: 1];
startAtNumber ← Convert.IntFromRope[ViewerTools.GetContents[ViewerFromParent[parent, $StartAt]]];
becomesNumber ← Convert.IntFromRope[ViewerTools.GetContents[ViewerFromParent[parent, $Becomes]]];
delta ← Convert.IntFromRope[ViewerTools.GetContents[ViewerFromParent[parent, $Delta]]];
do the generic renumbering
[] ← GenericRenumbering[viewer, startSearch, startAtNumber, becomesNumber, delta, patternRope, patternLooks, singleStep];
};
ViewerFromParent: PROC [parent: REF ANY, atom: ATOM]
RETURNS [v: ViewerClasses.Viewer] ~ {
ref: REF ~ ViewerOps.FetchProp[viewer: NARROW[parent, ViewerClasses.Viewer].parent, prop: atom];
IF ref # NIL AND ISTYPE[ref, ViewerClasses.Viewer] THEN
v ← NARROW[ref, ViewerClasses.Viewer];
};
StepProc: Buttons.ButtonProc ~ {
button: ViewerClasses.Viewer ~ NARROW[parent];
IF button.name.Equal["ForAll"] THEN
Buttons.ReLabel[button, "Single"]
ELSE
Buttons.ReLabel[button, "ForAll"];
};
FiguresProc: Buttons.ButtonProc ~ {
SetTextContents[ViewerFromParent[parent, $Pattern], "Figure ", ""];
};
FootnotesProc: Buttons.ButtonProc ~ {
SetTextContents[ViewerFromParent[parent, $Pattern], " ", "m"];
};
ReferencesProc: Buttons.ButtonProc ~ {
SetTextContents[ViewerFromParent[parent, $Pattern], "[", ""];
};
SetTextContents: PROC [viewer: ViewerClasses.Viewer, rope: Rope.ROPE, looks: Rope.ROPE] ~ {
IF viewer # NIL THEN {
ViewerTools.SetContents[viewer, rope];
IF ~looks.IsEmpty THEN {
TiogaOps.SaveSelA[];
TiogaOps.SelectDocument[viewer];
TiogaOps.SetLooks[looks];
TiogaOps.RestoreSelA[];
};
};
};
PatternProc: Buttons.ButtonProc ~ {
TextButton[viewer~ViewerFromParent[parent, $Pattern], mouseButton~mouseButton];
};
StartAtProc: Buttons.ButtonProc ~ {
TextButton[viewer~ViewerFromParent[parent, $StartAt], mouseButton~mouseButton];
};
BecomesProc: Buttons.ButtonProc ~ {
TextButton[viewer~ViewerFromParent[parent, $Becomes], mouseButton~mouseButton];
};
DeltaProc: Buttons.ButtonProc ~ {
TextButton[viewer~ViewerFromParent[parent, $Delta], mouseButton~mouseButton];
};
TextButton: PROC [viewer: ViewerClasses.Viewer, mouseButton: Menus.MouseButton] ~ {
IF viewer # NIL THEN {
IF mouseButton # red THEN ViewerTools.SetContents[viewer, ""];
ViewerTools.SetSelection[viewer];
};
};
renumberViewerClass: ViewerClasses.ViewerClass ← NEW[ViewerClasses.ViewerClassRec ← ViewerOps.FetchViewerClass[$Container]^];
containerInitProc: ViewerClasses.InitProc ← renumberViewerClass.init;
Command Interface
RenumberFootnotesCmd: Commander.CommandProc ~ {
argv: CommandTool.ArgumentVector;
currentNumber: INT ← 0;
argv ← CommandTool.Parse[cmd: cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
FOR i: NAT IN [1..argv.argc) DO
IF argv[i].Length[] = 0 THEN LOOP;
IF argv[i].Fetch[0] = '- THEN {
IF argv[i].Fetch[1] = 'n OR argv[i].Fetch[1] = 'N THEN
currentNumber ← Convert.IntFromRope[argv[i].Substr[2]];
LOOP;
};
[] ← FootNotes[argv[i], currentNumber];
IF AbortRequested[cmd, TRUE] THEN EXIT;
ENDLOOP;
};
RenumberFiguresCmd: Commander.CommandProc ~ {
argv: CommandTool.ArgumentVector;
startAfter: INT ← 0;
delta: INT ← 1;
argv ← CommandTool.Parse[cmd: cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
FOR i: NAT IN [1..argv.argc) DO
IF argv[i].Length[] = 0 THEN LOOP;
IF argv[i].Fetch[0] = '- THEN {
IF argv[i].Fetch[1] = 'a OR argv[i].Fetch[1] = 'A THEN
startAfter ← Convert.IntFromRope[argv[i].Substr[2]]
ELSE IF argv[i].Fetch[1] = 'd OR argv[i].Fetch[1] = 'D THEN
delta ← Convert.IntFromRope[argv[i].Substr[2]];
LOOP;
};
Figures[argv[i], startAfter, delta];
IF AbortRequested[cmd, TRUE] THEN EXIT;
ENDLOOP;
};
RenumberReferencesCmd: Commander.CommandProc ~ {
argv: CommandTool.ArgumentVector;
startAfter: INT ← 0;
delta: INT ← 1;
argv ← CommandTool.Parse[cmd: cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
FOR i: NAT IN [1..argv.argc) DO
IF argv[i].Length[] = 0 THEN LOOP;
IF argv[i].Fetch[0] = '- THEN {
IF argv[i].Fetch[1] = 'a OR argv[i].Fetch[1] = 'A THEN
startAfter ← Convert.IntFromRope[argv[i].Substr[2]]
ELSE IF argv[i].Fetch[1] = 'd OR argv[i].Fetch[1] = 'D THEN
delta ← Convert.IntFromRope[argv[i].Substr[2]];
LOOP;
};
References[argv[i], startAfter, delta];
IF AbortRequested[cmd, TRUE] THEN EXIT;
ENDLOOP;
};
RenumberCmd: Commander.CommandProc ~ {
argv: CommandTool.ArgumentVector;
startAfter: INT ← 0;
delta: INT ← 1;
patternRope, patternLooks: Rope.ROPE;
argv ← CommandTool.Parse[cmd: cmd ! CommandTool.Failed => { msg ← errorMsg; CONTINUE; }];
IF argv = NIL OR argv.argc = 1 THEN {
v: ViewerClasses.Viewer ~ ViewerOps.CreateViewer[flavor: $TiogaRenumber, info: [name: "Renumber", iconic: TRUE, column: right, scrollable: FALSE]];
ViewerOps.OpenIcon[v];
ViewerOps.TopViewer[v];
RETURN;
};
FOR i: NAT IN [1..argv.argc) DO
IF argv[i].Length[] = 0 THEN LOOP;
IF argv[i].Fetch[0] = '- THEN {
SELECT argv[i].Fetch[1] FROM
'a, 'A => startAfter ← Convert.IntFromRope[argv[i].Substr[2]];
'd, 'D => delta ← Convert.IntFromRope[argv[i].Substr[2]];
'p, 'P => patternRope ← argv[i].Substr[2];
'l, 'L => patternLooks ← argv[i].Substr[2];
ENDCASE => RETURN[$Failure, IO.PutFR["Bad -option syntax in %g\n..Aborted", IO.rope[argv[i]]]];
LOOP;
};
IF patternRope.IsEmpty THEN
RETURN[$Failure, "-p option to specify pattern missing\n..Aborted"];
[] ← DocumentRenumbering[argv[i], startAfter, delta, patternRope, patternLooks];
IF AbortRequested[cmd, TRUE] THEN EXIT;
ENDLOOP;
};
AbortRequested: PROC [cmd: Commander.Handle, reset: BOOLFALSE] RETURNS [BOOL] = {
Process.CheckForAbort[];
RETURN [FALSE];
};

Initialization
renumberViewerClass.init ← InitRenumberViewer;
ViewerOps.RegisterViewerClass[$TiogaRenumber, renumberViewerClass];
Commander.Register[key: "RenumberFootnotes", proc: RenumberFootnotesCmd, doc: "RenumberFootnotes document-name {-nxx} where xx is the first footnote to begin renumbering"];
Commander.Register[key: "RenumberFigures", proc: RenumberFiguresCmd, doc: "RenumberFigures {-axx} {-dyy} document-name where xx is the first figure after which to begin renumbering and yy is the increment in the figure numbers"];
Commander.Register[key: "RenumberReferences", proc: RenumberReferencesCmd, doc: "RenumberReferences {-axx} {-dyy} document-name where xx is the first reference after which to begin renumbering and yy is the increment in the figure numbers"];
Commander.Register[key: "TiogaRenumber", proc: RenumberCmd, doc: "Renumber -pPattern {-lz} {-axx} {-dyy} document-name where Pattern identifies the thing being renumbered, z is a set of looks to match with the pattern, xx is the first thing after which to begin renumbering and yy is the increment in the figure numbers"];
Commander.Register[key: "Renumber", proc: RenumberCmd, doc: "Renumber -pPattern {-lz} {-axx} {-dyy} document-name where Pattern identifies the thing being renumbered, z is a set of looks to match with the pattern, xx is the first thing after which to begin renumbering and yy is the increment in the figure numbers"];
END.