-- TextFind.mesa
-- derived from EditorFind.Mesa of Laurel 6
-- written by Bill Paxton, May 1981
-- last edit by Paxton, December 30, 1982 10:33 am
-- This module provides a "Find" operation for text nodes
-- The pattern is given as a substring of a text node
-- The text to be searched is also a substring of a text node
-- The search can be in either direction within the substring
-- If a match character in the pattern has looks,
-- the looks of the matching character(s) in the text will include those looks.
-- For example, if the pattern includes a * with looks x and y,
-- the characters matching the * will have looks x and y too.
-- The matching characters may have other looks too.
DIRECTORY
TextNode,
TextLooks,
Rope;
TextFind: CEDAR DEFINITIONS =
BEGIN
RefTextNode: TYPE = TextNode.RefTextNode;
Offset: TYPE = TextNode.Offset;
ROPE: TYPE = Rope.ROPE;
MaxLen: Offset = LAST[Offset];
CR: CHAR = 'M-100B;
MalformedPattern: ERROR [ec:PatternErrorCode];
PatternErrorCode: TYPE = {
toobig, -- pattern too long
endquote, -- pattern ends with '
endtilda, -- pattern ends with ~
boundary, -- pattern has | inside rather than at beginning or end
missingNameEnd, -- pattern has < without matching >
unmatchedNameEnd -- pattern has > without previous <
};
Finder: TYPE = REF FinderRec;
FinderRec: TYPE;
NameLoc: PROC [finder: Finder, name: ROPE] RETURNS [at, atEnd: Offset];
-- name is the name of a subpattern
-- value is where that subpattern matched last time
NameLooks: PROC [finder: Finder, name: ROPE] RETURNS [looks: TextLooks.Looks];
-- name is the name of a subpattern
-- value are looks that name had in the pattern
Create: PROC [
pattern: RefTextNode, literal, word, ignoreLooks, ignoreCase, addBounds: BOOLEANFALSE,
patternStart: Offset ← 0, patternLen: Offset ← MaxLen]
RETURNS [finder: Finder];
-- creates a record containing a "compiled" version of the pattern
-- if literal is true, each character in pattern is taken literally
-- if word flag is true, pattern only matches if no adjacent letters or digits
-- if ignoreLooks is true, then ignore the looks of the pattern characters
-- if ignoreCase is false, then alpha chars in pattern must match case
-- otherwise, they can match either upper or lower
-- if addBounds is true, add |'s to both ends of pattern
CreateFromRope: PROC [pattern: ROPE, literal, word, ignoreCase, addBounds: BOOLEANFALSE,
patternStart: Offset ← 0, patternLen: Offset ← MaxLen]
RETURNS [finder: Finder];
SearchRope: PROC [finder: Finder, rope: Rope.ROPE,
start: Offset ← 0, len: Offset ← MaxLen, interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset];
Try: PROC [finder: Finder, text: RefTextNode,
start: Offset ← 0, len: Offset ← MaxLen,
looksExact: BOOLEANFALSE,
interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset];
-- searches text for first match in [start..start+len)
-- i.e., searches up from start until reaches start+len
-- if finds a match, returns with found = true,
-- at = beginning of match or location corresponding to { in pattern
-- atEnd = end of match or location corresponding to } in pattern
-- after = end of entire match, which may be > atEnd if used } in pattern
-- before = start of entire match, which may be < at if used { in pattern
-- if looksExact is true, then match by equality, else by subset
-- if interrupt^ becomes true, will stop searching
SearchRopeBackwards: PROC [finder: Finder, rope: Rope.ROPE,
start: Offset ← 0, len: Offset ← MaxLen, interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset];
TryBackwards: PROC [finder: Finder, text: RefTextNode,
start: Offset ← 0, len: Offset ← MaxLen,
looksExact: BOOLEANFALSE,
interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset];
-- searches text for last match in [start..start+len)
-- i.e., searches down from start+len until reaches start
Find: PROC [pattern, text: RefTextNode,
literal, word, ignoreLooks, ignoreCase, looksExact, addBounds: BOOLEANFALSE,
patternStart: Offset ← 0, patternLen: Offset ← MaxLen,
textStart: Offset ← 0, textLen: Offset ← MaxLen,
interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset] = INLINE {
[found,at,atEnd,before,after] ←
Try[Create[pattern,literal,word,ignoreLooks,ignoreCase,addBounds,patternStart,patternLen],
text,textStart,textLen,looksExact,interrupt] };
BackwardsFind: PROC [pattern, text: RefTextNode,
literal, word, ignoreLooks, ignoreCase, looksExact, addBounds: BOOLEANFALSE,
patternStart: Offset ← 0, patternLen: Offset ← MaxLen,
textStart: Offset ← 0, textLen: Offset ← MaxLen,
interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset] = INLINE {
[found,at,atEnd,before,after] ← TryBackwards[
Create[pattern,literal,word,ignoreLooks,ignoreCase,addBounds,patternStart,patternLen],
text,textStart,textLen,looksExact,interrupt] };
-- ***** Initialization
Start: PROC; -- for initialization only
END.