mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 13:19:20 +02:00
SynEdit: Start paint-token-breaker for future bidi support
git-svn-id: trunk@38950 -
This commit is contained in:
parent
f50a958fad
commit
5f293d23ae
@ -1,6 +1,7 @@
|
||||
unit LazSynTextArea;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{x $INLINE OFF}
|
||||
|
||||
{off $DEFINE SynUseOldDrawer}
|
||||
|
||||
@ -25,6 +26,7 @@ type
|
||||
ExpandedExtraBytes: Integer; // tab and space expansion
|
||||
HasDoubleWidth: Boolean;
|
||||
Attr: TSynSelectedColor;
|
||||
NextPhysicalStart: Integer; // 1 based - Next toxen, may be BIDI
|
||||
end;
|
||||
|
||||
{ TLazSynPaintTokenBreaker }
|
||||
@ -32,20 +34,26 @@ type
|
||||
TLazSynPaintTokenBreaker = class
|
||||
private
|
||||
FBackgroundColor: TColor;
|
||||
FDisplayView: TLazSynDisplayView;
|
||||
FForegroundColor: TColor;
|
||||
FSpaceExtraByteCount: Integer;
|
||||
FTabExtraByteCount: Integer;
|
||||
FFirstCol, FLastCol: integer; // Physical
|
||||
|
||||
FDisplayView: TLazSynDisplayView;
|
||||
FLinesView: TSynEditStrings;
|
||||
FMarkupManager: TSynEditMarkupManager;
|
||||
|
||||
FCharWidths: TPhysicalCharWidths;
|
||||
FFirstCol, FLastCol: integer;
|
||||
FCharWidthsLen: Integer;
|
||||
FCurTxtLineIdx : Integer;
|
||||
|
||||
FCurViewToken: TLazSynDisplayTokenInfoEx;
|
||||
FCurViewinRTL: Boolean;
|
||||
FCurViewRtlPhysEnd: integer;
|
||||
FCurViewRtlLogEnd: integer;
|
||||
|
||||
FCurMarkupPhysPos, FNextMarkupPhysPos: Integer; // 1, -1
|
||||
FMarkupTokenAttr: TSynSelectedColor;
|
||||
FSpaceExtraByteCount: Integer;
|
||||
FTabExtraByteCount: Integer;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
@ -55,7 +63,7 @@ type
|
||||
);
|
||||
procedure SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx);
|
||||
function GetNextHighlighterTokenFromView(out ATokenInfo: TLazSynDisplayTokenInfoEx;
|
||||
AMaxPhysEnd: Integer
|
||||
APhysEnd: Integer
|
||||
): Boolean;
|
||||
function GetNextHighlighterTokenEx(out ATokenInfo: TLazSynDisplayTokenInfoEx): Boolean;
|
||||
property CharWidths: TPhysicalCharWidths read FCharWidths;
|
||||
@ -244,11 +252,14 @@ procedure TLazSynPaintTokenBreaker.SetHighlighterTokensLine(ALine: TLineIdx; out
|
||||
begin
|
||||
FDisplayView.SetHighlighterTokensLine(ALine, ARealLine);
|
||||
FCharWidths := FLinesView.GetPhysicalCharWidths(ARealLine);
|
||||
FCharWidthsLen := Length(FCharWidths);
|
||||
|
||||
FCurViewToken.Tk.TokenLength := 0;
|
||||
FCurViewToken.LogicalStart := 1;
|
||||
FCurViewToken.PhysicalStart := 1;
|
||||
FCurViewToken.NextPhysicalStart := 1;
|
||||
FCurViewToken.PhysicalPaintStart := FFirstCol;
|
||||
FCurViewinRTL := False;
|
||||
|
||||
FCurMarkupPhysPos := FFirstCol;
|
||||
FNextMarkupPhysPos := -1;
|
||||
@ -288,7 +299,7 @@ begin
|
||||
end;
|
||||
|
||||
function TLazSynPaintTokenBreaker.GetNextHighlighterTokenFromView(out
|
||||
ATokenInfo: TLazSynDisplayTokenInfoEx; AMaxPhysEnd: Integer): Boolean;
|
||||
ATokenInfo: TLazSynDisplayTokenInfoEx; APhysEnd: Integer): Boolean;
|
||||
|
||||
procedure InitSynAttr(var ATarget: TSynSelectedColor; ASource: TSynHighlighterAttributes;
|
||||
AnAttrStartX: Integer);
|
||||
@ -312,119 +323,363 @@ function TLazSynPaintTokenBreaker.GetNextHighlighterTokenFromView(out
|
||||
ATarget.EndX := -1; //PhysicalStartPos + TokenCharLen - 1;
|
||||
end;
|
||||
|
||||
function MaybeFetchToken: Boolean; inline;
|
||||
begin
|
||||
Result := FCurViewToken.Tk.TokenLength > 0;
|
||||
if Result or (FCurViewToken.Tk.TokenLength < 0) then exit;
|
||||
while FCurViewToken.Tk.TokenLength = 0 do begin // Todo: is SyncroEd-test a zero size token is returned
|
||||
Result := FDisplayView.GetNextHighlighterToken(FCurViewToken.Tk);
|
||||
if not Result then begin
|
||||
FCurViewToken.Tk.TokenLength := -1;
|
||||
exit;
|
||||
end;
|
||||
// Todo: concatenate with next token, if possible (only, if reaching token end)
|
||||
end;
|
||||
// TODO: wait with attr, if skipping none painted
|
||||
InitSynAttr(FCurViewToken.Attr, FCurViewToken.Tk.TokenAttr, FCurViewToken.PhysicalStart);
|
||||
end;
|
||||
|
||||
function GetCharWidthData(AIdx: Integer): TPhysicalCharWidth; inline;
|
||||
begin
|
||||
if AIdx >= FCharWidthsLen
|
||||
then Result := 1
|
||||
else Result := FCharWidths[AIdx];
|
||||
end;
|
||||
|
||||
Procedure AdjustCurTokenLogStart(ANewLogStart: Integer); inline;
|
||||
// ANewLogStart = 1 based
|
||||
var
|
||||
j: integer;
|
||||
begin
|
||||
j := (ANewLogStart - FCurViewToken.LogicalStart);
|
||||
FCurViewToken.Tk.TokenLength := FCurViewToken.Tk.TokenLength - j;
|
||||
FCurViewToken.Tk.TokenStart := FCurViewToken.Tk.TokenStart + j;
|
||||
FCurViewToken.LogicalStart := ANewLogStart;
|
||||
end;
|
||||
|
||||
procedure SkipLtrBeforeFirstCol(var ALogicIdx: integer; ALogicEnd: Integer); inline;
|
||||
var
|
||||
j: Integer;
|
||||
pcw: TPhysicalCharWidth;
|
||||
begin
|
||||
if (FCurViewToken.PhysicalStart >= FFirstCol) then
|
||||
exit;
|
||||
|
||||
pcw := GetCharWidthData(ALogicIdx);
|
||||
if (pcw and PCWFlagRTL <> 0) then exit;
|
||||
|
||||
j := (pcw and PCWMask);
|
||||
while (ALogicIdx < ALogicEnd) and (FCurViewToken.PhysicalStart + j <= FFirstCol) and
|
||||
(pcw and PCWFlagRTL = 0)
|
||||
do begin
|
||||
inc(FCurViewToken.PhysicalStart, j);
|
||||
repeat
|
||||
inc(ALogicIdx);
|
||||
until (ALogicIdx >= ALogicEnd) or
|
||||
(ALogicIdx >= FCharWidthsLen) or ((FCharWidths[ALogicIdx] and PCWMask) <> 0);
|
||||
|
||||
pcw := GetCharWidthData(ALogicIdx);
|
||||
j := pcw and PCWMask;
|
||||
end;
|
||||
|
||||
if ALogicIdx <> FCurViewToken.LogicalStart - 1 then begin
|
||||
AdjustCurTokenLogStart(ALogicIdx + 1);
|
||||
assert(FCurViewToken.Tk.TokenLength >= 0, 'FCurViewToken.Tk.TokenLength > 0');
|
||||
end;
|
||||
if FCurViewToken.PhysicalPaintStart < FFirstCol then
|
||||
FCurViewToken.PhysicalPaintStart := FFirstCol;
|
||||
end;
|
||||
|
||||
procedure SkipRtlOffScreen(var ALogicIdx: integer; ALogicEnd: Integer); inline;
|
||||
var
|
||||
j: Integer;
|
||||
pcw: TPhysicalCharWidth;
|
||||
begin
|
||||
if (FCurViewToken.PhysicalStart <= FFirstCol) then begin
|
||||
// TODO: end, if FCurViewRtlPhysEnd >= FLastCol;
|
||||
if ALogicIdx + FCurViewToken.Tk.TokenLength < FCurViewRtlLogEnd then begin
|
||||
FCurViewToken.LogicalStart := FCurViewToken.LogicalStart + FCurViewToken.Tk.TokenLength;
|
||||
FCurViewToken.Tk.TokenLength := 0;
|
||||
end
|
||||
else begin
|
||||
j := FCurViewRtlLogEnd - ALogicIdx;
|
||||
FCurViewToken.LogicalStart := FCurViewToken.LogicalStart + j;
|
||||
FCurViewToken.Tk.TokenStart := FCurViewToken.Tk.TokenStart + j;
|
||||
FCurViewToken.Tk.TokenLength := FCurViewToken.Tk.TokenLength - j;
|
||||
ALogicIdx := ALogicIdx + j;
|
||||
FCurViewToken.PhysicalStart := FCurViewRtlPhysEnd;
|
||||
FCurViewToken.PhysicalPaintStart := FCurViewRtlPhysEnd;
|
||||
assert(FCurViewToken.LogicalStart - 1 = FCurViewRtlLogEnd, 'SkipRtlOffScreen: FCurViewToken.LogicalStart = FCurViewRtlLogEnd');
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (FCurViewToken.PhysicalStart <= FLastCol) then
|
||||
exit;
|
||||
|
||||
pcw := GetCharWidthData(ALogicIdx);
|
||||
if (pcw and PCWFlagRTL = 0) then exit;
|
||||
|
||||
j := (pcw and PCWMask);
|
||||
while (ALogicIdx < ALogicEnd) and (FCurViewToken.PhysicalStart - j >= FLastCol) and
|
||||
(pcw and PCWFlagRTL <> 0)
|
||||
do begin
|
||||
dec(FCurViewToken.PhysicalStart, j);
|
||||
repeat
|
||||
inc(ALogicIdx);
|
||||
until (ALogicIdx >= ALogicEnd) or
|
||||
(ALogicIdx >= FCharWidthsLen) or ((FCharWidths[ALogicIdx] and PCWMask) <> 0);
|
||||
|
||||
pcw := GetCharWidthData(ALogicIdx);
|
||||
j := pcw and PCWMask;
|
||||
end;
|
||||
|
||||
if ALogicIdx <> FCurViewToken.LogicalStart - 1 then begin
|
||||
AdjustCurTokenLogStart(ALogicIdx + 1);
|
||||
assert(FCurViewToken.Tk.TokenLength >= 0, 'FCurViewToken.Tk.TokenLength > 0');
|
||||
end;
|
||||
if FCurViewToken.PhysicalPaintStart > FLastCol then
|
||||
FCurViewToken.PhysicalPaintStart := FLastCol;
|
||||
end;
|
||||
|
||||
procedure ChangeToRtl(ALogicIdx, ALogicEnd: Integer);
|
||||
var
|
||||
RtlRunPhysWidth, j: Integer;
|
||||
pcw: TPhysicalCharWidth;
|
||||
begin
|
||||
pcw := GetCharWidthData(ALogicIdx);
|
||||
|
||||
RtlRunPhysWidth := 0;
|
||||
j := (pcw and PCWMask);
|
||||
while (ALogicIdx < ALogicEnd) and (pcw and PCWFlagRTL <> 0) do begin
|
||||
inc(RtlRunPhysWidth, j);
|
||||
repeat
|
||||
inc(ALogicIdx);
|
||||
until (ALogicIdx >= ALogicEnd) or
|
||||
(ALogicIdx >= FCharWidthsLen) or ((FCharWidths[ALogicIdx] and PCWMask) <> 0);
|
||||
|
||||
pcw := GetCharWidthData(ALogicIdx);
|
||||
j := pcw and PCWMask;
|
||||
end;
|
||||
|
||||
FCurViewinRTL := True;
|
||||
FCurViewRTLLogEnd := ALogicIdx;
|
||||
FCurViewRtlPhysEnd := FCurViewToken.PhysicalStart + RtlRunPhysWidth;
|
||||
FCurViewToken.PhysicalStart := FCurViewRtlPhysEnd;
|
||||
FCurViewToken.PhysicalPaintStart := FCurViewRtlPhysEnd;
|
||||
end;
|
||||
|
||||
function MaybeChangeToRtl(ALogicIdx, ALogicEnd: Integer): boolean; inline;
|
||||
begin
|
||||
Result := (GetCharWidthData(ALogicIdx) and PCWFlagRTL) <> 0;
|
||||
if Result then
|
||||
ChangeToRtl(ALogicIdx, ALogicEnd);
|
||||
end;
|
||||
|
||||
procedure ChangeToLtr(ALogicIdx, ALogicEnd: Integer);
|
||||
begin
|
||||
FCurViewinRTL := False;
|
||||
FCurViewToken.PhysicalStart := FCurViewRtlPhysEnd;
|
||||
FCurViewToken.PhysicalPaintStart := FCurViewRtlPhysEnd;
|
||||
end;
|
||||
|
||||
function MaybeChangeToLtr(ALogicIdx, ALogicEnd: Integer): boolean; inline;
|
||||
begin
|
||||
Result := (GetCharWidthData(ALogicIdx) and PCWFlagRTL) = 0;
|
||||
if Result then
|
||||
ChangeToLtr(ALogicIdx, ALogicEnd);
|
||||
end;
|
||||
|
||||
var
|
||||
i, j, CharWidthsLen: Integer;
|
||||
i, j: Integer;
|
||||
pcw: TPhysicalCharWidth;
|
||||
c: Char;
|
||||
LogicIdx, LogicEnd, PhysPos: Integer;
|
||||
PrevLogicIdx, PrevPhysPos: Integer;
|
||||
PhysTokenStop: Integer;
|
||||
TabExtra: Integer;
|
||||
HasDouble: Boolean;
|
||||
begin
|
||||
if (AMaxPhysEnd > FLastCol) or (AMaxPhysEnd < 0) then
|
||||
AMaxPhysEnd := FLastCol;
|
||||
|
||||
Result := AMaxPhysEnd > FCurViewToken.PhysicalPaintStart;
|
||||
if not Result then exit;
|
||||
|
||||
while True do begin
|
||||
if FCurViewToken.Tk.TokenLength = 0 then begin
|
||||
Result := FDisplayView.GetNextHighlighterToken(FCurViewToken.Tk);
|
||||
if not Result then exit;
|
||||
if FCurViewToken.Tk.TokenLength = 0 then continue; // // Todo: is SyncroEd-test a zero size token is returned
|
||||
InitSynAttr(FCurViewToken.Attr, FCurViewToken.Tk.TokenAttr, FCurViewToken.PhysicalStart);
|
||||
// Todo: concatenate with next token, if possible
|
||||
end;
|
||||
Result := MaybeFetchToken; // Get token from View/Highlighter
|
||||
if not Result then exit;
|
||||
|
||||
CharWidthsLen := Length(FCharWidths);
|
||||
LogicIdx := FCurViewToken.LogicalStart - 1;
|
||||
LogicIdx := FCurViewToken.LogicalStart - 1;
|
||||
LogicEnd := LogicIdx + FCurViewToken.Tk.TokenLength;
|
||||
assert(GetCharWidthData(LogicIdx)<>0, 'GetNextHighlighterTokenFromView: Token starts with char');
|
||||
|
||||
// SKip out of screen
|
||||
while (LogicIdx < LogicEnd) and (FCurViewToken.PhysicalStart < FFirstCol) do begin
|
||||
if LogicIdx >= CharWidthsLen
|
||||
then j := 1
|
||||
else j := (FCharWidths[LogicIdx] and PCWMask);
|
||||
case FCurViewinRTL of
|
||||
False: // Left To Right
|
||||
begin
|
||||
SkipLtrBeforeFirstCol(LogicIdx, LogicEnd); // Skip out of screen
|
||||
if FCurViewToken.Tk.TokenLength = 0 then
|
||||
continue; // Get NEXT token
|
||||
|
||||
if FCurViewToken.PhysicalStart + j > FFirstCol then break;
|
||||
if MaybeChangeToRtl(LogicIdx, LogicEnd) then
|
||||
continue;
|
||||
|
||||
inc(FCurViewToken.PhysicalStart, j);
|
||||
repeat
|
||||
inc(LogicIdx);
|
||||
until (LogicIdx >= CharWidthsLen) or ((FCharWidths[LogicIdx] and PCWMask) <> 0);
|
||||
if APhysEnd > 0
|
||||
then PhysTokenStop := Min(FLastCol, APhysEnd)
|
||||
else PhysTokenStop := FLastCol;
|
||||
// TODO: APhysEnd should always allow some data. Compare with FLastCol? Assert for APhysEnd
|
||||
Result := PhysTokenStop > FCurViewToken.PhysicalPaintStart;
|
||||
if not Result then exit;
|
||||
|
||||
// Find end according to PhysTokenStop
|
||||
PhysPos := FCurViewToken.PhysicalStart;
|
||||
PrevLogicIdx := LogicIdx;
|
||||
PrevPhysPos := PhysPos;
|
||||
HasDouble := False;
|
||||
TabExtra := 0; // Extra bytes needed for expanded Tab/Space(utf8 visible space/dot)
|
||||
i := 0;
|
||||
|
||||
pcw := GetCharWidthData(LogicIdx);
|
||||
while (LogicIdx < LogicEnd) and (PhysPos < PhysTokenStop) and
|
||||
(pcw and PCWFlagRTL = 0)
|
||||
do begin
|
||||
j := pcw and PCWMask;
|
||||
|
||||
PrevLogicIdx := LogicIdx;
|
||||
PrevPhysPos := PhysPos;
|
||||
inc(PhysPos, j);
|
||||
if j <> 0 then begin
|
||||
c := (FCurViewToken.Tk.TokenStart + i)^;
|
||||
if c = #9 then
|
||||
inc(TabExtra, j-1 + FTabExtraByteCount)
|
||||
else
|
||||
if j > 1 then
|
||||
HasDouble := True;
|
||||
if c = ' ' then
|
||||
inc(TabExtra, FSpaceExtraByteCount);
|
||||
end;
|
||||
|
||||
repeat
|
||||
inc(LogicIdx);
|
||||
inc(i);
|
||||
until (LogicIdx >= FCharWidthsLen) or
|
||||
(LogicIdx >= LogicEnd) or ((FCharWidths[LogicIdx] and PCWMask) <> 0);
|
||||
pcw := GetCharWidthData(LogicIdx);
|
||||
end;
|
||||
Assert(PhysPos > FCurViewToken.PhysicalStart, 'PhysPos > FCurViewToken.PhysicalStart');
|
||||
|
||||
ATokenInfo := FCurViewToken;
|
||||
ATokenInfo.Tk.TokenLength := LogicIdx + 1 - ATokenInfo.LogicalStart;
|
||||
ATokenInfo.LogicalEnd := LogicIdx + 1;
|
||||
ATokenInfo.PhysicalEnd := PhysPos;
|
||||
ATokenInfo.PhysicalPaintEnd := Min(PhysPos, PhysTokenStop);
|
||||
ATokenInfo.ExpandedExtraBytes := TabExtra;
|
||||
ATokenInfo.HasDoubleWidth := HasDouble;
|
||||
|
||||
if PhysPos > PhysTokenStop then begin // Last char goes over paint boundary
|
||||
LogicIdx := PrevLogicIdx;
|
||||
PhysPos := PrevPhysPos;
|
||||
end
|
||||
else
|
||||
PhysTokenStop := PhysPos;
|
||||
AdjustCurTokenLogStart(LogicIdx + 1);
|
||||
FCurViewToken.PhysicalStart := PhysPos;
|
||||
FCurViewToken.PhysicalPaintStart := PhysTokenStop;
|
||||
|
||||
assert(FCurViewToken.Tk.TokenLength >= 0, 'FCurViewToken.Tk.TokenLength >= 0');
|
||||
if FCurViewToken.Tk.TokenLength = 0 then
|
||||
ATokenInfo.Attr.EndX := PhysPos-1;
|
||||
|
||||
//MaybeFetchToken;
|
||||
MaybeChangeToRtl(LogicIdx, LogicEnd); // get NextTokenPhysStart
|
||||
|
||||
ATokenInfo.NextPhysicalStart := FCurViewToken.PhysicalStart;
|
||||
|
||||
break;
|
||||
end; // case FCurViewinRTL = False;
|
||||
True: // Right To Left
|
||||
begin
|
||||
SkipRtlOffScreen(LogicIdx, LogicEnd);
|
||||
if FCurViewToken.Tk.TokenLength = 0 then
|
||||
continue; // Get NEXT token
|
||||
|
||||
if MaybeChangeToLtr(LogicIdx, LogicEnd) then
|
||||
continue;
|
||||
|
||||
if APhysEnd >= FCurViewRtlPhysEnd
|
||||
then PhysTokenStop := FFirstCol
|
||||
else PhysTokenStop := Max(FFirstCol, APhysEnd);
|
||||
// TODO: APhysEnd should always allow some data. Assert for APhysEnd
|
||||
// FFirstCol must be less PPS. Otherwise it would have gone LTR
|
||||
// Result := PhysTokenStop < FCurViewToken.PhysicalPaintStart;
|
||||
// if not Result then exit;
|
||||
|
||||
// Find end according to PhysTokenStop
|
||||
PhysPos := FCurViewToken.PhysicalStart;
|
||||
PrevLogicIdx := LogicIdx;
|
||||
PrevPhysPos := PhysPos;
|
||||
HasDouble := False;
|
||||
TabExtra := 0; // Extra bytes needed for expanded Tab/Space(utf8 visible space/dot)
|
||||
i := 0;
|
||||
|
||||
pcw := GetCharWidthData(LogicIdx);
|
||||
while (LogicIdx < LogicEnd) and (PhysPos > PhysTokenStop) and
|
||||
(pcw and PCWFlagRTL <> 0)
|
||||
do begin
|
||||
j := pcw and PCWMask;
|
||||
|
||||
PrevLogicIdx := LogicIdx;
|
||||
PrevPhysPos := PhysPos;
|
||||
dec(PhysPos, j);
|
||||
if j <> 0 then begin
|
||||
c := (FCurViewToken.Tk.TokenStart + i)^;
|
||||
if c = #9 then
|
||||
inc(TabExtra, j-1 + FTabExtraByteCount)
|
||||
else
|
||||
if j > 1 then
|
||||
HasDouble := True;
|
||||
if c = ' ' then
|
||||
inc(TabExtra, FSpaceExtraByteCount);
|
||||
end;
|
||||
|
||||
repeat
|
||||
inc(LogicIdx);
|
||||
inc(i);
|
||||
until (LogicIdx >= FCharWidthsLen) or
|
||||
(LogicIdx >= LogicEnd) or ((FCharWidths[LogicIdx] and PCWMask) <> 0);
|
||||
pcw := GetCharWidthData(LogicIdx);
|
||||
end;
|
||||
Assert(PhysPos < FCurViewToken.PhysicalStart, 'PhysPos > FCurViewToken.PhysicalStart');
|
||||
|
||||
ATokenInfo := FCurViewToken;
|
||||
ATokenInfo.Tk.TokenLength := LogicIdx + 1 - ATokenInfo.LogicalStart;
|
||||
ATokenInfo.LogicalEnd := LogicIdx + 1;
|
||||
ATokenInfo.PhysicalEnd := ATokenInfo.PhysicalStart;
|
||||
ATokenInfo.PhysicalPaintEnd := ATokenInfo.PhysicalPaintStart;
|
||||
ATokenInfo.PhysicalStart := PhysPos;
|
||||
ATokenInfo.PhysicalPaintStart := Max(PhysPos, PhysTokenStop);
|
||||
ATokenInfo.ExpandedExtraBytes := TabExtra;
|
||||
ATokenInfo.HasDoubleWidth := HasDouble;
|
||||
|
||||
if PhysPos < PhysTokenStop then begin // Last char goes over paint boundary
|
||||
LogicIdx := PrevLogicIdx;
|
||||
PhysPos := PrevPhysPos;
|
||||
end;
|
||||
//else
|
||||
// AMaxPhysEnd := PhysPos;
|
||||
AdjustCurTokenLogStart(LogicIdx + 1);
|
||||
FCurViewToken.PhysicalStart := PhysPos;
|
||||
FCurViewToken.PhysicalPaintStart := Max(PhysPos, PhysTokenStop);
|
||||
|
||||
assert(FCurViewToken.Tk.TokenLength >= 0, 'FCurViewToken.Tk.TokenLength >= 0');
|
||||
if FCurViewToken.Tk.TokenLength = 0 then
|
||||
ATokenInfo.Attr.EndX := PhysPos-1;
|
||||
|
||||
//MaybeFetchToken;
|
||||
MaybeChangeToLtr(LogicIdx, LogicEnd); // get NextTokenPhysStart
|
||||
|
||||
ATokenInfo.NextPhysicalStart := FCurViewToken.PhysicalStart;
|
||||
|
||||
break;
|
||||
end; // case FCurViewinRTL = True;
|
||||
end;
|
||||
|
||||
if LogicIdx <> FCurViewToken.LogicalStart - 1 then begin
|
||||
j := (LogicIdx + 1 - FCurViewToken.LogicalStart);
|
||||
FCurViewToken.Tk.TokenLength := FCurViewToken.Tk.TokenLength - j;
|
||||
FCurViewToken.Tk.TokenStart := FCurViewToken.Tk.TokenStart + j;
|
||||
FCurViewToken.LogicalStart := LogicIdx + 1;
|
||||
|
||||
if FCurViewToken.Tk.TokenLength = 0 then
|
||||
continue;
|
||||
assert(FCurViewToken.Tk.TokenLength > 0, 'FCurViewToken.Tk.TokenLength > 0');
|
||||
end;
|
||||
|
||||
// Find end according to AMaxPhysEnd
|
||||
LogicEnd := LogicIdx + FCurViewToken.Tk.TokenLength;
|
||||
PhysPos := FCurViewToken.PhysicalStart;
|
||||
PrevLogicIdx := LogicIdx;
|
||||
PrevPhysPos := PhysPos;
|
||||
HasDouble := False;
|
||||
TabExtra := 0; // Extra bytes needed for expanded Tab/Space(utf8 visible space/dot)
|
||||
i := 0;
|
||||
|
||||
while (LogicIdx < LogicEnd) and (PhysPos < AMaxPhysEnd) do begin
|
||||
if LogicIdx >= CharWidthsLen
|
||||
then j := 1
|
||||
else j := (FCharWidths[LogicIdx] and PCWMask);
|
||||
|
||||
PrevLogicIdx := LogicIdx;
|
||||
PrevPhysPos := PhysPos;
|
||||
inc(PhysPos, j);
|
||||
if j <> 0 then begin
|
||||
c := (FCurViewToken.Tk.TokenStart + i)^;
|
||||
if c = #9 then
|
||||
inc(TabExtra, j-1 + FTabExtraByteCount)
|
||||
else
|
||||
if j > 1 then
|
||||
HasDouble := True;
|
||||
if c = ' ' then
|
||||
inc(TabExtra, FSpaceExtraByteCount);
|
||||
end;
|
||||
|
||||
repeat
|
||||
inc(LogicIdx);
|
||||
inc(i);
|
||||
until (LogicIdx >= CharWidthsLen) or (LogicIdx >= LogicEnd) or ((FCharWidths[LogicIdx] and PCWMask) <> 0);
|
||||
end;
|
||||
Assert(PhysPos > FCurViewToken.PhysicalStart, 'PhysPos > FCurViewToken.PhysicalStart');
|
||||
|
||||
ATokenInfo := FCurViewToken;
|
||||
ATokenInfo.Tk.TokenLength := LogicIdx + 1 - ATokenInfo.LogicalStart;
|
||||
ATokenInfo.LogicalEnd := LogicIdx + 1;
|
||||
ATokenInfo.PhysicalEnd := PhysPos;
|
||||
ATokenInfo.PhysicalPaintEnd := Min(PhysPos, AMaxPhysEnd);
|
||||
ATokenInfo.ExpandedExtraBytes := TabExtra;
|
||||
ATokenInfo.HasDoubleWidth := HasDouble;
|
||||
|
||||
if PhysPos > AMaxPhysEnd then begin // Last char goes over paint boundary
|
||||
LogicIdx := PrevLogicIdx;
|
||||
PhysPos := PrevPhysPos;
|
||||
end
|
||||
else
|
||||
AMaxPhysEnd := PhysPos;
|
||||
j := LogicIdx + 1 - FCurViewToken.LogicalStart;
|
||||
FCurViewToken.Tk.TokenLength := FCurViewToken.Tk.TokenLength - j;
|
||||
FCurViewToken.Tk.TokenStart := FCurViewToken.Tk.TokenStart + j;
|
||||
FCurViewToken.LogicalStart := LogicIdx + 1;
|
||||
FCurViewToken.PhysicalStart := PhysPos;
|
||||
FCurViewToken.PhysicalPaintStart := AMaxPhysEnd;
|
||||
assert(FCurViewToken.Tk.TokenLength >= 0, 'FCurViewToken.Tk.TokenLength >= 0');
|
||||
|
||||
if FCurViewToken.Tk.TokenLength = 0 then
|
||||
ATokenInfo.Attr.EndX := PhysPos-1;
|
||||
break;
|
||||
end;
|
||||
end; // while True
|
||||
end;
|
||||
|
||||
{ TLazSynSurfaceManager }
|
||||
|
@ -1,12 +1,13 @@
|
||||
unit TestSynTextArea;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$INLINE OFF}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpcunit, testregistry, TestBase, SynHighlighterPas,
|
||||
LazSynTextArea, SynEditTypes;
|
||||
Classes, SysUtils, fpcunit, testregistry, TestBase, LazSynTextArea,
|
||||
SynEditTypes, SynEditMarkupBracket, SynEdit, SynHighlighterPosition, Graphics;
|
||||
|
||||
type
|
||||
|
||||
@ -14,12 +15,13 @@ type
|
||||
|
||||
TTestSynTextArea = class(TTestBase)
|
||||
private
|
||||
FTheHighLighter: TSynPasSyn;
|
||||
FTheHighLighter: TSynPositionHighlighter;
|
||||
FtkRed, FtkGreen, FtkBlue, FtkYellow: TtkTokenKind;
|
||||
protected
|
||||
FTokenBreaker: TLazSynPaintTokenBreaker;
|
||||
|
||||
procedure ReCreateEdit; reintroduce;
|
||||
function CreateTheHighLighter: TSynPasSyn;
|
||||
function CreateTheHighLighter: TSynPositionHighlighter;
|
||||
procedure SetUp; override;
|
||||
procedure TearDown; override;
|
||||
|
||||
@ -43,9 +45,13 @@ begin
|
||||
SynEdit.Highlighter := FTheHighLighter;
|
||||
end;
|
||||
|
||||
function TTestSynTextArea.CreateTheHighLighter: TSynPasSyn;
|
||||
function TTestSynTextArea.CreateTheHighLighter: TSynPositionHighlighter;
|
||||
begin
|
||||
Result := TSynPasSyn.Create(nil);
|
||||
Result := TSynPositionHighlighter.Create(nil);
|
||||
FtkRed := Result.CreateTokenID('red', clRed, clDefault, []);
|
||||
FtkGreen := Result.CreateTokenID('green', clGreen, clDefault, []);
|
||||
FtkBlue := Result.CreateTokenID('blue', clBlue, clDefault, []);
|
||||
FtkYellow := Result.CreateTokenID('yellow', clYellow, clDefault, []);
|
||||
end;
|
||||
|
||||
procedure TTestSynTextArea.SetUp;
|
||||
@ -63,15 +69,20 @@ end;
|
||||
procedure TTestSynTextArea.SetRealLinesText;
|
||||
begin
|
||||
ReCreateEdit;
|
||||
SetLines(['unit foo;',
|
||||
SetLines(['unit foo;', // 1
|
||||
'interface//',
|
||||
'const',
|
||||
' test =''abcDEF'';',
|
||||
' testa=''a あアア F'';',
|
||||
' testa=''a あアア F'';', // 5
|
||||
' testb=''aääDEF''; // föö bar',
|
||||
#9'i=123;',
|
||||
' a'#9'=0;',
|
||||
#9#9#9#9'end'
|
||||
#9#9#9#9'end',
|
||||
'', // 10
|
||||
'شس',
|
||||
'شس ي',
|
||||
'ABشس يCD',
|
||||
''
|
||||
]);
|
||||
end;
|
||||
|
||||
@ -80,6 +91,7 @@ var
|
||||
BaseName, Name: String;
|
||||
TkCnt: Integer;
|
||||
Token: TLazSynDisplayTokenInfoEx;
|
||||
UseViewTokenOnly: Boolean;
|
||||
|
||||
procedure TestToken(LStart, LEnd, PStart, PEnd, DStart, DEnd: Integer; AText: String);
|
||||
begin
|
||||
@ -97,7 +109,7 @@ var
|
||||
var
|
||||
RLine: TLineIdx;
|
||||
begin
|
||||
BaseName := Format('%s (Line=%d, F/L=%d-%d): ', [AName, ALine, AFirst, ALast]);
|
||||
BaseName := Format('%s::%s (Line=%d, F/L=%d-%d): ', [BaseTestName, AName, ALine, AFirst, ALast]);
|
||||
Name := BaseName;
|
||||
TkCnt := 0;
|
||||
FTokenBreaker.Prepare(SynEdit.ViewedTextBuffer.DisplayView,
|
||||
@ -115,7 +127,9 @@ var
|
||||
begin
|
||||
inc(TkCnt);
|
||||
Name := Format('%sL=%d (%d): ', [BaseName, APhysLimit, TkCnt]);
|
||||
R := FTokenBreaker.GetNextHighlighterTokenFromView(Token, APhysLimit);
|
||||
if UseViewTokenOnly
|
||||
then R := FTokenBreaker.GetNextHighlighterTokenFromView(Token, APhysLimit)
|
||||
else R := FTokenBreaker.GetNextHighlighterTokenEx(Token);
|
||||
AssertTrue(Name + 'Got Token', R);
|
||||
end;
|
||||
|
||||
@ -131,142 +145,320 @@ var
|
||||
begin
|
||||
inc(TkCnt);
|
||||
Name := Format('%sL=%d (%d): ', [BaseName, APhysLimit, TkCnt]);
|
||||
R := FTokenBreaker.GetNextHighlighterTokenFromView(Token, APhysLimit);
|
||||
if UseViewTokenOnly
|
||||
then R := FTokenBreaker.GetNextHighlighterTokenFromView(Token, APhysLimit)
|
||||
else R := FTokenBreaker.GetNextHighlighterTokenEx(Token);
|
||||
AssertFalse(Name + ' No further Token', R);
|
||||
end;
|
||||
|
||||
begin
|
||||
UseViewTokenOnly := True;
|
||||
SetRealLinesText;
|
||||
SynEdit.TabWidth := 4;
|
||||
SynEdit.ViewedTextBuffer.DisplayView.InitHighlighterTokens(FTheHighLighter);
|
||||
SynEdit.ViewedTextBuffer.DisplayView.InitHighlighterTokens(SynEdit.Highlighter);
|
||||
|
||||
{%region full line}
|
||||
TestStart('Scan full line', 2, 1, 100, 2);
|
||||
FTheHighLighter.AddToken(2-1, 9, FtkBlue); // interface
|
||||
FTheHighLighter.AddToken(7-1, 1, FtkYellow); // #9
|
||||
FTheHighLighter.AddToken(7-1, 2, FtkGreen); // i
|
||||
FTheHighLighter.AddToken(7-1, 3, FtkRed); // =
|
||||
FTheHighLighter.AddToken(7-1, 6, FtkGreen); // 123
|
||||
|
||||
TestNext(100, 1, 10, 1, 10, 1, 10, 'interface');
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%region LTR only }
|
||||
PushBaseName('LTR-Only');
|
||||
{%region full line}
|
||||
TestStart('Scan full line', 2, 1, 100, 2);
|
||||
TestNext(100, 1, 10, 1, 10, 1, 10, 'interface');
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
|
||||
TestStart('Scan full line', 2, 1, 100, 2);
|
||||
TestNext(-1, 1, 10, 1, 10, 1, 10, 'interface');
|
||||
TestNext(-1, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(-1);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off end of line}
|
||||
TestStart('Cut off end', 2, 1, 5, 2);
|
||||
|
||||
TestNext(100, 1, 5, 1, 5, 1, 5, 'inte');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off start of line}
|
||||
TestStart('Cut off start', 2, 3, 100, 2);
|
||||
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off start of line}
|
||||
TestStart('Cut off start 1 tok', 2, 10, 100, 2);
|
||||
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off start of line}
|
||||
TestStart('Cut off start 1.5 tok', 2, 11, 100, 2);
|
||||
|
||||
TestNext(100, 11, 12, 11, 12, 11, 12, '/');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off both}
|
||||
TestStart('Cut off both', 2, 3, 10, 2);
|
||||
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
//TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off both - 2 token}
|
||||
TestStart('Cut off both - 2 token', 2, 3, 11, 2);
|
||||
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
TestNext(100, 10, 11, 10, 11, 10, 11, '/');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off both - 1 token, skip first}
|
||||
TestStart('Cut off both - 1 token, skip 1st', 2, 10, 11, 2);
|
||||
|
||||
TestNext(100, 10, 11, 10, 11, 10, 11, '/');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region 1 token 2 parts}
|
||||
TestStart('1 token 2 parts', 2, 1, 100, 2);
|
||||
|
||||
TestNext( 3, 1, 3, 1, 3, 1, 3, 'in');
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
// part chars/tabs
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (begin)', 7, 2, 100, 7);
|
||||
|
||||
TestNext( 5, 1, 2, 1, 5, 2, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (end)', 7, 1, 100, 7);
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 1, 3, #9);
|
||||
TestNext(100, 1, 2, 1, 5, 3, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (end) next-limit', 7, 1, 100, 7);
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 1, 3, #9);
|
||||
TestNext( 5, 1, 2, 1, 5, 3, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (both) continue', 7, 2, 100, 7);
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestNext(100, 1, 2, 1, 5, 3, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (both) global-limit', 7, 2, 3, 7);
|
||||
|
||||
TestNext(100, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (both) next-limit', 7, 2, 100, 7);
|
||||
|
||||
TestNext(3, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestEnd(3);
|
||||
{%endregion}
|
||||
|
||||
{%region cut tab in many}
|
||||
TestStart('cut tab in many', 9, 2, 100, 9);
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestNext( 6, 1, 3, 1, 9, 3, 6, #9#9);
|
||||
TestNext( 11, 2, 4, 5, 13, 6, 11, #9#9);
|
||||
TestNext( 13, 3, 4, 9, 13, 11, 13, #9);
|
||||
TestNext( 15, 4, 5, 13, 17, 13, 15, #9);
|
||||
{%endregion}
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region cut off end of line}
|
||||
TestStart('Cut off end', 2, 1, 5, 2);
|
||||
SynEdit.ViewedTextBuffer.DisplayView.FinishHighlighterTokens;
|
||||
SynEdit.Highlighter := nil;
|
||||
SynEdit.ViewedTextBuffer.DisplayView.InitHighlighterTokens(SynEdit.Highlighter);
|
||||
{%region RTL only }
|
||||
PushBaseName('RTL-Only');
|
||||
{%region full line}
|
||||
TestStart('Scan full line', 11, 1, 100, 11);
|
||||
TestNext(100, 1, 5, 1, 3, 1, 3, 'شس');
|
||||
TestEnd(100);
|
||||
|
||||
TestNext(100, 1, 5, 1, 5, 1, 5, 'inte');
|
||||
TestEnd(100);
|
||||
TestStart('Scan full line', 11, 1, 100, 11);
|
||||
TestNext(-1, 1, 5, 1, 3, 1, 3, 'شس');
|
||||
TestEnd(-1);
|
||||
|
||||
TestStart('Scan full line (2 words)', 12, 1, 100, 12);
|
||||
TestNext(100, 1, 8, 1, 5, 1, 5, 'شس ي');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region part line}
|
||||
// 1 char parts
|
||||
TestStart('part line - begin', 12, 1, 2, 12);
|
||||
TestNext(100, 6, 8, 1, 2, 1, 2, 'ي');
|
||||
TestEnd(100);
|
||||
|
||||
TestStart('part line - mid', 12, 2, 3, 12);
|
||||
TestNext(100, 5, 6, 2, 3, 2, 3, ' ');
|
||||
TestEnd(100);
|
||||
|
||||
TestStart('part line - mid', 12, 3, 4, 12);
|
||||
TestNext(100, 3, 5, 3, 4, 3, 4, 'س');
|
||||
TestEnd(100);
|
||||
|
||||
TestStart('part line - end', 12, 4, 5, 12);
|
||||
TestNext(100, 1, 3, 4, 5, 4, 5, 'ش');
|
||||
TestEnd(100);
|
||||
|
||||
// 2 char parts
|
||||
TestStart('part line - begin(2)', 12, 1, 3, 12);
|
||||
TestNext(100, 5, 8, 1, 3, 1, 3, ' ي');
|
||||
TestEnd(100);
|
||||
|
||||
TestStart('part line - mid(2)', 12, 2, 4, 12);
|
||||
TestNext(100, 3, 6, 2, 4, 2, 4, 'س ');
|
||||
TestEnd(100);
|
||||
|
||||
TestStart('part line - end(2)', 12, 3, 5, 12);
|
||||
TestNext(100, 1, 5, 3, 5, 3, 5, 'شس');
|
||||
TestEnd(100);
|
||||
|
||||
// 1 char parts, several chunks
|
||||
TestStart('part line - begin', 12, 1, 100, 12);
|
||||
TestNext(4, 1, 3, 4, 5, 4, 5, 'ش');
|
||||
TestNext(3, 3, 5, 3, 4, 3, 4, 'س');
|
||||
TestNext(2, 5, 6, 2, 3, 2, 3, ' ');
|
||||
TestNext(1, 6, 8, 1, 2, 1, 2, 'ي');
|
||||
TestEnd(100);
|
||||
|
||||
// 1 char parts, several chunks
|
||||
TestStart('part line - begin', 12, 1, 100, 12);
|
||||
TestNext(4, 1, 3, 4, 5, 4, 5, 'ش');
|
||||
TestNext(3, 3, 5, 3, 4, 3, 4, 'س');
|
||||
TestNext(0, 5, 8, 1, 3, 1, 3, ' ي');
|
||||
TestEnd(100);
|
||||
|
||||
//TestStart('part line - begin', 12, 1, 100, 12);
|
||||
//TestNext(2, 1, 6, 2, 5, 2, 5, 'شس ');
|
||||
//TestNext(5, 1, 3, 4, 5, 4, 5, 'ي');
|
||||
//TestEnd(100);
|
||||
//
|
||||
//TestStart('part line - begin', 12, 1, 100, 12);
|
||||
//TestNext( 2, 1, 6, 2, 5, 2, 5, 'شس ');
|
||||
//TestNext(100, 1, 3, 4, 5, 4, 5, 'شس ي');
|
||||
//TestEnd(100);
|
||||
|
||||
{%endregion}
|
||||
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region cut off start of line}
|
||||
TestStart('Cut off start', 2, 3, 100, 2);
|
||||
{%region MIXED Rtl/Ltr }
|
||||
PushBaseName('MIXED Rtl/Ltr');
|
||||
{%region full line}
|
||||
TestStart('Scan full line', 13, 1, 100, 13);
|
||||
TestNext(-1, 1, 3, 1, 3, 1, 3, 'AB');
|
||||
TestNext(-1, 3, 10, 3, 7, 3, 7, 'شس ي');
|
||||
TestNext(-1, 10, 12, 7, 9, 7, 9, 'CD');
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
{%endregion}
|
||||
|
||||
{%region cut off start of line}
|
||||
TestStart('Cut off start 1 tok', 2, 10, 100, 2);
|
||||
{%region parts}
|
||||
TestStart('Scan part line, cut at start', 13, 2, 100, 13);
|
||||
TestNext(-1, 2, 3, 2, 3, 2, 3, 'B');
|
||||
TestNext(-1, 3, 10, 3, 7, 3, 7, 'شس ي');
|
||||
TestNext(-1, 10, 12, 7, 9, 7, 9, 'CD');
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
TestStart('Scan part line, cut at start', 13, 3, 100, 13);
|
||||
TestNext(-1, 3, 10, 3, 7, 3, 7, 'شس ي');
|
||||
TestNext(-1, 10, 12, 7, 9, 7, 9, 'CD');
|
||||
TestEnd(-1);
|
||||
|
||||
{%region cut off start of line}
|
||||
TestStart('Cut off start 1.5 tok', 2, 11, 100, 2);
|
||||
TestStart('Scan part line, cut at start', 13, 4, 100, 13);
|
||||
TestNext(-1, 3, 8, 4, 7, 4, 7, 'شس ');
|
||||
TestNext(-1, 10, 12, 7, 9, 7, 9, 'CD');
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext(100, 11, 12, 11, 12, 11, 12, '/');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
TestStart('Scan part line, cut at start', 13, 6, 100, 13);
|
||||
TestNext(-1, 3, 5, 6, 7, 6, 7, 'ش');
|
||||
TestNext(-1, 10, 12, 7, 9, 7, 9, 'CD');
|
||||
TestEnd(-1);
|
||||
|
||||
{%region cut off both}
|
||||
TestStart('Cut off both', 2, 3, 10, 2);
|
||||
TestStart('Scan part line, cut at start', 13, 7, 100, 13);
|
||||
TestNext(-1, 10, 12, 7, 9, 7, 9, 'CD');
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
//TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
TestStart('Scan part line, cut at start', 13, 8, 100, 13);
|
||||
TestNext(-1, 11, 12, 8, 9, 8, 9, 'D');
|
||||
TestEnd(-1);
|
||||
|
||||
{%region cut off both - 2 token}
|
||||
TestStart('Cut off both - 2 token', 2, 3, 11, 2);
|
||||
TestStart('Scan part line, cut at start', 13, 9, 100, 13);
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
TestNext(100, 10, 11, 10, 11, 10, 11, '/');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off both - 1 token, skip first}
|
||||
TestStart('Cut off both - 1 token, skip 1st', 2, 10, 11, 2);
|
||||
TestStart('Scan part line, cut at end', 13, 1, 8, 13);
|
||||
TestNext(-1, 1, 3, 1, 3, 1, 3, 'AB');
|
||||
TestNext(-1, 3, 10, 3, 7, 3, 7, 'شس ي');
|
||||
TestNext(-1, 10, 11, 7, 8, 7, 8, 'C');
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext(100, 10, 11, 10, 11, 10, 11, '/');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
TestStart('Scan part line, cut at end', 13, 1, 7, 13);
|
||||
TestNext(-1, 1, 3, 1, 3, 1, 3, 'AB');
|
||||
TestNext(-1, 3, 10, 3, 7, 3, 7, 'شس ي');
|
||||
TestEnd(-1);
|
||||
|
||||
{%region 1 token 2 parts}
|
||||
TestStart('1 token 2 parts', 2, 1, 100, 2);
|
||||
TestStart('Scan part line, cut at end', 13, 1, 6, 13);
|
||||
TestNext(-1, 1, 3, 1, 3, 1, 3, 'AB');
|
||||
TestNext(-1, 5, 10, 3, 6, 3, 6, 'س ي');
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext( 3, 1, 3, 1, 3, 1, 3, 'in');
|
||||
TestNext(100, 3, 10, 3, 10, 3, 10, 'terface');
|
||||
TestNext(100, 10, 12, 10, 12, 10, 12, '//');
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
TestStart('Scan part line, cut at end', 13, 1, 4, 13);
|
||||
TestNext(-1, 1, 3, 1, 3, 1, 3, 'AB');
|
||||
TestNext(-1, 8, 10, 3, 4, 3, 4, 'ي');
|
||||
TestEnd(-1);
|
||||
|
||||
// part chars/tabs
|
||||
TestStart('Scan part line, cut at end', 13, 1, 3, 13);
|
||||
TestNext(-1, 1, 3, 1, 3, 1, 3, 'AB');
|
||||
TestEnd(-1);
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (begin)', 7, 2, 100, 7);
|
||||
TestStart('Scan part line, cut at end', 13, 1, 2, 13);
|
||||
TestNext(-1, 1, 2, 1, 2, 1, 2, 'A');
|
||||
TestEnd(-1);
|
||||
|
||||
TestNext( 5, 1, 2, 1, 5, 2, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (end)', 7, 1, 100, 7);
|
||||
{%endregion}
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 1, 3, #9);
|
||||
TestNext(100, 1, 2, 1, 5, 3, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (end) next-limit', 7, 1, 100, 7);
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 1, 3, #9);
|
||||
TestNext( 5, 1, 2, 1, 5, 3, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (both) continue', 7, 2, 100, 7);
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestNext(100, 1, 2, 1, 5, 3, 5, #9);
|
||||
TestNext(100, 2, 3, 5, 6, 5, 6, 'i');
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (both) global-limit', 7, 2, 3, 7);
|
||||
|
||||
TestNext(100, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestEnd(100);
|
||||
{%endregion}
|
||||
|
||||
{%region cut off PART of char}
|
||||
TestStart('cut off PART of char (both) next-limit', 7, 2, 100, 7);
|
||||
|
||||
TestNext(3, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestEnd(3);
|
||||
{%endregion}
|
||||
|
||||
{%region cut tab in many}
|
||||
TestStart('cut tab in many', 9, 2, 100, 9);
|
||||
|
||||
TestNext( 3, 1, 2, 1, 5, 2, 3, #9);
|
||||
TestNext( 6, 1, 3, 1, 9, 3, 6, #9#9);
|
||||
TestNext( 11, 2, 4, 5, 13, 6, 11, #9#9);
|
||||
TestNext( 13, 3, 4, 9, 13, 11, 13, #9);
|
||||
TestNext( 15, 4, 5, 13, 17, 13, 15, #9);
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
|
||||
SynEdit.ViewedTextBuffer.DisplayView.FinishHighlighterTokens;
|
||||
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user