瀏覽代碼

UPD: Rewrite editor search dialog

Alexander Koblov 3 年之前
父節點
當前提交
439bd9ef66
共有 4 個文件被更改,包括 258 次插入392 次删除
  1. 27 135
      src/feditor.pas
  2. 56 43
      src/feditsearch.lfm
  3. 1 0
      src/feditsearch.lrj
  4. 174 214
      src/feditsearch.pas

+ 27 - 135
src/feditor.pas

@@ -3,7 +3,7 @@
    -------------------------------------------------------------------------
    Build-in Editor using SynEdit and his Highlighters
 
-   Copyright (C) 2006-2020  Alexander Koblov ([email protected])
+   Copyright (C) 2006-2022  Alexander Koblov ([email protected])
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -35,9 +35,9 @@ unit fEditor;
 interface
 
 uses
-  SysUtils, Classes, Controls, Forms, ActnList, Menus, SynEdit,
+  SysUtils, Classes, Controls, Forms, ActnList, Menus, SynEdit, StdCtrls,
   ComCtrls, SynEditSearch, SynEditHighlighter, uDebug, uOSForms, uShowForm, types, Graphics,
-  uFormCommands, uHotkeyManager, LCLVersion, SynPluginMultiCaret;
+  uFormCommands, uHotkeyManager, LCLVersion, SynPluginMultiCaret, fEditSearch;
 
 const
   HotkeysCategory = 'Editor';
@@ -151,14 +151,8 @@ type
     { Private declarations }
     bChanged:Boolean;
     bNoName: Boolean;
-    bSearchBackwards:Boolean;
-    bSearchCaseSensitive:Boolean;
-    bSearchFromCaret:Boolean;
-    bSearchSelectionOnly:Boolean;
-    bSearchWholeWords:Boolean;
-    bSearchRegExp:Boolean;
+    FSearchOptions: TEditSearchOptions;
     FFileName: String;
-    sSearchText, sReplaceText:String;
     sEncodingIn,
     sEncodingOut,
     sEncodingStat,
@@ -198,8 +192,6 @@ type
     procedure SetEncodingOut(Sender:TObject);
     procedure SetHighLighter(Sender:TObject);
     procedure UpdateHighlighter(Highlighter: TSynCustomHighlighter);
-    procedure DoSearchReplaceText(AReplace: boolean; ABackwards: boolean);
-    procedure ShowSearchReplaceDialog(AReplace: boolean);
     procedure LoadGlobalOptions;
 
     property FileName: String read FFileName write SetFileName;
@@ -241,7 +233,7 @@ implementation
 
 uses
   Clipbrd, dmCommonData, dmHigh, SynEditTypes, LCLType, LConvEncoding,
-  uLng, uShowMsg, fEditSearch, uGlobs, fOptions, DCClassesUtf8, uAdministrator,
+  uLng, uShowMsg, uGlobs, fOptions, DCClassesUtf8, uAdministrator,
   uOSUtils, uConvEncoding, fOptionsToolsEditor, uDCUtils, uClipboard, uFindFiles;
 
 procedure ShowEditor(const sFileName: String; WaitData: TWaitData = nil);
@@ -330,6 +322,7 @@ begin
       miEncodingOut.Add(mi);
     end;
   EncodingsList.Free;
+  FSearchOptions.Flags := [ssoEntireScope];
   // if we already search text then use last searched text
   if not gFirstTextSearch then
   begin
@@ -341,11 +334,11 @@ begin
         Continue;
 
       if (tsoMatchCase in Options) then
-        bSearchCaseSensitive:= True;
+        FSearchOptions.Flags += [ssoMatchCase];
       if (tsoRegExpr in Options) then
-        bSearchRegExp:= True;
+        FSearchOptions.Flags += [ssoRegExpr];
 
-      sSearchText:= glsSearchHistory[I];
+      FSearchOptions.SearchText:= glsSearchHistory[I];
       Break;
     end;
   end;
@@ -777,101 +770,6 @@ begin
   CanClose:= True;
 end;
 
