Recent

Author Topic: topic- search/replace dialogs with synedit - example  (Read 13931 times)

mike parr

  • New Member
  • *
  • Posts: 12
topic- search/replace dialogs with synedit - example
« on: May 12, 2010, 06:09:14 pm »
I know that a number of people want search/replace for synedit, so  am providing some code here.
I have a Delphi app that uses the Windows version of synedit, and successfully used the powerful provided search/replace demo in the synedit package.

However, I wanted to move it to Lazarus and work on Linux.  I've had trouble converting/finding some search/replace code that actually works and is straightforward to incorporate (I'm not a Laz expert).  I'm certain that the code I'm now using is not the best -far from it (Lazarus itself has powerful dialogs) but it works.  The basic functionality is all I need.

So - the code below was originally for Windows/Delphi - I downloaded it and amended it.  It uses a synMemo, and the built-in Lazarus findDialog and replaceDialog components.  If you are a beginner, then create your project, add a synMemo, and dialogs, and paste in the procedures.  Just for a demo, 2 buttons link to find and replace.  The comments in the code will also help.

Best wishes
Mike
-----------------------------
unit Unit1;
 {find/replace synedit/synmemo demo   }
{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,lcltype,
  StdCtrls, SynMemo;   //note the lcltype addition

type
  { TForm1 }

  TForm1 = class(TForm)
      replaceButton: TButton;
      findButton: TButton;
      FindDialog1: TFindDialog;
      ReplaceDialog1: TReplaceDialog;
      Memo1: TSynMemo;
      procedure replaceButtonClick(Sender: TObject);
      procedure findButtonClick(Sender: TObject);

      procedure ReplaceDialog1Find(Sender: TObject);
      procedure ReplaceDialog1Replace(Sender: TObject);
      procedure FindDialog1Find(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

 { ---------------------------------------------------------
  nb this code does not allow 'whole words' or 'up/down'
  search, so hide them via the dialog design-time properties.
  Also, the search always starts from the top of the text. The
  code does not allow a 'search from cursor'.  (Fine for me, but
  apologies if you wanted it.)

Original code from Peter van Hove on
http://logrus.shackspace.com/delphi/delphitips/note_43.htm
Thanks!

  If you are new to Lazarus:
  paste in the code of the large procedures below
  put a replace dialog and a find dialog  on your form - anywhere.

  Go to their properties, and the Events tab
  For the find dialog:
      connect the  OnFind event to FindDialog1Find

  For the replace dialog:
      connect the onFind event to ReplaceDialog1Find
      connect the onReplace event to ReplaceDialog1Replace

 nb the synedit component needs to named memo1
 ---------------------------------------------------------- }


  //These 2 vars for search/replace dialogs
  fPos:integer;
  found:boolean;

implementation
{$R *.lfm}

{ TForm1 }

procedure TForm1.replaceButtonClick(Sender: TObject);
begin
  FPos:=0;
  replaceDialog1.execute;
end;
//-----------------

procedure TForm1.findButtonClick(Sender: TObject);
begin
    FPos:=0;
    findDialog1.execute;
end;
//------------------



//----------------find/replace functionality:  ---------------

 {from -   logrus   peter van hove  http....

 Fixes/additions by Mike:
     Fixed the find bug:  e.g finding AAA in AAAAAA
     should be found twice, not 4 times.
     Added init of FPos before exec of dialogs, to allow
     proper restart after a cancel.
     Added a proc to simulate the selLength property, which
     the delphi synedit has.
     Added a replacement count.
     Added a case/not match

----------------}

//replacement for selLength prop - linux synedit doesnt have it - mike
procedure setSelLength(var textComponent:TSynMemo; newValue:integer);
begin
textComponent.SelEnd:=textComponent.SelStart+newValue ;
end;
//------

procedure TForm1.ReplaceDialog1Find(Sender: TObject);
var
  FindS: String;
  IPos, FLen, SLen: Integer; {Internpos, Lengde søkestreng, lengde memotekst}
  Res : integer;
begin
  {FPos is global}
  Found:= False;
  FLen := Length(ReplaceDialog1.FindText);
  SLen := Length(Memo1.Text);
  FindS := ReplaceDialog1.FindText;

 //following 'if' added by mike
  if frMatchcase in ReplaceDialog1.Options then
     IPos := Pos(FindS, Copy(Memo1.Text,FPos+1,SLen-FPos))
  else
     IPos := Pos(AnsiUpperCase(FindS),AnsiUpperCase( Copy(Memo1.Text,FPos+1,SLen-FPos)));

  If IPos > 0 then begin
    FPos := FPos + IPos;
 //   Hoved.BringToFront;       {Edit control must have focus in } - what is this? mike
    Memo1.SetFocus;
    Self.ActiveControl := Memo1;
    Memo1.SelStart:= FPos;  // removed -1;   mike   {Select the string found by POS}
    setSelLength(memo1, FLen);     //Memo1.SelLength := FLen;
    Found := True;
    FPos:=FPos+FLen-1;   //mike - move just past end of found item
  end
  Else
  begin
    If not (ReplaceDialog1.Options*[frReplaceAll] = [frReplaceAll]) then
      Res := Application.MessageBox('Text was not found!', 'Replace',
      mb_OK + mb_ICONWARNING);
    FPos := 0;     //mike  nb user might cancel dialog, so setting here is not enough
  end;             //   - also do it before exec of dialog.

end;
//-------------------

procedure TForm1.FindDialog1Find(Sender: TObject);  //based on replaceD1find
var
  FindS: String;
  IPos, FLen, SLen: Integer; {Internpos, Lengde søkestreng, lengde memotekst}
  Res : integer;
begin
  {FPos is global}
  Found:= False;
  FLen := Length(findDialog1.FindText);
  SLen := Length(Memo1.Text);
  FindS := findDialog1.FindText;

 //following 'if' added by mike
  if frMatchcase in findDialog1.Options then
     IPos := Pos(FindS, Copy(Memo1.Text,FPos+1,SLen-FPos))
  else
     IPos := Pos(AnsiUpperCase(FindS),AnsiUpperCase( Copy(Memo1.Text,FPos+1,SLen-FPos)));

  If IPos > 0 then begin
    FPos := FPos + IPos;
 //   Hoved.BringToFront;       {Edit control must have focus in }
    Memo1.SetFocus;
    Self.ActiveControl := Memo1;
    Memo1.SelStart:= FPos;  // -1;   mike   {Select the string found by POS}
    setSelLength(memo1, FLen);     //Memo1.SelLength := FLen;
    Found := True;
    FPos:=FPos+FLen-1;   //mike - move just past end of found item

  end
  Else
  begin
    Res := Application.MessageBox('Text was not found!',
           'Find',  mb_OK + mb_ICONWARNING);
    FPos := 0;     //mike  nb user might cancel dialog, so setting here is not enough
  end;             //   - also do it before exec of dialog.

end;
//-------------------

procedure TForm1.ReplaceDialog1Replace(Sender: TObject);
var
    Res, replaceCount:integer;   //added by mike
    countInfo:string;
begin
  If Found = False then       {If no search for string took place}
  begin
    ReplaceDialog1Find(Sender); {Search for string, replace if found}
    If Length(Memo1.SelText) > 0 then
        Memo1.SelText :=  ReplaceDialog1.ReplaceText;
  end
  Else                          {If search ran, replace string}
  begin
    If Length(Memo1.SelText) > 0 then
        Memo1.SelText := ReplaceDialog1.ReplaceText;
  end;
  Found := False;
  setSelLength(memo1, 0);    //Memo1.SelLength := 0;
  {Hvis Erstatt alle...}
  If (ReplaceDialog1.Options*[frReplaceAll] = [frReplaceAll]) then begin
      replaceCount:=0;
      Repeat
        ReplaceDialog1Find(Sender); {Search for string, replace if found}
        If Length(Memo1.SelText) > 0 then begin
            Memo1.SelText := ReplaceDialog1.ReplaceText;
            replaceCount:=replaceCount+1;
        end;                                   //laz, syn
      until Found = False;
      if replaceCount>0 then
         replaceCount:=replaceCount+1;   //the first 1, then loop for rest  - mike
      countInfo:=inttostr(replaceCount)+'  replacements made.';
      Res := Application.MessageBox(pchar(countInfo),
             'Replace', mb_OK + mb_ICONINFORMATION);

  end;
end;
//------------

end.




Gintas

  • Jr. Member
  • **
  • Posts: 71
    • Developer's Diary
Re: topic- search/replace dialogs with synedit - example
« Reply #1 on: May 26, 2010, 12:56:18 pm »
It's fine if you want to search in opened file,but I need a help with searching in files stored in TLazarusResourceStream. I need that after loading TSynEdit lines from LazResStream program will sniff all lines for given keyword until all files will be checked. It's something like Lazarus SearchInFiles,but just same search in compiled TLazarusResourceStream :)

dcelso

  • Full Member
  • ***
  • Posts: 158
Re: topic- search/replace dialogs with synedit - example
« Reply #2 on: March 21, 2013, 08:36:19 pm »
I did a feature to this function.
If anyone want it, it is in this other post

http://www.lazarus.freepascal.org/index.php/topic,20293.0.html

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5937
    • wiki
Re: topic- search/replace dialogs with synedit - example
« Reply #3 on: March 21, 2013, 10:18:36 pm »
ABout the initial post: Am I missing something?

SynEdit has
Code: [Select]
    function SearchReplace(const ASearch, AReplace: string;
      AOptions: TSynSearchOptions): integer;
    function SearchReplaceEx(const ASearch, AReplace: string;
      AOptions: TSynSearchOptions; AStart: TPoint): integer;

which provide search and replace, case sensitive or not, matching full words only or anything, reg-ex search, .....

dcelso

  • Full Member
  • ***
  • Posts: 158
Re: topic- search/replace dialogs with synedit - example
« Reply #4 on: March 21, 2013, 10:43:13 pm »
 :o, it is a great notice. I did not know it :'(, I lost my time :D.
Now I'll adapt my code to those functions.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5937
    • wiki
Re: topic- search/replace dialogs with synedit - example
« Reply #5 on: March 21, 2013, 11:45:01 pm »
no time lost. It is called learning...

there is a OnReplacre (or similar) event. Called, before a match is replaced. So you can ask the user.

For other notes on this (and some other SynEdit stuff) see http://wiki.lazarus.freepascal.org/Editor_Macros_PascalScript#Functions
It is not directly about SynEdit, but the functions are more or less the same

dcelso

  • Full Member
  • ***
  • Posts: 158
Re: topic- search/replace dialogs with synedit - example
« Reply #6 on: March 22, 2013, 09:30:31 am »
Thanks, very much, I will study it.