Subversion Repositories fastphp

Rev

Rev 23 | Rev 25 | 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.   protected
  47.     type
  48.       TFindDirection = (sdDefault, sdForwards, sdBackwards);
  49.  
  50.     procedure OnFind(Sender: TObject); virtual;
  51.     procedure OnReplace(Sender: TObject); virtual;
  52.  
  53.     procedure DoFind(dialog: TFindDialog; direction: TFindDirection);
  54.     procedure DoReplace(dialog: TReplaceDialog; direction: TFindDirection);
  55.  
  56.     function GetDirection(dialog: TFindDialog): TFindDirection;
  57.  
  58.   public
  59.     constructor Create(AOwner: TComponent); override;
  60.  
  61.     property FindDialog: TFindDialog read fFindDialog;
  62.     property ReplaceDialog: TReplaceDialog read fReplaceDialog;
  63.  
  64.     procedure CloseDialogs;
  65.  
  66.     procedure FindExecute;
  67.     procedure ReplaceExecute;
  68.  
  69.     procedure FindContinue;
  70.     procedure FindNext;
  71.     procedure FindPrev;
  72.  
  73.     procedure GoToLine(LineNumber: integer);
  74.  
  75.   published
  76.     property Editor: TSynEdit read fEditor write fEditor;
  77.   end;
  78.  
  79. implementation
  80.  
  81. uses
  82.   SynEditTypes;
  83.  
  84. constructor TSynEditFindReplace.Create(AOwner: TComponent);
  85. begin
  86.   inherited Create(AOwner);
  87.  
  88.   fFindDialog := TFindDialog.Create(Self);
  89.   fFindDialog.OnFind := OnFind;
  90.  
  91.   fReplaceDialog := TReplaceDialog.Create(Self);
  92.   fReplaceDialog.OnReplace := OnReplace;
  93.   fReplaceDialog.OnFind := OnFind;
  94.   fReplaceDialog.Options := fReplaceDialog.Options + [frHideWholeWord]; // TODO: currently not supported (see below)
  95. end;
  96.  
  97. function TSynEditFindReplace.GetDirection(dialog: TFindDialog): TFindDirection;
  98. begin
  99.   if frDown in dialog.Options then
  100.     result := sdForwards
  101.   else
  102.     result := sdBackwards;
  103. end;
  104.  
  105. procedure TSynEditFindReplace.DoFind(dialog: TFindDialog; direction: TFindDirection);
  106. var
  107.   opt: TSynSearchOptions;
  108.   found: boolean;
  109. begin
  110.   if direction = sdDefault then direction := GetDirection(dialog);
  111.  
  112.   if fEditor.SelAvail then
  113.   begin
  114.     if direction = sdForwards then
  115.     begin
  116.       fEditor.SelStart := fEditor.SelStart + 1;
  117.       fEditor.SelLength := 0;
  118.     end
  119.     else
  120.     begin
  121.       // Links von Selektion springen
  122.       fEditor.SelLength := 0;
  123.     end;
  124.   end;
  125.  
  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?
  135.  
  136.   found := fEditor.SearchReplace(dialog.FindText, '', opt) > 0;
  137.  
  138.   if not found then
  139.   begin
  140.     if direction = sdForwards then
  141.       ShowMessage('End of document reached.')
  142.     else
  143.       ShowMessage('Begin of document reached.');
  144.   end;
  145. end;
  146.  
  147. procedure TSynEditFindReplace.DoReplace(dialog: TReplaceDialog; direction: TFindDirection);
  148. var
  149.   opt: TSynSearchOptions;
  150.   numReplacements: integer;
  151. begin
  152.   if direction = sdDefault then direction := GetDirection(dialog);
  153.  
  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?
  163.  
  164.   fEditor.BeginUpdate; // TODO: geht nicht?
  165.   //fEditor.BeginUndoBlock;
  166.   try
  167.     numReplacements := fEditor.SearchReplace(dialog.FindText, dialog.ReplaceText, opt);
  168.   finally
  169.     //fEditor.EndUndoBlock;
  170.     fEditor.EndUpdate;
  171.   end;
  172.  
  173.   // TODO: numReplacements anzeigen
  174. end;
  175.  
  176. procedure TSynEditFindReplace.OnFind(Sender: TObject);
  177. begin
  178.   DoFind(Sender as TFindDialog, sdDefault);
  179. end;
  180.  
  181. procedure TSynEditFindReplace.OnReplace(Sender: TObject);
  182. begin
  183.   DoReplace(Sender as TReplaceDialog, sdDefault);
  184. end;
  185.  
  186. procedure TSynEditFindReplace.FindExecute;
  187. begin
  188.   fFindDialog.Execute;
  189. end;
  190.  
  191. procedure TSynEditFindReplace.ReplaceExecute;
  192. begin
  193.   fReplaceDialog.Execute;
  194. end;
  195.  
  196. procedure TSynEditFindReplace.FindContinue;
  197. begin
  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.  
  207. procedure TSynEditFindReplace.FindNext;
  208. begin
  209.   if fFindDialog.FindText = '' then
  210.   begin
  211.     fFindDialog.Options := fFindDialog.Options + [frDown];
  212.     FindExecute;
  213.   end
  214.   else
  215.     DoFind(fFindDialog, sdForwards);
  216. end;
  217.  
  218. procedure TSynEditFindReplace.FindPrev;
  219. begin
  220.   if fFindDialog.FindText = '' then
  221.   begin
  222.     fFindDialog.Options := fFindDialog.Options - [frDown];
  223.     FindExecute;
  224.   end
  225.   else
  226.     DoFind(fFindDialog, sdBackwards);
  227. end;
  228.  
  229. procedure TSynEditFindReplace.GoToLine(LineNumber: integer);
  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
  245.       inc(currentLine);
  246.   end;
  247. end;
  248.  
  249. procedure TSynEditFindReplace.CloseDialogs;
  250. begin
  251.   fFindDialog.CloseDialog;
  252.   fReplaceDialog.CloseDialog;
  253. end;
  254.  
  255. end.
  256.