<<-- 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: BOOLEAN _ FALSE, 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: BOOLEAN _ FALSE, patternStart: Offset _ 0, patternLen: Offset _ MaxLen] RETURNS [finder: Finder]; SearchRope: PROC [finder: Finder, rope: Rope.ROPE, start: Offset _ 0, len: Offset _ MaxLen, interrupt: REF BOOL _ NIL] RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset]; Try: PROC [finder: Finder, text: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, looksExact: BOOLEAN _ FALSE, interrupt: REF BOOL _ NIL] 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 BOOL _ NIL] RETURNS [found: BOOLEAN, at, atEnd, before, after: Offset]; TryBackwards: PROC [finder: Finder, text: RefTextNode, start: Offset _ 0, len: Offset _ MaxLen, looksExact: BOOLEAN _ FALSE, interrupt: REF BOOL _ NIL] 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: BOOLEAN _ FALSE, patternStart: Offset _ 0, patternLen: Offset _ MaxLen, textStart: Offset _ 0, textLen: Offset _ MaxLen, interrupt: REF BOOL _ NIL] 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: BOOLEAN _ FALSE, patternStart: Offset _ 0, patternLen: Offset _ MaxLen, textStart: Offset _ 0, textLen: Offset _ MaxLen, interrupt: REF BOOL _ NIL] 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.