-procedure TfrmEditor.DoSearchReplaceText(AReplace: boolean;
-  ABackwards: boolean);
-var
-  Options: TSynSearchOptions;
-begin
-  Statusbar.SimpleText := '';
-  if AReplace then
-    Options := [ssoPrompt, ssoReplace, ssoReplaceAll]
-  else
-    Options := [];
-  if ABackwards then
-    Include(Options, ssoBackwards);
-  if bSearchCaseSensitive then
-    Include(Options, ssoMatchCase);
-  if not bSearchFromCaret then
-    Include(Options, ssoEntireScope);
-  if bSearchSelectionOnly then
-    Include(Options, ssoSelectedOnly);
-  if bSearchWholeWords then
-    Include(Options, ssoWholeWord);
-  if bSearchRegExp then
-    Include(Options, ssoRegExpr);
-  try
-    if Editor.SearchReplace(sSearchText, sReplaceText, Options) = 0 then
-    begin
-      if ssoBackwards in Options then
-        Editor.BlockEnd := Editor.BlockBegin
-      else
-        Editor.BlockBegin := Editor.BlockEnd;
-      Editor.CaretXY := Editor.BlockBegin;
-      msgOK(Format(rsViewNotFound, ['"' + sSearchText + '"']));
-    end;
-  except
-    on E: Exception do msgError(E.Message);
-  end;
-end;
-
-procedure TfrmEditor.ShowSearchReplaceDialog(AReplace: boolean);
-var
-  dlg: TfrmEditSearchReplace;
-begin
-//  Statusbar.SimpleText := '';
-  dlg := TfrmEditSearchReplace.Create(Self, AReplace);
-  with dlg do try
-    // assign search options
-    SearchBackwards := bSearchBackwards;
-    SearchCaseSensitive := bSearchCaseSensitive;
-    SearchFromCursor := bSearchFromCaret;
-    SearchInSelectionOnly := bSearchSelectionOnly;
-    if Editor.SelAvail and not (Editor.BlockBegin.Y = Editor.BlockEnd.Y)
-    then
-      SearchInSelectionOnly := True;
-    SearchRegExp := bSearchRegExp;
-    // start with last search text
-    SearchText := sSearchText;
-{    if fSearchTextAtCaret then begin}
-      // if something is selected search for that text
-      if Editor.SelAvail and (Editor.BlockBegin.Y = Editor.BlockEnd.Y)
-      then
-        SearchText := Editor.SelText
-      else
-        SearchText := Editor.GetWordAtRowCol(Editor.CaretXY);
-//    end;
-    SearchTextHistory := glsSearchHistory.Text;
-    if AReplace then with dlg as TfrmEditSearchReplace do begin
-      ReplaceText := sReplaceText;
-      ReplaceTextHistory := glsReplaceHistory.Text;
-    end;
-    SearchWholeWords := bSearchWholeWords;
-    if ShowModal = mrOK then begin
-      bSearchBackwards := SearchBackwards;
-      bSearchCaseSensitive := SearchCaseSensitive;
-      bSearchFromCaret := SearchFromCursor;
-      bSearchSelectionOnly := SearchInSelectionOnly;
-      bSearchWholeWords := SearchWholeWords;
-      bSearchRegExp := SearchRegExp;
-      sSearchText := SearchText;
-      glsSearchHistory.Text := SearchTextHistory;
-      if AReplace then with dlg as TfrmEditSearchReplace do begin
-        sReplaceText := ReplaceText;
-        glsReplaceHistory.Text := ReplaceTextHistory;
-      end;
-//      bSearchFromCaret := gbSearchFromCaret;
-      if sSearchText <> '' then
-      begin
-        DoSearchReplaceText(AReplace, bSearchBackwards);
-        bSearchFromCaret:= True;
-        gFirstTextSearch:= False;
-      end;
-    end;
-  finally
-    FreeAndNil(dlg);
-  end;
-end;
-
 procedure TfrmEditor.cm_FileReload(const Params: array of string);
 begin
   if bChanged then
@@ -884,41 +782,35 @@ end;
 
 procedure TfrmEditor.cm_EditFind(const Params: array of string);
 begin
-  ShowSearchReplaceDialog(False);
+  ShowSearchReplaceDialog(Self, Editor, cbUnchecked, FSearchOptions);
 end;
 
-
 procedure TfrmEditor.cm_EditFindNext(const Params:array of string);
 begin
   if gFirstTextSearch then
-    begin
-      ShowSearchReplaceDialog(False);
-      Exit;
-    end;
-  if sSearchText <> '' then
-    begin
-      DoSearchReplaceText(False, bSearchBackwards);
-      bSearchFromCaret:= True;
-    end;
+    ShowSearchReplaceDialog(Self, Editor, cbUnchecked, FSearchOptions)
+  else if FSearchOptions.SearchText <> '' then
+  begin
+    DoSearchReplaceText(Editor, False, ssoBackwards in FSearchOptions.Flags, FSearchOptions);
+    FSearchOptions.Flags -= [ssoEntireScope];
+  end;
 end;
 
 procedure TfrmEditor.cm_EditFindPrevious(const Params: array of string);
 begin
   if gFirstTextSearch then
-    begin
-      bSearchBackwards:=True;
-      ShowSearchReplaceDialog(False);
-      Exit;
-    end;
-  if sSearchText <> '' then
-    begin
-      Editor.SelEnd:=Editor.SelStart;
-      DoSearchReplaceText(False, True);
-      bSearchFromCaret:= True;
-    end;
+  begin
+    FSearchOptions.Flags += [ssoBackwards];
+    ShowSearchReplaceDialog(Self, Editor, cbUnchecked, FSearchOptions);
+  end
+  else if FSearchOptions.SearchText <> '' then
+  begin
+    Editor.SelEnd := Editor.SelStart;
+    DoSearchReplaceText(Editor, False, True, FSearchOptions);
+    FSearchOptions.Flags -= [ssoEntireScope];
+  end;
 end;
 
-
 procedure TfrmEditor.cm_EditGotoLine(const Params:array of string);
 var
   P: TPoint;
