DIRECTORY Rope, RuntimeError, TextNode, TiogaRopes; TiogaRopesImpl: CEDAR PROGRAM IMPORTS Rope, RuntimeError, TextNode EXPORTS TiogaRopes = BEGIN OPEN TiogaRopes; Location: TYPE = TextNode.Location; TiogaRope: TYPE = REF TiogaRopePrivate; TiogaRopePrivate: TYPE = RECORD [ node: Node, start, length: INT, skipCommentNode: BOOL, curNode: Node _ NIL, curNodeStart, curNodeLength: INT _ 0, curRope: ROPE ]; RopeFromTioga: PUBLIC PROC [node: Node, start: INT _ 0, length: INT _ LAST[INT], skipCommentNode: BOOL _ FALSE] RETURNS [asRope: ROPE] = { end: Location = DocEnd[node, skipCommentNode]; nodeLoc: Location = [node, 0]; remSize: INT = TextNode.LocOffset[nodeLoc, end, 1, skipCommentNode]; IF start >= remSize THEN RETURN [NIL]; {curRope: ROPE = node.NodeRope[]; tr: TiogaRope = NEW [TiogaRopePrivate _ [ node: node, start: start, length: MIN[length, remSize - start], skipCommentNode: skipCommentNode, curNode: node, curNodeStart: 0, curNodeLength: curRope.Length[], curRope: curRope ]]; asRope _ Rope.MakeRope[tr, tr.length, FetchFromTiogaRope]; }}; JumpTo: PROC [tr: TiogaRope, index: INT] = { newOffset: INT = tr.start+index; here: Location = IF newOffset >= tr.curNodeStart/2 THEN LocRelative[[tr.curNode, 0], newOffset-tr.curNodeStart, 1, tr.skipCommentNode] ELSE LocRelative[[tr.node, 0], newOffset, 1, tr.skipCommentNode]; tr.curNode _ here.node; tr.curNodeStart _ newOffset - here.where; tr.curRope _ TextNode.NodeRope[tr.curNode]; tr.curNodeLength _ tr.curRope.Length[]; }; LocRelative: PROC [location: Location, count: INT, break: NAT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [rel: Location] = { SELECT count FROM =0 => rel _ location --avoid the bogosity in TextNodeImpl.LocRelative--; >0 => rel _ TextNode.LocRelative[location, count, break, skipCommentNodes]; <0 => {--TextNodeImpl.LocRelative won't backup over node boundaries backParent: Node _ NIL; rel _ location; WHILE count + rel.where < 0 DO count _ count + rel.where; [rel.node, backParent, ] _ TextNode.Backward[rel.node, backParent]; rel.where _ IF (NOT skipCommentNodes) OR (NOT rel.node.comment) THEN rel.node.rope.Length[] + break ELSE 0; ENDLOOP; rel.where _ count + rel.where; }; ENDCASE => ERROR; rel _ rel; }; FetchFromTiogaRope: PROC [data: REF, index: INT] RETURNS [char: CHAR] --Rope.FetchType-- = { tr: TiogaRope = NARROW[data]; IF NOT index IN [0 .. tr.length) THEN ERROR RuntimeError.BoundsFault; IF NOT index+tr.start - tr.curNodeStart IN [0 .. tr.curNodeLength] THEN JumpTo[tr, index]; index _ index+tr.start - tr.curNodeStart; char _ IF index < tr.curNodeLength THEN tr.curRope.Fetch[index] ELSE '\n; }; DocEnd: PROC [node: Node, skipCommentNode: BOOL] RETURNS [endLoc: Location] = { endNode: Node _ TextNode.Root[node]; IF endNode = NIL THEN ERROR; DO next: Node _ TextNode.LastChild[endNode]; IF next = NIL THEN EXIT; endNode _ next; ENDLOOP; IF skipCommentNode THEN WHILE endNode.comment DO endNode _ TextNode.StepBackward[endNode] ENDLOOP; endLoc _ [endNode, TextNode.NodeRope[endNode].Length[]+1]; }; END. HTiogaRopesImpl.mesa Mike Spreitzer August 5, 1986 4:26:06 pm PDT Κ‹– "cedar" style˜code™K™,—K˜KšΟk œ*˜3K˜šΟnœœ˜Kšœ˜$Kšœ ˜K˜—K˜Kšœœ ˜K˜Kšœ œ˜#K˜Kšœ œœ˜'šœœœ˜!K˜ Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜%Kšœ ˜ K˜—K˜šž œœœœœœœœœœ œ˜ŠKšœ.˜.K˜Kšœ œ8˜DKšœœœœ˜&Kšœ œ˜!šœœ˜)K˜ K˜ Kšœœ˜%Kšœ!˜!K˜K˜Kšœ ˜ K˜Kšœ˜—K˜:K˜—K˜šžœœœ˜,Kšœ œ˜ Kšœœ œPœ=˜ΘK˜Kšœ)˜)K˜+K˜'K˜—K˜šž œœœ œœœœ˜šœ˜KšœΟc2œ˜HKšœK˜KšœŸ<˜CKšœœ˜K˜šœ˜K˜K˜CKš œ œœœœœ œ˜kKšœ˜—K˜K˜—Kšœœ˜—K˜ K˜—K˜šžœœœ œœœŸœ˜\Kšœœ˜Kš œœœœœ˜EKšœœ"œœ˜ZKšœ)˜)Kšœœœœ˜IK˜—K˜šžœœœœ˜OK˜$Kšœ œœœ˜š˜K˜)Kšœœœœ˜K˜Kšœ˜—Kš œœœœ*œ˜bK˜:K˜—K˜Kšœ˜—…— ʝ