SynEdit: fix continuous frame for comment-color, if there are Pasdoc/Custom-words in comment

This commit is contained in:
Martin 2025-04-05 17:11:55 +02:00
parent 8fe4297b62
commit 569250707b
4 changed files with 126 additions and 51 deletions

View File

@ -18,6 +18,7 @@
unit LazEditTextAttributes;
{$mode objfpc}{$H+}
{$ModeSwitch advancedrecords}
interface
@ -26,10 +27,16 @@ uses
type
// TODO: TLazEditDisplayTokenBound is not yet supporting wrapped text - The Physical value may change
{ TLazEditDisplayTokenBound }
TLazEditDisplayTokenBound = record
Physical: Integer; // 1 based - May be in middle of char
Logical: Integer; // 1 based
Offset: Integer; // default 0. MultiWidth (e.g. Tab), if token starts in the middle of char
function HasValue: boolean; inline;
function Init(APhys, ALog: Integer; AnOffs: Integer = 0): boolean; inline;
end;
@ -262,6 +269,20 @@ type
implementation
{ TLazEditDisplayTokenBound }
function TLazEditDisplayTokenBound.HasValue: boolean;
begin
Result := (Physical > 0) or (Logical > 0);
end;
function TLazEditDisplayTokenBound.Init(APhys, ALog: Integer; AnOffs: Integer): boolean;
begin
Physical := APhys;
Logical := ALog;
Offset := AnOffs;
end;
{ TLazCustomEditTextAttribute }
function TLazCustomEditTextAttribute.GetColor(AnIndex: TLazTextAttributeColor): TColor;

View File