@@ -1073,7 +965,7 @@ end;
 
 procedure TfrmEditor.cm_EditRplc(const Params: array of string);
 begin
-  ShowSearchReplaceDialog(True);
+  ShowSearchReplaceDialog(Self, Editor, cbChecked, FSearchOptions)
 end;
 
 procedure TfrmEditor.frmEditorClose(Sender: TObject;

+ 56 - 43
src/feditsearch.lfm

@@ -1,13 +1,13 @@
 object frmEditSearchReplace: TfrmEditSearchReplace
   Left = 606
-  Height = 255
+  Height = 274
   Top = 251
   Width = 385
   ActiveControl = cbSearchText
   AutoSize = True
   BorderIcons = []
   ChildSizing.TopBottomSpacing = 6
-  ClientHeight = 255
+  ClientHeight = 274
   ClientWidth = 385
   Constraints.MinWidth = 385
   OnCloseQuery = FormCloseQuery
@@ -15,32 +15,34 @@ object frmEditSearchReplace: TfrmEditSearchReplace
   OnShow = FormShow
   Position = poOwnerFormCenter
   SessionProperties = 'Left;Top;Width;Height'
-  LCLVersion = '1.6.0.4'
+  LCLVersion = '2.2.0.4'
   object lblSearchFor: TLabel
     AnchorSideLeft.Control = Owner
     AnchorSideTop.Control = cbSearchText
     AnchorSideTop.Side = asrCenter
     Left = 12
-    Height = 14
-    Top = 15
-    Width = 66
+    Height = 15
+    Top = 16
+    Width = 56
     BorderSpacing.Left = 12
     Caption = '&Search for:'
     FocusControl = cbSearchText
     ParentColor = False
   end
-  object lblReplaceWith: TLabel
+  object lblReplaceWith: TCheckBox
     AnchorSideLeft.Control = Owner
     AnchorSideTop.Control = cbReplaceText
     AnchorSideTop.Side = asrCenter
     Left = 12
-    Height = 14
-    Top = 41
-    Width = 80
+    Height = 19
+    Top = 43
+    Width = 90
     BorderSpacing.Left = 12
     Caption = '&Replace with:'
-    FocusControl = cbReplaceText
+    Color = clDefault
+    OnChange = lblReplaceWithChange
     ParentColor = False
+    TabOrder = 1
   end
   object cbSearchText: TComboBox
     AnchorSideLeft.Control = lblSearchFor
@@ -48,15 +50,15 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     AnchorSideTop.Control = Owner
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
-    Left = 84
-    Height = 20
+    Left = 74
+    Height = 23
     Top = 12
-    Width = 293
+    Width = 303
     Anchors = [akTop, akLeft, akRight]
     BorderSpacing.Left = 6
     BorderSpacing.Top = 12
     BorderSpacing.Right = 8
-    ItemHeight = 14
+    ItemHeight = 15
     TabOrder = 0
   end
   object gbSearchOptions: TGroupBox
@@ -64,9 +66,9 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     AnchorSideTop.Control = cbReplaceText
     AnchorSideTop.Side = asrBottom
     Left = 12
-    Height = 133
-    Top = 70
-    Width = 162
+    Height = 156
+    Top = 76
+    Width = 142
     AutoSize = True
     BorderSpacing.Left = 12
     BorderSpacing.Top = 12
@@ -74,16 +76,16 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     Caption = 'Option'
     ChildSizing.LeftRightSpacing = 6
     ChildSizing.TopBottomSpacing = 6
-    ClientHeight = 115
-    ClientWidth = 158
-    TabOrder = 2
+    ClientHeight = 136
+    ClientWidth = 138
+    TabOrder = 3
     object cbSearchCaseSensitive: TCheckBox
       AnchorSideLeft.Control = gbSearchOptions
       AnchorSideTop.Control = gbSearchOptions
       Left = 8
       Height = 19
       Top = 6
-      Width = 117
+      Width = 100
       BorderSpacing.Left = 8
       BorderSpacing.Top = 2
       Caption = 'C&ase sensitivity'
@@ -96,7 +98,7 @@ object frmEditSearchReplace: TfrmEditSearchReplace
       Left = 8
       Height = 19
       Top = 27
-      Width = 131
+      Width = 115
       BorderSpacing.Left = 8
       BorderSpacing.Top = 2
       Caption = '&Whole words only'
@@ -109,7 +111,7 @@ object frmEditSearchReplace: TfrmEditSearchReplace
       Left = 8
       Height = 19
       Top = 48
-      Width = 134
+      Width = 113
       BorderSpacing.Left = 8
       BorderSpacing.Top = 2
       Caption = 'Selected &text only'
@@ -122,7 +124,7 @@ object frmEditSearchReplace: TfrmEditSearchReplace
       Left = 8
       Height = 19
       Top = 69
-      Width = 134
+      Width = 113
       BorderSpacing.Left = 8
       BorderSpacing.Top = 2
       Caption = 'S&earch from caret'
@@ -135,12 +137,25 @@ object frmEditSearchReplace: TfrmEditSearchReplace
       Left = 8
       Height = 19
       Top = 90
-      Width = 144
+      Width = 124
       BorderSpacing.Left = 8
       BorderSpacing.Top = 2
       Caption = '&Regular expressions'
       TabOrder = 4
     end
+    object cbMultiLine: TCheckBox
+      AnchorSideLeft.Control = gbSearchOptions
+      AnchorSideTop.Control = cbSearchRegExp
+      AnchorSideTop.Side = asrBottom
+      Left = 8
+      Height = 19
+      Top = 111
+      Width = 108
+      BorderSpacing.Left = 8
+      BorderSpacing.Top = 2
+      Caption = '&Multiline pattern'
+      TabOrder = 5
+    end
   end
   object rgSearchDirection: TRadioGroup
     AnchorSideLeft.Control = gbSearchOptions
@@ -149,10 +164,10 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     AnchorSideTop.Side = asrBottom
     AnchorSideRight.Control = cbSearchText
     AnchorSideRight.Side = asrBottom
-    Left = 180
+    Left = 160
     Height = 70
-    Top = 70
-    Width = 197
+    Top = 76
+    Width = 217
     Anchors = [akTop, akLeft, akRight]
     AutoFill = True
     AutoSize = True
@@ -167,13 +182,13 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     ChildSizing.ShrinkVertical = crsScaleChilds
     ChildSizing.Layout = cclLeftToRightThenTopToBottom
     ChildSizing.ControlsPerLine = 1
-    ClientHeight = 52
-    ClientWidth = 193
+    ClientHeight = 50
+    ClientWidth = 213
     Items.Strings = (
       '&Forward'
       '&Backward'
     )
-    TabOrder = 3
+    TabOrder = 4
   end
   object cbReplaceText: TComboBox
     AnchorSideLeft.Control = lblReplaceWith
@@ -182,16 +197,16 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     AnchorSideTop.Side = asrBottom
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
-    Left = 98
-    Height = 20
-    Top = 38
-    Width = 279
+    Left = 108
+    Height = 23
+    Top = 41
+    Width = 269
     Anchors = [akTop, akLeft, akRight]
     BorderSpacing.Left = 6
     BorderSpacing.Top = 6
     BorderSpacing.Right = 8
-    ItemHeight = 14
-    TabOrder = 1
+    ItemHeight = 15
+    TabOrder = 2
   end
   object ButtonPanel: TButtonPanel
     AnchorSideLeft.Control = Owner
@@ -200,15 +215,14 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 6
-    Height = 28
-    Top = 213
+    Height = 26
+    Top = 242
     Width = 373
     Align = alNone
     Anchors = [akTop, akLeft, akRight]
     BorderSpacing.Top = 4
     OKButton.Name = 'OKButton'
     OKButton.Caption = '&OK'
-    OKButton.DefaultCaption = False
     OKButton.OnClick = btnOKClick
     HelpButton.Name = 'HelpButton'
     HelpButton.DefaultCaption = True
@@ -216,8 +230,7 @@ object frmEditSearchReplace: TfrmEditSearchReplace
     CloseButton.DefaultCaption = True
     CancelButton.Name = 'CancelButton'
     CancelButton.Caption = '&Cancel'
-    CancelButton.DefaultCaption = False
-    TabOrder = 4
+    TabOrder = 5
     Spacing = 12
     ShowButtons = [pbOK, pbCancel]
     ShowBevel = False

+ 1 - 0
src/feditsearch.lrj

@@ -7,6 +7,7 @@
 {"hash":231163145,"name":"tfrmeditsearchreplace.cbsearchselectedonly.caption","sourcebytes":[83,101,108,101,99,116,101,100,32,38,116,101,120,116,32,111,110,108,121],"value":"Selected &text only"},
 {"hash":60025108,"name":"tfrmeditsearchreplace.cbsearchfromcursor.caption","sourcebytes":[83,38,101,97,114,99,104,32,102,114,111,109,32,99,97,114,101,116],"value":"S&earch from caret"},
 {"hash":8115171,"name":"tfrmeditsearchreplace.cbsearchregexp.caption","sourcebytes":[38,82,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115],"value":"&Regular expressions"},
+{"hash":135735390,"name":"tfrmeditsearchreplace.cbmultiline.caption","sourcebytes":[38,77,117,108,116,105,108,105,110,101,32,112,97,116,116,101,114,110],"value":"&Multiline pattern"},
 {"hash":146466142,"name":"tfrmeditsearchreplace.rgsearchdirection.caption","sourcebytes":[68,105,114,101,99,116,105,111,110],"value":"Direction"},
 {"hash":11067,"name":"tfrmeditsearchreplace.buttonpanel.okbutton.caption","sourcebytes":[38,79,75],"value":"&OK"},
 {"hash":177752476,"name":"tfrmeditsearchreplace.buttonpanel.cancelbutton.caption","sourcebytes":[38,67,97,110,99,101,108],"value":"&Cancel"}

+ 174 - 214
src/feditsearch.pas

@@ -1,57 +1,24 @@
 {
-  Search & Replace dialog
-  for lazarus converted from SynEdit by
-  Radek Cervinka, [email protected]
+   Double Commander
+   -------------------------------------------------------------------------
+   Search & Replace dialog
 
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the Free
-  Software Foundation; either version 2 of the License, or (at your option)
-  any later version.
+   Copyright (C) 2003-2004 Radek Cervinka ([email protected])
+   Copyright (C) 2006-2022 Alexander Koblov ([email protected])
 
-  This program is distributed in the hope that it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
-  for more details.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-  Place - Suite 330, Boston, MA 02111-1307, USA.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-
-
-based on SynEdit demo, original license:
-
--------------------------------------------------------------------------------
-
-Software distributed under the License is distributed on an "AS IS" basis,
-WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
-the specific language governing rights and limitations under the License.
-
-The Original Code is: dlgSearchText.pas, released 2000-06-23.
-
-The Original Code is part of the SearchReplaceDemo project, written by
-Michael Hieke for the SynEdit component suite.
-All Rights Reserved.
-
-Contributors to the SynEdit project are listed in the Contributors.txt file.
-
-Alternatively, the contents of this file may be used under the terms of the
-GNU General Public License Version 2 or later (the "GPL"), in which case
-the provisions of the GPL are applicable instead of those above.
-If you wish to allow use of your version of this file only under the terms
-of the GPL and not to allow others to use your version of this file
-under the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the GPL.
-If you do not delete the provisions above, a recipient may use your version
-of this file under either the MPL or the GPL.
-
-$Id: dlgSearchText.pas,v 1.3 2002/08/01 05:44:05 etrusco Exp $
-
-You may retrieve the latest version of this file at the SynEdit home page,
-located at http://SynEdit.SourceForge.net
-
-Known Issues:
--------------------------------------------------------------------------------}
+   You should have received a copy of the GNU General Public License
+   along with this program. If not, see <http://www.gnu.org/licenses/>.
+}
 
 unit fEditSearch;
 
