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];
=
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: BOOL ← FALSE, patternStart: INT ← 0, patternLen: INT ← LAST[INT]]
RETURNS [Finder] = {
RETURN [TextFind.Create[
pattern, literal, word, ignoreLooks, ignoreCase, addBounds, patternStart, patternLen]]
};
CreateFromRope:
PUBLIC
PROC [pattern:
ROPE, literal, word, ignoreCase, addBounds:
BOOL ←
FALSE, patternStart:
INT ← 0, patternLen:
INT ←
LAST[
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:
BOOLEAN ←
FALSE,
commentControl: CommentControl ← includeComments,
checkFormat:
BOOLEAN ←
FALSE,
format:
ATOM ←
NIL,
checkStyle:
BOOLEAN ←
FALSE,
style:
ATOM ←
NIL,
styleProc:
PROC [TextNode.Ref]
RETURNS [
ATOM] ←
NIL,
interrupt:
REF
BOOL ←
NIL]
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:
BOOLEAN ←
FALSE,
commentControl: CommentControl ← includeComments,
checkFormat:
BOOLEAN ←
FALSE,
format:
ATOM ←
NIL,
checkStyle:
BOOLEAN ←
FALSE,
style:
ATOM ←
NIL,
styleProc:
PROC [TextNode.Ref]
RETURNS [
ATOM] ←
NIL,
interrupt:
REF
BOOL ←
NIL]
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:
BOOLEAN ←
FALSE, commentControl: CommentControl ← includeComments,
checkFormat:
BOOLEAN ←
FALSE, format:
ATOM ←
NIL,
checkStyle:
BOOLEAN ←
FALSE, style:
ATOM ←
NIL,
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
};