<> <> <> <> <<>> 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 <> <> FootNotes: PROCEDURE [name: Rope.ROPE, startingAfter: INT _ 0] RETURNS[last: INT _ 0] = { last _ DocumentRenumbering[documentName: name, startingAfter: startingAfter, patternRope: " }; References: PROCEDURE [name: Rope.ROPE, startingAfter: INT, delta: INT] = { < startingAfter, changes nn to nn + delta.>> [] _ DocumentRenumbering[documentName: name, startingAfter: startingAfter, delta: delta, patternRope: "["]; }; Figures: PROCEDURE [name: Rope.ROPE, startingAfter: INT, delta: INT] = { < 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.ROPE _ NIL] RETURNS[last: INT _ 0] = { < 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]; }; <> 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.ROPE _ NIL, singleStep: BOOLEAN _ FALSE] RETURNS [last: INT _ FIRST[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 ~ { <> 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]; <> 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]; <> 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]]]; <> [] _ 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], " }; 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; <> 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: BOOL _ FALSE] 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.