TreeFindImpl.Mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
written by Bill Paxton, June 1981
last written by Paxton, December 30, 1982 10:33 am
Last Edited by: Maxwell, January 5, 1983 3:51 pm
Michael Plass, March 29, 1985 5:34:07 pm PST
Rick Beach, March 27, 1985 1:02:13 pm PST
DIRECTORY
Rope USING [ROPE],
TextEdit USING [Size],
TextFind USING [Create, CreateFromRope, Finder, Try, TryBackwards],
TextLooks USING [],
TextNode USING [Backward, Offset, Ref, RefTextNode, StepForward],
TreeFind USING [ApplyProc, CommentControl];
TreeFindImpl: CEDAR PROGRAM
IMPORTS TextFind, TextNode, TextEdit
EXPORTS TreeFind
= BEGIN OPEN TreeFind;
Finder: TYPE ~ TextFind.Finder;
ROPE: TYPE = Rope.ROPE;
RefTextNode: TYPE = TextNode.RefTextNode;
Create: PUBLIC PROC [
pattern: TextNode.RefTextNode, literal, word, ignoreLooks, ignoreCase, addBounds: BOOLFALSE, patternStart: INT ← 0, patternLen: INTLAST[INT]]
RETURNS [Finder] = { RETURN [TextFind.Create[
pattern, literal, word, ignoreLooks, ignoreCase, addBounds, patternStart, patternLen]]
};
CreateFromRope: PUBLIC PROC [pattern: ROPE, literal, word, ignoreCase, addBounds: BOOLFALSE, patternStart: INT ← 0, patternLen: INTLAST[INT]] RETURNS [Finder] = {
RETURN [
TextFind.CreateFromRope[pattern, literal, word, ignoreCase, addBounds, patternStart, patternLen]
]
};
Try: PUBLIC PROC [
finder: Finder,
first: TextNode.Ref,
start: TextNode.Offset ← 0,
last: TextNode.Ref ← NIL,
lastLen: TextNode.Offset ← LAST[INT],
looksExact: BOOLEANFALSE,
commentControl: CommentControl ← includeComments,
checkFormat: BOOLEANFALSE,
format: ATOMNIL,
checkStyle: BOOLEANFALSE,
style: ATOMNIL,
styleProc: PROC [TextNode.Ref] RETURNS [ATOM] ← NIL,
interrupt: REF BOOLNIL]
RETURNS
[found: BOOLEAN, where: TextNode.RefTextNode, at, atEnd, before, after: TextNode.Offset] = {
node: TextNode.Ref;
found ← FALSE;
IF (node ← first)=NIL THEN RETURN;
DO-- test new node each time through the loop
IF checkFormat AND node.formatName # format THEN NULL
ELSE IF checkStyle AND styleProc[node] # style THEN NULL
ELSE {
IF (SELECT commentControl FROM excludeComments => ~node.comment, commentsOnly => node.comment, ENDCASE => TRUE) THEN {
IF finder # NIL THEN [found, at, atEnd, before, after] ← TextFind.Try[finder, node, start, IF node=last THEN lastLen-start ELSE LAST[INT], looksExact, interrupt]
ELSE {
found ← TRUE;
at ← before ← 0;
atEnd ← after ← TextEdit.Size[node];
};
IF found THEN { where ← node; RETURN };
};
};
go to next one
start ← 0;
IF node=last THEN RETURN;
IF (node ← TextNode.StepForward[node])=NIL THEN RETURN;
ENDLOOP
};
TryBackwards: PUBLIC PROC [
finder: TextFind.Finder,
first: TextNode.Ref,
len: TextNode.Offset ← LAST[INT],
last: TextNode.Ref ← NIL,
lastStart: TextNode.Offset ← 0,
looksExact: BOOLEANFALSE,
commentControl: CommentControl ← includeComments,
checkFormat: BOOLEANFALSE,
format: ATOMNIL,
checkStyle: BOOLEANFALSE,
style: ATOMNIL,
styleProc: PROC [TextNode.Ref] RETURNS [ATOM] ← NIL,
interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, where: TextNode.RefTextNode, at, atEnd, before, after: TextNode.Offset] = {
node, parent: TextNode.Ref;
found ← FALSE;
IF (node ← first)=NIL THEN RETURN;
DO-- test new node each time through the loop
IF checkFormat AND node.formatName # format THEN NULL
ELSE IF checkStyle AND styleProc[node] # style THEN NULL
ELSE {
IF (SELECT commentControl FROM excludeComments => ~node.comment, commentsOnly => node.comment, ENDCASE => TRUE) THEN {
IF finder # NIL THEN [found, at, atEnd, before, after] ← TextFind.TryBackwards[finder, node, IF node=last THEN lastStart ELSE 0, len, looksExact, interrupt]
ELSE {
found ← TRUE;
at ← before ← 0;
atEnd ← after ← TextEdit.Size[node];
};
IF found THEN { where ← node; RETURN }
};
};
go to next one
len ← LAST[INT];
IF node=last THEN RETURN;
[node, parent] ← TextNode.Backward[node, parent];
IF node=NIL THEN RETURN;
ENDLOOP
};
Apply: PUBLIC PROC [
finder: Finder, first: TextNode.Ref, proc: ApplyProc, start: TextNode.Offset ← 0,
last: TextNode.Ref ← NIL, lastLen: TextNode.Offset ← LAST[INT],
looksExact: BOOLEANFALSE, commentControl: CommentControl ← includeComments,
checkFormat: BOOLEANFALSE, format: ATOMNIL,
checkStyle: BOOLEANFALSE, style: ATOMNIL,
styleProc: PROC [TextNode.Ref] RETURNS [ATOM] ← NIL]
RETURNS
[count: LONG INTEGER] = {
where: TextNode.RefTextNode;
node: TextNode.Ref;
at, atEnd, before, after, from, delta: TextNode.Offset;
found, continue, bumpCount: BOOLEAN;
count ← 0; node ← first;
UNTIL node=NIL DO
IF node=last AND start >= lastLen THEN RETURN;
[found, where, at, atEnd, before, after] ←
Try[finder, node, start, last, lastLen, looksExact, commentControl,
checkFormat, format, checkStyle, style, styleProc];
IF ~found THEN RETURN;
[continue, bumpCount, from, delta] ← proc[where, at, atEnd, before, after];
IF bumpCount THEN count ← count+1;
IF ~continue THEN RETURN;
IF where=last AND lastLen < LAST[INT] THEN lastLen ← lastLen+delta;
IF finder # NIL THEN { node ← where; start ← from }
ELSE { node ← TextNode.StepForward[node]; start ← 0 };
ENDLOOP
};
END.