@@ -61,9 +28,17 @@ interface
 
 uses
   Classes, SysUtils, Forms, Controls, StdCtrls, ExtCtrls, Buttons, ButtonPanel,
-  uOSForms, DCClassesUtf8;
+  SynEdit, SynEditTypes, uOSForms, DCClassesUtf8;
 
 type
+  { TEditSearchOptions }
+
+  TEditSearchOptions = record
+    SearchText: String;
+    ReplaceText: String;
+    Flags: TSynSearchOptions;
+  end;
+
   { TEditSearchDialogOption }
   //Not only it helps to show what we want to offer to user, it will help to determine the default
   //When used as parameters of function, place on required.
@@ -76,6 +51,7 @@ type
                                     eswoDirectionDisabled, eswoDirectionEnabledForward, eswoDirectionEnabledBackward);
 
   { TfrmEditSearchReplace }
+
   TfrmEditSearchReplace = class(TModalForm)
     ButtonPanel: TButtonPanel;
     cbSearchText: TComboBox;
@@ -85,67 +61,37 @@ type
     cbSearchFromCursor: TCheckBox;
     cbSearchRegExp: TCheckBox;
     cbReplaceText: TComboBox;
+    cbMultiLine: TCheckBox;
     gbSearchOptions: TGroupBox;
