From d5617322c3c26126bef579af6aed8e8682d75816 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 16 Oct 2012 13:45:54 +0000 Subject: [PATCH] SynEdit: ecLeft/Right for future bidi support git-svn-id: trunk@39102 - --- components/synedit/syneditmarkup.pp | 4 +- components/synedit/syneditpointclasses.pas | 62 ++++++++++++++++++++++ components/synedit/synedittextbuffer.pp | 15 +++--- components/synedit/test/testnavigation.pas | 2 +- 4 files changed, 73 insertions(+), 10 deletions(-) diff --git a/components/synedit/syneditmarkup.pp b/components/synedit/syneditmarkup.pp index 0d1dfe8d56..2be83662d4 100644 --- a/components/synedit/syneditmarkup.pp +++ b/components/synedit/syneditmarkup.pp @@ -530,8 +530,8 @@ function TSynEditMarkupManager.GetMarkupAttributeAtRowCol(const aRow: Integer; const aStartCol: TLazSynDisplayTokenBound; const AnRtlInfo: TLazSynDisplayRtlInfo) : TSynSelectedColor; begin assert(false); - //Result := MarkupInfo; - //Result.Clear; + Result := MarkupInfo; + Result.Clear; //MergeMarkupAttributeAtRowCol(aRow, aCol, GetNextMarkupColAfterRowCol(aRow, aCol) - 1, Result); end; diff --git a/components/synedit/syneditpointclasses.pas b/components/synedit/syneditpointclasses.pas index 7a5746c117..25a4c8c2b5 100644 --- a/components/synedit/syneditpointclasses.pas +++ b/components/synedit/syneditpointclasses.pas @@ -232,6 +232,7 @@ type function WasAtLineChar(aPoint: TPoint): Boolean; function WasAtLineByte(aPoint: TPoint): Boolean; function IsAtPos(aCaret: TSynEditCaret): Boolean; + function MoveHoriz(ACount: Integer): Boolean; // Logical property OldLinePos: Integer read FOldLinePos; property OldCharPos: Integer read FOldCharPos; @@ -492,6 +493,67 @@ begin Result := IsAtLineChar(aCaret.LineCharPos); end; +function TSynEditCaret.MoveHoriz(ACount: Integer): Boolean; +var + L: String; + CharWidths: TPhysicalCharWidths; + GotCharWidths: Boolean; + MaxOffs: Integer; + + function GetMaxOffs(AlogPos: Integer): Integer; + begin + if not GotCharWidths then + CharWidths := FLines.GetPhysicalCharWidths(Pchar(L), length(L), FLinePos-1); + GotCharWidths := True; + Result := CharWidths[AlogPos-1]; + end; + +begin + GotCharWidths := False; + L := LineText; + UpdateBytePos; + + If ACount > 0 then begin + if (FBytePos <= length(L)) and (L[FBytePos] = #9) and (not FSkipTabs) then + MaxOffs := GetMaxOffs(FBytePos) - 1 + else + MaxOffs := 0; + + while ACount > 0 do begin + if FBytePosOffset < MaxOffs then + inc(FBytePosOffset) + else begin + FBytePos := FLines.LogicPosAddChars(L, FBytePos, 1, True); + FBytePosOffset := 0; + if (FBytePos <= length(L)) and (L[FBytePos] = #9) and (not FSkipTabs) then + MaxOffs := GetMaxOffs(FBytePos) - 1 + else + MaxOffs := 0; + end; + dec(ACount); + end; + Result := FBytePos <= length(L) + 1; + end + else begin + while ACount < 0 do begin + if FBytePosOffset > 0 then + dec(FBytePosOffset) + else begin + if FBytePos = 1 then + break; + FBytePos := FLines.LogicPosAddChars(L, FBytePos, -1, True); + if (FBytePos <= length(L)) and (L[FBytePos] = #9) and (not FSkipTabs) then + FBytePosOffset := GetMaxOffs(FBytePos) - 1 + else + FBytePosOffset := 0; + end; + inc(ACount); + end; + Result := ACount = 0; + end; + CharPos := FLines.LogPhysConvertor.LogicalToPhysical(FLinePos - 1, FBytePos, FBytePosOffset); +end; + procedure TSynEditCaret.setLinePos(const AValue : Integer); begin InternalSetLineCharPos(AValue, FLastCharPos, True); diff --git a/components/synedit/synedittextbuffer.pp b/components/synedit/synedittextbuffer.pp index 38d9c30755..9ac1958a31 100644 --- a/components/synedit/synedittextbuffer.pp +++ b/components/synedit/synedittextbuffer.pp @@ -1057,15 +1057,14 @@ end; function TSynEditStringList.LogicPosAddChars(const ALine: String; ALogicalPos, ACount: integer; AllowPastEOL: Boolean): Integer; +var + l: Integer; begin // UTF8 handing of chars Result := ALogicalPos; - if (ALogicalPos < 1) or (ALogicalPos > length(ALine)) then begin - Result := Result + ACount; - exit; - end; + l := length(ALine); if ACount > 0 then begin; - while (Result < length(ALine)) and (ACount > 0) do begin + while (Result < l) and (ACount > 0) do begin inc(Result); if (ALine[Result] in [#0..#127, #192..#255]) and (not LogicPosIsCombining(ALine, Result)) then dec(ACount); @@ -1073,7 +1072,7 @@ begin if AllowPastEOL then Result := Result + ACount; - if (Result <= length(ALine)) then + if (Result <= l) then while (Result > 1) and ( (not(ALine[Result] in [#0..#127, #192..#255])) or LogicPosIsCombining(ALine, Result) ) do @@ -1081,7 +1080,9 @@ begin end else begin while (Result > 1) and (ACount < 0) do begin dec(Result); - if (ALine[Result] in [#0..#127, #192..#255]) and (not LogicPosIsCombining(ALine, Result)) then + if (Result > l) or + ( (ALine[Result] in [#0..#127, #192..#255]) and (not LogicPosIsCombining(ALine, Result)) ) + then inc(ACount); end; end; diff --git a/components/synedit/test/testnavigation.pas b/components/synedit/test/testnavigation.pas index 4a26030daf..918d831909 100644 --- a/components/synedit/test/testnavigation.pas +++ b/components/synedit/test/testnavigation.pas @@ -558,7 +558,7 @@ procedure TTestSynNavigation.TestCaretLeftRight; end; -begin +begin // TODO EOL/BOL at first/last (visible) line (with folding) SetTextLeftRight; {%region ecRight}