TiogaRopesImpl.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Mike Spreitzer August 5, 1986 4:26:06 pm PDT
Last tweaked by Mike Spreitzer on November 30, 1987 3:50:09 pm PST
Willie-s, April 3, 1992 5:29 pm PST
DIRECTORY Basics, 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.rope;
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, NIL, MoveFromTiogaRope];
}};
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 ¬ tr.curNode.rope;
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]
--Rope.FetchType-- = {
tr: TiogaRope = NARROW[data];
IF NOT index IN [0 .. tr.length) THEN ERROR RuntimeError.BoundsFault;
{rel: INT ¬ index+tr.start - tr.curNodeStart;
{IF rel<0 THEN GOTO Fixit;
SELECT tr.curNodeLength
FROM
>rel => GOTO TakeIt;
=rel => RETURN ['\n];
ENDCASE => GOTO Fixit;
EXITS
Fixit => {
JumpTo[tr, index];
rel ¬ index+tr.start - tr.curNodeStart;
IF rel=tr.curNodeLength THEN RETURN ['\n]};
TakeIt => NULL};
RETURN [tr.curRope.Fetch[rel]]}};
MoveFromTiogaRope:
UNSAFE
PROC [block: Basics.UnsafeBlock, data:
REF
ANY, start:
INT]
RETURNS [charsMoved:
INT ¬ 0] ~
CHECKED {
tr: TiogaRope = NARROW[data];
IF NOT start IN [0 .. tr.length) THEN ERROR RuntimeError.BoundsFault;
WHILE block.count>0
DO
rel: INT ¬ start + tr.start - tr.curNodeStart;
IF rel NOT IN [0 .. tr.curNodeLength] THEN {JumpTo[tr, start]; rel ¬ start + tr.start - tr.curNodeStart};
IF rel < tr.curNodeLength
THEN {
n: INT;
TRUSTED {n ¬ Rope.UnsafeMoveChars[block: block, rope: tr.curRope, start: rel]};
start ¬ start + n;
charsMoved ¬ charsMoved + n;
block.startIndex ¬ block.startIndex + n;
block.count ¬ block.count - n;
};
IF block.count # 0
THEN {
TRUSTED {LOOPHOLE[block.base, LONG POINTER TO Basics.RawChars][block.startIndex] ¬ '\n};
start ¬ start + 1;
charsMoved ¬ charsMoved + 1;
block.startIndex ¬ block.startIndex + 1;
block.count ¬ block.count - 1;
};
ENDLOOP;
RETURN};
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, endNode.rope.Length[]+1];
};
END.