-    lblReplaceWith: TLabel;
+    lblReplaceWith: TCheckBox;
     lblSearchFor: TLabel;
     rgSearchDirection: TRadioGroup;
     procedure btnOKClick(Sender: TObject);
     procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
     procedure FormCreate(Sender: TObject);
     procedure FormShow(Sender: TObject);
+    procedure lblReplaceWithChange(Sender: TObject);
     procedure RequestAlign(Data: PtrInt);
   private
-    function GetSearchBackwards: boolean;
-    function GetSearchCaseSensitive: boolean;
-    function GetSearchFromCursor: boolean;
-    function GetSearchInSelection: boolean;
-    function GetSearchText: string;
-    function GetSearchTextHistory: string;
-    function GetSearchWholeWords: boolean;
-    function GetSearchRegExp: boolean;
-    function GetReplaceText: string;
-    function GetReplaceTextHistory: string;
-    procedure SetSearchBackwards(Value: boolean);
-    procedure SetSearchCaseSensitive(Value: boolean);
-    procedure SetSearchFromCursor(Value: boolean);
-    procedure SetSearchInSelection(Value: boolean);
-    procedure SetSearchText(Value: string);
-    procedure SetSearchTextHistory(Value: string);
-    procedure SetSearchWholeWords(Value: boolean);
-    procedure SetSearchRegExp(Value: boolean);
-    procedure SetReplaceText(Value: string);
-    procedure SetReplaceTextHistory(Value: string);
+    function GetSearchOptions: TEditSearchOptions;
+    procedure SetSearchOptions(AValue: TEditSearchOptions);
     function GetTextSearchOptions: UIntPtr;
   public
