Subversion Repositories fastphp

Rev

Rev 24 | Rev 49 | 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
 
24 daniel-mar 3
  (*
4
  TSynSearchOption = (ssoMatchCase, ssoWholeWord, ssoBackwards,
5
    ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt);
13 daniel-mar 6
 
24 daniel-mar 7
  frDisableMatchCase
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.
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
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
  *)
34
 
13 daniel-mar 35
interface
36
 
37
uses
38
  Windows, Messages, SysUtils, Classes, Dialogs, SynEdit;
39
 
40
type
24 daniel-mar 41
  TSynEditFindReplace = class(TComponent)
13 daniel-mar 42
  private
24 daniel-mar 43
    fEditor: TSynEdit;
44
    fReplaceDialog: TReplaceDialog;
45
    fFindDialog: TFindDialog;
25 daniel-mar 46
    fAutofocus: boolean;
13 daniel-mar 47
  protected
22 daniel-mar 48
    type
49
      TFindDirection = (sdDefault, sdForwards, sdBackwards);
50
 
24 daniel-mar 51
    procedure OnFind(Sender: TObject); virtual;
52
    procedure OnReplace(Sender: TObject); virtual;
13 daniel-mar 53
 
24 daniel-mar 54
    procedure DoFind(dialog: TFindDialog; direction: TFindDirection);
55
    procedure DoReplace(dialog: TReplaceDialog; direction: TFindDirection);
13 daniel-mar 56
 
24 daniel-mar 57
    function GetDirection(dialog: TFindDialog): TFindDirection;
13 daniel-mar 58
 
59
  public
24 daniel-mar 60
    constructor Create(AOwner: TComponent); override;
13 daniel-mar 61
 
22 daniel-mar 62
    property FindDialog: TFindDialog read fFindDialog;
63
    property ReplaceDialog: TReplaceDialog read fReplaceDialog;
13 daniel-mar 64
 
22 daniel-mar 65
    procedure CloseDialogs;
66
 
13 daniel-mar 67
    procedure FindExecute;
68
    procedure ReplaceExecute;
69
 
22 daniel-mar 70
    procedure FindContinue;
71
    procedure FindNext;
72
    procedure FindPrev;
73
 
24 daniel-mar 74
    procedure GoToLine(LineNumber: integer);
13 daniel-mar 75
 
76
  published
22 daniel-mar 77
    property Editor: TSynEdit read fEditor write fEditor;
25 daniel-mar 78
    property Autofocus: boolean read fAutofocus write fAutofocus;
13 daniel-mar 79
  end;
80
 
81
implementation
82
 
24 daniel-mar 83
uses
84
  SynEditTypes;
13 daniel-mar 85
 
24 daniel-mar 86
constructor TSynEditFindReplace.Create(AOwner: TComponent);
13 daniel-mar 87
begin
24 daniel-mar 88
  inherited Create(AOwner);
13 daniel-mar 89
 
24 daniel-mar 90
  fFindDialog := TFindDialog.Create(Self);
13 daniel-mar 91
  fFindDialog.OnFind := OnFind;
92
 
24 daniel-mar 93
  fReplaceDialog := TReplaceDialog.Create(Self);
13 daniel-mar 94
  fReplaceDialog.OnReplace := OnReplace;
95
  fReplaceDialog.OnFind := OnFind;
23 daniel-mar 96
  fReplaceDialog.Options := fReplaceDialog.Options + [frHideWholeWord]; // TODO: currently not supported (see below)
13 daniel-mar 97
end;
98
 
24 daniel-mar 99
function TSynEditFindReplace.GetDirection(dialog: TFindDialog): TFindDirection;
13 daniel-mar 100
begin
24 daniel-mar 101
  if frDown in dialog.Options then
102
    result := sdForwards
103
  else
104
    result := sdBackwards;
13 daniel-mar 105
end;
106
 
24 daniel-mar 107
procedure TSynEditFindReplace.DoFind(dialog: TFindDialog; direction: TFindDirection);
13 daniel-mar 108
var
24 daniel-mar 109
  opt: TSynSearchOptions;
110
  found: boolean;
13 daniel-mar 111
begin
24 daniel-mar 112
  if direction = sdDefault then direction := GetDirection(dialog);
13 daniel-mar 113
 
24 daniel-mar 114
  if fEditor.SelAvail then
22 daniel-mar 115
  begin
24 daniel-mar 116
    if direction = sdForwards then
117
    begin
118
      fEditor.SelStart := fEditor.SelStart + 1;
119
      fEditor.SelLength := 0;
120
    end
22 daniel-mar 121
    else
24 daniel-mar 122
    begin
123
      // Links von Selektion springen
124
      fEditor.SelLength := 0;
125
    end;
22 daniel-mar 126
  end;
13 daniel-mar 127
 
24 daniel-mar 128
  opt := [];
129
  if frMatchCase in dialog.Options then Include(opt, ssoMatchCase);
130
  if frWholeWord in dialog.Options then Include(opt, ssoWholeWord);
131
  //if frReplace in dialog.Options then Include(opt, ssoReplace);
132
  //if frReplaceAll in dialog.Options then Include(opt, ssoReplaceAll);
133
  if direction = sdBackwards then Include(opt, ssoBackwards);
134
  //Include(opt, ssoPrompt); // TODO: test. geht nicht?
135
  //if fEditor.SelAvail then Include(opt, ssoSelectedOnly);  // TODO: geht nicht, weil er bei einer suche ja dann etwas selektirert und dann nicht weitergeht
136
  Exclude(opt, ssoEntireScope); // TODO: ok?
13 daniel-mar 137
 
