<> <> <> <> <> <> <> <> <> DIRECTORY Atom USING [GetPName, MakeAtom], EditSpan USING [CompareNodeOrder, NodeOrder], MessageWindow USING [Append], NodeProps USING [CopyInfoProc, GetProp, MapProps, NullCopy, NullRead, NullWrite, PutProp, ReadSpecsProc, Register, RemProp, WriteSpecsProc], NodeStyleOps USING [StyleNameForNode], PutGet USING [FromFile, ToFile], Rope USING [Concat, FromChar, IsEmpty, Map, ROPE], TEditDocument USING [Selection, SpinAndLock, TEditDocumentData, Unlock], TEditDocumentPrivate USING [CloseAndOpenPreviousFile, DefaultMenus, DoCloseAndNewViewer, DoCloseAndOpenImplFile, DoLoadFile, DoLoadImplFile, DoNewViewer, DoOpenFile, DoOpenImplFile, DoStoreFile, EmptyViewer, JumpToPrevious, LoadPreviousFile, OpenPreviousFile, Reselect, Reset, Save], TEditInput USING [AllLevels, CloseEvent, CommandProc, FewerLevels, FirstLevelOnly, FreeTree, MoreLevels, Normalize, Register, UnRegister], TEditInputOps USING [CallWithLocks, DoFindPlaceholders, DoNextViewer, DoSelectMatchingBrackets], TEditOps USING [RememberCurrentPosition], TEditProfile USING [selectionCaret], TEditRefresh USING [ScrollToEndOfSel], TEditScrolling USING [ScrollToPosition], TEditSelection USING [FindWhere, MakeSelection, Position, pSel, SetSelLooks], TextEdit USING [ChangeLooks, FetchLooks, FetchLooksRun, FromRope, LooksRun, Size], TextFind USING [Finder, MalformedPattern, PatternErrorCode], TextFindPrivate USING [FinderRecord], TextLooks USING [allLooks, Look, Looks, LooksAnd, noLooks], TextNode USING [FirstChild, FirstSibling, LastChild, LastLocWithin, LastSibling, LastWithin, Location, Next, Node, NodeRep, NodeProps, Parent, Previous, Root, StepBackward, StepForward], TiogaExtraOps USING [MapPropsAction], TiogaMenuOps USING [], TiogaOps USING [CommandProc, CommentControl, Dir, Finder, FinderRec, Pattern, PatternErrorCode, PatternRec, SearchDir, SetSelection], TiogaOpsDefs USING [Location, Order, WhichSelection], TreeFind USING [CommentControl, Create, CreateFromRope, Try, TryBackwards], ViewerClasses USING [Column, Viewer]; TiogaOps2Impl: CEDAR PROGRAM IMPORTS Atom, EditSpan, MessageWindow, NodeProps, NodeStyleOps, PutGet, Rope, TEditDocument, TEditDocumentPrivate, TEditInput, TEditInputOps, TEditOps, TEditProfile, TEditRefresh, TEditScrolling, TEditSelection, TextEdit, TextFind, TextLooks, TextNode, TiogaOps, TreeFind EXPORTS TiogaOpsDefs, TiogaOps, TiogaMenuOps, TiogaExtraOps ~ BEGIN ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; Column: TYPE ~ ViewerClasses.Column; Node: TYPE = TextNode.Node; -- points to a Tioga node NodeBody: PUBLIC TYPE = TextNode.NodeRep; -- export opaque type Finder: TYPE = REF FinderRec; FinderRec: PUBLIC TYPE = TextFindPrivate.FinderRecord; -- export opaque type MakeName: PROC [r: ROPE] RETURNS [ATOM] ~ { RETURN [IF r.IsEmpty THEN NIL ELSE Atom.MakeAtom[r]]; }; <> LooksRope: PROC [looks: TextLooks.Looks] RETURNS [r: ROPE] = { FOR c: CHAR IN TextLooks.Look DO IF looks[c] THEN r _ Rope.Concat[r, Rope.FromChar[c]]; ENDLOOP }; RopeToLooks: PROC [r: ROPE] RETURNS [looks: TextLooks.Looks] = { Set: PROC [c: CHAR] RETURNS [quit: BOOL _ FALSE] = { looks[c] _ TRUE }; [] _ Rope.Map[base: r, action: Set]; }; tiogaOpsEcFromTextFindEc: ARRAY TextFind.PatternErrorCode OF TiogaOps.PatternErrorCode _ [ toobig: toobig, endquote: endquote, endtilda: endtilda, boundary: boundary, missingNameEnd: missingNameEnd, unmatchedNameEnd: unmatchedNameEnd ]; MalformedPattern: PUBLIC ERROR [ec: TiogaOps.PatternErrorCode] ~ CODE; ReportMalformedPattern: PROC [textFindEc: TextFind.PatternErrorCode] ~ { tiogaOpsEc: TiogaOps.PatternErrorCode ~ tiogaOpsEcFromTextFindEc[textFindEc]; ERROR MalformedPattern[tiogaOpsEc]; }; CreateGeneralPattern: PUBLIC PROC [ target: Node, -- node from which to get the pattern text: BOOL _ TRUE, -- if true, match target text looks: BOOL _ FALSE, -- if true, match target looks format: BOOL _ FALSE, -- if true, match target format style: BOOL _ FALSE, -- if true, match target style comment: BOOL _ FALSE, -- if true, match target comment property case: BOOL _ TRUE, -- if true, match case literal: BOOL _ FALSE, -- if true, treat target literally rather than as a pattern word: BOOL _ FALSE, -- if true, match words only subset: BOOL _ TRUE, -- if true, use subset for looks test, else use equality addBounds: BOOL _ FALSE] -- if true, add |'s to both ends of pattern RETURNS [pattern: TiogaOps.Pattern] = { error: BOOL _ FALSE; errorCode: TextFind.PatternErrorCode; txt: Node = target; patternTxt: Node _ txt; pattern _ NEW[TiogaOps.PatternRec]; IF looks AND ~text THEN { -- make a phony search pattern and get the looks size: INT = TextEdit.Size[txt]; lks: TextLooks.Looks = IF size=0 THEN TextLooks.noLooks ELSE TextEdit.FetchLooks[txt,0]; pattern.searchLooks _ LooksRope[lks]; FOR i: INT IN [1..size) DO IF TextEdit.FetchLooks[txt,i]#lks THEN { MessageWindow.Append["Search pattern does not have uniform looks.",TRUE]; MessageWindow.Append[" Using looks from first char."]; EXIT }; ENDLOOP; literal _ FALSE; patternTxt _ TextEdit.FromRope["#*"]; TextEdit.ChangeLooks[root: NIL, node: patternTxt, remove: TextLooks.allLooks, add: lks]; }; pattern.text _ text; pattern.looks _ looks; pattern.word _ word; pattern.looksExact _ ~subset; pattern.commentControl _ IF ~comment OR txt=NIL THEN includeComments ELSE IF txt.comment THEN commentsOnly ELSE excludeComments; pattern.checkFormat _ format; pattern.format _ IF target=NIL OR target.formatName=NIL THEN NIL ELSE Atom.GetPName[target.formatName]; pattern.checkStyle _ style; pattern.style _ IF ~style THEN NIL ELSE Atom.GetPName[NodeStyleOps.StyleNameForNode[target]]; IF text OR looks THEN { -- create a description of the pattern pattern.finder _ TreeFind.Create[patternTxt, literal, word, ~looks, ~case, addBounds ! TextFind.MalformedPattern => { errorCode _ ec; error _ TRUE; CONTINUE }]; }; IF error THEN ReportMalformedPattern[errorCode]; }; CreateSimplePattern: PUBLIC PROC [ target: ROPE, -- node from which to get the pattern case: BOOL _ TRUE, -- if true, match case literal: BOOL _ FALSE, -- if true, treat target literally rather than as a pattern word: BOOL _ FALSE, -- if true, match words only addBounds: BOOL _ FALSE] -- if true, add |'s to both ends of pattern RETURNS [pattern: TiogaOps.Pattern] = { error: BOOL _ FALSE; errorCode: TextFind.PatternErrorCode; pattern _ NEW[TiogaOps.PatternRec]; pattern.text _ TRUE; pattern.looks _ FALSE; pattern.word _ word; pattern.commentControl _ includeComments; pattern.checkFormat _ FALSE; pattern.format _ NIL; pattern.checkStyle _ FALSE; pattern.style _ NIL; pattern.finder _ TreeFind.CreateFromRope[target, literal, word, ~case, addBounds ! TextFind.MalformedPattern => { errorCode _ ec; error _ TRUE; CONTINUE }]; IF error THEN ReportMalformedPattern[errorCode]; }; FindCC: PROC [cc: TiogaOps.CommentControl] RETURNS [TreeFind.CommentControl] = { RETURN [SELECT cc FROM includeComments => includeComments, excludeComments => excludeComments, commentsOnly => commentsOnly, ENDCASE => ERROR] }; SelectionSearch: PUBLIC PROC [ pattern: TiogaOps.Pattern, whichDir: TiogaOps.SearchDir _ forwards, interrupt: REF BOOL _ NIL, startBoundaryNode, endBoundaryNode: Node _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found: BOOL] = { pSel: TEditDocument.Selection = TEditSelection.pSel; Found: PROC [tSel: TEditDocument.Selection] = { tSel.viewer _ pSel.viewer; tSel.data _ pSel.data; TEditOps.RememberCurrentPosition[pSel.viewer]; TEditSelection.SetSelLooks[tSel]; TEditSelection.MakeSelection[new: tSel]; TEditInput.CloseEvent[]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, FALSE] }; Locations: PROC RETURNS [start, end: TextNode.Location] = { start _ pSel.start.pos; end _ pSel.end.pos }; found _ DoSearch[pattern, whichDir, interrupt, Found, Locations, startBoundaryNode, endBoundaryNode, startBoundaryOffset, endBoundaryOffset] }; DocLoc: PROC [loc: TiogaOpsDefs.Location] RETURNS [TextNode.Location] = { RETURN [[loc.node, loc.where]] }; MyLoc: PROC [loc: TextNode.Location] RETURNS [TiogaOpsDefs.Location] = { RETURN [[loc.node, loc.where]] }; NodeSearch: PUBLIC PROC [ pattern: TiogaOps.Pattern, whichDir: TiogaOps.SearchDir _ forwards, startLoc, endLoc: TiogaOpsDefs.Location, interrupt: REF BOOL _ NIL, startBoundaryNode, endBoundaryNode: Node _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found: BOOL, start, end: TiogaOpsDefs.Location] = { Found: PROC [tSel: TEditDocument.Selection] = { start _ MyLoc[tSel.start.pos]; end _ MyLoc[tSel.end.pos] }; Locations: PROC RETURNS [start, end: TextNode.Location] = { start _ DocLoc[startLoc]; end _ DocLoc[endLoc] }; found _ DoSearch[pattern, whichDir, interrupt, Found, Locations, startBoundaryNode, endBoundaryNode, startBoundaryOffset, endBoundaryOffset] }; DoSearch: PROC [ pattern: TiogaOps.Pattern, whichDir: TiogaOps.SearchDir _ forwards, interrupt: REF BOOL _ NIL, foundProc: PROC [tSel: TEditDocument.Selection], locationProc: PROC RETURNS [start, end: TextNode.Location], startBoundaryNode, endBoundaryNode: Node _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found: BOOL] = { at, atEnd, offset: INT; first: Node; where: Node; startLoc, endLoc: TextNode.Location; DoLookForPattern: PROC [root: Node, tSel: TEditDocument.Selection] = { Forwards: PROC = { IF (offset _ endLoc.where+1) >= TextEdit.Size[first _ endLoc.node] THEN { first _ TextNode.StepForward[first]; offset _ 0 }; [found,where,at,atEnd,,] _ TreeFind.Try[finder: pattern.finder, first: first, start: offset, last: endBoundaryNode, lastLen: endBoundaryOffset, interrupt: interrupt, looksExact: pattern.looksExact, checkFormat: pattern.checkFormat, format: MakeName[pattern.format], commentControl: FindCC[pattern.commentControl], checkStyle: pattern.checkStyle, style: MakeName[pattern.style], styleProc: NodeStyleOps.StyleNameForNode] }; Backwards: PROC = { IF (offset _ startLoc.where)=0 THEN { first _ TextNode.StepBackward[startLoc.node]; offset _ LAST[INT] } ELSE first _ startLoc.node; [found,where,at,atEnd,,] _ TreeFind.TryBackwards[finder: pattern.finder, first: first, len: offset, last: startBoundaryNode, lastStart: startBoundaryOffset, interrupt: interrupt, looksExact: pattern.looksExact, checkFormat: pattern.checkFormat, format: MakeName[pattern.format], commentControl: FindCC[pattern.commentControl], checkStyle: pattern.checkStyle, style: MakeName[pattern.style], styleProc: NodeStyleOps.StyleNameForNode] }; [startLoc, endLoc] _ locationProc[]; IF interrupt#NIL THEN interrupt^ _ FALSE; SELECT whichDir FROM forwards => Forwards[]; backwards => Backwards[]; anywhere => { Forwards[]; IF found THEN whichDir _ forwards ELSE { whichDir _ backwards; Backwards[] } }; ENDCASE => ERROR; IF ~found OR where=NIL THEN RETURN; IF pattern.looks AND ~pattern.text AND ~pattern.word THEN [at,atEnd] _ Extend[whichDir=forwards, pattern.looksExact, RopeToLooks[pattern.searchLooks], where, at, atEnd]; tSel.start.pos _ [where,at]; tSel.end.pos _ [where,MAX[0,atEnd-1]]; tSel.granularity _ IF ~pattern.looks AND ~pattern.text THEN node ELSE IF pattern.word THEN word ELSE char; tSel.insertion _ IF TEditProfile.selectionCaret=before THEN before ELSE after; foundProc[tSel]; }; TEditInputOps.CallWithLocks[DoLookForPattern, read] }; Extend: PROC [forward, looksExact: BOOL, searchLooks: TextLooks.Looks, where: Node, at, atEnd: INT, last: Node _ NIL, lastLen: INT _ LAST[INT] ] RETURNS [newAt, newAtEnd: INT] = { IF forward THEN { -- extend toward end of node size: INT ~ TextEdit.Size[where]; end: INT ~ IF where=last THEN MIN[size, lastLen] ELSE size; WHILE atEnd0 DO looksRun: TextEdit.LooksRun ~ TextEdit.FetchLooksRun[where, at-1]; looks: TextLooks.Looks ~ IF looksExact THEN looksRun.looks ELSE TextLooks.LooksAnd[looksRun.looks, searchLooks]; IF looks=searchLooks THEN at _ looksRun.start ELSE EXIT; ENDLOOP; }; RETURN[at, atEnd]; }; SelectMatchingBrackets: PUBLIC PROC [before, after: CHAR] RETURNS [found: BOOL] = { found _ TEditInputOps.DoSelectMatchingBrackets[before, after] }; NextPlaceholder: PUBLIC PROC [dir: TiogaOps.Dir _ forward, gotoend: BOOL, startBoundaryNode, endBoundaryNode: Node _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found, wenttoend: BOOL] = { [found, wenttoend] _ TEditInputOps.DoFindPlaceholders[ dir=forward, gotoend, startBoundaryNode, endBoundaryNode, startBoundaryOffset, endBoundaryOffset] }; NextViewer: PUBLIC PROC [dir: TiogaOps.Dir _ forward] RETURNS [found: BOOL] = { found _ TEditInputOps.DoNextViewer[dir=forward] }; SearchWhere: PROC [whichDir: TiogaOps.SearchDir] RETURNS [TEditSelection.FindWhere] = INLINE { RETURN [SELECT whichDir FROM forwards => forwards, backwards => backwards, anywhere => anywhere, ENDCASE => ERROR] }; <> Position: PUBLIC PROC [viewer: Viewer] = { TEditSelection.Position[viewer]; }; Normalize: PUBLIC PROC [viewer: Viewer] = { [] _ TEditInput.Normalize[viewer]; }; PrevPlace: PUBLIC PROC [viewer: Viewer] = { TEditDocumentPrivate.JumpToPrevious[viewer]; }; Reselect: PUBLIC PROC [viewer: Viewer] = { TEditDocumentPrivate.Reselect[viewer]; }; <> Save: PUBLIC PROC [viewer: Viewer] = { TEditDocumentPrivate.Save[viewer]; }; Load: PUBLIC PROC [viewer: Viewer, fileName: ROPE _ NIL, fileNameProcViewer: Viewer _ NIL] = { [] _ TEditDocumentPrivate.DoLoadFile[viewer, fileName, FALSE, fileNameProcViewer]; }; Open: PUBLIC PROC [fileName: ROPE _ NIL, fileNameProcViewer: Viewer _ NIL, column: Column _ left] RETURNS [Viewer] = { RETURN [TEditDocumentPrivate.DoOpenFile[fileName, column, fileNameProcViewer]]; }; CloseAndOpen: PUBLIC PROC [viewer: Viewer, fileName: ROPE _ NIL, fileNameProcViewer: Viewer _ NIL] RETURNS [Viewer] = { RETURN [TEditDocumentPrivate.DoLoadFile[viewer, fileName, TRUE, fileNameProcViewer]]; }; LoadImpl: PUBLIC PROC [viewer: Viewer, fileName: ROPE _ NIL] = { [] _ TEditDocumentPrivate.DoLoadImplFile[viewer, fileName]; }; OpenImpl: PUBLIC PROC [fileName: ROPE _ NIL, column: Column _ left] RETURNS [Viewer] = { RETURN [TEditDocumentPrivate.DoOpenImplFile[fileName, column]]; }; CloseAndOpenImpl: PUBLIC PROC [viewer: Viewer, fileName: ROPE _ NIL] RETURNS [Viewer] = { RETURN [TEditDocumentPrivate.DoCloseAndOpenImplFile[viewer, fileName]]; }; LoadPreviousFile: PUBLIC PROC [parent: Viewer] = { TEditDocumentPrivate.LoadPreviousFile[parent]; }; OpenPreviousFile: PUBLIC PROC [parent: Viewer] = { TEditDocumentPrivate.OpenPreviousFile[parent]; }; CloseAndOpenPreviousFile: PUBLIC PROC [parent: Viewer] = { TEditDocumentPrivate.CloseAndOpenPreviousFile[parent]; }; DefaultMenus: PUBLIC PROC [viewer: Viewer, paint: BOOL _ FALSE] = { TEditDocumentPrivate.DefaultMenus[viewer, paint]; }; Store: PUBLIC PROC [viewer: Viewer, fileName: ROPE _ NIL] = { TEditDocumentPrivate.DoStoreFile[viewer, fileName]; }; New: PUBLIC PROC [column: Column _ left] RETURNS [Viewer] = { RETURN [TEditDocumentPrivate.DoNewViewer[column]]; }; Empty: PUBLIC PROC [viewer: Viewer] = { TEditDocumentPrivate.EmptyViewer[viewer]; }; CloseAndNewViewer: PUBLIC PROC [viewer: Viewer] RETURNS [Viewer] = { RETURN [TEditDocumentPrivate.DoCloseAndNewViewer[viewer]]; }; Reset: PUBLIC PROC [viewer: Viewer] = { TEditDocumentPrivate.Reset[viewer]; }; Jump: PUBLIC PROC [viewer: Viewer, loc: TiogaOpsDefs.Location] = { [] _ TEditScrolling.ScrollToPosition[viewer, [loc.node, loc.where]]; }; <> FirstLevelOnly: PUBLIC PROC [viewer: Viewer] = { [] _ TEditInput.FirstLevelOnly[viewer] }; MoreLevels: PUBLIC PROC [viewer: Viewer] = { [] _ TEditInput.MoreLevels[viewer] }; FewerLevels: PUBLIC PROC [viewer: Viewer] = { [] _ TEditInput.FewerLevels[viewer] }; AllLevels: PUBLIC PROC [viewer: Viewer] = { [] _ TEditInput.AllLevels[viewer] }; <> <> GetRope: PUBLIC PROC [node: Node] RETURNS [ROPE] = { RETURN [IF node=NIL THEN NIL ELSE node.rope] }; Parent: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.Parent[node]] }; Root: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.Root[node]] }; Next: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.Next[node]] }; Previous: PUBLIC PROC [node: Node, parent: Node _ NIL] RETURNS [nx: Node] = { RETURN [TextNode.Previous[node]] }; StepForward: PUBLIC PROC [node: Node] RETURNS [nx: Node] = { RETURN [TextNode.StepForward[node]] }; StepBackward: PUBLIC PROC [node: Node, parent: Node _ NIL] RETURNS [back: Node] = { RETURN [TextNode.StepBackward[node, parent]] }; FirstSibling: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.FirstSibling[node]] }; LastSibling: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.LastSibling[node]] }; LastWithin: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.LastWithin[node]] }; LastLocWithin: PUBLIC PROC [node: Node] RETURNS [TiogaOpsDefs.Location] = { loc: TextNode.Location ~ TextNode.LastLocWithin[node]; RETURN [[loc.node, loc.where]]; }; FirstChild: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.FirstChild[node]] }; LastChild: PUBLIC PROC [node: Node] RETURNS [Node] = { RETURN [TextNode.LastChild[node]] }; IsDirty: PUBLIC PROC [node: Node] RETURNS [BOOL] = { RETURN [node.dirty] }; IsNew: PUBLIC PROC [node: Node] RETURNS [BOOL] = { RETURN [node.new] }; ClearDirty: PUBLIC PROC [node: Node] = { node.dirty _ FALSE }; ClearNew: PUBLIC PROC [node: Node] = { node.new _ FALSE }; ViewerDoc: PUBLIC PROC [viewer: Viewer] RETURNS [root: Node] = { tdd: TEditDocument.TEditDocumentData = NARROW[viewer.data]; IF tdd = NIL THEN RETURN [NIL]; [] _ TEditDocument.SpinAndLock[tdd, "ViewerDoc"]; -- make sure nothing else going on root _ tdd.text; TEditDocument.Unlock[tdd] }; <> <<>> PutProp: PUBLIC PROC [n: Node, name: ATOM, value: REF] = { NodeProps.PutProp[n, name, value] }; <<>> GetProp: PUBLIC PROC [n: Node, name: ATOM] RETURNS [REF] = { RETURN [NodeProps.GetProp[n, name]] }; RemProp: PUBLIC PROC [n: Node, name: ATOM] = { NodeProps.RemProp[n, name] }; MapProps: PUBLIC PROC [n: Node, action: TiogaExtraOps.MapPropsAction, formatFlag, commentFlag: BOOL _ TRUE] RETURNS [BOOL] = { RETURN [NodeProps.MapProps[n, action, formatFlag, commentFlag]] }; <> RegisterPropProc: PUBLIC PROC [name: ATOM, reader: NodeProps.ReadSpecsProc, writer: NodeProps.WriteSpecsProc, copier: NodeProps.CopyInfoProc] = { NodeProps.Register[name, reader, writer, copier]; }; NullRead: PUBLIC NodeProps.ReadSpecsProc = { [] _ NodeProps.NullRead[name, specs] }; NullWrite: PUBLIC NodeProps.WriteSpecsProc = { [] _ NodeProps.NullWrite[name, value] }; NullCopy: PUBLIC NodeProps.CopyInfoProc = { [] _ NodeProps.NullCopy[name, value] }; <> <<>> NodeOrder: PROC [order: EditSpan.NodeOrder] RETURNS [TiogaOpsDefs.Order] = { RETURN [SELECT order FROM before => before, same => same, after => after, disjoint => disjoint, ENDCASE => ERROR] }; CompareLocOrder: PUBLIC PROC [loc1, loc2: TiogaOpsDefs.Location] RETURNS [order: TiogaOpsDefs.Order] = { order _ NodeOrder[EditSpan.CompareNodeOrder[loc1.node, loc2.node]]; IF order=same THEN order _ SELECT loc1.where FROM < loc2.where => before, = loc2.where => same, ENDCASE => after }; CompareNodeOrder: PUBLIC PROC [node1, node2: Node] RETURNS [order: TiogaOpsDefs.Order] = { RETURN [NodeOrder[EditSpan.CompareNodeOrder[node1, node2]]] }; <<>> <> <<>> GetFile: PUBLIC PROC [name: ROPE] RETURNS [root: Node] = { RETURN [PutGet.FromFile[name]] }; PutFile: PUBLIC PROC [name: ROPE, root: Node] = { [] _ PutGet.ToFile[name, root] }; FreeTree: PUBLIC PROC [root: Node] = { TEditInput.FreeTree[root] }; <<>> <> <<>> SelectPoint: PUBLIC PROC [viewer: Viewer, caret: TiogaOpsDefs.Location, which: TiogaOpsDefs.WhichSelection _ primary] = { TiogaOps.SetSelection[viewer: viewer, start: caret, end: caret, level: point, which: which]; }; <> <<>> RegisterCommand: PUBLIC PROC [name: ATOM, proc: TiogaOps.CommandProc, before: BOOL _ TRUE] = { TEditInput.Register[name, proc, before] }; UnRegisterCommand: PUBLIC PROC [name: ATOM, proc: TiogaOps.CommandProc] = { TEditInput.UnRegister[name, proc] }; <<>> END.