-    constructor Create(AOwner: TComponent; AReplace: Boolean); reintroduce;
-    property SearchBackwards: boolean read GetSearchBackwards
-      write SetSearchBackwards;
-    property SearchCaseSensitive: boolean read GetSearchCaseSensitive
-      write SetSearchCaseSensitive;
-    property SearchFromCursor: boolean read GetSearchFromCursor
-      write SetSearchFromCursor;
-    property SearchInSelectionOnly: boolean read GetSearchInSelection
-      write SetSearchInSelection;
-    property SearchText: string read GetSearchText write SetSearchText;
-    property SearchTextHistory: string read GetSearchTextHistory
-      write SetSearchTextHistory;
-    property SearchWholeWords: boolean read GetSearchWholeWords
-      write SetSearchWholeWords;
-    property SearchRegExp: boolean read GetSearchRegExp
-      write SetSearchRegExp;
-    property ReplaceText: string read GetReplaceText write SetReplaceText;
-    property ReplaceTextHistory: string read GetReplaceTextHistory
-      write SetReplaceTextHistory;
+    constructor Create(AOwner: TComponent; AReplace: TCheckBoxState); reintroduce;
+    property SearchOptions: TEditSearchOptions read GetSearchOptions write SetSearchOptions;
   end;
 
-  function GetSimpleSearchAndReplaceString(AOwner:TComponent; OptionAllowed:TEditSearchDialogOption; var sSearchText:string; var sReplaceText:string; var OptionsToReturn:TEditSearchDialogOption; PastSearchList:TStringListEx; PastReplaceList:TStringListEx):boolean;
+  function GetSimpleSearchAndReplaceString(AOwner: TComponent; OptionAllowed: TEditSearchDialogOption; var sSearchText: string; var sReplaceText: string; var OptionsToReturn:TEditSearchDialogOption; PastSearchList:TStringListEx; PastReplaceList:TStringListEx):boolean;
+
+  procedure DoSearchReplaceText(AEditor: TCustomSynEdit; AReplace, ABackwards: Boolean; AOptions: TEditSearchOptions);
+  procedure ShowSearchReplaceDialog(AOwner: TComponent; AEditor: TCustomSynEdit; AReplace: TCheckBoxState; var AOptions: TEditSearchOptions);
 
 implementation
 
 {$R *.lfm}
 
 uses
-  Math, Graphics, uGlobs, uLng, uDCUtils, uFindFiles;
+  Math, Graphics, uGlobs, uLng, uDCUtils, uFindFiles, uShowMsg;
 
 function GetSimpleSearchAndReplaceString(AOwner:TComponent; OptionAllowed:TEditSearchDialogOption; var sSearchText:string; var sReplaceText:string; var OptionsToReturn:TEditSearchDialogOption; PastSearchList:TStringListEx; PastReplaceList:TStringListEx):boolean;
 var
@@ -154,7 +100,7 @@ begin
   result:=FALSE;
   OptionsToReturn:=[];
 
-  dlg := TfrmEditSearchReplace.Create(AOwner, TRUE);
+  dlg := TfrmEditSearchReplace.Create(AOwner, cbChecked);
   try
     with dlg do
     begin
@@ -176,12 +122,12 @@ begin
 
       //3. Setup the SEARCH info
       if sSearchText='' then sSearchText:=rsEditSearchCaption;
-      SearchTextHistory:=PastSearchList.Text;
-      cbSearchText.Text:=sSearchText;
+      cbSearchText.Items.Assign(PastSearchList);
+      cbSearchText.Text:= sSearchText;
 
       //4. Setup the REPLACE info
       if sReplaceText='' then sReplaceText:=rsEditSearchReplace;
-      ReplaceTextHistory:=PastReplaceList.Text;
+      cbReplaceText.Items.Assign(PastReplaceList);
       cbReplaceText.Text:=sReplaceText;
 
       //5. Get feedback from user
@@ -202,8 +148,8 @@ begin
           if rgSearchDirection.ItemIndex=1 then OptionsToReturn:=OptionsToReturn+[eswoDirectionEnabledBackward] else OptionsToReturn:=OptionsToReturn+[eswoDirectionEnabledForward];
 
         //7. Let's set our history
-        PastSearchList.Text:=SearchTextHistory;
-        PastReplaceList.Text:=ReplaceTextHistory;
+        PastSearchList.Assign(cbSearchText.Items);
+        PastReplaceList.Assign(cbReplaceText.Items);
 
         //8. And FINALLY, our valuable text to search we wanted to replace!
         sSearchText:=cbSearchText.Text;
@@ -217,6 +163,81 @@ begin
   end;
 end;
 
