unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Types, FileUtil, SynEdit, SynEditTypes, Forms, Controls,
Graphics, Dialogs, StdCtrls, ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
btnFindFirst: TButton;
btnFindNext: TButton;
btnReplaceAll: TButton;
btnReplaceFirst: TButton;
btnReplaceNext: TButton;
edtFind: TEdit;
edtRplc: TEdit;
rgDirection: TRadioGroup;
SynEdit1: TSynEdit;
xbxMatchCase: TCheckBox;
xbxFromTop :TCheckBox;
xbxWhole: TCheckBox;
procedure btnFindFirstClick(Sender: TObject);
procedure btnReplaceFirstClick(Sender: TObject);
private
FSrch_rng: TPoint;
FSearchOpts:TSynSearchOptions;
FInBlock : TRect;
public
constructor Create(TheOwner :TComponent); override;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
const
cEmptyRect : TRect = (Left:0;Top:0;Right:0;Bottom:0);
{ TForm1 }
//function EqualPoints(const aPnt1, aPnt2:TPoint):Boolean;
//begin
// Result := (aPnt1.x = aPnt2.x) and (aPnt1.Y = aPnt2.Y);
//end;
//
Function RectInRect(const aOuterRect, aInnerRect:TRect):Boolean;
begin
Result := (aInnerRect.Left >= aOuterRect.Left) and (aInnerRect.Left <= aOuterRect.Right) and
(aInnerRect.Right >= aOuterRect.Left) and (aInnerRect.Right <= aOuterRect.Right) and
(aInnerRect.Top >= aOuterRect.Top) and (aInnerRect.Top <= aOuterRect.Bottom) and
(aInnerRect.Bottom >= aOuterRect.Top) and (aInnerRect.Bottom <= aOuterRect.Bottom);
end;
//
function RectIsEmpty(const aRect:TRect):Boolean;
begin
Result := (aRect.Left = 0) and (aRect.Top = 0)
and (aRect.Right = 0) and (aRect.Bottom = 0);
end;
function ToRect(const aTopLeft, aBottomRight:TPoint):TRect; overload;
begin
Result.TopLeft := aTopLeft;
Result.BottomRight := aBottomRight;
end;
function ToRect(const aTop, aLeft, aBottom, aRight : LongInt):TRect; overload;
begin
Result.Top := aTop;
Result.Left := aLeft;
Result.Bottom := aBottom;
Result.Right := aRight;
end;
procedure TForm1.btnFindFirstClick(Sender: TObject);
var
vMatches :Integer;
vOutOfBlock :Boolean;
function Search :LongInt;
begin
Result := SynEdit1.SearchReplaceEx(edtFind.Text, '', FSearchOpts, FSrch_rng);
if (Result > 0) then begin
if (not RectIsEmpty(FInBlock)) and (not RectInRect(FInBlock,ToRect(SynEdit1.BlockBegin, SynEdit1.BlockEnd))) then begin
vOutOfBlock := True;
Result := 0;
end;
end;
end;
begin
vOutOfBlock := False;
if (Sender = btnFindNext) then begin
if SynEdit1.SelAvail then
FSrch_rng := SynEdit1.BlockEnd
else
FSrch_rng := SynEdit1.CaretXY;
end else begin
if xbxFromTop.Checked then
FSrch_rng := Point(1,1)
else
FSrch_rng := SynEdit1.CaretXY;
FSearchOpts := [];
if (SynEdit1.SelAvail) then begin
FInBlock.TopLeft := SynEdit1.BlockBegin;
FInBlock.BottomRight := SynEdit1.BlockEnd;
end else
FInBlock := cEmptyRect;
end;
if (SynEdit1.SelAvail) and (Sender = btnFindFirst) then begin
Include(FSearchOpts, ssoSelectedOnly);
end;
if xbxFromTop.Checked then
FSearchOpts := FSearchOpts + [ssoEntireScope]
else begin
FSearchOpts := FSearchOpts - [ssoEntireScope];
end;
if rgDirection.ItemIndex = 1 then
Include(FSearchOpts, ssoBackwards);
if xbxWhole.Checked then
Include(FSearchOpts, ssoWholeWord);
if xbxMatchCase.Checked then
Include(FSearchOpts, ssoMatchCase);
if Sender = btnFindNext then begin
Exclude(FSearchOpts, ssoEntireScope);
Exclude(FSearchOpts, ssoSelectedOnly);
Include(FSearchOpts, ssoFindContinue);
end;
vMatches := Search;
if vMatches > 0 then begin
btnFindNext.Enabled := True;
end else begin
btnFindNext.Enabled := False;
FInBlock := cEmptyRect; //start a new find.
if vOutOfBlock then begin
SynEdit1.CaretXY := FInBlock.BottomRight;
SynEdit1.EnsureCursorPosVisible;
end;
ShowMessage(edtFind.Text + ' not found');
end;
end;
procedure TForm1.btnReplaceFirstClick(Sender: TObject);
var
vMatches: Integer;
function Search:LongInt;
begin
Result := SynEdit1.SearchReplaceEx(edtFind.Text, '', FSearchOpts, FSrch_rng);
if (Result > 0) then begin
if (not RectIsEmpty(FInBlock)) and (not RectInRect(FInBlock, ToRect(SynEdit1.BlockBegin, SynEdit1.BlockEnd))) then
Result := 0;
end;
end;
begin
if (Sender = btnReplaceNext) then begin
if SynEdit1.SelAvail then
FSrch_rng := SynEdit1.BlockEnd
else
FSrch_rng := SynEdit1.CaretXY;
end else begin
if xbxFromTop.Checked then
FSrch_rng := Point(1,1)
else
FSrch_rng := SynEdit1.CaretXY;
FSearchOpts := [];
end;
if rgDirection.ItemIndex = 1 then
Include(FSearchOpts, ssoBackwards);
if xbxWhole.Checked then
Include(FSearchOpts, ssoWholeWord);
if xbxMatchCase.Checked then
Include(FSearchOpts, ssoMatchCase);
if xbxFromTop.Checked then
FSearchOpts := FSearchOpts + [ssoEntireScope]
else begin
FSearchOpts := FSearchOpts - [ssoEntireScope];
end;
if SynEdit1.SelAvail and (sender = btnReplaceFirst) then begin
Include(FSearchOpts, ssoSelectedOnly);
FInBlock.TopLeft := SynEdit1.BlockBegin;
FInBlock.BottomRight := SynEdit1.BlockEnd;
end;
Include(FSearchOpts, ssoPrompt);
if Sender = btnReplaceAll then
Include(FSearchOpts, ssoReplaceAll)
else
Include(FSearchOpts, ssoReplace);
vMatches := SynEdit1.SearchReplaceEx(edtFind.Text, edtRplc.Text, FSearchOpts, fsrch_rng);
if vMatches > 0 then
begin
ShowMessage(IntToStr(vMatches) + ' Replaced');
end;
end;
constructor TForm1.Create(TheOwner :TComponent);
begin
inherited Create(TheOwner);
FInBlock := cEmptyRect;
end;
{TSynSearchOption =
( ssoMatchCase, ssoWholeWord,
ssoBackwards,
ssoEntireScope, ssoSelectedOnly,
ssoReplace, ssoReplaceAll,
ssoPrompt,
ssoSearchInReplacement, // continue search-replace in replacement (with ssoReplaceAll) // replace recursive
ssoRegExpr, ssoRegExprMultiLine,
ssoFindContinue}
end.