Subversion Repositories fastphp

Rev

Rev 24 | Rev 49 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit FindReplace;
  2.  
  3.   (*
  4.   TSynSearchOption = (ssoMatchCase, ssoWholeWord, ssoBackwards,
  5.     ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt);
  6.  
  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.  
  35. interface
  36.  
  37. uses
  38.   Windows, Messages, SysUtils, Classes, Dialogs, SynEdit;
  39.  
  40. type
  41.   TSynEditFindReplace = class(TComponent)
  42.   private
  43.     fEditor: TSynEdit;
  44.     fReplaceDialog: TReplaceDialog;
  45.     fFindDialog: TFindDialog;
  46.     fAutofocus: boolean;
  47.   protected
  48.     type
  49.       TFindDirection = (sdDefault, sdForwards, sdBackwards);
  50.  
  51.     procedure OnFind(Sender: TObject); virtual;
  52.     procedure OnReplace(Sender: TObject); virtual;
  53.  
  54.     procedure DoFind(dialog: TFindDialog; direction: TFindDirection);
  55.     procedure DoReplace(dialog: TReplaceDialog; direction: TFindDirection);
  56.  
  57.     function GetDirection(dialog: TFindDialog): TFindDirection;
  58.  
  59.   public
  60.     constructor Create(AOwner: TComponent); override;
  61.  
  62.     property FindDialog: TFindDialog read fFindDialog;
  63.     property ReplaceDialog: TReplaceDialog read fReplaceDialog;
  64.  
  65.     procedure CloseDialogs;
  66.  
  67.     procedure FindExecute;
  68.     procedure ReplaceExecute;
  69.  
  70.     procedure FindContinue;
  71.     procedure FindNext;
  72.     procedure FindPrev;
  73.  
  74.     procedure GoToLine(LineNumber: integer);
  75.  
  76.   published
  77.     property Editor: TSynEdit read fEditor write fEditor;
  78.     property Autofocus: boolean read fAutofocus write fAutofocus;
  79.   end;
  80.  
  81. implementation
  82.  
  83. uses
  84.   SynEditTypes;
  85.  
  86. constructor TSynEditFindReplace.Create(AOwner: TComponent);
  87. begin
  88.   inherited Create(AOwner);
  89.  
  90.   fFindDialog := TFindDialog.Create(Self);
  91.   fFindDialog.OnFind := OnFind;
  92.  
  93.   fReplaceDialog := TReplaceDialog.Create(Self);
  94.   fReplaceDialog.OnReplace := OnReplace;
  95.   fReplaceDialog.OnFind := OnFind;
  96.   fReplaceDialog.Options := fReplaceDialog.Options + [frHideWholeWord]; // TODO: currently not supported (see below)
  97. end;
  98.  
  99. function TSynEditFindReplace.GetDirection(dialog: TFindDialog): TFindDirection;
  100. begin
  101.   if frDown in dialog.Options then
  102.     result := sdForwards
  103.   else
  104.     result := sdBackwards;
  105. end;
  106.  
  107. procedure TSynEditFindReplace.DoFind(dialog: TFindDialog; direction: TFindDirection);
  108. var
  109.   opt: TSynSearchOptions;
  110.   found: boolean;
  111. begin
  112.   if direction = sdDefault then direction := GetDirection(dialog);
  113.  
  114.   if fEditor.SelAvail then
  115.   begin
  116.     if direction = sdForwards then
  117.     begin
  118.       fEditor.SelStart := fEditor.SelStart + 1;
  119.       fEditor.SelLength := 0;
  120.     end
  121.     else
  122.     begin
  123.       // Links von Selektion springen
  124.       fEditor.SelLength := 0;
  125.     end;
  126.   end;
  127.  
  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?
  137.  
  138.   found := fEditor.SearchReplace(dialog.FindText, '', opt) > 0;
  139.  
  140.   if not found then
  141.   begin
  142.     if direction = sdForwards then
  143.       ShowMessage('End of document reached.')
  144.     else
  145.       ShowMessage('Begin of document reached.');
  146.   end;
  147.  
  148.   if fAutofocus and fEditor.CanFocus then fEditor.SetFocus;
  149. end;
  150.  
  151. procedure TSynEditFindReplace.DoReplace(dialog: TReplaceDialog; direction: TFindDirection);
  152. var
  153.   opt: TSynSearchOptions;
  154.   numReplacements: integer;
  155. begin
  156.   if direction = sdDefault then direction := GetDirection(dialog);
  157.  
  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?
  167.  
  168.   fEditor.BeginUpdate; // TODO: geht nicht?
  169.   //fEditor.BeginUndoBlock;
  170.   try
  171.     numReplacements := fEditor.SearchReplace(dialog.FindText, dialog.ReplaceText, opt);
  172.   finally
  173.     //fEditor.EndUndoBlock;
  174.     fEditor.EndUpdate;
  175.   end;
  176.  
  177.   ShowMessageFmt('%d replaced.', [numReplacements]);
  178.  
  179.   if fAutofocus and fEditor.CanFocus then fEditor.SetFocus;
  180. end;
  181.  
  182. procedure TSynEditFindReplace.OnFind(Sender: TObject);
  183. begin
  184.   DoFind(Sender as TFindDialog, sdDefault);
  185. end;
  186.  
  187. procedure TSynEditFindReplace.OnReplace(Sender: TObject);
  188. begin
  189.   DoReplace(Sender as TReplaceDialog, sdDefault);
  190. end;
  191.  
  192. procedure TSynEditFindReplace.FindExecute;
  193. begin
  194.   fFindDialog.Execute;
  195. end;
  196.  
  197. procedure TSynEditFindReplace.ReplaceExecute;
  198. begin
  199.   fReplaceDialog.Execute;
  200. end;
  201.  
  202. procedure TSynEditFindReplace.FindContinue;
  203. begin
  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.  
  213. procedure TSynEditFindReplace.FindNext;
  214. begin
  215.   if fFindDialog.FindText = '' then
  216.   begin
  217.     fFindDialog.Options := fFindDialog.Options + [frDown];
  218.     FindExecute;
  219.   end
  220.   else
  221.     DoFind(fFindDialog, sdForwards);
  222. end;
  223.  
  224. procedure TSynEditFindReplace.FindPrev;
  225. begin
  226.   if fFindDialog.FindText = '' then
  227.   begin
  228.     fFindDialog.Options := fFindDialog.Options - [frDown];
  229.     FindExecute;
  230.   end
  231.   else
  232.     DoFind(fFindDialog, sdBackwards);
  233. end;
  234.  
  235. procedure TSynEditFindReplace.GoToLine(LineNumber: integer);
  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
  251.       inc(currentLine);
  252.   end;
  253. end;
  254.  
  255. procedure TSynEditFindReplace.CloseDialogs;
  256. begin
  257.   fFindDialog.CloseDialog;
  258.   fReplaceDialog.CloseDialog;
  259. end;
  260.  
  261. end.
  262.