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.htmThanks!
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.