Author: Jonas Bilinkevicius
How to do a backward search in a TRichEdit
Answer:
Solve 1:
This is how to find text searching backwards:
1
2 function FindPreviousInstanceOfSubstring(substr, S: string; startAt: Integer):
3 Integer;
4 var
5 i: Integer;
6 ch: Char;
7 begin
8 ch := substr[1];
9 i := startAt;
10 Result := 0; {assume we fail}
11 while i >= 1 do
12 begin
13 if S[i] = ch then
14 begin
15 if AnsiCompareStr(substr, Copy(S, i, Length(substr))) = 0 then
16 begin
17 {found an instance}
18 Result := i;
19 Break;
20 end;
21 end;
22 Dec(i);
23 end;
24 end;
25
26 procedure TForm1.Button2Click(Sender: TObject);
27 begin
28 richedit1.selstart := FindPreviousInstanceOfSubstring
29 (edit1.text, richedit1.text, richedit1.gettextlen) - 1;
30 richedit1.sellength := Length(edit1.text);
31 end;
Solve 2:
32 {Function FindTextBackwards
33
34 Parameters:
35 findWhat: text to find
36 inString: string to find it in
37 startAt : character index to start at (1-based)
38 caseSensitive: determines whether search is case-sensitive
39 words: if true the characters immediately surrounding a found location must not be
40 alphanumeric
41
42 Returns: character index (1-based) of first character of a found location, or 0,
43 if the text was not found.
44
45 Description:
46 Performs a simple sequential search for a string in a larger string, starting at
47 the specified
48 position and working towards the start of the string.
49
50 Error Conditions: none
51
52 Created: 27.02.99 by P. Below}
53
54 function FindTextBackwards(findWhat, inString: string; startAt: Integer;
55 caseSensitive, words: Boolean): Integer;
56 var
57 i, patternlen, findpos: Integer;
58 lastchar, firstchar: Char;
59 begin
60 Result := 0; {assume failure}
61 patternlen := Length(findWhat);
62 {Do a few sanity checks on the parameters}
63 if (patternlen = 0) or (startAt < patternlen) or (Length(inString) < patternlen)
64 then
65 Exit;
66 if not caseSensitive then
67 begin
68 {convert both strings to lower case}
69 findWhat := AnsiLowercase(findWhat);
70 inString := AnsiLowercase(inString);
71 end;
72 i := startAt;
73 lastchar := findWhat[patternlen];
74 firstchar := findWhat[1];
75 while (Result = 0) and (i >= patternlen) do
76 begin
77 if inString[i] = lastchar then
78 begin
79 findPos := i - patternlen + 1;
80 if inString[findPos] = firstchar then
81 begin
82 {We have a candidate. Compare the substring of length patternlen
83 starting at findPos with findWhat.
84 With AnsiStrLComp we can do that without having to copy the substring to
85 a temp string first.}
86 if AnsiStrLComp(@findWhat[1], @inString[findPos], patternlen) = 0 then
87 begin
88 {We have a match!}
89 Result := findPos;
90 if words then
91 begin
92 {Check the characters surrounding the hit.
93 For the hit to constitute a word they must not be alphanumeric.}
94 if (findPos > 1) and IsCharAlphanumeric(inString[findPos - 1]) then
95 begin
96 {Not a match after all}
97 Result := 0;
98 end
99 else
100 begin
101 if (i < Length(inString)) and IsCharAlphanumeric(inString[i + 1]) then
102 begin
103 {Not a match after all}
104 Result := 0;
105 end;
106 end;
107 end;
108 end;
109 end;
110 end;
111 Dec(i);
112 end;
113 end;
114
115 //Here's how to use it:
116
117 procedure TForm1.Button1Click(Sender: TObject);
118 var
119 findPos: Integer;
120 begin
121 findPos := FindTextBackwards(findEdit.Text, richedit1.Text, richedit1.selstart +
122 1,
123 caseCheckbox.checked, wordsCheckbox.checked);
124 if findPos > 0 then
125 begin
126 with richedit1 do
127 begin
128 selstart := findPos - 1;
129 sellength := findEdit.GetTextLen;
130 perform(em_scrollcaret, 0, 0);
131 setfocus;
132 end;
133 end
134 else
135 showmessage('Text not found');
136 end;
|