TreeFindImpl.Mesa; written by Bill Paxton, June 1981
edited by McGregor, February 8, 1983 9:59 am
edited by Paxton, June 9, 1983 10:44 am
edited by Maxwell, January 5, 1983 3:51 pm
DIRECTORY
TreeFind,
TextFind,
TiogaNode,
TiogaNodeOps,
TiogaPathOps,
TextEdit,
NameSymbolTable,
Rope;
TreeFindImpl:
CEDAR
PROGRAM
IMPORTS TextFind, TiogaNodeOps, TiogaPathOps
EXPORTS TreeFind =
BEGIN OPEN TreeFind, TiogaNode;
Try:
PUBLIC
PROC [finder: Finder, first: Path, start: Offset ← 0,
last: Path ← [NIL, NIL], lastLen: Offset ← MaxLen, looksExact: BOOLEAN ← FALSE,
commentControl: CommentControl ← includeComments,
checkFormat: BOOLEAN ← FALSE, format: TiogaNode.Name ← TiogaNode.nullName,
checkStyle: BOOLEAN ← FALSE, style: NameSymbolTable.Name ← NameSymbolTable.nullName,
styleProc: PROC [Ref] RETURNS [NameSymbolTable.Name] ← NIL,
interrupt: REF BOOL ← NIL]
RETURNS [found: BOOLEAN, where: Path, at, atEnd, before, after: Offset] = TRUSTED {
p: Path ← first;
found ← FALSE;
DO
-- test new node each time through the loop
n: TiogaNode.RefTextNode;
node: TiogaNode.Ref;
lastOne: BOOL = TiogaPathOps.Equal[p, last];
IF (node ← p.node)=NIL THEN RETURN;
IF checkFormat AND node.format # format THEN NULL
ELSE IF checkStyle AND styleProc[node] # style THEN NULL
ELSE
IF (n ← TiogaNodeOps.NarrowToTextNode[node])#
NIL
THEN
BEGIN
IF (
SELECT commentControl
FROM
excludeComments => ~n.comment,
commentsOnly => n.comment,
ENDCASE =>
TRUE)
THEN
BEGIN
IF finder #
NIL
THEN
[found,at,atEnd,before,after] ←
TextFind.Try[finder,n,start,
IF lastOne THEN lastLen-start ELSE MaxLen,looksExact,interrupt]
ELSE {
found ← TRUE;
at ← before ← 0;
atEnd ← after ← TiogaNodeOps.Size[n] };
END;
IF found THEN { where ← p; RETURN };
END;
go to next one
start ← 0;
IF lastOne THEN RETURN;
p ← TiogaPathOps.StepForwardNode[p];
ENDLOOP };
TryBackwards:
PUBLIC
PROC [finder: TextFind.Finder, first: Path,
len: Offset ← MaxLen, last: Path ← [NIL, NIL], lastStart: Offset ← 0,
looksExact: BOOLEAN ← FALSE, commentControl: CommentControl ← includeComments,
checkFormat: BOOLEAN ← FALSE, format: TiogaNode.Name ← TiogaNode.nullName,
checkStyle: BOOLEAN ← FALSE, style: NameSymbolTable.Name ← NameSymbolTable.nullName,
styleProc: PROC [Ref] RETURNS [NameSymbolTable.Name] ← NIL,
interrupt: REF BOOL ← NIL]
RETURNS [found: BOOLEAN, where: Path, at, atEnd, before, after: Offset] = TRUSTED {
p, parent: Path;
found ← FALSE;
p ← first;
DO
-- test new node each time through the loop
n: TiogaNode.RefTextNode;
node: TiogaNode.Ref;
lastOne: BOOL = TiogaPathOps.Equal[p, last];
IF (node ← p.node)=NIL THEN RETURN;
IF checkFormat AND node.format # format THEN NULL
ELSE IF checkStyle AND styleProc[node] # style THEN NULL
ELSE
IF (n ← TiogaNodeOps.NarrowToTextNode[node])#
NIL
THEN
BEGIN
IF (
SELECT commentControl
FROM
excludeComments => ~n.comment,
commentsOnly => n.comment,
ENDCASE =>
TRUE)
THEN
BEGIN
IF finder #
NIL
THEN
[found,at,atEnd,before,after] ← TextFind.TryBackwards[finder,n,
IF lastOne THEN lastStart ELSE 0,len,looksExact,interrupt]
ELSE {
found ← TRUE;
at ← before ← 0;
atEnd ← after ← TiogaNodeOps.Size[n] };
END;
IF found THEN { where ← p; RETURN };
END;
go to next one
IF lastOne THEN RETURN;
[p,parent] ← TiogaPathOps.StepBackwardNode[p,parent];
len ← MaxLen;
ENDLOOP };
Apply:
PUBLIC
PROC [finder: Finder, first: Path, proc: ApplyProc, start: Offset ← 0,
last: Path ← [NIL, NIL], lastLen: Offset ← MaxLen, looksExact: BOOLEAN ← FALSE,
commentControl: CommentControl ← includeComments,
checkFormat: BOOLEAN ← FALSE, format: TiogaNode.Name ← TiogaNode.nullName,
checkStyle: BOOLEAN ← FALSE, style: NameSymbolTable.Name ← NameSymbolTable.nullName,
styleProc: PROC [Ref] RETURNS [NameSymbolTable.Name] ← NIL]
RETURNS [count: LONG INTEGER] = {
where, p: Path;
at, atEnd, before, after, from, delta: Offset;
found, continue, bumpCount: BOOLEAN;
count ← 0; p ← first;
UNTIL p.node=
NIL
DO
IF TiogaPathOps.Equal[p, last] AND start >= lastLen THEN RETURN;
[found,where,at,atEnd,before,after] ←
Try[finder,p,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 TiogaPathOps.Equal[where, last] AND lastLen < MaxLen THEN lastLen ← lastLen+delta;
IF finder # NIL THEN { p ← where; start ← from }
ELSE { p ← TiogaPathOps.StepForwardNode[p]; start ← 0 };
ENDLOOP };
END.