24 daniel-mar 138
  found := fEditor.SearchReplace(dialog.FindText, '', opt) > 0;
13 daniel-mar 139
 
24 daniel-mar 140
  if not found then
13 daniel-mar 141
  begin
24 daniel-mar 142
    if direction = sdForwards then
143
      ShowMessage('End of document reached.')
22 daniel-mar 144
    else
24 daniel-mar 145
      ShowMessage('Begin of document reached.');
13 daniel-mar 146
  end;
25 daniel-mar 147
 
148
  if fAutofocus and fEditor.CanFocus then fEditor.SetFocus;
22 daniel-mar 149
end;
13 daniel-mar 150
 
24 daniel-mar 151
procedure TSynEditFindReplace.DoReplace(dialog: TReplaceDialog; direction: TFindDirection);
22 daniel-mar 152
var
24 daniel-mar 153
  opt: TSynSearchOptions;
154
  numReplacements: integer;
22 daniel-mar 155
begin
24 daniel-mar 156
  if direction = sdDefault then direction := GetDirection(dialog);
13 daniel-mar 157
 
24 daniel-mar 158
  opt := [];
159
  if frMatchCase in dialog.Options then Include(opt, ssoMatchCase);
160
  if frWholeWord in dialog.Options then Include(opt, ssoWholeWord);
161
  if frReplace in dialog.Options then Include(opt, ssoReplace);
162
  if frReplaceAll in dialog.Options then Include(opt, ssoReplaceAll);
163
  if direction = sdBackwards then Include(opt, ssoBackwards);
164
  Include(opt, ssoPrompt); // TODO: test. geht nicht?
165
  if fEditor.SelAvail then Include(opt, ssoSelectedOnly);
166
  Exclude(opt, ssoEntireScope); // TODO: ok?
13 daniel-mar 167
 
24 daniel-mar 168
  fEditor.BeginUpdate; // TODO: geht nicht?
169
  //fEditor.BeginUndoBlock;
23 daniel-mar 170
  try
24 daniel-mar 171
    numReplacements := fEditor.SearchReplace(dialog.FindText, dialog.ReplaceText, opt);
23 daniel-mar 172
  finally
24 daniel-mar 173
    //fEditor.EndUndoBlock;
23 daniel-mar 174
    fEditor.EndUpdate;
13 daniel-mar 175
  end;
24 daniel-mar 176
 
25 daniel-mar 177
  ShowMessageFmt('%d replaced.', [numReplacements]);
178
 
179
  if fAutofocus and fEditor.CanFocus then fEditor.SetFocus;
13 daniel-mar 180
end;
181
 
24 daniel-mar 182
procedure TSynEditFindReplace.OnFind(Sender: TObject);
183
begin
184
  DoFind(Sender as TFindDialog, sdDefault);
185
end;
13 daniel-mar 186
 
24 daniel-mar 187
procedure TSynEditFindReplace.OnReplace(Sender: TObject);
13 daniel-mar 188
begin
24 daniel-mar 189
  DoReplace(Sender as TReplaceDialog, sdDefault);
13 daniel-mar 190
end;
191
 
24 daniel-mar 192
procedure TSynEditFindReplace.FindExecute;
13 daniel-mar 193
begin
194
  fFindDialog.Execute;
195
end;
196
 
24 daniel-mar 197
procedure TSynEditFindReplace.ReplaceExecute;
13 daniel-mar 198
begin
199
  fReplaceDialog.Execute;
200
end;
201
 
24 daniel-mar 202
procedure TSynEditFindReplace.FindContinue;
13 daniel-mar 203
begin
22 daniel-mar 204
  if fFindDialog.FindText = '' then
205
  begin
206
    fFindDialog.Options := fFindDialog.Options + [frDown]; // Default direction: down
207
    FindExecute;
208
  end
209
  else
210
    DoFind(fFindDialog, sdDefault);
211
end;
212
 
24 daniel-mar 213
procedure TSynEditFindReplace.FindNext;
13 daniel-mar 214
begin
22 daniel-mar 215
  if fFindDialog.FindText = '' then
216
  begin
217
    fFindDialog.Options := fFindDialog.Options + [frDown];
218
    FindExecute;
219
  end
220
  else
221
    DoFind(fFindDialog, sdForwards);
13 daniel-mar 222
end;
223
 
24 daniel-mar 224
procedure TSynEditFindReplace.FindPrev;
13 daniel-mar 225
begin
226
  if fFindDialog.FindText = '' then
227
  begin
22 daniel-mar 228
    fFindDialog.Options := fFindDialog.Options - [frDown];
229
    FindExecute;
230
  end
231
  else
232
    DoFind(fFindDialog, sdBackwards);
13 daniel-mar 233
end;
234
 
24 daniel-mar 235
procedure TSynEditFindReplace.GoToLine(LineNumber: integer);
13 daniel-mar 236
var
237
  currentLine: integer;
238
  i: integer;
239
begin
240
  currentLine := 1;
241
 
242
  for i := 1 to fEditor.GetTextLen do
243
  begin
244
    if currentLine = LineNumber then
245
    begin
246
      fEditor.selStart := i;
247
      fEditor.SetFocus;
248
      Exit;
249
    end
250
    else if fEditor.Text = #$D then
24 daniel-mar 251
      inc(currentLine);
13 daniel-mar 252
  end;
253
end;
254
 
24 daniel-mar 255
procedure TSynEditFindReplace.CloseDialogs;
22 daniel-mar 256
begin
257
  fFindDialog.CloseDialog;
258
  fReplaceDialog.CloseDialog;
259
end;
260
 
13 daniel-mar 261
end.