SynEdit: Current word markup: reduce search overhead

git-svn-id: trunk@39860 -
This commit is contained in:
martin 2013-01-15 13:03:39 +00:00
parent 0308e3759d
commit a589532b57

View File

@ -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;