mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-15 03:59:10 +02:00
SynEdit: Current word markup: reduce search overhead
git-svn-id: trunk@39860 -
This commit is contained in:
parent
0308e3759d
commit
a589532b57
@ -80,6 +80,7 @@ type
|
|||||||
FSearch: TSynEditSearch;
|
FSearch: TSynEditSearch;
|
||||||
FNextPosIdx, FNextPosRow: Integer;
|
FNextPosIdx, FNextPosRow: Integer;
|
||||||
FNeedValidate, FNeedValidatePaint: Boolean;
|
FNeedValidate, FNeedValidatePaint: Boolean;
|
||||||
|
FMarkupEnabled: Boolean;
|
||||||
|
|
||||||
FStartPoint : TPoint; // First found position, before TopLine of visible area
|
FStartPoint : TPoint; // First found position, before TopLine of visible area
|
||||||
FSearchedEnd: TPoint;
|
FSearchedEnd: TPoint;
|
||||||
@ -109,7 +110,9 @@ type
|
|||||||
procedure DoLinesInWindoChanged(OldLinesInWindow : Integer); override;
|
procedure DoLinesInWindoChanged(OldLinesInWindow : Integer); override;
|
||||||
procedure DoMarkupChanged(AMarkup: TSynSelectedColor); override;
|
procedure DoMarkupChanged(AMarkup: TSynSelectedColor); override;
|
||||||
procedure DoTextChanged(StartLine, EndLine: Integer); override; // 1 based
|
procedure DoTextChanged(StartLine, EndLine: Integer); override; // 1 based
|
||||||
property MatchCount: Integer read GetMatchCount;
|
function HasVisibleMatch: Boolean; // does not check, if in visible line range. Only Count and DideSingleMatch
|
||||||
|
property MatchCount: Integer read GetMatchCount;
|
||||||
|
property MarkupEnabled: Boolean read FMarkupEnabled;
|
||||||
public
|
public
|
||||||
constructor Create(ASynEdit : TSynEditBase);
|
constructor Create(ASynEdit : TSynEditBase);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -153,6 +156,7 @@ type
|
|||||||
FToggledWord: String;
|
FToggledWord: String;
|
||||||
FToggledOption: TSynSearchOptions;
|
FToggledOption: TSynSearchOptions;
|
||||||
FStateChanged, FValidateNeeded: Boolean;
|
FStateChanged, FValidateNeeded: Boolean;
|
||||||
|
FWaitForHandle: Boolean;
|
||||||
procedure SetFullWord(const AValue: Boolean);
|
procedure SetFullWord(const AValue: Boolean);
|
||||||
procedure SetFullWordMaxLen(const AValue: Integer);
|
procedure SetFullWordMaxLen(const AValue: Integer);
|
||||||
procedure SetHighlighter(const AValue: TSynCustomHighlighter);
|
procedure SetHighlighter(const AValue: TSynCustomHighlighter);
|
||||||
@ -173,7 +177,8 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(ASynEdit : TSynEditBase);
|
constructor Create(ASynEdit : TSynEditBase);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure CheckState; // Todo need a global lock, including the markup
|
procedure DecPaintLock; override;
|
||||||
|
procedure CheckState;
|
||||||
procedure ToggleCurrentWord;
|
procedure ToggleCurrentWord;
|
||||||
property WaitTime: Integer read FWaitTime write SetWaitTime;
|
property WaitTime: Integer read FWaitTime write SetWaitTime;
|
||||||
property Trim: Boolean read FTrim write SetTrim;
|
property Trim: Boolean read FTrim write SetTrim;
|
||||||
@ -402,6 +407,7 @@ begin
|
|||||||
FFirstInvalidLine := 1;
|
FFirstInvalidLine := 1;
|
||||||
FLastInvalidLine := MaxInt;
|
FLastInvalidLine := MaxInt;
|
||||||
FHideSingleMatch := False;
|
FHideSingleMatch := False;
|
||||||
|
FMarkupEnabled := MarkupInfo.IsEnabled;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TSynEditMarkupHighlightAll.Destroy;
|
destructor TSynEditMarkupHighlightAll.Destroy;
|
||||||
@ -424,7 +430,7 @@ end;
|
|||||||
procedure TSynEditMarkupHighlightAll.DecPaintLock;
|
procedure TSynEditMarkupHighlightAll.DecPaintLock;
|
||||||
begin
|
begin
|
||||||
inherited DecPaintLock;
|
inherited DecPaintLock;
|
||||||
if FPaintLock = 0 then
|
if (FPaintLock = 0) and FNeedValidate then
|
||||||
ValidateMatches(not FNeedValidatePaint);
|
ValidateMatches(not FNeedValidatePaint);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -464,7 +470,11 @@ end;
|
|||||||
|
|
||||||
procedure TSynEditMarkupHighlightAll.DoMarkupChanged(AMarkup : TSynSelectedColor);
|
procedure TSynEditMarkupHighlightAll.DoMarkupChanged(AMarkup : TSynSelectedColor);
|
||||||
begin
|
begin
|
||||||
SendLineInvalidation;
|
If (not FMarkupEnabled) and MarkupInfo.IsEnabled then
|
||||||
|
Invalidate
|
||||||
|
else
|
||||||
|
SendLineInvalidation;
|
||||||
|
FMarkupEnabled := MarkupInfo.IsEnabled;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynEditMarkupHighlightAll.FindInitialize;
|
procedure TSynEditMarkupHighlightAll.FindInitialize;
|
||||||
@ -500,7 +510,7 @@ function TSynEditMarkupHighlightAll.FindMatches(AStartPoint, AEndPoint: TPoint;
|
|||||||
var
|
var
|
||||||
ptFoundStart, ptFoundEnd: TPoint;
|
ptFoundStart, ptFoundEnd: TPoint;
|
||||||
begin
|
begin
|
||||||
//debugln(['FindMatches IDX=', AIndex,' # ',dbgs(AStartPoint),' - ',dbgs(AEndPoint), 'AStopAfterLine=',AStopAfterLine, ' cnt=',FMatches.Count]);
|
//debugln(['FindMatches IDX=', AIndex,' # ',dbgs(AStartPoint),' - ',dbgs(AEndPoint), ' AStopAfterLine=',AStopAfterLine, ' cnt=',FMatches.Count, ' Back=', dbgs(ABackward)]);
|
||||||
fSearch.Backwards := ABackward;
|
fSearch.Backwards := ABackward;
|
||||||
While (true) do begin
|
While (true) do begin
|
||||||
if not fSearch.FindNextOne(Lines, AStartPoint, AEndPoint, ptFoundStart, ptFoundEnd)
|
if not fSearch.FindNextOne(Lines, AStartPoint, AEndPoint, ptFoundStart, ptFoundEnd)
|
||||||
@ -581,7 +591,6 @@ procedure TSynEditMarkupHighlightAll.ValidateMatches(SkipPaint: Boolean);
|
|||||||
( (FFirstInvalidLine < 1) or (APos.y < FFirstInvalidLine) or
|
( (FFirstInvalidLine < 1) or (APos.y < FFirstInvalidLine) or
|
||||||
( (FLastInvalidLine > 0) and (APos.y > FLastInvalidLine) )
|
( (FLastInvalidLine > 0) and (APos.y > FLastInvalidLine) )
|
||||||
);
|
);
|
||||||
// or to far back
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IsStartAtMatch0: Boolean; // Check if FStartPoint = FMatches[0]
|
function IsStartAtMatch0: Boolean; // Check if FStartPoint = FMatches[0]
|
||||||
@ -598,9 +607,94 @@ procedure TSynEditMarkupHighlightAll.ValidateMatches(SkipPaint: Boolean);
|
|||||||
|
|
||||||
var
|
var
|
||||||
LastLine : Integer; // Last visible
|
LastLine : Integer; // Last visible
|
||||||
|
|
||||||
|
procedure MaybeDropOldMatches;
|
||||||
|
var
|
||||||
|
Idx: Integer;
|
||||||
|
begin
|
||||||
|
// remove matches, that are too far off the current visible area
|
||||||
|
if FMatches.Count > MATCHES_CLEAN_CNT_THRESHOLD then begin
|
||||||
|
if TopLine - FMatches.EndPoint[0].y > MATCHES_CLEAN_LINE_THRESHOLD then begin
|
||||||
|
Idx := FMatches.IndexOfFirstMatchForLine(TopLine - MATCHES_CLEAN_LINE_KEEP) - 1;
|
||||||
|
FMatches.Delete(0, Idx);
|
||||||
|
FStartPoint.y := -1;
|
||||||
|
end;
|
||||||
|
if FMatches.StartPoint[FMatches.Count-1].y - LastLine > MATCHES_CLEAN_LINE_THRESHOLD then begin
|
||||||
|
Idx := FMatches.IndexOfLastMatchForLine(LastLine + MATCHES_CLEAN_LINE_KEEP) + 1;
|
||||||
|
FMatches.Delete(Idx, FMatches.Count - Idx);
|
||||||
|
FSearchedEnd.y := -1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DeleteInvalidMatches: Integer;
|
||||||
|
var
|
||||||
|
FirstInvalIdx, LastInvalIdx: Integer;
|
||||||
|
begin
|
||||||
|
// Delete Matches from the invalidated line range
|
||||||
|
FirstInvalIdx := -1;
|
||||||
|
LastInvalIdx := -1;
|
||||||
|
if (FFirstInvalidLine > 0) or (FLastInvalidLine > 0) then begin
|
||||||
|
FirstInvalIdx := FMatches.IndexOfFirstMatchForLine(FFirstInvalidLine);
|
||||||
|
LastInvalIdx := FMatches.IndexOfLastMatchForLine(FLastInvalidLine);
|
||||||
|
if (FirstInvalIdx >= 0) xor (LastInvalIdx >= 0) then begin
|
||||||
|
if FirstInvalIdx < 0 then
|
||||||
|
FirstInvalIdx := 0;
|
||||||
|
if LastInvalIdx < 0 then
|
||||||
|
LastInvalIdx := FMatches.Count - 1;
|
||||||
|
end;
|
||||||
|
if FirstInvalIdx >= 0 then begin
|
||||||
|
if (not SkipPaint) and HasVisibleMatch then
|
||||||
|
SendLineInvalidation(FirstInvalIdx, LastInvalIdx);
|
||||||
|
FMatches.Delete(FirstInvalIdx, LastInvalIdx-FirstInvalIdx+1);
|
||||||
|
if FirstInvalIdx >= FMatches.Count then
|
||||||
|
FirstInvalIdx := -1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result := FirstInvalIdx;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindStartPoint(var AFirstKeptValidIdx: Integer): Boolean;
|
||||||
|
var
|
||||||
|
Idx, Idx2 : Integer;
|
||||||
|
begin
|
||||||
|
Result := False; // No Gap at start to fill
|
||||||
|
|
||||||
|
if (FMatches.Count > 0) and (FMatches.StartPoint[0].y < TopLine) then begin
|
||||||
|
// New StartPoint from existing matches
|
||||||
|
FStartPoint := FMatches.StartPoint[0];
|
||||||
|
if AFirstKeptValidIdx = 0 then
|
||||||
|
AFirstKeptValidIdx := -1;
|
||||||
|
end
|
||||||
|
|
||||||
|
else begin
|
||||||
|
Result := True;
|
||||||
|
if SearchStringMaxLines > 0 then
|
||||||
|
// New StartPoint at fixed offset
|
||||||
|
FStartPoint := Point(1, TopLine - (SearchStringMaxLines - 1))
|
||||||
|
else begin
|
||||||
|
// New StartPoint Search backward
|
||||||
|
Idx := 0;
|
||||||
|
FindMatches(Point(1, Max(1, TopLine-SEARCH_START_OFFS)),
|
||||||
|
Point(1, TopLine),
|
||||||
|
Idx, 0, True); // stopAfterline=0, do only ONE find
|
||||||
|
if Idx > 0 then begin
|
||||||
|
FStartPoint := FMatches.EndPoint[0];
|
||||||
|
if (AFirstKeptValidIdx >= 0) then
|
||||||
|
inc(AFirstKeptValidIdx, Idx);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
FStartPoint := Point(1, TopLine) // no previous match found
|
||||||
|
end;
|
||||||
|
//debugln(['ValidateMatches: startpoint ', dbgs(FStartPoint)]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
EndOffsLine : Integer; // Stop search (LastLine + Offs)
|
EndOffsLine : Integer; // Stop search (LastLine + Offs)
|
||||||
Idx, Idx2 : Integer;
|
Idx, Idx2 : Integer;
|
||||||
FirstInvalIdx, LastInvalIdx: Integer;
|
FirstKeptValidIdx: Integer; // The first index, kept after the removed invalidated range
|
||||||
p: TPoint;
|
p: TPoint;
|
||||||
begin
|
begin
|
||||||
if FPaintLock > 0 then begin
|
if FPaintLock > 0 then begin
|
||||||
@ -612,158 +706,127 @@ begin
|
|||||||
FNeedValidate := False;
|
FNeedValidate := False;
|
||||||
|
|
||||||
if (fSearchString = '') or (not MarkupInfo.IsEnabled) then begin
|
if (fSearchString = '') or (not MarkupInfo.IsEnabled) then begin
|
||||||
|
if (not SkipPaint) and (fMatches.Count > 0) then
|
||||||
|
SendLineInvalidation;
|
||||||
fMatches.Count := 0;
|
fMatches.Count := 0;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
LastLine := ScreenRowToRow(LinesInWindow);
|
LastLine := ScreenRowToRow(LinesInWindow+1);
|
||||||
|
|
||||||
// remove matches, that are too far off the current visible area
|
|
||||||
if FMatches.Count > MATCHES_CLEAN_CNT_THRESHOLD then begin
|
|
||||||
if TopLine - FMatches.EndPoint[0].y > MATCHES_CLEAN_LINE_THRESHOLD then begin
|
|
||||||
Idx := FMatches.IndexOfFirstMatchForLine(TopLine - MATCHES_CLEAN_LINE_KEEP) - 1;
|
|
||||||
FMatches.Delete(0, Idx);
|
|
||||||
end;
|
|
||||||
if FMatches.StartPoint[FMatches.Count-1].y - LastLine > MATCHES_CLEAN_LINE_THRESHOLD then begin
|
|
||||||
Idx := FMatches.IndexOfLastMatchForLine(LastLine + MATCHES_CLEAN_LINE_KEEP) + 1;
|
|
||||||
FMatches.Delete(Idx, FMatches.Count - Idx);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
FirstInvalIdx := -1;
|
|
||||||
LastInvalIdx := -1;
|
|
||||||
if (FFirstInvalidLine > 0) or (FLastInvalidLine > 0) then begin
|
|
||||||
FirstInvalIdx := FMatches.IndexOfFirstMatchForLine(FFirstInvalidLine);
|
|
||||||
LastInvalIdx := FMatches.IndexOfLastMatchForLine(FLastInvalidLine);
|
|
||||||
if (FirstInvalIdx >= 0) xor (LastInvalIdx >= 0) then begin
|
|
||||||
if FirstInvalIdx < 0 then
|
|
||||||
FirstInvalIdx := 0;
|
|
||||||
if LastInvalIdx < 0 then
|
|
||||||
LastInvalIdx := FMatches.Count - 1;
|
|
||||||
end;
|
|
||||||
if FirstInvalIdx >= 0 then begin
|
|
||||||
if (not SkipPaint) then
|
|
||||||
SendLineInvalidation(FirstInvalIdx, LastInvalIdx);
|
|
||||||
FMatches.Delete(FirstInvalIdx, LastInvalIdx-FirstInvalIdx+1);
|
|
||||||
if FirstInvalIdx >= FMatches.Count then
|
|
||||||
FirstInvalIdx := -1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
if not IsPosValid(FSearchedEnd) then
|
|
||||||
FSearchedEnd.y := -1;
|
|
||||||
//DebugLnEnter(['>>> ValidateMatches ', FFirstInvalidLine, ' - ',FLastInvalidLine, ' Cnt=',FMatches.Count, ' Idx: ', FirstInvalIdx, ' - ',LastInvalIdx, ' ',SynEdit.Name, ' # ',fSearchString]);
|
|
||||||
|
|
||||||
|
MaybeDropOldMatches;
|
||||||
|
FirstKeptValidIdx := DeleteInvalidMatches;
|
||||||
|
//DebugLnEnter(['>>> ValidateMatches ', FFirstInvalidLine, ' - ',FLastInvalidLine, ' Cnt=',FMatches.Count, ' Idx: ', FirstKeptValidIdx, ' ',SynEdit.Name, ' # ',fSearchString]);
|
||||||
|
|
||||||
FindInitialize;
|
FindInitialize;
|
||||||
|
|
||||||
|
if not IsPosValid(FSearchedEnd) then
|
||||||
|
FSearchedEnd.y := -1;
|
||||||
|
|
||||||
if not ( IsPosValid(FStartPoint) and
|
if not ( IsPosValid(FStartPoint) and
|
||||||
( (IsStartAtMatch0 and (FStartPoint.y < TopLine)) or
|
( (IsStartAtMatch0 and (FStartPoint.y < TopLine)) or
|
||||||
(FStartPoint.y < TopLine - AdjustedSearchStrMaxLines) or
|
(FStartPoint.y < TopLine - AdjustedSearchStrMaxLines) or
|
||||||
((FStartPoint.y = TopLine - AdjustedSearchStrMaxLines) and (FStartPoint.x > 1))
|
((FStartPoint.y = TopLine - AdjustedSearchStrMaxLines) and (FStartPoint.x = 1))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
then begin
|
then begin
|
||||||
|
if FindStartPoint(FirstKeptValidIdx)
|
||||||
if (FMatches.Count > 0) and (FMatches.StartPoint[0].y < TopLine) then begin
|
then begin
|
||||||
// New StartPoint from existing matches
|
// Maybe created a gap at start
|
||||||
FStartPoint := FMatches.StartPoint[0];
|
if IsStartAtMatch0
|
||||||
if FirstInvalIdx = 0 then
|
then Idx := 1
|
||||||
FirstInvalIdx := -1;
|
else Idx := 0;
|
||||||
end
|
if (FMatches.Count > Idx) then begin
|
||||||
|
if FMatches.StartPoint[Idx].y > LastLine+SEARCH_START_OFFS then begin
|
||||||
else begin
|
// New search has smaller range than gap
|
||||||
// New StartPoint
|
FMatches.Delete(Idx, FMatches.Count - Idx);
|
||||||
Idx := 0;
|
end
|
||||||
if SearchStringMaxLines > 0 then
|
else begin
|
||||||
FStartPoint := Point(1, TopLine - (SearchStringMaxLines - 1))
|
// *** Fill gap at start
|
||||||
else begin // Search backward
|
Idx2 := Idx;
|
||||||
FindMatches(Point(1, Max(1, TopLine-SEARCH_START_OFFS)),
|
FindMatches(FStartPoint, FMatches.StartPoint[Idx], Idx);
|
||||||
Point(1, TopLine),
|
// We already had at least one match, so now we must have 2 or more and can ignore HideSingleMatch
|
||||||
Idx, 0, True); // stopAfterline=0, do only ONE find
|
if (not SkipPaint) and (Idx > Idx2) then
|
||||||
if Idx = 0
|
SendLineInvalidation(Idx2, Idx-1);
|
||||||
then FStartPoint := Point(1, TopLine) // no previous match found
|
if FirstKeptValidIdx = Idx2 then
|
||||||
else FStartPoint := FMatches.EndPoint[0];
|
FirstKeptValidIdx := -1;
|
||||||
end;
|
end;
|
||||||
//debugln(['ValidateMatches: startpoint ', dbgs(FStartPoint)]);
|
|
||||||
if FMatches.Count > Idx then begin
|
|
||||||
// Fill at start
|
|
||||||
Idx2 := Idx;
|
|
||||||
FindMatches(FStartPoint, FMatches.StartPoint[Idx], Idx);
|
|
||||||
if (not SkipPaint) and (Idx > Idx2) and
|
|
||||||
( (not HideSingleMatch) or (FMatches.Count > 1) or
|
|
||||||
// Might still get more matches.
|
|
||||||
(FirstInvalIdx > 0) or (FMatches.EndPoint[FMatches.Count - 1].y <= LastLine)
|
|
||||||
)
|
|
||||||
then
|
|
||||||
SendLineInvalidation(Idx2, Idx-1);
|
|
||||||
if FirstInvalIdx = 0 then
|
|
||||||
FirstInvalIdx := -1;
|
|
||||||
end;
|
|
||||||
if (FirstInvalIdx >= 0) and (Idx > 0) then begin
|
|
||||||
inc(FirstInvalIdx, Idx);
|
|
||||||
inc(LastInvalIdx, Idx);
|
|
||||||
end;
|
end;
|
||||||
|
if (FirstKeptValidIdx >= 0) and (Idx > Idx2) then
|
||||||
|
inc(FirstKeptValidIdx, Idx-Idx2);
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end; // StartPoint
|
|
||||||
|
|
||||||
if FMatches.Count = 0 then begin
|
if FMatches.Count = 0 then begin
|
||||||
//debugln(['ValidateMatches cnt was 0']);
|
// *** Complete search
|
||||||
Idx := 0;
|
EndOffsLine := min(LastLine+AdjustedSearchStrMaxLines, Lines.Count);
|
||||||
EndOffsLine := min(LastLine+SEARCH_START_OFFS, Lines.Count);
|
|
||||||
if (FSearchedEnd.y < 0) or (EndOffsLine > FSearchedEnd.y) then begin
|
if (FSearchedEnd.y < 0) or (EndOffsLine > FSearchedEnd.y) then begin
|
||||||
FSearchedEnd := FindMatches(FStartPoint,
|
if HideSingleMatch then
|
||||||
Point(Length(Lines[EndOffsLine - 1]), EndOffsLine),
|
EndOffsLine := min(LastLine+SEARCH_START_OFFS, Lines.Count);
|
||||||
|
Idx := 0;
|
||||||
|
FSearchedEnd := FindMatches(FStartPoint, Point(Length(Lines[EndOffsLine - 1]), EndOffsLine),
|
||||||
Idx, LastLine);
|
Idx, LastLine);
|
||||||
if (not SkipPaint) and (Idx > 0) and
|
if (not SkipPaint) and (Idx > 0) and HasVisibleMatch then
|
||||||
( (not HideSingleMatch) or (FMatches.Count > 1) )
|
|
||||||
then
|
|
||||||
SendLineInvalidation(0, Idx-1);
|
SendLineInvalidation(0, Idx-1);
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
|
|
||||||
if (FirstInvalIdx >= 0) and (FirstInvalIdx < FMatches.Count) then begin
|
if (FirstKeptValidIdx >= 0) and (FirstKeptValidIdx < FMatches.Count) then begin
|
||||||
//debugln(['ValidateMatches REPLACE']);
|
// Gap from invalidation
|
||||||
// Replace invalidated
|
if FMatches.StartPoint[Idx].y > LastLine+SEARCH_START_OFFS then begin
|
||||||
Idx := FirstInvalIdx; // actually first valid now
|
// New search (extend end) has smaller range than gap
|
||||||
if Idx > 0 then begin
|
FMatches.Delete(Idx, FMatches.Count - Idx);
|
||||||
FindMatches(FMatches.EndPoint[Idx-1], FMatches.StartPoint[Idx], Idx);
|
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
FindMatches(FStartPoint, FMatches.StartPoint[Idx], Idx);
|
// *** Fill the gap created by invalidation
|
||||||
|
Idx := FirstKeptValidIdx; // actually first valid now
|
||||||
|
if Idx > 0 then
|
||||||
|
FindMatches(FMatches.EndPoint[Idx-1], FMatches.StartPoint[Idx], Idx)
|
||||||
|
else
|
||||||
|
FindMatches(FStartPoint, FMatches.StartPoint[Idx], Idx);
|
||||||
|
// We already had at least one match, so now we must have 2 or more and can ignore HideSingleMatch
|
||||||
|
if (not SkipPaint) and (Idx > FirstKeptValidIdx) then
|
||||||
|
SendLineInvalidation(FirstKeptValidIdx, Idx-1);
|
||||||
end;
|
end;
|
||||||
if (not SkipPaint) and (Idx > FirstInvalIdx) and
|
|
||||||
( (not HideSingleMatch) or (FMatches.Count > 1) or
|
|
||||||
// Might still get more matches.
|
|
||||||
(FMatches.EndPoint[FMatches.Count - 1].y <= LastLine)
|
|
||||||
)
|
|
||||||
then
|
|
||||||
SendLineInvalidation(FirstInvalIdx, Idx-1);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// TODO: store a searched until position
|
|
||||||
if FMatches.EndPoint[FMatches.Count - 1].y <= LastLine then begin
|
if FMatches.EndPoint[FMatches.Count - 1].y <= LastLine then begin
|
||||||
//debugln(['ValidateMatches AT END']);
|
// *** extend at end
|
||||||
// extend at end
|
if HideSingleMatch and (FMatches.Count = 1) then
|
||||||
Idx := FMatches.Count;
|
EndOffsLine := min(LastLine+SEARCH_START_OFFS, Lines.Count) // Search full range, might find a 2nd match
|
||||||
Idx2 := Idx;
|
else
|
||||||
EndOffsLine := min(LastLine+SEARCH_START_OFFS, Lines.Count);
|
EndOffsLine := min(LastLine+AdjustedSearchStrMaxLines, Lines.Count); // Search only for visible new matches
|
||||||
if (FSearchedEnd.y < 0) or (EndOffsLine > FSearchedEnd.y) then begin
|
if (FSearchedEnd.y < 0) or (EndOffsLine > FSearchedEnd.y) then begin
|
||||||
|
Idx := FMatches.Count;
|
||||||
|
Idx2 := Idx;
|
||||||
p := FMatches.EndPoint[Idx-1];
|
p := FMatches.EndPoint[Idx-1];
|
||||||
if (FSearchedEnd.y - AdjustedSearchStrMaxLines > p.y) then
|
if (FSearchedEnd.y - AdjustedSearchStrMaxLines > p.y) then
|
||||||
p := point(1, FSearchedEnd.y - AdjustedSearchStrMaxLines);
|
p := point(1, FSearchedEnd.y - AdjustedSearchStrMaxLines);
|
||||||
FSearchedEnd := FindMatches(p,
|
FSearchedEnd := FindMatches(p, Point(Length(Lines[EndOffsLine - 1]), EndOffsLine),
|
||||||
Point(Length(Lines[EndOffsLine - 1]), EndOffsLine),
|
|
||||||
Idx, LastLine);
|
Idx, LastLine);
|
||||||
if (not SkipPaint) and (Idx > Idx2) and
|
if (not SkipPaint) and (Idx > Idx2) and HasVisibleMatch then
|
||||||
( (not HideSingleMatch) or (FMatches.Count > 1) )
|
|
||||||
then
|
|
||||||
SendLineInvalidation(Idx2, Idx-1);
|
SendLineInvalidation(Idx2, Idx-1);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if HideSingleMatch and (FMatches.Count = 1) and
|
||||||
|
(FMatches.StartPoint[0].y <= LastLine) and (FStartPoint.y > TopLine - SEARCH_START_OFFS)
|
||||||
|
then begin
|
||||||
|
// A single match in visible lines is hidden, check for 2nd match before FStartPoint
|
||||||
|
Idx := 0;
|
||||||
|
FindMatches(Point(1, Max(1, TopLine-SEARCH_START_OFFS)), FStartPoint,
|
||||||
|
Idx, 0, True); // stopAfterline=0, do only ONE find // Search backwards
|
||||||
|
if Idx > 0 then begin
|
||||||
|
FStartPoint := FMatches.EndPoint[0];
|
||||||
|
SendLineInvalidation;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
//DebugLnExit(['<<< ValidateMatches Cnt=',FMatches.Count]) //;
|
//DebugLnExit(['<<< ValidateMatches Cnt=',FMatches.Count]) //;
|
||||||
FFirstInvalidLine := 0;
|
FFirstInvalidLine := 0;
|
||||||
FLastInvalidLine := 0;
|
FLastInvalidLine := 0;
|
||||||
@ -776,6 +839,12 @@ begin
|
|||||||
InvalidateLines(StartLine, MaxInt); // EndLine); // Might be LineCount changed
|
InvalidateLines(StartLine, MaxInt); // EndLine); // Might be LineCount changed
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSynEditMarkupHighlightAll.HasVisibleMatch: Boolean;
|
||||||
|
begin
|
||||||
|
Result := ( HideSingleMatch and (FMatches.Count > 1) ) or
|
||||||
|
( (not HideSingleMatch) and (FMatches.Count > 0) );
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSynEditMarkupHighlightAll.InvalidateLines(AFirstLine: Integer; ALastLine: Integer;
|
procedure TSynEditMarkupHighlightAll.InvalidateLines(AFirstLine: Integer; ALastLine: Integer;
|
||||||
SkipPaint: Boolean);
|
SkipPaint: Boolean);
|
||||||
begin
|
begin
|
||||||
@ -984,14 +1053,16 @@ procedure TSynEditMarkupHighlightAllCaret.SetHighlighter(const AValue: TSynCusto
|
|||||||
begin
|
begin
|
||||||
if FHighlighter = AValue then exit;
|
if FHighlighter = AValue then exit;
|
||||||
FHighlighter := AValue;
|
FHighlighter := AValue;
|
||||||
ScrollTimerHandler(self);
|
if FIgnoreKeywords and (SearchString <> '') then
|
||||||
|
ScrollTimerHandler(self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynEditMarkupHighlightAllCaret.SetIgnoreKeywords(const AValue: Boolean);
|
procedure TSynEditMarkupHighlightAllCaret.SetIgnoreKeywords(const AValue: Boolean);
|
||||||
begin
|
begin
|
||||||
if FIgnoreKeywords = AValue then exit;
|
if FIgnoreKeywords = AValue then exit;
|
||||||
FIgnoreKeywords := AValue;
|
FIgnoreKeywords := AValue;
|
||||||
ScrollTimerHandler(self);
|
if Assigned(FHighlighter) and (SearchString <> '') then
|
||||||
|
ScrollTimerHandler(self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynEditMarkupHighlightAllCaret.SetSelection(const AValue: TSynEditSelection);
|
procedure TSynEditMarkupHighlightAllCaret.SetSelection(const AValue: TSynEditSelection);
|
||||||
@ -1007,7 +1078,10 @@ procedure TSynEditMarkupHighlightAllCaret.SetTrim(const AValue: Boolean);
|
|||||||
begin
|
begin
|
||||||
if FTrim = AValue then exit;
|
if FTrim = AValue then exit;
|
||||||
FTrim := AValue;
|
FTrim := AValue;
|
||||||
ScrollTimerHandler(self);
|
if (SearchString <> '') then
|
||||||
|
ScrollTimerHandler(self)
|
||||||
|
else
|
||||||
|
RestartTimer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynEditMarkupHighlightAllCaret.CheckState;
|
procedure TSynEditMarkupHighlightAllCaret.CheckState;
|
||||||
@ -1062,13 +1136,23 @@ end;
|
|||||||
|
|
||||||
procedure TSynEditMarkupHighlightAllCaret.DoMarkupChanged(AMarkup: TSynSelectedColor);
|
procedure TSynEditMarkupHighlightAllCaret.DoMarkupChanged(AMarkup: TSynSelectedColor);
|
||||||
begin
|
begin
|
||||||
SearchString := '';
|
IncPaintLock;
|
||||||
RestartTimer;
|
try
|
||||||
|
inherited DoMarkupChanged(AMarkup);
|
||||||
|
SearchString := '';
|
||||||
|
RestartTimer;
|
||||||
|
finally
|
||||||
|
DecPaintLock;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynEditMarkupHighlightAllCaret.RestartTimer;
|
procedure TSynEditMarkupHighlightAllCaret.RestartTimer;
|
||||||
begin
|
begin
|
||||||
FTimer.Enabled := False;
|
FTimer.Enabled := False;
|
||||||
|
if not SynEdit.HandleAllocated then begin
|
||||||
|
FWaitForHandle := True; // HandleCreation will call paintlock, check there
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
if (MarkupInfo.IsEnabled) and (FWaitTime > 0) then
|
if (MarkupInfo.IsEnabled) and (FWaitTime > 0) then
|
||||||
FTimer.Enabled := True;
|
FTimer.Enabled := True;
|
||||||
end;
|
end;
|
||||||
@ -1076,6 +1160,11 @@ end;
|
|||||||
procedure TSynEditMarkupHighlightAllCaret.ScrollTimerHandler(Sender: TObject);
|
procedure TSynEditMarkupHighlightAllCaret.ScrollTimerHandler(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
FTimer.Enabled := False;
|
FTimer.Enabled := False;
|
||||||
|
if not SynEdit.HandleAllocated then begin
|
||||||
|
FWaitForHandle := True; // HandleCreation will call paintlock, check there
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
FWaitForHandle := False;
|
||||||
if (SearchString = GetCurrentText) and (SearchOptions = GetCurrentOption) then
|
if (SearchString = GetCurrentText) and (SearchOptions = GetCurrentOption) then
|
||||||
exit;
|
exit;
|
||||||
SearchString := ''; // prevent double update
|
SearchString := ''; // prevent double update
|
||||||
@ -1143,6 +1232,7 @@ end;
|
|||||||
constructor TSynEditMarkupHighlightAllCaret.Create(ASynEdit: TSynEditBase);
|
constructor TSynEditMarkupHighlightAllCaret.Create(ASynEdit: TSynEditBase);
|
||||||
begin
|
begin
|
||||||
inherited Create(ASynEdit);
|
inherited Create(ASynEdit);
|
||||||
|
FWaitForHandle := False;
|
||||||
FStateChanged := False;
|
FStateChanged := False;
|
||||||
FValidateNeeded := False;
|
FValidateNeeded := False;
|
||||||
HideSingleMatch := True;
|
HideSingleMatch := True;
|
||||||
@ -1157,7 +1247,7 @@ begin
|
|||||||
FTimer.Enabled := False;
|
FTimer.Enabled := False;
|
||||||
FTimer.Interval := FWaitTime;
|
FTimer.Interval := FWaitTime;
|
||||||
FTimer.OnTimer := @ScrollTimerHandler;
|
FTimer.OnTimer := @ScrollTimerHandler;
|
||||||
MarkupInfo.Clear;
|
MarkupInfo.Clear; // calls RestartTimer
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TSynEditMarkupHighlightAllCaret.Destroy;
|
destructor TSynEditMarkupHighlightAllCaret.Destroy;
|
||||||
@ -1168,6 +1258,13 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditMarkupHighlightAllCaret.DecPaintLock;
|
||||||
|
begin
|
||||||
|
inherited DecPaintLock;
|
||||||
|
if FWaitForHandle and SynEdit.HandleAllocated then
|
||||||
|
ScrollTimerHandler(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSynEditMarkupHighlightAllCaret.ToggleCurrentWord;
|
procedure TSynEditMarkupHighlightAllCaret.ToggleCurrentWord;
|
||||||
var
|
var
|
||||||
s: String;
|
s: String;
|
||||||
|
Loading…
Reference in New Issue
Block a user