TiogaRopesImpl.mesa
Mike Spreitzer August 5, 1986 4:26:06 pm PDT
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: INTLAST[INT], skipCommentNode: BOOLFALSE] 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: BOOLFALSE] 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.