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
function HasVisibleMatch: Boolean; // does not check, if in visible line range. Only Count and DideSingleMatch
property MatchCount: Integer read GetMatchCount; 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
If (not FMarkupEnabled) and MarkupInfo.IsEnabled then
Invalidate
else
SendLineInvalidation; 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,38 +607,31 @@ procedure TSynEditMarkupHighlightAll.ValidateMatches(SkipPaint: Boolean);
var var
LastLine : Integer; // Last visible LastLine : Integer; // Last visible
EndOffsLine : Integer; // Stop search (LastLine + Offs)
Idx, Idx2 : Integer; procedure MaybeDropOldMatches;
FirstInvalIdx, LastInvalIdx: Integer; var
p: TPoint; Idx: Integer;
begin begin
if FPaintLock > 0 then begin
FNeedValidate := True;
if not SkipPaint then
FNeedValidatePaint := True;
exit;
end;
FNeedValidate := False;
if (fSearchString = '') or (not MarkupInfo.IsEnabled) then begin
fMatches.Count := 0;
exit;
end;
LastLine := ScreenRowToRow(LinesInWindow);
// remove matches, that are too far off the current visible area // remove matches, that are too far off the current visible area
if FMatches.Count > MATCHES_CLEAN_CNT_THRESHOLD then begin if FMatches.Count > MATCHES_CLEAN_CNT_THRESHOLD then begin
if TopLine - FMatches.EndPoint[0].y > MATCHES_CLEAN_LINE_THRESHOLD then begin if TopLine - FMatches.EndPoint[0].y > MATCHES_CLEAN_LINE_THRESHOLD then begin
Idx := FMatches.IndexOfFirstMatchForLine(TopLine - MATCHES_CLEAN_LINE_KEEP) - 1; Idx := FMatches.IndexOfFirstMatchForLine(TopLine - MATCHES_CLEAN_LINE_KEEP) - 1;
FMatches.Delete(0, Idx); FMatches.Delete(0, Idx);
FStartPoint.y := -1;
end; end;
if FMatches.StartPoint[FMatches.Count-1].y - LastLine > MATCHES_CLEAN_LINE_THRESHOLD then begin if FMatches.StartPoint[FMatches.Count-1].y - LastLine > MATCHES_CLEAN_LINE_THRESHOLD then begin
Idx := FMatches.IndexOfLastMatchForLine(LastLine + MATCHES_CLEAN_LINE_KEEP) + 1; Idx := FMatches.IndexOfLastMatchForLine(LastLine + MATCHES_CLEAN_LINE_KEEP) + 1;
FMatches.Delete(Idx, FMatches.Count - Idx); FMatches.Delete(Idx, FMatches.Count - Idx);
FSearchedEnd.y := -1;
end;
end; end;
end; end;
function DeleteInvalidMatches: Integer;
var
FirstInvalIdx, LastInvalIdx: Integer;
begin
// Delete Matches from the invalidated line range
FirstInvalIdx := -1; FirstInvalIdx := -1;
LastInvalIdx := -1; LastInvalIdx := -1;
if (FFirstInvalidLine > 0) or (FLastInvalidLine > 0) then begin if (FFirstInvalidLine > 0) or (FLastInvalidLine > 0) then begin
@ -642,128 +644,189 @@ begin
LastInvalIdx := FMatches.Count - 1; LastInvalIdx := FMatches.Count - 1;
end; end;
if FirstInvalIdx >= 0 then begin if FirstInvalIdx >= 0 then begin
if (not SkipPaint) then if (not SkipPaint) and HasVisibleMatch then
SendLineInvalidation(FirstInvalIdx, LastInvalIdx); SendLineInvalidation(FirstInvalIdx, LastInvalIdx);
FMatches.Delete(FirstInvalIdx, LastInvalIdx-FirstInvalIdx+1); FMatches.Delete(FirstInvalIdx, LastInvalIdx-FirstInvalIdx+1);
if FirstInvalIdx >= FMatches.Count then if FirstInvalIdx >= FMatches.Count then
FirstInvalIdx := -1; FirstInvalIdx := -1;
end; end;
end; end;
if not IsPosValid(FSearchedEnd) then Result := FirstInvalIdx;
FSearchedEnd.y := -1; end;
//DebugLnEnter(['>>> ValidateMatches ', FFirstInvalidLine, ' - ',FLastInvalidLine, ' Cnt=',FMatches.Count, ' Idx: ', FirstInvalIdx, ' - ',LastInvalIdx, ' ',SynEdit.Name, ' # ',fSearchString]);
function FindStartPoint(var AFirstKeptValidIdx: Integer): Boolean;
FindInitialize; var
if not ( IsPosValid(FStartPoint) and Idx, Idx2 : Integer;
( (IsStartAtMatch0 and (FStartPoint.y < TopLine)) or begin
(FStartPoint.y < TopLine - AdjustedSearchStrMaxLines) or Result := False; // No Gap at start to fill
((FStartPoint.y = TopLine - AdjustedSearchStrMaxLines) and (FStartPoint.x > 1))
)
)
then begin
if (FMatches.Count > 0) and (FMatches.StartPoint[0].y < TopLine) then begin if (FMatches.Count > 0) and (FMatches.StartPoint[0].y < TopLine) then begin
// New StartPoint from existing matches // New StartPoint from existing matches
FStartPoint := FMatches.StartPoint[0]; FStartPoint := FMatches.StartPoint[0];
if FirstInvalIdx = 0 then if AFirstKeptValidIdx = 0 then
FirstInvalIdx := -1; AFirstKeptValidIdx := -1;
end end
else begin else begin
// New StartPoint Result := True;
Idx := 0;
if SearchStringMaxLines > 0 then if SearchStringMaxLines > 0 then
// New StartPoint at fixed offset
FStartPoint := Point(1, TopLine - (SearchStringMaxLines - 1)) FStartPoint := Point(1, TopLine - (SearchStringMaxLines - 1))
else begin // Search backward else begin
// New StartPoint Search backward
Idx := 0;
FindMatches(Point(1, Max(1, TopLine-SEARCH_START_OFFS)), FindMatches(Point(1, Max(1, TopLine-SEARCH_START_OFFS)),
Point(1, TopLine), Point(1, TopLine),
Idx, 0, True); // stopAfterline=0, do only ONE find Idx, 0, True); // stopAfterline=0, do only ONE find
if Idx = 0 if Idx > 0 then begin
then FStartPoint := Point(1, TopLine) // no previous match found FStartPoint := FMatches.EndPoint[0];
else FStartPoint := FMatches.EndPoint[0]; if (AFirstKeptValidIdx >= 0) then
inc(AFirstKeptValidIdx, Idx);
end
else
FStartPoint := Point(1, TopLine) // no previous match found
end; end;
//debugln(['ValidateMatches: startpoint ', dbgs(FStartPoint)]); //debugln(['ValidateMatches: startpoint ', dbgs(FStartPoint)]);
if FMatches.Count > Idx then begin end;
// Fill at start end;
var
EndOffsLine : Integer; // Stop search (LastLine + Offs)
Idx, Idx2 : Integer;
FirstKeptValidIdx: Integer; // The first index, kept after the removed invalidated range
p: TPoint;
begin
if FPaintLock > 0 then begin
FNeedValidate := True;
if not SkipPaint then
FNeedValidatePaint := True;
exit;
end;
FNeedValidate := False;
if (fSearchString = '') or (not MarkupInfo.IsEnabled) then begin
if (not SkipPaint) and (fMatches.Count > 0) then
SendLineInvalidation;
fMatches.Count := 0;
exit;
end;
LastLine := ScreenRowToRow(LinesInWindow+1);
MaybeDropOldMatches;
FirstKeptValidIdx := DeleteInvalidMatches;
//DebugLnEnter(['>>> ValidateMatches ', FFirstInvalidLine, ' - ',FLastInvalidLine, ' Cnt=',FMatches.Count, ' Idx: ', FirstKeptValidIdx, ' ',SynEdit.Name, ' # ',fSearchString]);
FindInitialize;
if not IsPosValid(FSearchedEnd) then
FSearchedEnd.y := -1;
if not ( IsPosValid(FStartPoint) and
( (IsStartAtMatch0 and (FStartPoint.y < TopLine)) or
(FStartPoint.y < TopLine - AdjustedSearchStrMaxLines) or
((FStartPoint.y = TopLine - AdjustedSearchStrMaxLines) and (FStartPoint.x = 1))
)
)
then begin
if FindStartPoint(FirstKeptValidIdx)
then begin
// Maybe created a gap at start
if IsStartAtMatch0
then Idx := 1
else Idx := 0;
if (FMatches.Count > Idx) then begin
if FMatches.StartPoint[Idx].y > LastLine+SEARCH_START_OFFS then begin
// New search has smaller range than gap
FMatches.Delete(Idx, FMatches.Count - Idx);
end
else begin
// *** Fill gap at start
Idx2 := Idx; Idx2 := Idx;
FindMatches(FStartPoint, FMatches.StartPoint[Idx], Idx); FindMatches(FStartPoint, FMatches.StartPoint[Idx], Idx);
if (not SkipPaint) and (Idx > Idx2) and // We already had at least one match, so now we must have 2 or more and can ignore HideSingleMatch
( (not HideSingleMatch) or (FMatches.Count > 1) or if (not SkipPaint) and (Idx > Idx2) then
// Might still get more matches.
(FirstInvalIdx > 0) or (FMatches.EndPoint[FMatches.Count - 1].y <= LastLine)
)
then
SendLineInvalidation(Idx2, Idx-1); SendLineInvalidation(Idx2, Idx-1);
if FirstInvalIdx = 0 then if FirstKeptValidIdx = Idx2 then
FirstInvalIdx := -1; FirstKeptValidIdx := -1;
end; end;
if (FirstInvalIdx >= 0) and (Idx > 0) then begin end;
inc(FirstInvalIdx, Idx); if (FirstKeptValidIdx >= 0) and (Idx > Idx2) then
inc(LastInvalIdx, Idx); inc(FirstKeptValidIdx, Idx-Idx2);
end; 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
// *** 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); 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
EndOffsLine := min(LastLine+SEARCH_START_OFFS, Lines.Count) // Search full range, might find a 2nd match
else
EndOffsLine := min(LastLine+AdjustedSearchStrMaxLines, Lines.Count); // Search only for visible new matches
if (FSearchedEnd.y < 0) or (EndOffsLine > FSearchedEnd.y) then begin
Idx := FMatches.Count; Idx := FMatches.Count;
Idx2 := Idx; Idx2 := Idx;
EndOffsLine := min(LastLine+SEARCH_START_OFFS, Lines.Count);
if (FSearchedEnd.y < 0) or (EndOffsLine > FSearchedEnd.y) then begin
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,6 +1053,7 @@ procedure TSynEditMarkupHighlightAllCaret.SetHighlighter(const AValue: TSynCusto
begin begin
if FHighlighter = AValue then exit; if FHighlighter = AValue then exit;
FHighlighter := AValue; FHighlighter := AValue;
if FIgnoreKeywords and (SearchString <> '') then
ScrollTimerHandler(self); ScrollTimerHandler(self);
end; end;
@ -991,6 +1061,7 @@ procedure TSynEditMarkupHighlightAllCaret.SetIgnoreKeywords(const AValue: Boolea
begin begin
if FIgnoreKeywords = AValue then exit; if FIgnoreKeywords = AValue then exit;
FIgnoreKeywords := AValue; FIgnoreKeywords := AValue;
if Assigned(FHighlighter) and (SearchString <> '') then
ScrollTimerHandler(self); ScrollTimerHandler(self);
end; end;
@ -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
IncPaintLock;
try
inherited DoMarkupChanged(AMarkup);
SearchString := ''; SearchString := '';
RestartTimer; 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;