Rev 13 | Rev 23 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
13 | daniel-mar | 1 | unit FindReplace; |
2 | |||
22 | daniel-mar | 3 | // FindReplace.pas |
13 | daniel-mar | 4 | // Source: http://www.tek-tips.com/viewthread.cfm?qid=160357 |
22 | daniel-mar | 5 | // 18 Nov 2001 "bearsite4" |
6 | // Changes by Daniel Marschall, especially to make it compatible with TSynEdit |
||
13 | daniel-mar | 7 | |
8 | interface |
||
9 | |||
10 | uses |
||
11 | Windows, Messages, SysUtils, Classes, Dialogs, SynEdit; |
||
12 | |||
13 | type |
||
14 | FindReplaceCommunication = ( frcAlertUser, frcAlertReplace, frcEndReached ); |
||
15 | {allows the replace functions to use the find function avoiding alot |
||
16 | of code duplication. frcAlertuser means that when the find function |
||
17 | has reached the end of the text while searching for a word it will pop |
||
18 | up a message saying the word can't be found. frcAlertReplace |
||
19 | tells the find function not to display a message to the user saying that |
||
20 | the word can't be found but instead to set the state to frcEndReached to |
||
21 | let the replace function know it's reached the end of the text} |
||
22 | |||
22 | daniel-mar | 23 | TReplaceFunc = function ( const S1, S2: string ): Integer; |
24 | |||
13 | daniel-mar | 25 | TFindReplace = class(TComponent) |
26 | private |
||
27 | fEditor: TSynEdit; {the richedit or memo component to hook it up to} |
||
28 | fReplaceDialog: TReplaceDialog; {the replace dialog} |
||
29 | fFindDialog: TFindDialog; {the find dialog} |
||
30 | |||
31 | FindActionOnEnd: FindReplaceCommunication; {the action the find function |
||
32 | should take when it reaches the end of the text while searching for the |
||
33 | word} |
||
34 | |||
35 | function TestWholeWord( Sender: TFindDialog; TestString: string ): boolean; |
||
36 | {returns a true or false depending on whether the user chose the whole word |
||
37 | only option and whether or not the word is a whole word. Actually, it can |
||
38 | test multiple words in a single string as well.} |
||
39 | |||
40 | protected |
||
22 | daniel-mar | 41 | type |
42 | TFindDirection = (sdDefault, sdForwards, sdBackwards); |
||
43 | |||
13 | daniel-mar | 44 | procedure FindForwards( Sender: TFindDialog; start, finish: integer ); |
45 | {search through the editor in a forwards direction} |
||
22 | daniel-mar | 46 | procedure FindBackwards( Sender: TFindDialog; start, finish: integer ); |
13 | daniel-mar | 47 | {search through the editor in a backwards direction} |
48 | |||
49 | {defined event handlers} |
||
50 | procedure OnFind( Sender: TObject ); virtual; |
||
51 | procedure OnReplace( Sender: TObject ); virtual; |
||
52 | |||
53 | {the centralised find/replace functions} |
||
54 | function TryAndMatch( Sender: TFindDialog; index, finish: integer ): boolean; virtual; |
||
22 | daniel-mar | 55 | function TryAndReplace(dialog: TReplaceDialog): boolean; virtual; |
13 | daniel-mar | 56 | |
22 | daniel-mar | 57 | procedure DoReplace(dialog: TReplaceDialog); virtual; |
13 | daniel-mar | 58 | {the replace function that coordinates all the work} |
22 | daniel-mar | 59 | procedure DoReplaceAll(dialog: TReplaceDialog); virtual; |
13 | daniel-mar | 60 | {the replace all function that coordinates all the work} |
61 | |||
22 | daniel-mar | 62 | procedure DoFind(dialog: TFindDialog; direction: TFindDirection); |
63 | |||
13 | daniel-mar | 64 | public |
65 | constructor Create( AOwner: TComponent); override; |
||
66 | |||
22 | daniel-mar | 67 | property FindDialog: TFindDialog read fFindDialog; |
68 | property ReplaceDialog: TReplaceDialog read fReplaceDialog; |
||
13 | daniel-mar | 69 | |
22 | daniel-mar | 70 | procedure CloseDialogs; |
71 | |||
13 | daniel-mar | 72 | procedure FindExecute; |
73 | {opens the find dialog} |
||
74 | procedure ReplaceExecute; |
||
75 | {opens the replace dialog} |
||
76 | |||
22 | daniel-mar | 77 | procedure FindContinue; |
78 | procedure FindNext; |
||
79 | procedure FindPrev; |
||
80 | |||
13 | daniel-mar | 81 | procedure GoToLine( LineNumber: integer ); |
82 | procedure GetLineNumber( Position: Integer; var LineNumber, ColumnNumber: Integer ); |
||
83 | {returns the line and column number the cursor is on in the editor} |
||
84 | |||
85 | published |
||
22 | daniel-mar | 86 | property Editor: TSynEdit read fEditor write fEditor; |
13 | daniel-mar | 87 | end; |
88 | |||
89 | (* |
||
90 | procedure Register; |
||
91 | *) |
||
92 | |||
93 | implementation |
||
94 | |||
95 | (* |
||
96 | {$R findrep.dcr} |
||
97 | *) |
||
98 | |||
99 | constructor TFindReplace.Create( AOwner: TComponent ); |
||
100 | begin |
||
101 | inherited; |
||
102 | |||
103 | {create the find dialog} |
||
104 | fFindDialog := TFindDialog.Create( Self ); |
||
105 | {set up the event handlers} |
||
106 | fFindDialog.OnFind := OnFind; |
||
107 | |||
108 | {create the replace dialog} |
||
109 | fReplaceDialog := TReplaceDialog.Create( Self ); |
||
110 | {set up the event handlers} |
||
111 | fReplaceDialog.OnReplace := OnReplace; |
||
112 | fReplaceDialog.OnFind := OnFind; |
||
113 | |||
114 | {set find's default action on end of text to alert the user. |
||
115 | If a replace function changes this it is it's responsibility |
||
116 | to change it back} |
||
117 | FindActionOnEnd := frcAlertUser; |
||
118 | end; |
||
119 | |||
120 | procedure TFindReplace.FindForwards( Sender: TFindDialog; start, finish: integer ); |
||
121 | var |
||
122 | i: integer; |
||
123 | |||
124 | begin |
||
125 | |||
126 | {to find the word we go through the text on a character by character |
||
127 | basis} |
||
128 | for i := start to finish do |
||
129 | if TryAndMatch( Sender, i, finish ) then |
||
130 | {if we've got a match then stop} |
||
131 | Exit; |
||
132 | |||
133 | end; |
||
134 | |||
22 | daniel-mar | 135 | procedure TFindReplace.FindBackwards( Sender: TFindDialog; start, finish: Integer ); |
13 | daniel-mar | 136 | {since only find has a (search) up option and replace doesn't |
137 | we don't have to worry about sender since only the onFind will |
||
22 | daniel-mar | 138 | be calling this function} |
13 | daniel-mar | 139 | |
140 | var |
||
141 | i: integer; |
||
142 | |||
143 | begin |
||
144 | {See comments for findforward} |
||
145 | |||
146 | {to find the word we go through the text on a character by character |
||
147 | basis but working backwards} |
||
148 | for i := finish downto start do |
||
22 | daniel-mar | 149 | if TryAndMatch( Sender, i, start ) then |
13 | daniel-mar | 150 | Exit; |
151 | |||
152 | end; |
||
153 | |||
154 | function TFindReplace.TryAndMatch( Sender: TFindDialog; index, finish: integer ): boolean; |
||
155 | {returns true if there was a match and false otherwise} |
||
156 | var |
||
157 | StringToTest: string; |
||
158 | |||
22 | daniel-mar | 159 | StringComparison: TReplaceFunc; |
160 | {the function to use to compare 2 strings. Should be assigned |
||
161 | different values according to the search criteria} |
||
162 | |||
163 | FindTextLength: integer; |
||
164 | |||
165 | resourcestring |
||
166 | S_CANT_BE_FOUND = '%s could not be found'; |
||
13 | daniel-mar | 167 | begin |
22 | daniel-mar | 168 | FindTextLength := Length( Sender.FindText ); |
169 | |||
13 | daniel-mar | 170 | {create a new string to test against} |
171 | StringToTest := copy( fEditor.Text, index+1, FindTextLength ); |
||
172 | |||
22 | daniel-mar | 173 | {assign a case sensitive or case insensitive string |
174 | comparison function to StringComparison depending |
||
175 | on the whether or not the user chose to match case. |
||
176 | The functions assigned are normal VCL functions.} |
||
177 | if frMatchCase in Sender.Options then |
||
178 | StringComparison := CompareStr |
||
179 | else |
||
180 | StringComparison := CompareText; |
||
181 | |||
182 | if (StringComparison( StringToTest, Sender.FindText ) = 0) and |
||
13 | daniel-mar | 183 | TestWholeWord( Sender, copy( fEditor.Text, index, FindTextLength+2 ) ) then |
184 | {with TestWholeWord we pass the value index not index+1 so that it will also |
||
185 | get the previous character. We pass the value FindTextLenght+2 so it |
||
186 | will copy the next character after the test string aswell} |
||
187 | begin {if all true then we've found the text} |
||
188 | {highlight the word} |
||
189 | fEditor.SetFocus; |
||
190 | fEditor.SelStart := index; |
||
191 | fEditor.SelLength := FindTextLength; |
||
192 | |||
193 | {quit the function} |
||
194 | Result := true; {because we've found the word} |
||
195 | Exit; |
||
196 | end |
||
197 | {if we've tried the last character and we can't find it then |
||
198 | display a message saying so.} |
||
199 | else if (index = finish) and (FindActionOnEnd = frcAlertUser) then |
||
22 | daniel-mar | 200 | ShowMessageFmt(S_CANT_BE_FOUND, [Sender.FindText]) |
13 | daniel-mar | 201 | {otherwise if the replace function requested us to keep quiet |
202 | about it then don't display the message to the user} |
||
203 | else if (index = finish) and (FindActionOnEnd = frcAlertReplace) then |
||
204 | FindActionOnEnd := frcEndReached; |
||
205 | |||
206 | Result := false; {didn't find it} |
||
207 | end; |
||
208 | |||
22 | daniel-mar | 209 | procedure TFindReplace.DoFind(dialog: TFindDialog; direction: TFindDirection); |
13 | daniel-mar | 210 | var |
211 | // highlightedText: pChar; |
||
212 | highlightedText: string; |
||
213 | |||
214 | begin |
||
22 | daniel-mar | 215 | if direction = sdDefault then |
216 | begin |
||
217 | if frDown in dialog.Options then |
||
218 | direction := sdForwards |
||
219 | else |
||
220 | direction := sdBackwards; |
||
221 | end; |
||
13 | daniel-mar | 222 | |
223 | {check if there is already some highlighted text. If there is and |
||
224 | this text is the text to search for then it's probably been highlighted |
||
225 | by the previous find operation. In this case, move selStart to |
||
226 | the position after the final character so the find operation won't find |
||
227 | the same word again. If the user chose to search up then move selStart |
||
228 | to the character before the highlighted word} |
||
229 | if fEditor.SelLength > 0 then |
||
230 | begin |
||
231 | (* |
||
232 | GetMem( highlightedText, fEditor.SelLength + 1 ); |
||
233 | fEditor.GetSelTextBuf( highlightedText, fEditor.SelLength+1 ); |
||
234 | *) |
||
235 | highlightedText := fEditor.SelText; |
||
236 | |||
237 | {compare the two strings} |
||
22 | daniel-mar | 238 | if StrIComp( PChar(highlightedText), pChar( dialog.FindText ) ) = 0 then |
13 | daniel-mar | 239 | begin |
22 | daniel-mar | 240 | if direction = sdForwards then |
13 | daniel-mar | 241 | fEditor.selStart := fEditor.SelStart + fEditor.SelLength |
22 | daniel-mar | 242 | else |
243 | fEditor.selStart := fEditor.SelStart - 1; |
||
13 | daniel-mar | 244 | end; |
245 | |||
246 | (* |
||
247 | FreeMem( highlightedText, fEditor.SelLength + 1 ); |
||
248 | *) |
||
249 | end; |
||
250 | |||
251 | {begin the search} |
||
22 | daniel-mar | 252 | if direction = sdForwards then {the user choose to search down} |
13 | daniel-mar | 253 | begin |
254 | {if the user has highlighted a block of text only search |
||
255 | within that block} |
||
256 | if fEditor.SelLength > 0 then |
||
22 | daniel-mar | 257 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ) |
13 | daniel-mar | 258 | {otherwise search the whole of the text} |
22 | daniel-mar | 259 | else |
260 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
||
13 | daniel-mar | 261 | end |
262 | else {the user chose to search up} |
||
263 | begin |
||
264 | {if the user has highlighted a block of text only search |
||
265 | within that block} |
||
266 | if fEditor.SelLength > 0 then |
||
22 | daniel-mar | 267 | FindBackwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ) |
13 | daniel-mar | 268 | {otherwise search the whole of the text} |
22 | daniel-mar | 269 | else |
270 | FindBackwards( dialog, 0, fEditor.selStart ); |
||
13 | daniel-mar | 271 | end; |
22 | daniel-mar | 272 | end; |
13 | daniel-mar | 273 | |
22 | daniel-mar | 274 | procedure TFindReplace.OnFind(Sender: TObject); |
275 | var |
||
276 | FindDialog: TFindDialog; |
||
277 | begin |
||
278 | FindDialog := Sender as TFindDialog; |
||
279 | DoFind(FindDialog, sdDefault); |
||
13 | daniel-mar | 280 | end; |
281 | |||
22 | daniel-mar | 282 | procedure TFindReplace.OnReplace( Sender: TObject ); |
283 | var |
||
284 | ReplaceDialog: TReplaceDialog; |
||
13 | daniel-mar | 285 | begin |
22 | daniel-mar | 286 | ReplaceDialog := Sender as TReplaceDialog; |
13 | daniel-mar | 287 | |
288 | {set the action on end to alert the function not the user} |
||
289 | FindActionOnEnd := frcAlertReplace; |
||
290 | |||
291 | {now replace the word} |
||
22 | daniel-mar | 292 | if frReplace in ReplaceDialog.Options then |
293 | DoReplace(ReplaceDialog) |
||
294 | else |
||
295 | DoReplaceAll(ReplaceDialog); |
||
13 | daniel-mar | 296 | |
297 | {reset the action on end to alert the user} |
||
298 | FindActionOnEnd := frcAlertUser; |
||
299 | end; |
||
300 | |||
22 | daniel-mar | 301 | procedure TFindReplace.DoReplace(dialog: TReplaceDialog); |
13 | daniel-mar | 302 | begin |
303 | |||
304 | {if the user has highlighted a block of text only replace |
||
305 | within that block} |
||
306 | if fEditor.SelLength > 0 then |
||
307 | begin |
||
22 | daniel-mar | 308 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
309 | TryAndReplace(dialog); |
||
13 | daniel-mar | 310 | end |
311 | {otherwise replace within the whole of the text} |
||
312 | else |
||
313 | begin |
||
22 | daniel-mar | 314 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
315 | TryAndReplace(dialog); |
||
13 | daniel-mar | 316 | end; |
317 | |||
318 | end; |
||
319 | |||
22 | daniel-mar | 320 | procedure TFindReplace.DoReplaceAll(dialog: TReplaceDialog); |
13 | daniel-mar | 321 | begin |
322 | {see comments for DoReplace} |
||
323 | |||
324 | if fEditor.SelLength > 0 then |
||
325 | begin |
||
22 | daniel-mar | 326 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
13 | daniel-mar | 327 | {keep replacing until we reach the end of the text} |
328 | while FindActionOnEnd <> frcEndReached do |
||
329 | begin |
||
330 | {we enclose the TryAndReplace in a loop because there might be more |
||
331 | than one occurence of the word in the line} |
||
22 | daniel-mar | 332 | while TryAndReplace(dialog) do |
333 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
||
13 | daniel-mar | 334 | |
22 | daniel-mar | 335 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
13 | daniel-mar | 336 | end; |
337 | end |
||
338 | else |
||
339 | begin |
||
22 | daniel-mar | 340 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
13 | daniel-mar | 341 | while FindActionOnEnd <> frcEndReached do |
342 | begin |
||
22 | daniel-mar | 343 | while TryAndReplace(dialog) do |
344 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
||
13 | daniel-mar | 345 | |
22 | daniel-mar | 346 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
13 | daniel-mar | 347 | end; |
348 | end; |
||
349 | |||
350 | end; |
||
351 | |||
22 | daniel-mar | 352 | function TFindReplace.TryAndReplace(dialog: TReplaceDialog): boolean; |
13 | daniel-mar | 353 | {returns true if a replacement was made and false otherwise. This is |
354 | so a function can keep calling TryAndReplace until it returns false |
||
355 | since there might be more than one occurence of the word to replace |
||
356 | in the line} |
||
357 | |||
358 | var |
||
359 | LineNumber, ColumnNumber: integer; |
||
360 | ReplacementString: string; {string used to replace the text} |
||
361 | |||
22 | daniel-mar | 362 | OldSelStart: integer; {the position of the cursor prior to the text |
13 | daniel-mar | 363 | being replaced} |
364 | |||
365 | |||
366 | begin |
||
367 | {assume no replacement was made} |
||
368 | Result := false; |
||
369 | |||
370 | {check to see if the word was found otherwise we don't add the |
||
371 | replaceText to the editor. That is, only delete the selected text |
||
372 | and insert the replacement text if the end was not reached} |
||
373 | if not (FindActionOnEnd = frcEndReached) then |
||
374 | begin |
||
375 | {get the line number and column number of the cursor which |
||
376 | is needed for string manipulations later. We should do this |
||
377 | before the call to clear selection} |
||
378 | GetLineNumber( fEditor.SelStart, LineNumber, ColumnNumber ); |
||
379 | {get the position of the cursor prior to the replace operation |
||
380 | so we cab restore it later} |
||
381 | OldSelStart := fEditor.SelStart; |
||
382 | |||
383 | {delete the unwanted word} |
||
384 | fEditor.ClearSelection; |
||
385 | |||
386 | {Add the replacement text} |
||
387 | {Since we can't directly manipulate the Lines field of the |
||
388 | TCustomMemo component we'll extract the line, manipulate it |
||
389 | then put it back} |
||
390 | ReplacementString := fEditor.Lines[ LineNumber ]; |
||
391 | {truncate the newline (#$A#$D) at the end of tempstring} |
||
392 | SetLength( ReplacementString, Length( ReplacementString )-2 ); |
||
393 | {add the replacement text into tempstring} |
||
22 | daniel-mar | 394 | Insert( dialog.ReplaceText, ReplacementString, ColumnNumber+1 ); |
13 | daniel-mar | 395 | {remove the old string and add the new string into the editor} |
396 | fEditor.Lines.Delete( LineNumber ); |
||
397 | fEditor.Lines.Insert( LineNumber, ReplacementString ); |
||
398 | |||
399 | {set the result to true since we have made a replacement} |
||
400 | Result := true; |
||
401 | |||
402 | {reposition the cursor to the character after the last chracter in |
||
403 | the newly replacing text. This is mainly so we can locate multiple |
||
404 | occurences of the to-be-replaced text in the same line} |
||
22 | daniel-mar | 405 | fEditor.SelStart := oldSelStart + length( dialog.ReplaceText ); |
13 | daniel-mar | 406 | end |
407 | end; |
||
408 | |||
409 | procedure TFindReplace.FindExecute; |
||
410 | begin |
||
411 | fFindDialog.Execute; |
||
412 | end; |
||
413 | |||
414 | procedure TFindReplace.ReplaceExecute; |
||
415 | begin |
||
416 | fReplaceDialog.Execute; |
||
417 | end; |
||
418 | |||
419 | function TFindReplace.TestWholeWord( Sender: TFindDialog; TestString: string ): boolean; |
||
22 | daniel-mar | 420 | var |
421 | FindTextLength: integer; |
||
13 | daniel-mar | 422 | begin |
423 | {assume it's not a whole word} |
||
424 | Result := false; |
||
425 | |||
22 | daniel-mar | 426 | FindTextLength := Length( Sender.FindText ); |
427 | |||
13 | daniel-mar | 428 | {if the user didn't choose whole words only then basically |
429 | we don't care about it so return true} |
||
430 | if not (frWholeWord in Sender.Options) then |
||
431 | begin |
||
432 | Result := true; |
||
433 | Exit; |
||
434 | end; |
||
435 | |||
436 | {Test if the word is a whole word} |
||
437 | {Basically there are 4 cases: ( _ denotes whitespace ) |
||
438 | 1. _word_ |
||
439 | 2. \nword_ |
||
440 | 3. _word\n |
||
441 | 4.\nword\n} |
||
442 | {case 1, note: #9 tab, #$A newline} |
||
443 | if (CharInSet(TestString[1], [' ', #9 ])) and (CharInSet(TestString[FindTextLength + 2], [' ', #9 ])) then |
||
444 | Result := true |
||
445 | {case 2} |
||
446 | else if(TestString[1] = #$A) and (CharInSet(TestString[FindTextLength + 2], [' ', #9 ])) then |
||
447 | Result := true |
||
448 | {case 3, note: #$D end of line} |
||
449 | else if(CharInSet(TestString[1], [' ', #9 ])) and (TestString[FindTextLength + 2] = #$D) then |
||
450 | Result := true |
||
451 | else if (TestString[1] = #$A) and (TestString[FindTextLength + 2] = #$D) then |
||
452 | Result := true |
||
453 | |||
454 | end; |
||
455 | |||
22 | daniel-mar | 456 | procedure TFindReplace.FindContinue; |
457 | begin |
||
458 | if fFindDialog.FindText = '' then |
||
459 | begin |
||
460 | fFindDialog.Options := fFindDialog.Options + [frDown]; // Default direction: down |
||
461 | FindExecute; |
||
462 | end |
||
463 | else |
||
464 | DoFind(fFindDialog, sdDefault); |
||
465 | end; |
||
466 | |||
13 | daniel-mar | 467 | procedure TFindReplace.FindNext; |
468 | begin |
||
22 | daniel-mar | 469 | if fFindDialog.FindText = '' then |
470 | begin |
||
471 | fFindDialog.Options := fFindDialog.Options + [frDown]; |
||
472 | FindExecute; |
||
473 | end |
||
474 | else |
||
475 | DoFind(fFindDialog, sdForwards); |
||
13 | daniel-mar | 476 | end; |
477 | |||
22 | daniel-mar | 478 | procedure TFindReplace.FindPrev; |
13 | daniel-mar | 479 | begin |
480 | if fFindDialog.FindText = '' then |
||
481 | begin |
||
22 | daniel-mar | 482 | fFindDialog.Options := fFindDialog.Options - [frDown]; |
483 | FindExecute; |
||
484 | end |
||
485 | else |
||
486 | DoFind(fFindDialog, sdBackwards); |
||
13 | daniel-mar | 487 | end; |
488 | |||
489 | procedure TFindReplace.GetLineNumber( Position: Integer; var LineNumber, ColumnNumber: integer ); |
||
490 | var |
||
491 | i: integer; |
||
492 | |||
493 | begin |
||
494 | {initialise line number to 0} |
||
495 | LineNumber := 0; |
||
496 | |||
497 | {increment line number each time we encounter a newline (#$D) in the text} |
||
498 | for i := 1 to Position do |
||
499 | if fEditor.Text = #$D then |
||
500 | inc( LineNumber ); |
||
501 | |||
502 | {set the column number to position first} |
||
503 | ColumnNumber := Position; |
||
504 | {get the columnNumber by subtracting the length of each previous line} |
||
505 | for i := 0 to (LineNumber-1) do |
||
506 | dec( ColumnNumber, (*Length( fEditor.Lines )*) fEditor.Lines.Strings[i].Length ); |
||
507 | |||
508 | end; |
||
509 | |||
510 | procedure TFindReplace.GoToLine( LineNumber: integer ); |
||
511 | var |
||
512 | currentLine: integer; |
||
513 | i: integer; |
||
514 | |||
515 | begin |
||
516 | {set the current line to 1} |
||
517 | currentLine := 1; |
||
518 | |||
519 | {go through the whole text looking for the line} |
||
520 | for i := 1 to fEditor.GetTextLen do |
||
521 | begin |
||
522 | if currentLine = LineNumber then |
||
523 | begin |
||
524 | {goto the position corresponding to the line} |
||
525 | fEditor.selStart := i; |
||
526 | fEditor.SetFocus; |
||
527 | {quit the function} |
||
528 | Exit; |
||
529 | end |
||
530 | else if fEditor.Text = #$D then |
||
531 | inc( currentLine ); |
||
532 | end; |
||
533 | |||
534 | end; |
||
535 | |||
22 | daniel-mar | 536 | procedure TFindReplace.CloseDialogs; |
537 | begin |
||
538 | fFindDialog.CloseDialog; |
||
539 | fReplaceDialog.CloseDialog; |
||
540 | end; |
||
541 | |||
13 | daniel-mar | 542 | (* |
543 | procedure Register; |
||
544 | begin |
||
545 | RegisterComponents('Tek-tips', [TFindReplace]); |
||
546 | end; |
||
547 | *) |
||
548 | |||
549 | end. |