Subversion Repositories fastphp

Rev

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