+procedure DoSearchReplaceText(AEditor: TCustomSynEdit; AReplace,
+  ABackwards: Boolean; AOptions: TEditSearchOptions);
+var
+  Flags: TSynSearchOptions;
+begin
+  Flags := AOptions.Flags;
+
+  if ABackwards then
+    Include(Flags, ssoBackwards)
+  else begin
+    Exclude(Flags, ssoBackwards);
+  end;
+
+  if AReplace then begin
+    Flags += [ssoPrompt, ssoReplace, ssoReplaceAll];
+  end;
+
+  try
+    if AEditor.SearchReplace(AOptions.SearchText, AOptions.ReplaceText, Flags) = 0 then
+    begin
+      if ssoBackwards in Flags then
+        AEditor.BlockEnd := AEditor.BlockBegin
+      else begin
+        AEditor.BlockBegin := AEditor.BlockEnd;
+      end;
+      AEditor.CaretXY := AEditor.BlockBegin;
+      msgOK(Format(rsViewNotFound, ['"' + AOptions.SearchText + '"']));
+    end;
+  except
+    on E: Exception do msgError(E.Message);
+  end;
+end;
+
+procedure ShowSearchReplaceDialog(AOwner: TComponent; AEditor: TCustomSynEdit;
+  AReplace: TCheckBoxState; var AOptions: TEditSearchOptions);
+var
+  Options: TEditSearchOptions;
+begin
+  with TfrmEditSearchReplace.Create(AOwner, AReplace) do
+  try
+    Options := AOptions;
+
+    if AEditor.SelAvail and (AEditor.BlockBegin.Y <> AEditor.BlockEnd.Y) then
+      Options.Flags += [ssoSelectedOnly];
+
+    // If something is selected then search for that text
+    if AEditor.SelAvail and (AEditor.BlockBegin.Y = AEditor.BlockEnd.Y) then
+      Options.SearchText := AEditor.SelText
+    else begin
+      Options.SearchText := AEditor.GetWordAtRowCol(AEditor.CaretXY);
+    end;
+
+    cbSearchText.Items.Text := glsSearchHistory.Text;
+    cbReplaceText.Items.Text := glsReplaceHistory.Text;
+
+    // Assign search options
+    SearchOptions := Options;
+
+    if ShowModal = mrOK then
+    begin
+      AOptions := SearchOptions;
+      glsSearchHistory.Assign(cbSearchText.Items);
+      glsReplaceHistory.Assign(cbReplaceText.Items);
+      if AOptions.SearchText <> '' then
+      begin
+        DoSearchReplaceText(AEditor, AReplace = cbChecked, ssoBackwards in AOptions.Flags, AOptions);
+        AOptions.Flags -= [ssoEntireScope];
+        gFirstTextSearch := False;
+      end;
+    end;
+  finally
+    Free;
+  end;
+end;
+
 { TfrmEditSearchReplace }
 
 procedure TfrmEditSearchReplace.btnOKClick(Sender: TObject);
@@ -250,118 +271,58 @@ begin
   Application.QueueAsyncCall(@RequestAlign, 0);
 end;
 
-procedure TfrmEditSearchReplace.RequestAlign(Data: PtrInt);
-begin
-  Width := Width + 1;
-  Width := Width - 1;
-end;
-
-function TfrmEditSearchReplace.GetSearchBackwards: boolean;
-begin
-  Result := rgSearchDirection.ItemIndex = 1;
-end;
-
-function TfrmEditSearchReplace.GetSearchCaseSensitive: boolean;
-begin
-  Result := cbSearchCaseSensitive.Checked;
-end;
-
-function TfrmEditSearchReplace.GetSearchFromCursor: boolean;
+procedure TfrmEditSearchReplace.lblReplaceWithChange(Sender: TObject);
 begin
-  Result := cbSearchFromCursor.Checked;
-end;
-
-function TfrmEditSearchReplace.GetSearchInSelection: boolean;
-begin
-  Result := cbSearchSelectedOnly.Checked;
-end;
-
-function TfrmEditSearchReplace.GetSearchText: string;
-begin
-  Result := cbSearchText.Text;
-end;
-
-function TfrmEditSearchReplace.GetSearchTextHistory: string;
-var
-  i: integer;
-begin
-  for i:= cbSearchText.Items.Count - 1 downto 25 do
-    cbSearchText.Items.Delete(i);
-  Result:=cbSearchText.Items.Text;
-end;
-
-function TfrmEditSearchReplace.GetSearchWholeWords: boolean;
-begin
-  Result := cbSearchWholeWords.Checked;
-end;
-
-function TfrmEditSearchReplace.GetSearchRegExp: boolean;
-begin
-  Result:= cbSearchRegExp.Checked;
-end;
-
-function TfrmEditSearchReplace.GetReplaceText: string;
-begin
-  Result := cbReplaceText.Text;
-end;
-
-function TfrmEditSearchReplace.GetReplaceTextHistory: string;
-var
-  i: integer;
-begin
-  for i:= cbSearchText.Items.Count - 1 downto 25 do
-    cbReplaceText.Items.Delete(i);
-  Result:=cbReplaceText.Items.Text;
-end;
-
-procedure TfrmEditSearchReplace.SetSearchBackwards(Value: boolean);
-begin
-  rgSearchDirection.ItemIndex := Ord(Value);
-end;
-
-procedure TfrmEditSearchReplace.SetSearchCaseSensitive(Value: boolean);
-begin
-  cbSearchCaseSensitive.Checked := Value;
-end;
-
-procedure TfrmEditSearchReplace.SetSearchFromCursor(Value: boolean);
-begin
-  cbSearchFromCursor.Checked := Value;
-end;
-
-procedure TfrmEditSearchReplace.SetSearchInSelection(Value: boolean);
-begin
-  cbSearchSelectedOnly.Checked := Value;
-end;
-
-procedure TfrmEditSearchReplace.SetSearchText(Value: string);
-begin
-  cbSearchText.Text := Value;
-end;
-
-procedure TfrmEditSearchReplace.SetSearchTextHistory(Value: string);
-begin
-  cbSearchText.Items.Text := Value;
+  if lblReplaceWith.Checked then
+    Caption:= rsEditSearchReplace
+  else begin
+    Caption:= rsEditSearchCaption;
+  end;
+  cbReplaceText.Enabled := lblReplaceWith.Checked;
 end;
 
