DIRECTORY Rope, NameSymbolTable, TextLooks; TextNode: CEDAR DEFINITIONS = BEGIN Offset: TYPE = LONG INTEGER _ 0; MaxLen: Offset = LAST[Offset]; ROPE: TYPE = Rope.ROPE; Ref: TYPE = REF Body; Body: TYPE = RECORD [ next: Ref, -- points to next sibling, or if last=true, to parent child: Ref, -- points to first child, if any, of this node props: NodeProps, -- points to node property list class: REF ANY, -- for Scott to play with typename: TypeName _ nullTypeName, -- name of type for the node last: BOOLEAN _ FALSE, -- true if this is last sibling hasstyledef: BOOLEAN _ FALSE, -- true if node has StyleDef prop (simply an accelerator) hasprefix: BOOLEAN _ FALSE, -- true if node has Prefix prop (simply an accelerator) haspostfix: BOOLEAN _ FALSE, -- true if has Postfix prop (also an accelerator) deleted: BOOLEAN _ FALSE, -- true if has been deleted or is root pending delete dirty: BOOLEAN _ FALSE, -- true if has been edited (contents, or children moved, inserted, ...) new: BOOLEAN _ FALSE, -- true if created during this editing session (i.e., not from file) body: SELECT kind:OfNode FROM text => [ comment: BOOLEAN _ FALSE, -- true if node is a comment count: [0..countMax] _ 0, -- incremented by text edit routines rope: ROPE, runs: TextLooks.Runs ], other => [ variety: ATOM, info: REF ANY ], ENDCASE]; Location: TYPE = RECORD [node: Ref, where: Offset]; NodeItself: Offset = -1; nullLocation: Location = [NIL,NodeItself]; MakeNodeLoc: PROC [n: Ref] RETURNS [Location] = INLINE { RETURN [[n,NodeItself]] }; Span: TYPE = RECORD [start, end: Location _ nullLocation]; nullSpan: Span = [nullLocation,nullLocation]; MakeNodeSpan: PROC [first, last: Ref] RETURNS [Span] = INLINE { RETURN [[MakeNodeLoc[first],MakeNodeLoc[last]]] }; countMax: NAT=63; -- 6 bits for count OfNode: TYPE = {text,other}; TextBody: TYPE = text Body; RefTextNode: TYPE = REF TextBody; OtherBody: TYPE = other Body; RefOtherNode: TYPE = REF OtherBody; NodeList: TYPE = REF NodeListBody; NodeListBody: TYPE = RECORD [node: Ref, next: NodeList]; NodeProps: TYPE = REF NodePropsBody; NodePropsBody: TYPE; -- exported by NodePropsImpl NewTextNode: PROC RETURNS [txt: RefTextNode]; NewOtherNode: PROC RETURNS [oth: RefOtherNode]; NarrowToTextNode: PROC [n: Ref] RETURNS [txt: RefTextNode] = TRUSTED INLINE { IF n#NIL THEN WITH x:n SELECT FROM text => txt _ @x; ENDCASE }; NarrowToOtherNode: PROC [n: Ref] RETURNS [othr: RefOtherNode] = TRUSTED INLINE { IF n#NIL THEN WITH x:n SELECT FROM other => othr _ @x; ENDCASE }; Parent: PROC [n: Ref] RETURNS [Ref]; Root: PROC [n: Ref] RETURNS [Ref]; Next: PROC [n: Ref] RETURNS [Ref]; Previous: PROC [n: Ref, parent: Ref _ NIL] RETURNS [nx: Ref]; StepForward: PROC [node: Ref] RETURNS [nx: Ref] = INLINE { [nx,] _ Forward[node] }; StepBackward: PROC [node: Ref, parent: Ref _ NIL] RETURNS [back: Ref] = INLINE { [back,,] _ Backward[node,parent] }; Forward: PROC [node: Ref] RETURNS [nx: Ref, levelDelta: INTEGER]; Backward: PROC [node: Ref, parent: Ref _ NIL] RETURNS [back, backparent: Ref, levelDelta: INTEGER]; Level: PROC [node: Ref] RETURNS [level: INTEGER]; ForwardClipped: PROC [ node: Ref, maxLevel: INTEGER, nodeLevel: INTEGER _ 0] RETURNS [nx: Ref, nxLevel: INTEGER]; BackwardClipped: PROC [ node: Ref, maxLevel: INTEGER, parent: Ref _ NIL, nodeLevel: INTEGER _ 0] RETURNS [back, backparent: Ref, backLevel: INTEGER]; LocRelative: PROC [location: Location, count: Offset, break: NAT _ 1, skipCommentNodes: BOOLEAN _ FALSE] RETURNS [Location]; LocWithin: PROC [n: Ref, count: Offset, break: NAT _ 1, skipCommentNodes: BOOLEAN _ FALSE] RETURNS [Location] = INLINE { RETURN [LocRelative[[n,0],count,break,skipCommentNodes]] }; LocOffset: PROC [loc1, loc2: Location, break: NAT _ 1, skipCommentNodes: BOOLEAN _ FALSE] RETURNS [count: Offset]; BadArgs: ERROR; LocNumber: PROC [at: Location, break: NAT _ 1, skipCommentNodes: BOOLEAN _ FALSE] RETURNS [count: Offset] = INLINE { RETURN [LocOffset[[Root[at.node],0],at,break,skipCommentNodes]] }; FirstSibling: PROC [n: Ref] RETURNS [Ref]; LastSibling: PROC [n: Ref] RETURNS [Ref]; LastWithin: PROC [n: Ref] RETURNS [Ref]; LastLocWithin: PROC [n: Ref] RETURNS [Location]; FirstChild: PROC [n: Ref] RETURNS [Ref]; LastChild: PROC [n: Ref] RETURNS [Ref]; NthChild: PROC [n: Ref, location: Offset] RETURNS [child: Ref]; NthSibling: PROC [n: Ref, cnt: Offset] RETURNS [Ref]; CountChildren: PROC [n: Ref] RETURNS [count: Offset]; CountFollowing: PROC [n: Ref] RETURNS [count: Offset]; CountToParent: PROC [n: Ref] RETURNS [count: Offset, parent: Ref]; CountToChild: PROC [parent, child: Ref] RETURNS [count: Offset]; NodeRope: PROC [n: RefTextNode] RETURNS [ROPE]; NodeRuns: PROC [n: RefTextNode] RETURNS [TextLooks.Runs]; Props: PROC [n: Ref] RETURNS [NodeProps]; NodeType: PROC [n: Ref] RETURNS [TypeName]; IsLastSibling: PROC [n: Ref] RETURNS [BOOLEAN]; EndPos: PROC [n: Ref] RETURNS [Offset]; TypeName: TYPE = NameSymbolTable.Name; nullTypeName: TypeName = NameSymbolTable.nullName; qZone: ZONE; -- quantized zone pZone: ZONE; -- prefix zone Start: PROC; END. -- TextNode.Mesa -- written by Bill Paxton. December 1980 -- last written by Paxton. December 21, 1982 9:46 am Last Edited by: Maxwell, January 5, 1983 12:37 pm -- where >= length of text means at end -- where = loc in [0..length) means before that character -- e.g., where = 0 means at start of text -- where = NodeItself means location is the node itself rather than in its contents -- start.node can equal end.node -- in which case either both start.where and end.where = NodeItself, or -- neither do and start.where <= end.where -- otherwise, end.node should follow start.node in the tree -- nodes need not be siblings -- no restrictions on start.where or end.where -- here are some access procedures for use with nodes -- returns n as a RefTextNode if possible, else returns NIL -- returns n as a RefOtherNode if possible, else returns NIL -- returns next sibling of n -- returns NIL if n is last sibling -- returns previous sibling of n -- returns NIL if n is first sibling -- runs faster if can supply parent -- returns next node in standard tree walk order -- returns preceeding node in standard tree walk order -- returns next node in standard tree walk order -- levelDelta is level(node)-level(nx), where level is depth in tree -- levelDelta = 0 if nx and node are siblings -- levelDelta = 1 if nx is child of node -- levelDelta < 0 if do Parent* and Next to reach nx from node -- for backing through tree -- runs faster if can supply parent -- levelDelta same as for Forward -- Level[Root[x]] == 0; Level[FirstChild[n]]=Level[n]+1 -- like Forward, but limits how deep will go in tree -- if pass nodeLevel=0, correct value will be computed -- nxLevel = Level[nx] <= MAX[maxLevel,Level[node]] -- like Backward, but limits how deep will go in tree -- backLevel = Level[back] <= MAX[maxLevel,Level[node]] -- count is interpreted as a character offset from given location -- returns location corresponding to count -- adds in break at the end of each text subnode -- if skipCommentNodes is true, then ignores them in walking the tree -- returns character offset of location2 relative to location1 -- loc1 and loc2 can be in same node -- but loc2 must not be in node before loc1 or get ERROR BadArgs -- if skipCommentNodes is true, then ignores them in walking the tree -- returns character offset of location relative to root -- returns the last node within the branch -- i.e., goes to last child of last child of last child ... until no child -- returns the last location within the branch -- TypeNames are the same as names in NameSymbolTable -- Initialization Ê~˜JšÏc™Jš(™(Jš4™4J™1šÏk ˜ J˜J˜J˜ J˜—Jšœ žœ˜Jšž˜J˜Jšœžœžœžœ˜ Jšœžœ ˜Jšžœžœžœ˜J˜Jšœžœžœ˜šœžœžœ˜Jšœ 5˜@Jšœ .˜:Jšœ˜1Jšœžœžœ˜)Jšœ#˜?Jšœžœžœ˜6Jšœ žœžœ9˜WJšœ žœžœ7˜SJšœ žœžœ1˜NJšœ žœžœ5˜OJšœžœžœG˜_JšœžœžœD˜Zšœžœ ž˜˜ Jšœ žœžœ˜6Jšœ$˜>Jšœžœ˜ J˜—Jšœžœžœžœ˜*Jšžœ˜ J˜——šœ žœžœ˜3Jš'™'š9™9Jš)™)—JšS™SJ˜—J˜J˜Jšœžœ ˜*J˜Jš Ïn œžœ žœžœžœ˜SJ˜šœžœžœ'˜:š ™ JšG™GJš*™*—š;™;Jš™Jš.™.J˜——J˜-J˜šŸ œžœžœ žœ˜?Jšžœ,˜2J˜—Jšœ žœ˜%Jšœžœ˜J˜Jšœ žœ ˜Jšœ žœžœ ˜!Jšœ žœ˜Jšœžœžœ ˜#J˜Jšœ žœžœ˜"Jšœžœžœ˜8J˜Jšœ žœžœ˜$Jšœžœ˜1J˜Jš5™5J˜JšŸ œžœžœ˜-J˜JšŸ œžœžœ˜/J˜š Ÿœžœ žœžœžœ˜MJš;™;Jšžœžœžœžœžœžœžœ˜?J˜—š Ÿœžœ žœžœžœ˜PJš<™™>J˜——šŸœžœžœ˜-Jšžœ%žœ˜5Jš™Jš#™#Jš!™!J˜—šŸœžœ žœ žœ˜1Jš7™7J˜—šŸœžœ˜Jšœžœ žœ˜5Jšžœžœ˜$Jš4™4Jš7™7Jš3™3J˜—šŸœžœ˜Jšœžœžœ žœ˜HJšžœ$žœ˜4Jš5™5Jš7™7J˜—š Ÿ œžœ,žœžœžœ˜hJšžœ ˜JšA™AJš8™8Jš0™0JšE™EJ˜—š Ÿ œžœ žœžœžœ˜ZJšžœžœžœ5˜YJ˜—šŸ œžœ˜&Jš œžœžœžœžœ˜KJš>™>Jš$™$Jš@™@JšE™EJ˜—Jšœ žœ˜J˜š Ÿ œžœžœžœžœ˜QJšžœžœ˜"Jšžœ<˜BJš8™8J˜—JšŸ œžœ žœ˜*J˜JšŸ œžœ žœ˜)J˜šŸ œžœ žœ˜(Jš+™+JšJ™JJ˜—šŸ œžœ žœ ˜0Jš/™/J˜—JšŸ œžœ žœ˜(J˜JšŸ œžœ žœ˜'J˜JšŸœžœžœ˜?J˜JšŸ œžœžœ˜5J˜JšŸ œžœ žœ˜5J˜JšŸœžœ žœ˜6J˜JšŸ œžœ žœ˜BJ˜JšŸ œžœžœ˜@J˜JšŸœžœžœžœ˜/J˜JšŸœžœžœ˜9J˜JšŸœžœ žœ ˜)J˜JšŸœžœ žœ ˜+J˜JšŸ œžœ žœžœ˜/J˜JšŸœžœ žœ ˜'J˜Jš5™5J˜Jšœ žœ˜&J˜2J˜Jšœžœ˜Jšœžœ˜J˜Jš™J˜JšŸœžœ˜ J˜Jšžœ˜J˜—…—à&~