Subversion Repositories fastphp

Rev

Rev 23 | Rev 25 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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