Skip to content

Commit 7b80773

Browse files
committed
Improve handling of overlapping indicators and selections if there's multiple selections. Wouldn't be necessary if I knew how to tell Scintilla to prioritize selection over indicators.
1 parent b45c41f commit 7b80773

File tree

2 files changed

+76
-37
lines changed

2 files changed

+76
-37
lines changed

Components/ScintEdit.pas

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,14 @@ TScintEditChangeInfo = record
5252
TScintRange = record
5353
StartPos, EndPos: Integer;
5454
constructor Create(const AStartPos, AEndPos: Integer);
55+
function Empty: Boolean;
5556
function Overlaps(const ARange: TScintRange): Boolean;
5657
function Within(const ARange: TScintRange): Boolean;
5758
end;
58-
TScintRangeList = TList<TScintRange>;
59+
TScintRangeList = class(TList<TScintRange>)
60+
function Overlaps(const ARange: TScintRange;
61+
var AOverlappingRange: TScintRange): Boolean;
62+
end;
5963
TScintRawCharSet = set of AnsiChar;
6064
TScintRawString = type RawByteString;
6165
TScintRectangle = record
@@ -240,6 +244,7 @@ TScintEdit = class(TWinControl)
240244
function GetPositionOfMatchingBrace(const Pos: Integer): Integer;
241245
function GetRawTextLength: Integer;
242246
function GetRawTextRange(const StartPos, EndPos: Integer): TScintRawString;
247+
procedure GetSelections(const RangeList: TScintRangeList);
243248
function GetStyleAtPosition(const Pos: Integer): TScintStyleNumber;
244249
function GetTextRange(const StartPos, EndPos: Integer): String;
245250
function GetVisibleLineFromDocLine(const DocLine: Integer): Integer;
@@ -1034,6 +1039,16 @@ function TScintEdit.GetSelection: TScintRange;
10341039
Result.EndPos := Call(SCI_GETSELECTIONEND, 0, 0);
10351040
end;
10361041

1042+
procedure TScintEdit.GetSelections(const RangeList: TScintRangeList);
1043+
begin
1044+
RangeList.Clear;
1045+
for var I := 0 to SelectionCount-1 do begin
1046+
var StartPos := Call(SCI_GETSELECTIONNSTART, I, 0);
1047+
var EndPos := Call(SCI_GETSELECTIONNEND, I, 0);
1048+
RangeList.Add(TScintRange.Create(StartPos, EndPos));
1049+
end;
1050+
end;
1051+
10371052
function TScintEdit.GetSelectionAnchorPosition(Selection: Integer): Integer;
10381053
begin
10391054
Result := Call(SCI_GETSELECTIONNANCHOR, Selection, 0);
@@ -2429,12 +2444,31 @@ constructor TScintRange.Create(const AStartPos, AEndPos: Integer);
24292444

24302445
function TScintRange.Overlaps(const ARange: TScintRange): Boolean;
24312446
begin
2432-
Result := (StartPos <= ARange.EndPos) and (EndPos >= ARange.StartPos);
2447+
Result := not ARange.Empty and (StartPos <= ARange.EndPos) and (EndPos >= ARange.StartPos);
2448+
end;
2449+
2450+
function TScintRange.Empty: Boolean;
2451+
begin
2452+
Result := StartPos = EndPos;
24332453
end;
24342454

24352455
function TScintRange.Within(const ARange: TScintRange): Boolean;
24362456
begin
24372457
Result := (StartPos >= ARange.StartPos) and (EndPos <= ARange.EndPos);
24382458
end;
24392459

2460+
{ TScintRangeList }
2461+
2462+
function TScintRangeList.Overlaps(const ARange: TScintRange;
2463+
var AOverlappingRange: TScintRange): Boolean;
2464+
begin
2465+
for var Item in Self do begin
2466+
if Item.Overlaps(ARange) then begin
2467+
AOverlappingRange := Item;
2468+
Exit(True);
2469+
end;
2470+
end;
2471+
Result := False;
2472+
end;
2473+
24402474
end.

Projects/Src/CompForm.pas

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3281,72 +3281,77 @@ procedure TCompileForm.UpdateOccurrenceIndicators(const AMemo: TCompScintEdit);
32813281

32823282
procedure FindTextAndAddRanges(const AMemo: TCompScintEdit;
32833283
const TextToFind: TScintRawString; const Options: TScintFindOptions;
3284-
const SelNotEmpty: Boolean; const Selection: TScintRange;
3285-
const ARangeList: TScintRangeList);
3284+
const SelectionRanges, IndicatorRanges: TScintRangeList);
32863285
begin
32873286
if ScintRawStringIsBlank(TextToFind) then
32883287
Exit;
32893288

32903289
var StartPos := 0;
32913290
var EndPos := AMemo.RawTextLength;
3292-
var Range: TScintRange;
3291+
var FoundRange: TScintRange;
32933292

32943293
while (StartPos < EndPos) and
3295-
AMemo.FindRawText(StartPos, EndPos, TextToFind, Options, Range) do begin
3296-
StartPos := Range.EndPos;
3294+
AMemo.FindRawText(StartPos, EndPos, TextToFind, Options, FoundRange) do begin
3295+
StartPos := FoundRange.EndPos;
32973296