-procedure TfrmEditSearchReplace.SetSearchWholeWords(Value: boolean);
+procedure TfrmEditSearchReplace.RequestAlign(Data: PtrInt);
 begin
-  cbSearchWholeWords.Checked := Value;
+  Width := Width + 1;
+  Width := Width - 1;
 end;
 
-procedure TfrmEditSearchReplace.SetSearchRegExp(Value: boolean);
+function TfrmEditSearchReplace.GetSearchOptions: TEditSearchOptions;
 begin
-  cbSearchRegExp.Checked:= Value;
-end;
+  Result.SearchText:= cbSearchText.Text;
+  Result.ReplaceText := cbReplaceText.Text;
 
-procedure TfrmEditSearchReplace.SetReplaceText(Value: string);
-begin
-  cbReplaceText.Items.Text := Value;
+  Result.Flags := [];
+  if cbSearchCaseSensitive.Checked then
+    Result.Flags += [ssoMatchCase];
+  if cbSearchWholeWords.Checked then
+    Result.Flags += [ssoWholeWord];
+  if cbSearchSelectedOnly.Checked then
+    Result.Flags += [ssoSelectedOnly];
+  if not cbSearchFromCursor.Checked then
+    Result.Flags += [ssoEntireScope];
+  if cbSearchRegExp.Checked then
+    Result.Flags += [ssoRegExpr];
+  if cbMultiLine.Checked then
+    Result.Flags += [ssoRegExprMultiLine];
+  if rgSearchDirection.ItemIndex = 1 then
+    Result.Flags += [ssoBackwards];
 end;
 
-procedure TfrmEditSearchReplace.SetReplaceTextHistory(Value: string);
+procedure TfrmEditSearchReplace.SetSearchOptions(AValue: TEditSearchOptions);
 begin
-  cbReplaceText.Items.Text := Value;
+  cbSearchText.Text := AValue.SearchText;
+  cbReplaceText.Text := AValue.ReplaceText;
+  with AValue do
+  begin
+    cbSearchCaseSensitive.Checked := ssoMatchCase in Flags;
+    cbSearchWholeWords.Checked := ssoWholeWord in Flags;
+    cbSearchSelectedOnly.Checked := ssoSelectedOnly in Flags;
+    cbSearchFromCursor.Checked := not (ssoEntireScope in Flags);
+    cbSearchRegExp.Checked := ssoRegExpr in Flags;
+    cbMultiLine.Checked := ssoRegExprMultiLine in Flags;
+    rgSearchDirection.ItemIndex := Ord(ssoBackwards in Flags);
+  end;
 end;
 
 function TfrmEditSearchReplace.GetTextSearchOptions: UIntPtr;
@@ -375,23 +336,22 @@ begin
     Include(Options, tsoRegExpr);
 end;
 
-constructor TfrmEditSearchReplace.Create(AOwner: TComponent; AReplace: Boolean);
+constructor TfrmEditSearchReplace.Create(AOwner: TComponent; AReplace: TCheckBoxState);
 begin
   inherited Create(AOwner);
-  Color:= clForm;
-  if AReplace then
-    begin
-      Caption:= rsEditSearchReplace;
-      lblReplaceWith.Visible:= True;
-      cbReplaceText.Visible:= True;
-    end
-  else
-    begin
-      Caption:= rsEditSearchCaption;
-      lblReplaceWith.Visible:= False;
-      cbReplaceText.Visible:= False;
-      Height:= Height - cbReplaceText.Height;
-    end;
+
+  lblReplaceWith.Visible:= (AReplace <> cbGrayed);
+  cbReplaceText.Visible:= (AReplace <> cbGrayed);
+
+  cbReplaceText.Enabled := (AReplace = cbChecked);
+  lblReplaceWith.Checked := (AReplace = cbChecked);
+
+  if (AReplace = cbChecked) then
+    Caption:= rsEditSearchReplace
+  else begin
+    Caption:= rsEditSearchCaption;
+  end;
+
   rgSearchDirection.Items.Strings[0]:= rsEditSearchFrw;
   rgSearchDirection.Items.Strings[1]:= rsEditSearchBack;
 end;