<> <> <> DIRECTORY FS USING [OpenFile], ImagerFont USING [BYTE, XChar], IO USING [STREAM], Rope USING [ROPE], TextLooks USING [Looks, allLooks, noLooks, Runs]; Tioga: CEDAR DEFINITIONS ~ BEGIN <> <> CharSet: TYPE ~ ImagerFont.BYTE; XChar: TYPE ~ ImagerFont.XChar; ROPE: TYPE ~ Rope.ROPE; Runs: TYPE ~ TextLooks.Runs; Looks: TYPE ~ TextLooks.Looks; noLooks: Looks ~ TextLooks.noLooks; allLooks: Looks ~ TextLooks.allLooks; <> Node: TYPE ~ REF NodeBody; NodeBody: TYPE ~ RECORD [ next: Node, -- points to next sibling, or if last=true, to parent child: Node, -- points to first child, if any, of this node props: Props, -- points to node property list formatName: ATOM _ NIL, -- name of format for the node last: BOOL _ FALSE, -- true if this is last sibling hasstyledef: BOOL _ FALSE, -- true if node has StyleDef prop (accelerator) hasprefix: BOOL _ FALSE, -- true if node has Prefix prop (accelerator) haspostfix: BOOL _ FALSE, -- true if node has Postfix prop (accelerator) hascharprops: BOOL _ FALSE, -- true if node has CharProps prop (accelerator) hascharsets: BOOL _ FALSE, -- true if node has CharSets prop (accelerator) hasartwork: BOOL _ FALSE, -- true if node has Artwork prop (accelerator) deleted: BOOL _ FALSE, -- true if has been deleted or is root pending delete dirty: BOOL _ FALSE, -- true if has been edited (contents, or children moved, inserted, ...) new: BOOL _ FALSE, -- true if created during this editing session (i.e., not from file) comment: BOOL _ FALSE, -- true if node is a comment count: [0..countMax] _ 0, -- incremented by text edit routines rope: ROPE, runs: Runs ]; Props: TYPE ~ REF PropsBody; PropsBody: TYPE ~ RECORD [name: ATOM, value: REF, next: Props]; countMax: NAT ~ 37B; -- 5 bits for count <> maxLen: INT ~ INT.LAST; nodeItself: INT ~ -1; Location: TYPE ~ RECORD [node: Node, where: INT _ 0]; <= length of text means at end>> <> <> <> nullLocation: Location ~ [node: NIL, where: nodeItself]; MakeNodeLoc: PROC [n: Node] RETURNS [Location] ~ INLINE { RETURN [[node: n, where: nodeItself]] }; Text: TYPE ~ RECORD [node: Node, start: INT _ 0, len: INT _ maxLen]; <> end: PROC [text: Text] RETURNS [INT] ~ INLINE { RETURN[text.start+text.len] }; <> Span: TYPE ~ RECORD [start, end: Location _ nullLocation]; <> <> <> <> <> <> nullSpan: Span ~ [nullLocation, nullLocation]; MakeNodeSpan: PROC [first, last: Node] RETURNS [Span] ~ INLINE { RETURN [[MakeNodeLoc[first], MakeNodeLoc[last]]] }; <> World: TYPE ~ REF WorldRep; WorldRep: TYPE; <> <> Parent: PROC [n: Node] RETURNS [Node]; <> <> Root: PROC [n: Node] RETURNS [Node]; <> Next: PROC [n: Node] RETURNS [Node]; <> <> Previous: PROC [n: Node, parent: Node _ NIL] RETURNS [Node]; <> <> <> IsLastSibling: PROC [n: Node] RETURNS [BOOL]; <> FirstChild: PROC [n: Node] RETURNS [Node]; <> LastChild: PROC [n: Node] RETURNS [Node]; <> FirstSibling: PROC [n: Node] RETURNS [Node]; <> LastSibling: PROC [n: Node] RETURNS [Node]; <> LastWithin: PROC [n: Node] RETURNS [Node]; <> <> Level: PROC [n: Node] RETURNS [INT]; <> <> NthChild: PROC [n: Node, index: INT] RETURNS [Node]; <> NthSibling: PROC [n: Node, index: INT] RETURNS [Node]; CountChildren: PROC [n: Node] RETURNS [count: INT]; CountFollowing: PROC [n: Node] RETURNS [count: INT]; CountToParent: PROC [n: Node] RETURNS [count: INT, parent: Node]; CountToChild: PROC [parent, child: Node] RETURNS [count: INT]; <> Forward: PROC [node: Node] RETURNS [nx: Node, levelDelta: INT]; <> <> <> <> <> Backward: PROC [node: Node, parent: Node _ NIL] RETURNS [back, backparent: Node, levelDelta: INT]; <> <> <> StepForward: PROC [node: Node] RETURNS [Node]; <> StepBackward: PROC [node: Node, parent: Node _ NIL] RETURNS [Node]; <> <> ForwardClipped: PROC [node: Node, maxLevel: INT, nodeLevel: INT _ 0] RETURNS [nx: Node, nxLevel: INT]; <> <> <> BackwardClipped: PROC [node: Node, maxLevel: INT, parent: Node _ NIL, nodeLevel: INT _ 0] RETURNS [back, backparent: Node, backLevel: INT]; <> <> <> BadArgs: ERROR; LocRelative: PROC [location: Location, count: INT, break: INT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [Location]; <> < location corresponding to count>> <> <> LocWithin: PROC [n: Node, count: INT, break: INT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [Location]; <> LocOffset: PROC [loc1, loc2: Location, break: INT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [count: INT]; <> <> <> <> LocNumber: PROC [at: Location, break: INT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [count: INT]; <> LastLocWithin: PROC [n: Node] RETURNS [Location]; <> <> Order: TYPE ~ { before, same, after, disjoint }; <<>> CompareNodeOrder: PROC [node1, node2: Node] RETURNS [Order]; <> <> <> <> <> CompareLocOrder: PROC [loc1, loc2: Location] RETURNS [Order]; <> <> NewNode: PROC RETURNS [Node]; NodeFromRope: PROC [rope: ROPE, looks: Looks _ noLooks] RETURNS [Node]; <> RopeFromString: PROC [string: REF READONLY TEXT, start: NAT _ 0, len: NAT _ NAT.LAST] RETURNS [ROPE]; <> <<>> DocFromNode: PROC [child: Node] RETURNS [root: Node]; <> <> <<>> <> Size: PROC [node: Node] RETURNS [INT]; FetchChar: PROC [node: Node, index: INT] RETURNS [XChar]; <> <> FetchLooks: PROC [node: Node, index: INT] RETURNS [Looks]; <> <> Fetch: PROC [node: Node, index: INT] RETURNS [char: XChar, looks: Looks]; <> <> GetRope: PROC [node: Node] RETURNS [ROPE]; GetRuns: PROC [node: Node] RETURNS [Runs]; <> PropList: TYPE ~ LIST OF Prop; -- assumed immutable! Prop: TYPE ~ REF PropRep; PropRep: TYPE ~ RECORD [name: ATOM, value: REF]; PropListGet: PROC [propList: PropList, name: ATOM] RETURNS [value: REF]; PropListPut: PROC [propList: PropList, name: ATOM, value: REF] RETURNS [PropList]; <<>> MapPropsAction: TYPE ~ PROC [name: ATOM, value: REF] RETURNS [quit: BOOL _ FALSE]; PropListMap: PROC [propList: PropList, action: MapPropsAction] RETURNS [quit: BOOL]; <<>> <> GetProp: PROC [node: Node, name: ATOM] RETURNS [REF]; GetFormat: PROC [node: Node] RETURNS [ATOM]; GetComment: PROC [node: Node] RETURNS [BOOL]; MapProps: PROC [node: Node, action: MapPropsAction, formatFlag, commentFlag: BOOL _ TRUE] RETURNS [quit: BOOL]; <> <> <> <> <<>> GetCharProp: PROC [node: Node, index: INT, name: ATOM] RETURNS [REF]; GetCharPropList: PROC [node: Node, index: INT] RETURNS [PropList]; MapCharProps: PROC [node: Node, index: INT, action: MapPropsAction] RETURNS [quit: BOOL]; <> <<>> <> PropReader: TYPE ~ PROC [name: ATOM, specs: ROPE] RETURNS [value: REF]; <> PropWriter: TYPE ~ PROC [name: ATOM, value: REF] RETURNS [specs: ROPE]; <> PropCopier: TYPE ~ PROC [name: ATOM, value: REF] RETURNS [new: REF]; <> ReadProp: PropReader; <> <> WriteProp: PropWriter; <> <> <<>> CopyProp: PropCopier; <> <> <<>> NullRead: PropReader; NullWrite: PropWriter; NullCopy: PropCopier; <> <<>> RegisterProp: PROC [name: ATOM, reader: PropReader, writer: PropWriter, copier: PropCopier]; <> <> <> <> ReplaceByRope: PROC [world: World, root: Node, dest: Text, rope: ROPE, inherit: BOOL _ TRUE, looks: Looks _ noLooks, charSet: CharSet _ 0] RETURNS [Text]; <> <> <> <> < 0, then get looks from previous char,>> <> <> InsertRope: PROC [world: World, root: Node, dest: Location, rope: ROPE, inherit: BOOL _ TRUE, looks: Looks _ noLooks, charSet: CharSet _ 0] RETURNS [Text] ~ INLINE{ RETURN ReplaceByRope[world: world, root: root, dest: [dest.node, dest.where, 0], rope: rope, inherit: inherit, looks: looks, charSet: charSet] }; AppendRope: PROC [world: World, root: Node, dest: Node, rope: ROPE, inherit: BOOL _ TRUE, looks: Looks _ noLooks, charSet: CharSet _ 0] RETURNS [Text] ~ INLINE{ RETURN ReplaceByRope[world: world, root: root, dest: [dest, maxLen, 0], rope: rope, inherit: inherit, looks: looks, charSet: charSet] }; <> <> ReplaceText: PROC [world: World, destRoot, sourceRoot: Node, dest: Text, source: Text] RETURNS [result: Text]; <> <> <> DeleteText: PROC [world: World, root: Node, text: Text]; <> <> CopyText: PROC [world: World, destRoot, sourceRoot: Node, dest: Location, source: Text] RETURNS [result: Text]; <> <> MoveText: PROC [world: World, destRoot, sourceRoot: Node, dest: Location, source: Text] RETURNS [result: Text]; <> <> <> <> <> MoveTextOnto: PROC [world: World, destRoot, sourceRoot: Node, dest: Text, source: Text] RETURNS [result: Text]; <> <> TransposeText: PROC [world: World, alphaRoot, betaRoot: Node, alpha: Text, beta: Text] RETURNS [alphaResult: Text, betaResult: Text]; <> <> <> <> <> Place: TYPE ~ { before, after, sibling, child }; <> <> <> <> <> <> Replace: PROC [world: World, destRoot, sourceRoot: Node, dest, source: Span, saveForPaste: BOOL _ TRUE] RETURNS [result: Span]; <> <> Delete: PROC [world: World, root: Node, del: Span, saveForPaste: BOOL _ TRUE]; SaveForPaste: PROC [world: World, span: Span]; SavedForPaste: PROC [world: World] RETURNS [span: Span]; <> Copy: PROC [world: World, destRoot, sourceRoot: Node, dest: Location, source: Span, where: Place _ after, nesting: INT _ 0] RETURNS [result: Span]; <> Move: PROC [world: World, destRoot, sourceRoot: Node, dest: Location, source: Span, where: Place _ after, nesting: INT _ 0] RETURNS [result: Span]; <> <> <> <> MoveOnto: PROC [world: World, destRoot, sourceRoot: Node, dest, source: Span, saveForPaste: BOOL _ TRUE] RETURNS [result: Span]; <> <> Transpose: PROC [world: World, alphaRoot, betaRoot: Node, alpha, beta: Span] RETURNS [newAlpha, newBeta: Span]; <> <> CannotDoEdit: ERROR; <> Insert: PROC [world: World, root: Node, old: Node, where: Place _ after, inherit: BOOL _ TRUE] RETURNS [new: Node]; <> <> Split: PROC [world: World, root: Node, loc: Location] RETURNS [new: Node]; <> <> <> <> <> <> Merge: PROC [world: World, root: Node, node: Node] RETURNS [loc: Location]; <> <> ChangeNesting: PROC [world: World, root: Node, span: Span, change: INT] RETURNS [Span]; <> <0 is deeper in the tree, change<0 is shallower>> <> SetProp: PROC [world: World, node: Node, name: ATOM, value: REF, root: Node _ NIL]; SetComment: PROC [world: World, node: Node, comment: BOOL, root: Node _ NIL]; <> SetFormat: PROC [world: World, node: Node, formatName: ATOM, root: Node _ NIL]; <> SetStyle: PROC [world: World, node: Node, styleName: ROPE, root: Node _ NIL]; < style to end of node prefix>> <> SetCharProp: PROC [world: World, text: Text, name: ATOM, value: REF, root: Node _ NIL]; <> <> SetCharPropList: PROC [world: World, text: Text, propList: PropList, root: Node _ NIL]; ModifyPropsAction: TYPE ~ PROC [value: REF, start: INT, len: INT] RETURNS [quit: BOOL _ FALSE, newValue: REF]; ModifyCharProps: PROC [world: World, text: Text, name: ATOM, action: ModifyPropsAction, root: Node _ NIL] RETURNS [quit: BOOL]; <> <<>> <> ChangeTextLooks: PROC [world: World, root: Node, text: Text, remove, add: Looks]; <> ChangeLooks: PROC [world: World, root: Node, span: Span, remove, add: Looks]; <> CapChange: TYPE ~ {allCaps, allLower, initCaps, firstCap}; ChangeTextCaps: PROC [world: World, root: Node, text: Text, how: CapChange _ allCaps]; ChangeCaps: PROC [world: World, root: Node, span: Span, how: CapChange _ allCaps]; <> <> <<"Find" operation for text nodes>> <<>> <> <> <> <> <> <> <> <> MalformedPattern: ERROR [ec: PatternErrorCode]; PatternErrorCode: TYPE = { toobig, -- pattern too long endquote, -- pattern ends with ' endtilda, -- pattern ends with ~ boundary, -- pattern has | inside rather than at beginning or end missingNameEnd, -- pattern has < without matching > unmatchedNameEnd -- pattern has > without previous < }; Finder: TYPE = REF FinderRec; FinderRec: TYPE; FinderFromText: PROC [pattern: Text, literal, word, ignoreLooks, ignoreCase, addBounds: BOOL _ FALSE] RETURNS [finder: Finder]; <> <> <> <> <> <> <> FinderFromRope: PROC [pattern: ROPE, start: INT _ 0, len: INT _ maxLen, literal, word, ignoreCase, addBounds: BOOL _ FALSE] RETURNS [finder: Finder]; NameLoc: PROC [finder: Finder, name: ROPE] RETURNS [at, atEnd: INT]; <> <> NameLooks: PROC [finder: Finder, name: ROPE] RETURNS [looks: Looks]; <> <> SearchDirection: TYPE ~ {forward, backward}; SearchText: PROC [finder: Finder, text: Text, looksExact: BOOL _ FALSE, direction: SearchDirection _ forward, interrupt: REF BOOL _ NIL ] RETURNS [found: BOOL, at, atEnd, before, after: INT]; <> <> <> <> <> <> <> < atEnd if used } in pattern>> <> <> <> SearchRope: PROC [finder: Finder, rope: ROPE, start: INT _ 0, len: INT _ maxLen, direction: SearchDirection _ forward, interrupt: REF BOOL _ NIL ] RETURNS [found: BOOL, at, atEnd, before, after: INT]; <> CommentControl: TYPE = { includeComments, excludeComments, commentsOnly }; Search: PROC [finder: Finder, span: Span, looksExact: BOOL _ FALSE, commentControl: CommentControl _ includeComments, checkFormat: BOOL _ FALSE, format: ATOM _ NIL, checkStyle: BOOL _ FALSE, style: ATOM _ NIL, styleProc: PROC [Node] RETURNS [ATOM] _ NIL, direction: SearchDirection _ forward, interrupt: REF BOOL _ NIL ] RETURNS [found: BOOL, where: Node, at, atEnd, before, after: INT]; <> <> <> <> <> <> <> < atEnd if used } in pattern>> <> <> <> <> <> <> <> <> SearchApplyProc: TYPE = PROC [where: Node, at, atEnd, before, after: INT] RETURNS [continue, bumpCount: BOOL, from, delta: INT]; <> <> <> <> <> <> <> SearchApply: PROC [finder: Finder, span: Span, proc: SearchApplyProc, looksExact: BOOL _ FALSE, commentControl: CommentControl _ includeComments, checkFormat: BOOL _ FALSE, format: ATOM _ NIL, checkStyle: BOOL _ FALSE, style: ATOM _ NIL, styleProc: PROC [Node] RETURNS [ATOM] _ NIL ] RETURNS [count: INT]; <> <> <> ToStream: PROC [stream: IO.STREAM, node: Node, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT]; <> <> FromStream: PROC [stream: IO.STREAM, len: INT _ maxLen] RETURNS [Node]; <> ToStreamPlain: PROC [stream: IO.STREAM, root: Node, restoreDashes: BOOL _ FALSE]; <> ToFile: PROC [fileName: ROPE, node: Node, start: INT _ 0, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT]; ToFileC: PROC [file: FS.OpenFile, node: Node, start: INT _ 0, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT]; <> <> <> <> FromFile: PROC [fileName: ROPE, start: INT _ 0, len: INT _ maxLen] RETURNS [Node]; FromFileC: PROC [file: FS.OpenFile, start: INT _ 0, len: INT _ maxLen] RETURNS [Node]; <> <> <> <> <> FromFileError: ERROR; ToFilePlain: PROC [fileName: ROPE, root: Node, restoreDashes: BOOL _ FALSE]; ToFileCPlain: PROC [file: FS.OpenFile, root: Node, restoreDashes: BOOL _ FALSE]; <> <> ReadIndent: PROC [fileName: ROPE, tabIndent: NAT _ 4] RETURNS [Node]; <<>> <> ToRope: PROC [node: Node, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT, output: ROPE]; <> FromRope: PROC [rope: ROPE, start: INT _ 0, len: INT _ maxLen] RETURNS [Node]; <> ToRopePlain: PROC [root: Node, restoreDashes: BOOL _ FALSE] RETURNS [output: ROPE]; END.