32983297
{ Don't add indicators on lines which have a line marker }
3299-
var Line := AMemo.GetLineFromPosition(Range.StartPos);
3298+
var Line := AMemo.GetLineFromPosition(FoundRange.StartPos);
33003299
var Markers := AMemo.GetMarkers(Line);
33013300
if Markers * [mmLineError, mmLineBreakpointBad, mmLineStep] <> [] then
33023301
Continue;
33033302

3304-
{ Add indicator while making sure it does not overlap the regular selection
3305-
styling (only looks at main selection and not any additional selections
3306-
atm - so if you ctrl+double click a word and then do the same on an
3307-
occurrence somewhere else the additional selection becomes hidden by the
3308-
indicator except for the very top and bottom (due to use of
3309-
INDIC_STRAIGHTBOX instead of INDIC_FULLBOX) }
3310-
if SelNotEmpty and Range.Overlaps(Selection) then begin
3311-
if Range.StartPos < Selection.StartPos then
3312-
ARangeList.Add(TScintRange.Create(Range.StartPos, Selection.StartPos));
3313-
if Range.EndPos > Selection.EndPos then
3314-
ARangeList.Add(TScintRange.Create(Selection.EndPos, Range.EndPos));
3303+
{ Add indicator while making sure it does not overlap any regular selection
3304+
styling for either the main selection or any additional selection. Does
3305+
not account for an indicator overlapping more than 1 selection. }
3306+
var OverlappingSelection: TScintRange;
3307+
if SelectionRanges.Overlaps(FoundRange, OverlappingSelection) then begin
3308+
if FoundRange.StartPos < OverlappingSelection.StartPos then
3309+
IndicatorRanges.Add(TScintRange.Create(FoundRange.StartPos, OverlappingSelection.StartPos));
3310+
if FoundRange.EndPos > OverlappingSelection.EndPos then
3311+
IndicatorRanges.Add(TScintRange.Create(OverlappingSelection.EndPos, FoundRange.EndPos));
33153312
end else
3316-
ARangeList.Add(TScintRange.Create(Range.StartPos, Range.EndPos));
3313+
IndicatorRanges.Add(FoundRange);
33173314
end;
33183315
end;
33193316

33203317
begin
33213318
{ Add occurrence indicators for the word at cursor if there's any and the
3322-
selection is within this word. On top of those add occurrence indicators for
3323-
the selected text if there's any. Don't do anything of the selection is not
3324-
single line. All of these things are just like VSCode. }
3319+
main selection is within this word. On top of those add occurrence indicators
3320+
for the main selected text if there's any. Don't do anything if the main
3321+
selection is not single line. All of these things are just like VSCode. }
33253322

3326-
var Selection: TScintRange;
3327-
var SelNotEmpty := AMemo.SelNotEmpty(Selection);
3328-
var SelSingleLine := AMemo.GetLineFromPosition(Selection.StartPos) =
3329-
AMemo.GetLineFromPosition(Selection.EndPos);
3323+
var MainSelection: TScintRange;
3324+
var MainSelNotEmpty := AMemo.SelNotEmpty(MainSelection);
3325+
var MainSelSingleLine := AMemo.GetLineFromPosition(MainSelection.StartPos) =
3326+
AMemo.GetLineFromPosition(MainSelection.EndPos);
33303327

3331-
var RangeList := TScintRangeList.Create;
3328+
var IndicatorRanges: TScintRangeList := nil;
3329+
var SelectionRanges: TScintRangeList := nil;
33323330
try
3333-
if FOptions.HighlightWordAtCursorOccurrences and (AMemo.CaretVirtualSpace = 0) and SelSingleLine then begin
3331+
IndicatorRanges := TScintRangeList.Create;
3332+
SelectionRanges := TScintRangeList.Create;
3333+
3334+
if FOptions.HighlightWordAtCursorOccurrences and (AMemo.CaretVirtualSpace = 0) and MainSelSingleLine then begin
33343335
var Word := AMemo.WordAtCursorRange;
3335-
if (Word.StartPos <> Word.EndPos) and Selection.Within(Word) then begin
3336+
if (Word.StartPos <> Word.EndPos) and MainSelection.Within(Word) then begin
33363337
var TextToIndicate := AMemo.GetRawTextRange(Word.StartPos, Word.EndPos);
3337-
FindTextAndAddRanges(AMemo, TextToIndicate, GetWordOccurrenceFindOptions, SelNotEmpty, Selection, RangeList);
3338+
AMemo.GetSelections(SelectionRanges); { Gets any additional selections as well }
3339+
FindTextAndAddRanges(AMemo, TextToIndicate, GetWordOccurrenceFindOptions, SelectionRanges, IndicatorRanges);
33383340
end;
33393341
end;
3340-
AMemo.UpdateIndicators(RangeList, inWordAtCursorOccurrence);
3342+
AMemo.UpdateIndicators(IndicatorRanges, inWordAtCursorOccurrence);
33413343

3342-
RangeList.Clear;
3343-
if FOptions.HighlightSelTextOccurrences and SelNotEmpty and SelSingleLine then begin
3344+
IndicatorRanges.Clear;
3345+
if FOptions.HighlightSelTextOccurrences and MainSelNotEmpty and MainSelSingleLine then begin
33443346
var TextToIndicate := AMemo.RawSelText;
3345-
FindTextAndAddRanges(AMemo, TextToIndicate, GetSelTextOccurrenceFindOptions, SelNotEmpty, Selection, RangeList);
3347+
if SelectionRanges.Count = 0 then { If 0 then we didn't already call GetSelections above}
3348+
AMemo.GetSelections(SelectionRanges);
3349+
FindTextAndAddRanges(AMemo, TextToIndicate, GetSelTextOccurrenceFindOptions,SelectionRanges, IndicatorRanges);
33463350
end;
3347-
AMemo.UpdateIndicators(RangeList, inSelTextOccurrence);
3351+
AMemo.UpdateIndicators(IndicatorRanges, inSelTextOccurrence);
33483352
finally
3349-
RangeList.Free;
3353+
SelectionRanges.Free;
3354+
IndicatorRanges.Free;
33503355
end;
33513356
end;
33523357

0 commit comments

Comments
 (0)