@ -539,8 +539,10 @@ function TLazSynPaintTokenBreaker.GetNextHighlighterTokenFromView(out
ATarget.Style := []; // Font.Style; // currently always cleared
end;
// ATarget.MergeFinalStyle := True;
ATarget.StartX := AnAttrStartX;
ATarget.EndX := NoEnd;
if not ATarget.StartX.HasValue then
ATarget.StartX := AnAttrStartX;
if not ATarget.EndX.HasValue then
ATarget.EndX := NoEnd;
end;
function MaybeFetchToken: Boolean; inline;
@ -832,7 +834,8 @@ begin
FrameStartPos.Physical := 1 + FCurLinePhysStartOffset;
FrameStartPos.Offset := 0;
InitSynAttr(FCurViewAttr, FCurViewToken.TokenAttr, FrameStartPos);
FCurViewAttr.EndX := FWrapEndBound;
if not FCurViewAttr.EndX.HasValue then
FCurViewAttr.EndX := FWrapEndBound;
ATokenInfo.Attr := FCurViewAttr;
end
else
@ -983,7 +986,9 @@ begin
assert(FCurViewToken.TokenLength >= 0, 'FCurViewToken.TokenLength >= 0');
InitSynAttr(FCurViewAttr, FCurViewToken.TokenAttr, FCurViewCurTokenStartPos);
if FCurViewToken.TokenLength = 0 then
if (FCurViewToken.TokenLength = 0) and
(not ATokenInfo.Attr.EndX.HasValue)
then
ATokenInfo.Attr.EndX := ATokenInfo.EndPos; // PhysPos-1;
MaybeFetchToken;
@ -1118,7 +1123,9 @@ begin
assert(FCurViewToken.TokenLength >= 0, 'FCurViewToken.TokenLength >= 0');
InitSynAttr(FCurViewAttr, FCurViewToken.TokenAttr, FCurViewCurTokenStartPos);
if FCurViewToken.TokenLength = 0 then
if (FCurViewToken.TokenLength = 0) and
(not ATokenInfo.Attr.EndX.HasValue)
then
ATokenInfo.Attr.EndX := ATokenInfo.EndPos; // PhysPos-1;
MaybeFetchToken;

View File

@ -516,10 +516,10 @@ type
FMergeInfos: array [TSynSelectedColorEnum] of TSynSelectedColorMergeInfo;
function IsMatching(ABound1, ABound2: TLazSynDisplayTokenBound): Boolean;
function IsMatching(const ABound1, ABound2: TLazSynDisplayTokenBound): Boolean;
function GetFrameSideOrigin(Side: TLazSynBorderSide): TSynFrameEdges;
procedure SetCurrentEndX(AValue: TLazSynDisplayTokenBound);
procedure SetCurrentStartX(AValue: TLazSynDisplayTokenBound);
procedure SetCurrentEndX(const AValue: TLazSynDisplayTokenBound);
procedure SetCurrentStartX(const AValue: TLazSynDisplayTokenBound);
protected
function GetFrameSideColors(Side: TLazSynBorderSide): TColor; override;
function GetFrameSidePriority(Side: TLazSynBorderSide): integer; override;
@ -546,9 +546,9 @@ type
procedure InitMergeInfo; // (called automatically) Set all MergeInfo to the start values. After this was called, ay Changes to the color properties are ignored
procedure ProcessMergeInfo; // copy the merge result, to the actual color properties
procedure CleanupMergeInfo; // free the alpha arrays
procedure Merge(Other: TSynHighlighterAttributesModifier);
procedure Merge(Other: TSynHighlighterAttributesModifier; LeftCol, RightCol: TLazSynDisplayTokenBound);
procedure MergeFrames(Other: TSynHighlighterAttributesModifier; LeftCol, RightCol: TLazSynDisplayTokenBound);
procedure Merge(Other: TLazCustomEditTextAttribute);
procedure Merge(Other: TLazCustomEditTextAttribute; LeftCol, RightCol: TLazSynDisplayTokenBound);
procedure MergeFrames(Other: TLazCustomEditTextAttribute; LeftCol, RightCol: TLazSynDisplayTokenBound);
end;
{ TLazSynSurface }
@ -1034,8 +1034,8 @@ end;
{ TSynSelectedColorMergeResult }
function TSynSelectedColorMergeResult.IsMatching(ABound1,
ABound2: TLazSynDisplayTokenBound): Boolean;
function TSynSelectedColorMergeResult.IsMatching(const ABound1, ABound2: TLazSynDisplayTokenBound
): Boolean;
begin
Result := ( (ABound1.Physical > 0) and
(ABound1.Physical = ABound2.Physical)
@ -1100,7 +1100,7 @@ begin
else Result := slsSolid;
end;
procedure TSynSelectedColorMergeResult.SetCurrentEndX(AValue: TLazSynDisplayTokenBound);
procedure TSynSelectedColorMergeResult.SetCurrentEndX(const AValue: TLazSynDisplayTokenBound);
begin
//if FCurrentEndX = AValue then Exit;
FCurrentEndX := AValue;
@ -1111,7 +1111,7 @@ begin
end;
end;
procedure TSynSelectedColorMergeResult.SetCurrentStartX(AValue: TLazSynDisplayTokenBound);
procedure TSynSelectedColorMergeResult.SetCurrentStartX(const AValue: TLazSynDisplayTokenBound);
begin
//if FCurrentStartX = AValue then Exit;
FCurrentStartX := AValue;
@ -1373,12 +1373,12 @@ begin
FMergeInfoInitialized := False;
end;
procedure TSynSelectedColorMergeResult.Merge(Other: TSynHighlighterAttributesModifier);
procedure TSynSelectedColorMergeResult.Merge(Other: TLazCustomEditTextAttribute);
begin
Merge(Other, StartX, EndX); // always merge frame
end;
procedure TSynSelectedColorMergeResult.Merge(Other: TSynHighlighterAttributesModifier; LeftCol,
procedure TSynSelectedColorMergeResult.Merge(Other: TLazCustomEditTextAttribute; LeftCol,
RightCol: TLazSynDisplayTokenBound);
var
sKeep, sSet, sClr, sInv, sInvInv: TFontStyles;
@ -1426,7 +1426,7 @@ begin
EndUpdate;
end;
procedure TSynSelectedColorMergeResult.MergeFrames(Other: TSynHighlighterAttributesModifier; LeftCol,
procedure TSynSelectedColorMergeResult.MergeFrames(Other: TLazCustomEditTextAttribute; LeftCol,
RightCol: TLazSynDisplayTokenBound);
//procedure SetSide(ASide: TLazSynBorderSide; ASrc: TSynHighlighterAttributesModifier);
@ -1457,7 +1457,7 @@ procedure TSynSelectedColorMergeResult.MergeFrames(Other: TSynHighlighterAttribu
//end;
procedure SetSide(AInfoSide: TSynSelectedColorEnum; ASide: TLazSynBorderSide;
ASrc: TSynHighlighterAttributesModifier);
ASrc: TLazCustomEditTextAttribute);
begin
if (FMergeInfos[AInfoSide].BaseColor <> clNone) and
( (ASrc.FramePriority < FMergeInfos[AInfoSide].BasePriority) or
@ -1481,6 +1481,14 @@ procedure TSynSelectedColorMergeResult.MergeFrames(Other: TSynHighlighterAttribu
FFrameSideOrigin[ASide] := ASrc.FrameEdges;
end;
function HasFrameBound(AnAttr: TLazCustomEditTextAttribute; const ABnd: TLazSynDisplayTokenBound): boolean;
begin
(* Highlighter Attribs (NON-TSynSelectedColor) did NOT have a StartX/EndX
So theire frames would be drawn at any location
*)
Result := (Other is TSynSelectedColor) or ABnd.HasValue;
end;
begin
if not FFrameSidesInitialized then
MaybeInitFrameSides;
@ -1492,12 +1500,12 @@ begin
case Other.FrameEdges of
sfeAround: begin
// UpdateOnly, frame keeps behind individual sites
if (not (Other is TSynSelectedColor)) or // always merge, if it has no startx
IsMatching(TSynSelectedColor(Other).StartX, LeftCol)
if (not HasFrameBound(Other, Other.StartX)) or
IsMatching(Other.StartX, LeftCol)
then
SetSide(sscFrameLeft, bsLeft, Other);
if (not (Other is TSynSelectedColor)) or
IsMatching(TSynSelectedColor(Other).EndX, RightCol)
if (not HasFrameBound(Other, Other.EndX)) or
IsMatching(Other.EndX, RightCol)
then
SetSide(sscFrameRight, bsRight, Other);
SetSide(sscFrameBottom, bsBottom, Other);

View File

@ -5724,11 +5724,22 @@ end;
function TSynPasSyn.GetTokenAttribute: TSynHighlighterAttributes;
var
x1, x2: Integer;
begin
case GetTokenID of
tkAsm: Result := fAsmAttri;
tkIDEDirective, tkComment:
tkIDEDirective, tkComment: begin
Result := fCommentAttri;
//x1 := ToPos(fTokenPos);
//x2 := ToPos(Run);
//FCustomCommentTokenMergedMarkup.SetFrameBoundsLog(x1, x2);
//if not GetTokenIsCommentStart(True) then
// x1 := 1;
//if (not GetTokenIsCommentEnd) then
// x2 := fLineLen;
//Result.SetFrameBoundsLog(x1, x2);
end;
tkIdentifier: begin
if eaGotoLabel in FTokenExtraAttribs then
Result := FGotoLabelAttr
@ -5750,8 +5761,20 @@ end;
function TSynPasSyn.GetTokenAttributeEx: TLazCustomEditTextAttribute;
var
tid: TtkTokenKind;
i: Integer;
i, x1, x2: Integer;
LeftCol, RightCol: TLazSynDisplayTokenBound;
attr: TSynHighlighterAttributesModifier;
procedure InitMergeRes(AMergeRes: TSynSelectedColorMergeResult; AnAttr: TLazCustomEditTextAttribute);
begin
if AnAttr is TSynSelectedColorMergeResult then begin
AMergeRes.Assign(AnAttr);
end
else begin
AMergeRes.Clear;
AMergeRes.Merge(AnAttr, LeftCol, RightCol);
end;
end;
begin
Result := GetTokenAttribute;
if Result = nil then
@ -5759,9 +5782,20 @@ begin
tid := GetTokenID;
x1 := ToPos(fTokenPos);
x2 := ToPos(Run);
LeftCol.Init(-1, x1);
RightCol.Init(-1, x2);
if tid in [tkIDEDirective, tkComment] then begin
if not GetTokenIsCommentStart(True) then x1 := 1;
if (not GetTokenIsCommentEnd) then x2 := fLineLen;
Result.SetFrameBoundsLog(x1, x2);
end;
if tid = tkIDEDirective then begin
FCurIDEDirectiveAttri.Assign(FCommentAttri);
FCurIDEDirectiveAttri.Merge(FIDEDirectiveAttri);
FCurIDEDirectiveAttri.Merge(FIDEDirectiveAttri, LeftCol, RightCol);
Result := FCurIDEDirectiveAttri;
end;
@ -5771,26 +5805,29 @@ begin
)
then begin
FCurCaseLabelAttri.Assign(Result);
FCurCaseLabelAttri.Merge(FCaseLabelAttri);
FCurCaseLabelAttri.Merge(FCaseLabelAttri, LeftCol, RightCol);
Result := FCurCaseLabelAttri;
end;
if FIsPasDocKey then begin
FCurPasDocAttri.Assign(Result);
FCurPasDocAttri.Merge(fPasDocKeyWordAttri);
InitMergeRes(FCurPasDocAttri, Result);
FCurPasDocAttri.Merge(fPasDocKeyWordAttri, LeftCol, RightCol);
Result := FCurPasDocAttri;
Result.SetFrameBoundsLog(x1, x2);
end
else
if FIsPasDocSym then begin
FCurPasDocAttri.Assign(Result);
FCurPasDocAttri.Merge(fPasDocSymbolAttri);
InitMergeRes(FCurPasDocAttri, Result);
FCurPasDocAttri.Merge(fPasDocSymbolAttri, LeftCol, RightCol);
Result := FCurPasDocAttri;
Result.SetFrameBoundsLog(x1, x2);
end
else
if FIsPasUnknown then begin
FCurPasDocAttri.Assign(Result);
FCurPasDocAttri.Merge(fPasDocUnknownAttr);
InitMergeRes(FCurPasDocAttri, Result);
FCurPasDocAttri.Merge(fPasDocUnknownAttr, LeftCol, RightCol);
Result := FCurPasDocAttri;
Result.SetFrameBoundsLog(x1, x2);
end;
case FTokenTypeDeclExtraAttrib of
@ -5801,73 +5838,74 @@ begin
(PasCodeFoldRange.BracketNestLevel = 0)
then begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderNameAttr);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderNameAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
end;
eaPropertyName: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FPropertyNameAttr);
FCurProcTypeDeclExtraAttr.Merge(FPropertyNameAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaProcParam: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderParamAttr);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderParamAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaProcType: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderTypeAttr);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderTypeAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaProcValue: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderValueAttr);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderValueAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaProcResult: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderResultAttr);
FCurProcTypeDeclExtraAttr.Merge(FProcedureHeaderResultAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaDeclVarName: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationVarConstNameAttr);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationVarConstNameAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaDeclTypeName: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationTypeNameAttr);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationTypeNameAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaDeclType: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationTypeAttr);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationTypeAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
eaDeclValue: begin
FCurProcTypeDeclExtraAttr.Assign(Result);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationValueAttr);
FCurProcTypeDeclExtraAttr.Merge(FDeclarationValueAttr, LeftCol, RightCol);
Result := FCurProcTypeDeclExtraAttr;
end;
end;
if eaStructMemeber in FTokenExtraAttribs then begin
FCurStructMemberExtraAttri.Assign(Result);
FCurStructMemberExtraAttri.Merge(FStructMemberAttr);
FCurStructMemberExtraAttri.Merge(FStructMemberAttr, LeftCol, RightCol);
Result := FCurStructMemberExtraAttri;
end;
if FCustomTokenMarkup <> nil then begin
FCustomTokenMergedMarkup.Assign(Result);
FCustomTokenMergedMarkup.Merge(FCustomTokenMarkup);
Result := FCustomTokenMergedMarkup;
end;
if FCustomCommentTokenMarkup <> nil then begin
FCustomCommentTokenMergedMarkup.Assign(Result);
FCustomCommentTokenMergedMarkup.Merge(FCustomCommentTokenMarkup);
InitMergeRes(FCustomCommentTokenMergedMarkup, Result);
FCustomCommentTokenMarkup.SetFrameBoundsLog(x1, x2);
FCustomCommentTokenMergedMarkup.Merge(FCustomCommentTokenMarkup, LeftCol, RightCol);
Result := FCustomCommentTokenMergedMarkup;
end;
if FCustomTokenMarkup <> nil then begin
InitMergeRes(FCustomTokenMergedMarkup, Result);
FCustomTokenMergedMarkup.Merge(FCustomTokenMarkup, LeftCol, RightCol);
Result := FCustomTokenMergedMarkup;
end;
if (FTokenID = tkSymbol) and (Run - fTokenPos = 1) and (fLine[fTokenPos] in ['(', ')'])
then begin
@ -5886,6 +5924,7 @@ begin
end;
end;
//Result.SetFrameBoundsLog(-1, -1); // TODO: Textdrawer will do its own bounds, so all frames must be cleared while merging
end;
function TSynPasSyn.GetTokenKind: integer;