mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-16 23:49:28 +02:00
SourceEditor: Fixed searching from cursor, if selection exists / Cleanup Search code. Issue #0014449
git-svn-id: trunk@27952 -
This commit is contained in:
parent
ed30c1caeb
commit
1099ea482a
@ -824,10 +824,8 @@ type
|
||||
{$IFDEF SYN_LAZARUS}const {$ENDIF}RowCol: TPoint): TPoint;
|
||||
function SearchReplace(const ASearch, AReplace: string;
|
||||
AOptions: TSynSearchOptions): integer;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function SearchReplaceEx(const ASearch, AReplace: string;
|
||||
AOptions: TSynSearchOptions; AStart: TPoint): integer;
|
||||
{$ENDIF}
|
||||
procedure SelectAll;
|
||||
Procedure SetHighlightSearch(const ASearch: String; AOptions: TSynSearchOptions);
|
||||
procedure SelectToBrace;
|
||||
@ -6991,14 +6989,22 @@ end;
|
||||
// find / replace
|
||||
function TCustomSynEdit.SearchReplace(const ASearch, AReplace: string;
|
||||
AOptions: TSynSearchOptions): integer;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
var
|
||||
StartPos: TPoint;
|
||||
begin
|
||||
Result := SearchReplaceEx(ASearch, AReplace, AOptions, LogicalCaretXY);
|
||||
if (ssoFindContinue in AOptions) and SelAvail then begin
|
||||
if ssoBackwards in AOptions then
|
||||
StartPos := BlockBegin
|
||||
else
|
||||
StartPos := BlockEnd;
|
||||
end
|
||||
else
|
||||
StartPos := LogicalCaretXY;
|
||||
Result := SearchReplaceEx(ASearch, AReplace, AOptions, StartPos);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.SearchReplaceEx(const ASearch, AReplace: string;
|
||||
AOptions: TSynSearchOptions; AStart: TPoint): integer;
|
||||
{$ENDIF}
|
||||
var
|
||||
ptStart, ptEnd: TPoint; // start and end of the search range
|
||||
ptCurrent: TPoint; // current search position
|
||||
@ -7007,12 +7013,8 @@ var
|
||||
bPrompt: boolean;
|
||||
bReplace, bReplaceAll: boolean;
|
||||
nAction: TSynReplaceAction;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
CurReplace: string;
|
||||
ptFoundStart, ptFoundEnd: TPoint;
|
||||
{$ELSE}
|
||||
n, nSearchLen, nReplaceLen, nInLine: integer;
|
||||
{$ENDIF}
|
||||
|
||||
function InValidSearchRange(First, Last: integer): boolean;
|
||||
begin
|
||||
@ -7060,9 +7062,9 @@ begin
|
||||
ptEnd.X := Length(FTheLinesView[ptEnd.Y - 1]) + 1;
|
||||
if bFromCursor then
|
||||
if bBackward then
|
||||
ptEnd := {$IFDEF SYN_LAZARUS}AStart{$ELSE}CaretXY{$ENDIF}
|
||||
ptEnd := AStart
|
||||
else
|
||||
ptStart := {$IFDEF SYN_LAZARUS}AStart{$ELSE}CaretXY{$ENDIF};
|
||||
ptStart := AStart;
|
||||
if bBackward then ptCurrent := ptEnd else ptCurrent := ptStart;
|
||||
end;
|
||||
// initialize the search engine
|
||||
@ -7070,18 +7072,12 @@ begin
|
||||
fTSearch.Whole := ssoWholeWord in AOptions;
|
||||
fTSearch.Pattern := ASearch;
|
||||
fTSearch.RegularExpressions := ssoRegExpr in AOptions;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
fTSearch.RegExprMultiLine := ssoRegExprMultiLine in AOptions;
|
||||
fTSearch.Replacement:=AReplace;
|
||||
fTSearch.Backwards:=bBackward;
|
||||
{$ELSE}
|
||||
nSearchLen := Length(ASearch);
|
||||
nReplaceLen := Length(AReplace);
|
||||
{$ENDIF}
|
||||
// search while the current search position is inside of the search range
|
||||
IncPaintLock;
|
||||
try
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
//DebugLn(['TCustomSynEdit.SearchReplace ptStart=',dbgs(ptStart),' ptEnd=',dbgs(ptEnd),' ASearch="',dbgstr(ASearch),'" AReplace="',dbgstr(AReplace),'"']);
|
||||
while fTSearch.FindNextOne(FTheLinesView,ptStart,ptEnd,ptFoundStart,ptFoundEnd) do
|
||||
begin
|
||||
@ -7156,60 +7152,6 @@ begin
|
||||
end;
|
||||
//DebugLn(['TCustomSynEdit.SearchReplace FIND NEXT ptStart=',dbgs(ptStart),' ptEnd=',dbgs(ptEnd)]);
|
||||
end;
|
||||
{$ELSE}
|
||||
while (ptCurrent.Y >= ptStart.Y) and (ptCurrent.Y <= ptEnd.Y) do begin
|
||||
nInLine := fTSearch.FindAll(Lines[ptCurrent.Y - 1]);
|
||||
if bBackward then n := Pred(fTSearch.ResultCount) else n := 0;
|
||||
// Operate on all results in this line.
|
||||
while nInLine > 0 do begin
|
||||
nFound := fTSearch.Results[n];
|
||||
if bBackward then Dec(n) else Inc(n);
|
||||
Dec(nInLine);
|
||||
// Is the search result entirely in the search range?
|
||||
if not InValidSearchRange(nFound, nFound + nSearchLen) then continue;
|
||||
Inc(Result);
|
||||
// Select the text, so the user can see it in the OnReplaceText event
|
||||
// handler or as the search result.
|
||||
ptCurrent.X := nFound;
|
||||
BlockBegin := ptCurrent;
|
||||
if bBackward then CaretXY := ptCurrent;
|
||||
Inc(ptCurrent.X, nSearchLen);
|
||||
BlockEnd := ptCurrent;
|
||||
if not bBackward then CaretXY := ptCurrent;
|
||||
// If it's a search only we can leave the procedure now.
|
||||
if not (bReplace or bReplaceAll) then exit;
|
||||
// Prompt and replace or replace all. If user chooses to replace
|
||||
// all after prompting, turn off prompting.
|
||||
if bPrompt and Assigned(fOnReplaceText) then begin
|
||||
EnsureCursorPosVisible;
|
||||
nAction := DoOnReplaceText(ASearch,AReplace,ptCurrent.Y, nFound);
|
||||
if nAction = raCancel then exit;
|
||||
end else
|
||||
nAction := raReplace;
|
||||
if not (nAction = raSkip) then begin
|
||||
// user has been prompted and has requested to silently replace all
|
||||
// so turn off prompting
|
||||
if nAction = raReplaceAll then begin
|
||||
if not bReplaceAll then begin
|
||||
bReplaceAll := TRUE;
|
||||
end;
|
||||
bPrompt := False;
|
||||
end;
|
||||
SetSelTextExternal(AReplace);
|
||||
end;
|
||||
// fix the caret position and the remaining results
|
||||
if not bBackward then begin
|
||||
CaretX := nFound + nReplaceLen;
|
||||
if (nSearchLen <> nReplaceLen) and (nAction <> raSkip) then
|
||||
fTSearch.FixResults(nFound, nSearchLen - nReplaceLen);
|
||||
end;
|
||||
if not bReplaceAll then
|
||||
exit;
|
||||
end;
|
||||
// search next / previous line
|
||||
if bBackward then Dec(ptCurrent.Y) else Inc(ptCurrent.Y);
|
||||
end;
|
||||
{$ENDIF}
|
||||
finally
|
||||
DecPaintLock;
|
||||
end;
|
||||
|
@ -69,11 +69,17 @@ type
|
||||
TSynSelectionMode = (smNormal, smLine, smColumn, smCurrent);
|
||||
{$IFDEF SYN_LAZARUS}{$PACKENUM 4}{$ENDIF SYN_LAZARUS}
|
||||
|
||||
TSynSearchOption = (ssoMatchCase, ssoWholeWord, ssoBackwards,
|
||||
ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt
|
||||
{$IFDEF SYN_LAZARUS},
|
||||
ssoSearchInReplacement,// continue search in replacement
|
||||
ssoRegExpr, ssoRegExprMultiLine{$ENDIF});
|
||||
TSynSearchOption =
|
||||
( ssoMatchCase, ssoWholeWord,
|
||||
ssoBackwards,
|
||||
ssoEntireScope, ssoSelectedOnly,
|
||||
ssoReplace, ssoReplaceAll,
|
||||
ssoPrompt,
|
||||
ssoSearchInReplacement, // continue search-replace in replacement (with ssoReplaceAll) // replace recursive
|
||||
ssoRegExpr, ssoRegExprMultiLine,
|
||||
ssoFindContinue // Assume the current selection is the last match, and start search behind selection
|
||||
// (before if ssoBackward) // Default is to start at caret (Only SearchReplace / SearchReplaceEx has start/end param)
|
||||
);
|
||||
TSynSearchOptions = set of TSynSearchOption;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
|
@ -323,7 +323,8 @@ const
|
||||
'Prompt',
|
||||
'SearchInReplacement',
|
||||
'RegExpr',
|
||||
'RegExprMultiLine'
|
||||
'RegExprMultiLine',
|
||||
'ssoFindContinue'
|
||||
);
|
||||
LazFindInFileSearchOptionsDefault = [fifSearchOpen];
|
||||
LazFindInFileSearchOptionNames: array[TLazFindInFileSearchOption] of string =(
|
||||
|
@ -347,7 +347,7 @@ type
|
||||
string; Line, Column: integer; var Action: TSrcEditReplaceAction); override;
|
||||
procedure OnReplace(Sender: TObject; const ASearch, AReplace:
|
||||
string; Line, Column: integer; var Action: TSynReplaceAction);
|
||||
function DoFindAndReplace: Integer;
|
||||
function DoFindAndReplace(aFindText, aReplaceText: String; anOptions: TSynSearchOptions): Integer;
|
||||
procedure FindNextUTF8;
|
||||
procedure FindPrevious;
|
||||
procedure FindNextWordOccurrence(DirectionForward: boolean);
|
||||
@ -2485,7 +2485,8 @@ begin
|
||||
InputHistories.AddToReplaceHistory(LazFindReplaceDialog.ReplaceText);
|
||||
InputHistories.AddToFindHistory(LazFindReplaceDialog.FindText);
|
||||
InputHistories.Save;
|
||||
DoFindAndReplace;
|
||||
DoFindAndReplace(LazFindReplaceDialog.FindText, LazFindReplaceDialog.ReplaceText,
|
||||
LazFindReplaceDialog.Options);
|
||||
finally
|
||||
//Restore original find options
|
||||
if bSelectedTextOption then
|
||||
@ -2518,44 +2519,39 @@ procedure TSourceEditor.FindNextUTF8;
|
||||
var
|
||||
OldOptions: TSynSearchOptions;
|
||||
begin
|
||||
if snIncrementalFind in FSourceNoteBook.States
|
||||
then begin
|
||||
if snIncrementalFind in FSourceNoteBook.States then begin
|
||||
FSourceNoteBook.IncrementalSearch(True, False);
|
||||
end
|
||||
else if LazFindReplaceDialog.FindText = ''
|
||||
then begin
|
||||
else if LazFindReplaceDialog.FindText = '' then begin
|
||||
StartFindAndReplace(False)
|
||||
end
|
||||
else begin
|
||||
OldOptions:=LazFindReplaceDialog.Options;
|
||||
LazFindReplaceDialog.Options:=LazFindReplaceDialog.Options
|
||||
-[ssoEntireScope,ssoReplaceAll];
|
||||
DoFindAndReplace;
|
||||
LazFindReplaceDialog.Options:=OldOptions;
|
||||
DoFindAndReplace(LazFindReplaceDialog.FindText, LazFindReplaceDialog.ReplaceText,
|
||||
LazFindReplaceDialog.Options - [ssoEntireScope, ssoSelectedOnly, ssoReplaceAll]
|
||||
+ [ssoFindContinue]);
|
||||
end;
|
||||
End;
|
||||
|
||||
{---------------------------F I N D P R E V I O U S ------------------------}
|
||||
procedure TSourceEditor.FindPrevious;
|
||||
var
|
||||
OldOptions: TSynSearchOptions;
|
||||
SrchOptions: TSynSearchOptions;
|
||||
begin
|
||||
if snIncrementalFind in FSourceNoteBook.States
|
||||
then begin
|
||||
if snIncrementalFind in FSourceNoteBook.States then begin
|
||||
FSourceNoteBook.IncrementalSearch(True, True);
|
||||
end
|
||||
else begin
|
||||
OldOptions:=LazFindReplaceDialog.Options;
|
||||
LazFindReplaceDialog.Options:=LazFindReplaceDialog.Options-[ssoEntireScope];
|
||||
if ssoBackwards in LazFindReplaceDialog.Options then
|
||||
LazFindReplaceDialog.Options:=LazFindReplaceDialog.Options-[ssoBackwards]
|
||||
else if LazFindReplaceDialog.FindText = '' then begin
|
||||
// TODO: maybe start with default set to backwards direction? But StartFindAndReplace replaces it with input-history
|
||||
StartFindAndReplace(False);
|
||||
end else begin
|
||||
SrchOptions:=LazFindReplaceDialog.Options - [ssoEntireScope, ssoSelectedOnly, ssoReplaceAll]
|
||||
+ [ssoFindContinue];
|
||||
if ssoBackwards in SrchOptions then
|
||||
SrchOptions := SrchOptions - [ssoBackwards]
|
||||
else
|
||||
LazFindReplaceDialog.Options:=LazFindReplaceDialog.Options+[ssoBackwards];
|
||||
if LazFindReplaceDialog.FindText = '' then
|
||||
StartFindAndReplace(False)
|
||||
else
|
||||
DoFindAndReplace;
|
||||
LazFindReplaceDialog.Options:=OldOptions;
|
||||
SrchOptions := SrchOptions + [ssoBackwards];
|
||||
DoFindAndReplace(LazFindReplaceDialog.FindText, LazFindReplaceDialog.ReplaceText,
|
||||
SrchOptions);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2580,37 +2576,25 @@ begin
|
||||
'',Flags);
|
||||
end;
|
||||
|
||||
function TSourceEditor.DoFindAndReplace: integer;
|
||||
function TSourceEditor.DoFindAndReplace(aFindText, aReplaceText: String;
|
||||
anOptions: TSynSearchOptions): integer;
|
||||
var
|
||||
OldCaretXY: TPoint;
|
||||
AText, ACaption: String;
|
||||
NewTopLine: integer;
|
||||
begin
|
||||
Result:=0;
|
||||
if SourceNotebook<>nil then
|
||||
Manager.AddJumpPointClicked(Self);
|
||||
if (ssoReplace in LazFindReplaceDialog.Options)
|
||||
and ReadOnly then begin
|
||||
if (ssoReplace in anOptions) and ReadOnly then begin
|
||||
DebugLn(['TSourceEditor.DoFindAndReplace Read only']);
|
||||
exit;
|
||||
end;
|
||||
if SourceNotebook<>nil then
|
||||
Manager.AddJumpPointClicked(Self);
|
||||
|
||||
OldCaretXY:=EditorComponent.CaretXY;
|
||||
if EditorComponent.SelAvail and
|
||||
not(ssoSelectedOnly in LazFindReplaceDialog.Options)
|
||||
then begin
|
||||
// Adjust the cursor. to exclude the selection from being searched
|
||||
// needed for find next / find previous
|
||||
if ssoBackwards in LazFindReplaceDialog.Options then
|
||||
EditorComponent.LogicalCaretXY:=EditorComponent.BlockBegin
|
||||
else
|
||||
EditorComponent.LogicalCaretXY:=EditorComponent.BlockEnd
|
||||
end;
|
||||
//debugln('TSourceEditor.DoFindAndReplace A LazFindReplaceDialog.FindText="',dbgstr(LazFindReplaceDialog.FindText),'" ssoEntireScope=',dbgs(ssoEntireScope in LazFindReplaceDialog.Options),' ssoBackwards=',dbgs(ssoBackwards in LazFindReplaceDialog.Options));
|
||||
//debugln('TSourceEditor.DoFindAndReplace A aFindText="',dbgstr(aFindText),'" ssoEntireScope=',dbgs(ssoEntireScope in anOptions),' ssoBackwards=',dbgs(ssoBackwards in anOptions));
|
||||
try
|
||||
Result:=EditorComponent.SearchReplace(
|
||||
LazFindReplaceDialog.FindText,LazFindReplaceDialog.ReplaceText,
|
||||
LazFindReplaceDialog.Options);
|
||||
Result:=EditorComponent.SearchReplace(aFindText, aReplaceText, anOptions);
|
||||
except
|
||||
on E: ERegExpr do begin
|
||||
MessageDlg(lisUEErrorInRegularExpression,
|
||||
@ -2621,20 +2605,15 @@ begin
|
||||
|
||||
if (OldCaretXY.X = EditorComponent.CaretX) and
|
||||
(OldCaretXY.Y = EditorComponent.CaretY) and
|
||||
not (ssoReplaceAll in LazFindReplaceDialog.Options) then
|
||||
begin
|
||||
not (ssoReplaceAll in anOptions)
|
||||
then begin
|
||||
ACaption := lisUENotFound;
|
||||
AText := Format(lisUESearchStringNotFound, [ValidUTF8String(LazFindReplaceDialog.FindText)]);
|
||||
AText := Format(lisUESearchStringNotFound, [ValidUTF8String(aFindText)]);
|
||||
MessageDlg(ACaption, AText, mtInformation, [mbOk], 0);
|
||||
Manager.DeleteLastJumpPointClicked(Self);
|
||||
end else
|
||||
if (EditorComponent.CaretY <= EditorComponent.TopLine + 1) or
|
||||
(EditorComponent.CaretY >= EditorComponent.TopLine + EditorComponent.LinesInWindow - 1) then
|
||||
begin
|
||||
NewTopLine := EditorComponent.CaretY - (EditorComponent.LinesInWindow div 2);
|
||||
if NewTopLine < 1 then
|
||||
NewTopLine := 1;
|
||||
EditorComponent.TopLine := NewTopLine;
|
||||
end
|
||||
else begin
|
||||
CenterCursor(True);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -4566,17 +4545,15 @@ const
|
||||
ssoRegExprMultiLine
|
||||
);
|
||||
var
|
||||
OldOptions, NewOptions: TSynSearchOptions;
|
||||
NewOptions: TSynSearchOptions;
|
||||
o: TSrcEditSearchOption;
|
||||
begin
|
||||
OldOptions:=LazFindReplaceDialog.Options;
|
||||
NewOptions:=[];
|
||||
for o:=Low(TSrcEditSearchOption) to High(TSrcEditSearchOption) do
|
||||
if o in SearchOptions then
|
||||
Include(NewOptions,SrcEdit2SynEditSearchOption[o]);
|
||||
LazFindReplaceDialog.Options:=NewOptions;
|
||||
Result:=DoFindAndReplace;
|
||||
LazFindReplaceDialog.Options:=OldOptions;
|
||||
Result:=DoFindAndReplace(LazFindReplaceDialog.FindText, LazFindReplaceDialog.ReplaceText,
|
||||
NewOptions);
|
||||
end;
|
||||
|
||||
function TSourceEditor.GetSourceText: string;
|
||||
|
Loading…
Reference in New Issue
Block a user