DIRECTORY TextNode, TextLooks, Rope, RopeEdit, SafeStorage; TextNodeImpl: CEDAR PROGRAM IMPORTS SafeStorage, RopeEdit, TextNode EXPORTS TextNode = BEGIN OPEN TextNode; qZone: PUBLIC ZONE _ SafeStorage.NewZone[quantized]; -- quantized zone pZone: PUBLIC ZONE _ SafeStorage.NewZone[prefixed]; -- prefix zone NewTextNode: PUBLIC PROC RETURNS [txt: RefTextNode] = { txt _ qZone.NEW[TextBody]; txt.last _ TRUE }; NewOtherNode: PUBLIC PROC RETURNS [oth: RefOtherNode] = { oth _ qZone.NEW[OtherBody]; oth.last _ TRUE }; Parent: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN [InlineParent[n]] }; InlineParent: PROC [n: Ref] RETURNS [Ref] = INLINE { DO IF n=NIL OR n.deleted THEN RETURN [NIL]; IF n.last THEN RETURN [n.next]; n _ n.next; ENDLOOP }; Root: PUBLIC PROC [n: Ref] RETURNS [Ref] = { p: Ref; DO IF (p _ InlineParent[n])=NIL THEN RETURN [IF n=NIL OR n.deleted THEN NIL ELSE n]; n _ p; ENDLOOP }; Next: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[IF n=NIL OR n.last OR n.deleted THEN NIL ELSE n.next] }; Previous: PUBLIC PROC [n: Ref, parent: Ref _ NIL] RETURNS [nx: Ref] = { nx2: Ref; IF parent=NIL THEN parent _ InlineParent[n]; IF n=NIL OR parent=NIL OR (nx _ parent.child)=n THEN RETURN [NIL]; DO IF (nx2_nx.next)=n THEN RETURN; nx _ nx2; ENDLOOP }; Forward: PUBLIC PROC [node: Ref] RETURNS [nx: Ref, levelDelta: INTEGER] = { [nx, levelDelta] _ InlineForward[node] }; InlineForward: PROC [node: Ref] RETURNS [nx: Ref, levelDelta: INTEGER] = INLINE { child: Ref; IF node=NIL THEN RETURN [NIL,0]; IF (child _ node.child) # NIL THEN RETURN [child,1]; -- descend in the tree levelDelta _ 0; DO -- move to next node, sibling or up* then sibling IF ~node.last THEN RETURN [node.next,levelDelta]; -- the sibling IF (node _ node.next) = NIL THEN RETURN [NIL,levelDelta]; -- the parent levelDelta _ levelDelta-1; ENDLOOP }; Backward: PUBLIC PROC [node: Ref, parent: Ref _ NIL] RETURNS [back, backparent: Ref, levelDelta: INTEGER] = { child, child2: Ref; IF parent = NIL THEN parent _ InlineParent[node]; IF parent = NIL OR node = NIL THEN RETURN [NIL,NIL,0]; IF (child _ parent.child) = node THEN RETURN [parent,Parent[parent],-1]; DO IF child.last THEN ERROR; -- incorrect value supplied for parent IF (child2 _ child.next)=node THEN EXIT; child _ child2; ENDLOOP; levelDelta _ 0; DO IF (child2 _ LastChild[child]) = NIL THEN RETURN [child,parent,levelDelta]; levelDelta _ levelDelta+1; parent _ child; child _ child2; ENDLOOP }; Level: PUBLIC PROC [node: Ref] RETURNS [level: INTEGER] = { level _ 0; UNTIL (node _ InlineParent[node])=NIL DO level _ level+1; ENDLOOP }; ForwardClipped: PUBLIC PROC [ node: Ref, maxLevel: INTEGER, nodeLevel: INTEGER _ 0] RETURNS [nx: Ref, nxLevel: INTEGER] = { child: Ref; IF node=NIL THEN RETURN [NIL,0]; IF nodeLevel <= 0 THEN nodeLevel _ Level[node]; IF nodeLevel < maxLevel AND (child _ node.child) # NIL THEN RETURN [child,nodeLevel+1]; -- return the child DO -- move to next node, sibling or up* then sibling IF ~node.last THEN RETURN [node.next,nodeLevel]; -- return the sibling IF (node _ node.next) = NIL THEN RETURN [NIL,0]; -- go to the parent nodeLevel _ nodeLevel-1; ENDLOOP }; BackwardClipped: PUBLIC PROC [ node: Ref, maxLevel: INTEGER, parent: Ref _ NIL, nodeLevel: INTEGER _ 0] RETURNS [back, backparent: Ref, backLevel: INTEGER] = { child, child2: Ref; IF parent = NIL THEN parent _ InlineParent[node]; IF parent = NIL OR node = NIL THEN RETURN [NIL,NIL,0]; IF nodeLevel <= 0 THEN nodeLevel _ Level[node]; IF (child _ parent.child) = node THEN RETURN [parent,InlineParent[parent],nodeLevel-1]; DO -- search for sibling just before node IF child.last THEN ERROR; -- incorrect value supplied for parent IF (child2 _ child.next)=node THEN EXIT; child _ child2; ENDLOOP; DO -- go deeper in tree until reach maxLevel IF nodeLevel >= maxLevel OR (child2 _ LastChild[child]) = NIL THEN RETURN [child,parent,nodeLevel]; nodeLevel _ nodeLevel+1; parent _ child; child _ child2; ENDLOOP }; LocRelative: PUBLIC PROC [location: Location, count: Offset, break: NAT _ 1, skipCommentNodes: BOOLEAN _ FALSE] RETURNS [Location] = { n: Ref _ location.node; size, lastSize, where: Offset; init: Ref _ n; txt, lastTxt: RefTextNode; IF count=0 AND InlineParent[n]=NIL THEN RETURN [[FirstChild[n],0]]; -- avoid returning root node where _ MAX[location.where,0]; -- where we are in the current node WHILE n # NIL DO txt _ NarrowToTextNode[n]; IF txt # NIL AND (~skipCommentNodes OR ~txt.comment) THEN { lastSize _ size _ RopeEdit.Size[txt.rope]; IF (count _ count-(size-where)) <= 0 THEN RETURN [[n,MAX[0,count+size]]]; lastTxt _ txt; count _ count-break }; [n,] _ InlineForward[n]; where _ 0; ENDLOOP; IF lastTxt # NIL THEN RETURN [[lastTxt,lastSize]]; -- end of last text node RETURN [[init,0]] }; BadArgs: PUBLIC ERROR = CODE; LocOffset: PUBLIC PROC [loc1, loc2: Location, break: NAT _ 1, skipCommentNodes: BOOLEAN _ FALSE] RETURNS [count: Offset] = { node: Ref _ loc2.node; n: Ref _ loc1.node; txt: RefTextNode; count _ IF loc2.where # NodeItself THEN loc2.where ELSE 0; count _ count - MAX[loc1.where,0]; DO -- add in counts for text nodes before location SELECT n FROM node => RETURN; NIL => ERROR BadArgs; ENDCASE; txt _ NarrowToTextNode[n]; IF txt # NIL AND (~skipCommentNodes OR ~txt.comment) THEN count _ count+RopeEdit.Size[txt.rope]+break; [n,] _ InlineForward[n]; ENDLOOP }; FirstSibling: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[FirstChild[Parent[n]]]}; LastSibling: PUBLIC PROC [n: Ref] RETURNS [Ref] = { IF n=NIL THEN RETURN [NIL]; DO IF n.last THEN RETURN [n]; n _ n.next; ENDLOOP }; FirstChild: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[IF n=NIL THEN NIL ELSE n.child]}; LastChild: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[LastSibling[FirstChild[n]]] }; LastWithin: PUBLIC PROC [n: Ref] RETURNS [Ref] = { nxt: Ref; IF n=NIL THEN RETURN [NIL]; IF (nxt _ n.child)=NIL THEN RETURN [n]; n _ nxt; DO -- keep going to child of last sibling IF n.last THEN { IF (nxt _ n.child)=NIL THEN RETURN [n]; n _ nxt } ELSE n _ n.next; ENDLOOP }; LastLocWithin: PUBLIC PROC [n: Ref] RETURNS [Location] = { last: Ref _ LastWithin[n]; lastText: RefTextNode _ NarrowToTextNode[last]; where: Offset _ IF lastText # NIL THEN RopeEdit.Size[lastText.rope] ELSE NodeItself; RETURN [[last,where]] }; NthChild: PUBLIC PROC [n: Ref, location: Offset] RETURNS [child: Ref] = { IF n=NIL OR (child _ n.child)=NIL THEN RETURN; DO IF location=0 THEN RETURN [child]; IF child.last THEN RETURN [NIL]; child _ child.next; location _ location-1; ENDLOOP }; NthSibling: PUBLIC PROC [n: Ref, cnt: Offset] RETURNS [Ref] = { IF n=NIL THEN RETURN [NIL]; DO IF cnt=0 THEN RETURN [n]; IF n.last THEN RETURN [NIL]; n _ n.next; cnt _ cnt-1; ENDLOOP }; CountChildren: PUBLIC PROC [n: Ref] RETURNS [count: Offset] = { child: Ref; count _ 0; IF (child _ FirstChild[n])=NIL THEN RETURN; DO count _ count+1; IF child.last THEN RETURN; child _ child.next; ENDLOOP }; CountFollowing: PUBLIC PROC [n: Ref] RETURNS [count: Offset] = { count _ 0; IF n=NIL THEN RETURN; DO IF n.last THEN RETURN; n _ n.next; count _ count+1; ENDLOOP }; CountToParent: PUBLIC PROC [n: Ref] RETURNS [count: Offset, parent: Ref] = { count _ 0; IF n=NIL THEN RETURN; DO IF n.last THEN EXIT; n _ n.next; count _ count+1; ENDLOOP; parent _ n.next }; CountToChild: PUBLIC PROC [parent, child: Ref] RETURNS [count: Offset] = { n: Ref; count _ 0; IF parent=NIL OR child=NIL THEN RETURN; n _ parent.child; DO SELECT n FROM child => RETURN [count]; NIL => RETURN [MaxLen]; ENDCASE; n _ Next[n]; count _ count+1; ENDLOOP }; NodeRope: PUBLIC PROC [n: RefTextNode] RETURNS [ROPE] = { RETURN[IF n=NIL THEN NIL ELSE n.rope]}; NodeRuns: PUBLIC PROC [n: RefTextNode] RETURNS [TextLooks.Runs] = { RETURN[IF n=NIL THEN NIL ELSE n.runs]}; Props: PUBLIC PROC [n: Ref] RETURNS [NodeProps] = { RETURN[IF n=NIL THEN NIL ELSE n.props]}; NodeType: PUBLIC PROC [n: Ref] RETURNS [TypeName] = { RETURN[IF n=NIL THEN nullTypeName ELSE n.typename]}; IsLastSibling: PUBLIC PROC [n: Ref] RETURNS [BOOLEAN] = { RETURN[IF n=NIL THEN FALSE ELSE n.last] }; EndPos: PUBLIC PROC [n: Ref] RETURNS [Offset] = { node: RefTextNode = NarrowToTextNode[n]; IF node=NIL THEN RETURN [0]; RETURN [MAX[RopeEdit.Size[node.rope],1]-1] }; Start: PUBLIC PROC = { }; END. Ê-- TextNodeImpl.mesa -- written by Bill Paxton, March 1981 -- last edit by Bill Paxton, August 11, 1982 9:51 am Last Edited by: Plass, April 20, 1983 8:59 am -- ***** Declarations -- ***** Operations -- applies Parent repeatedly until reaches root -- returns next node in standard tree walk order -- returns preceeding node in standard tree walk order -- 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]] -- returns character offset of location2 relative to location1 -- note: NthChild[n,0]==FirstChild[n]; NthChild[n,k+1]==Next[NthChild[n,k]] -- note: NthSibling[n,0]==n; NthSibling[n,k+1]==Next[NthSibling[n,k]] -- note: CountToChild[parent,FirstChild[parent]]==0 -- ***** Initialization Ê ˜JšÏc™Jš%™%Jš4™4J™-JšÏk ˜ J˜ J˜ J˜J˜ J˜ J˜šœž ˜Jšžœ ˜'Jšžœ ˜—Jšž˜Jšžœ ˜J˜Jš™J˜Jšœžœžœ#˜FJšœžœžœ"˜BJ˜Jš™J˜šÏn œžœžœžœ˜7Jšœ žœžœ˜-J˜—šŸ œžœžœžœ˜9Jšœ žœžœ˜.J˜—Jš Ÿœžœžœ žœ žœ˜JJ˜šŸ œžœ žœ žœ˜5šžœžœžœžœ žœžœžœ˜+Jšžœžœžœ ˜Jšœ ˜ Jšž˜—Jšœ˜J˜—šŸœžœžœ žœ ˜-Jš/™/J˜šžœžœžœžœžœžœžœžœ žœžœžœ˜TJšœ˜Jšž˜—Jšœ˜J˜—šŸœžœžœ žœ ˜,Jšžœžœžœžœžœ žœžœžœ ˜?J˜—š Ÿœžœžœžœžœ˜GJ˜ Jšžœžœžœ˜,Jšžœžœžœžœžœžœžœžœ˜BJš žœžœžœžœ žœ˜7J˜—š Ÿœžœžœ žœžœ˜KJ˜)J˜—š Ÿ œžœ žœžœžœ˜QJš0™0J˜ Jš žœžœžœžœžœ˜ Jš žœžœžœžœ ˜KJ˜šžœ1˜4Jšžœ žœžœ˜@Jš žœžœžœžœžœ ˜GJ˜Jšžœ˜ J˜——šŸœžœžœžœ˜4Jšžœ%žœ˜8Jš6™6J˜Jšžœ žœžœ˜1Jšžœ žœžœžœžœžœžœžœ˜6Jšžœžœžœ˜Hš žœžœ žœžœ&˜CJšžœžœžœ˜(J˜Jšžœ˜—J˜š žœžœžœžœžœ˜NJ˜Jšœ žœ˜*J˜——š Ÿœžœžœ žœ žœ˜;Jš7™7Jš œ žœžœžœžœ˜PJ˜—šŸœžœžœ˜Jšœžœ žœ˜5Jšžœžœ˜'Jš4™4Jš7™7Jš3™3J˜ Jš žœžœžœžœžœ˜ Jšžœžœ˜/šžœžœžœž˜;Jšžœ˜/—šžœ1˜4Jšžœ žœžœ˜FJš žœžœžœžœžœ˜DJ˜Jšžœ˜ J˜——šŸœžœžœ˜Jšœžœžœ žœ˜HJšžœ$žœ˜7Jš5™5Jš7™7J˜Jšžœ žœžœ˜1Jšžœ žœžœžœžœžœžœžœ˜6Jšžœžœ˜/Jšžœžœžœ+˜Wšžœ&˜)Jšžœ žœžœ&˜@Jšžœžœžœ˜(J˜Jšžœ˜—šžœ)˜,šžœžœžœž˜BJšžœ˜ —J˜J˜J˜Jšžœ˜ J˜——šŸ œžœžœ$˜™>J˜J˜J˜Jšœžœžœ žœ˜:Jšœžœ˜"šžœ/˜2šžœž˜ Jšœžœ˜Jšžœžœ ˜Jšžœ˜ —J˜š žœžœžœžœž˜9J˜,—J˜Jšžœ˜ J˜——šŸ œžœžœ žœ ˜4Jšžœ˜J˜—šŸ œžœžœ žœ ˜3Jš žœžœžœžœžœ˜Jš žœžœžœžœžœ˜4J˜—šŸ œžœžœ žœ ˜2Jš žœžœžœžœžœžœ ˜(J˜—šŸ œžœžœ žœ ˜1Jšžœ˜%J˜—šŸ œžœžœ žœ ˜2J˜ Jš žœžœžœžœžœ˜Jšžœžœžœžœ˜'J˜šžœ&˜)šžœžœ˜Jšžœžœžœžœ˜'J˜ —Jšžœ ˜Jšžœ˜ J˜——šŸ œžœžœ žœ˜:J˜J˜/Jš œžœ žœžœžœ ˜TJšžœ˜J˜—šŸœžœžœžœ˜IJšK™KJš žœžœžœžœžœžœ˜.šžœžœ žœžœ ˜%Jšžœ žœžœžœ˜ J˜Jšœžœ˜!J˜——šŸ œžœžœžœ ˜?JšE™EJš žœžœžœžœžœ˜šžœžœžœžœ˜Jšžœžœžœžœ˜J˜ Jšœ žœ˜J˜——šŸ œžœžœ žœ˜?J˜ J˜ Jšžœžœžœžœ˜+šžœ˜Jšžœ žœžœ˜J˜Jšžœ˜ J˜——šŸœžœžœ žœ˜@J˜ Jšžœžœžœžœ˜šžœžœžœžœ˜J˜ J˜Jšžœ˜ J˜——šŸ œžœžœ žœ!˜LJ˜ Jšžœžœžœžœ˜šžœžœžœžœ˜J˜ J˜Jšžœ˜—J˜J˜—šŸ œžœžœžœ˜JJš3™3J˜J˜ Jš žœžœžœžœžœžœ˜'J˜šžœžœž˜Jšœ žœ ˜Jšžœžœ ˜Jšžœ˜J˜ J˜Jšžœ˜ J˜——š Ÿœžœžœžœžœ˜9Jš žœžœžœžœžœžœ ˜'J˜—šŸœžœžœžœ˜CJš žœžœžœžœžœžœ ˜'J˜—šŸœžœžœ žœ˜3Jš žœžœžœžœžœžœ ˜(J˜—šŸœžœžœ žœ˜5Jš žœžœžœžœžœ˜4J˜—š Ÿ œžœžœ žœžœ˜9Jš žœžœžœžœžœžœ ˜*J˜—šŸœžœžœ žœ ˜1Jšœ(˜(Jšžœžœžœžœ˜Jšžœžœ"˜-—J˜Jš™J˜šŸœžœžœ˜J˜J˜—Jšžœ˜J˜—…— 61