From 0fbdea80f80f688256e5c0f9733f85b4dea56356 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 3 Feb 2020 20:23:57 +0000 Subject: [PATCH] SynEdit: Use logical pos to mark selection (column mode shows fragmented start/end on double width char) git-svn-id: trunk@62606 - --- components/synedit/syneditmarkupselection.pp | 95 +++++++++++--------- components/synedit/syneditpointclasses.pas | 62 +++++++++++++ 2 files changed, 116 insertions(+), 41 deletions(-) diff --git a/components/synedit/syneditmarkupselection.pp b/components/synedit/syneditmarkupselection.pp index 5da8514e4a..d4b7b181fe 100644 --- a/components/synedit/syneditmarkupselection.pp +++ b/components/synedit/syneditmarkupselection.pp @@ -27,7 +27,7 @@ interface uses Classes, SysUtils, Graphics, Controls, LCLProc, - SynEditMarkup, SynEditMiscClasses, SynEditPointClasses; + SynEditMarkup, SynEditMiscClasses, SynEditPointClasses, SynEditMiscProcs; type @@ -150,22 +150,24 @@ begin nSelStart := 1; nSelEnd := -1; // line end if (FSelection.ActiveSelectionMode = smColumn) then begin - p1 := LogicalToPhysicalPos(p1); - p2 := LogicalToPhysicalPos(p2); - if (p1.X < p2.X) then begin - nSelStart := p1.X; - nSelEnd := p2.X; - end else begin - nSelStart := p2.X; - nSelEnd := p1.X; - end; + nSelStart := FSelection.ColumnStartBytePos[aRow]; + nSelEnd := FSelection.ColumnEndBytePos[aRow]; + //p1 := LogicalToPhysicalPos(p1); + //p2 := LogicalToPhysicalPos(p2); + //if (p1.X < p2.X) then begin + // nSelStart := p1.X; + // nSelEnd := p2.X; + //end else begin + // nSelStart := p2.X; + // nSelEnd := p1.X; + //end; end else if (FSelection.ActiveSelectionMode = smNormal) then begin if p1.y = aRow then begin - p1 := LogicalToPhysicalPos(p1); +// p1 := LogicalToPhysicalPos(p1); nSelStart := p1.x; end; if p2.y = aRow then begin - p2 := LogicalToPhysicalPos(p2); +// p2 := LogicalToPhysicalPos(p2); nSelEnd := p2.x; end; @@ -173,7 +175,7 @@ begin if FColorTillEol then begin p2.x := Length(Lines[aRow-1]) + 1; p2.y := aRow; - p2 := LogicalToPhysicalPos(p2); +// p2 := LogicalToPhysicalPos(p2); if (nSelEnd = -1) then Inc(p2.x, 1); @@ -190,20 +192,24 @@ function TSynEditMarkupSelection.GetMarkupAttributeAtRowCol(const aRow: Integer; const aStartCol: TLazSynDisplayTokenBound; const AnRtlInfo: TLazSynDisplayRtlInfo): TSynSelectedColor; begin result := nil; - if AnRtlInfo.IsRtl then begin - if ( ((nSelStart >= aStartCol.Physical) and (nSelStart < AnRtlInfo.PhysRight) ) or - (nSelStart <= AnRtlInfo.PhysLeft) - ) and - ( ((nSelEnd < aStartCol.Physical) and (nSelEnd > AnRtlInfo.PhysLeft)) or - (nSelEnd >= AnRtlInfo.PhysRight) or (nSelEnd < 0)) - then - Result := MarkupInfo; - end else begin - if (nSelStart <= aStartCol.Physical) and - ((nSelEnd > aStartCol.Physical) or (nSelEnd < 0)) - then - Result := MarkupInfo; - end; + + if (nSelStart <= aStartCol.Logical) and ((nSelEnd > aStartCol.Logical) or (nSelEnd < 0)) then + Result := MarkupInfo; + + //if AnRtlInfo.IsRtl then begin + // if ( ((nSelStart >= aStartCol.Physical) and (nSelStart < AnRtlInfo.PhysRight) ) or + // (nSelStart <= AnRtlInfo.PhysLeft) + // ) and + // ( ((nSelEnd < aStartCol.Physical) and (nSelEnd > AnRtlInfo.PhysLeft)) or + // (nSelEnd >= AnRtlInfo.PhysRight) or (nSelEnd < 0)) + // then + // Result := MarkupInfo; + //end else begin + // if (nSelStart <= aStartCol.Physical) and + // ((nSelEnd > aStartCol.Physical) or (nSelEnd < 0)) + // then + // Result := MarkupInfo; + //end; end; procedure TSynEditMarkupSelection.GetNextMarkupColAfterRowCol(const aRow: Integer; @@ -212,20 +218,27 @@ procedure TSynEditMarkupSelection.GetNextMarkupColAfterRowCol(const aRow: Intege begin ANextLog := -1; ANextPhys := -1; - if AnRtlInfo.IsRtl then begin - if (nSelStart < aStartCol.Physical) then - ANextPhys := nSelStart; - if (nSelEnd < aStartCol.Physical) and (nSelEnd > 0) and - ( (nSelStart >= aStartCol.Physical) or - ((nSelStart <= AnRtlInfo.PhysLeft) and (nSelStart > 0)) ) - then - ANextPhys := nSelEnd; - end else begin - if (nSelStart > aStartCol.Physical) then - ANextPhys := nSelStart; - if (nSelEnd > aStartCol.Physical) and (nSelStart <= aStartCol.Physical) then - ANextPhys := nSelEnd; - end; + + if nSelStart > aStartCol.Logical then + ANextLog := nSelStart + else + if nSelEnd > aStartCol.Logical then + ANextLog := nSelEnd; + + //if AnRtlInfo.IsRtl then begin + // if (nSelStart < aStartCol.Physical) then + // ANextPhys := nSelStart; + // if (nSelEnd < aStartCol.Physical) and (nSelEnd > 0) and + // ( (nSelStart >= aStartCol.Physical) or + // ((nSelStart <= AnRtlInfo.PhysLeft) and (nSelStart > 0)) ) + // then + // ANextPhys := nSelEnd; + //end else begin + // if (nSelStart > aStartCol.Physical) then + // ANextPhys := nSelStart; + // if (nSelEnd > aStartCol.Physical) and (nSelStart <= aStartCol.Physical) then + // ANextPhys := nSelEnd; + //end; end; end. diff --git a/components/synedit/syneditpointclasses.pas b/components/synedit/syneditpointclasses.pas index bdb89532c1..c96a1fa098 100644 --- a/components/synedit/syneditpointclasses.pas +++ b/components/synedit/syneditpointclasses.pas @@ -121,6 +121,8 @@ type FAltStartLinePos, FAltStartBytePos: Integer; // 1 based // Alternate, for min selection FEndLinePos: Integer; // 1 based FEndBytePos: Integer; // 1 based + FLeftCharPos: Integer; + FRightCharPos: Integer; FPersistent: Boolean; FPersistentLock, FWeakPersistentIdx, FStrongPersistentIdx: Integer; FIgnoreNextCaretMove: Boolean; @@ -131,9 +133,13 @@ type FLastCarePos: TPoint; FStickyAutoExtend: Boolean; function AdjustBytePosToCharacterStart(Line: integer; BytePos: integer): integer; + function GetColumnEndBytePos(ALinePos: Integer): integer; + function GetColumnStartBytePos(ALinePos: Integer): integer; function GetFirstLineBytePos: TPoint; function GetLastLineBytePos: TPoint; function GetLastLineHasSelection: Boolean; + function GetColumnLeftCharPos: Integer; + function GetColumnRightCharPos: Integer; procedure SetAutoExtend(AValue: Boolean); procedure SetCaret(const AValue: TSynEditCaret); procedure SetEnabled(const Value : Boolean); @@ -197,6 +203,12 @@ type // First and Last Pos are ordered according to the text flow (LTR) property FirstLineBytePos: TPoint read GetFirstLineBytePos; property LastLineBytePos: TPoint read GetLastLineBytePos; + // For column mode selection: Phys-Char pos of left and right side. (Start/End could each be either left or right) + property ColumnLeftCharPos: Integer read GetColumnLeftCharPos; + property ColumnRightCharPos: Integer read GetColumnRightCharPos; + property ColumnStartBytePos[ALinePos: Integer]: integer read GetColumnStartBytePos; + property ColumnEndBytePos[ALinePos: Integer]: integer read GetColumnEndBytePos; + // property LastLineHasSelection: Boolean read GetLastLineHasSelection; property InvalidateLinesMethod : TInvalidateLines write FInvalidateLinesMethod; property Caret: TSynEditCaret read FCaret write SetCaret; @@ -1858,6 +1870,8 @@ procedure TSynEditSelection.DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBy var empty, back: Boolean; begin + FLeftCharPos := -1; + FRightCharPos := -1; if FIsSettingText then exit; if FPersistent or (FPersistentLock > 0) or ((FCaret <> nil) and (not FCaret.Locked)) @@ -2232,6 +2246,8 @@ begin FStickyAutoExtend := False; FAltStartLinePos := -1; FAltStartBytePos := -1; + FLeftCharPos := -1; + FRightCharPos := -1; WasAvail := SelAvail; ConstrainStartLineBytePos(Value); @@ -2262,6 +2278,8 @@ end; procedure TSynEditSelection.AdjustStartLineBytePos(Value: TPoint); begin + FLeftCharPos := -1; + FRightCharPos := -1; if FEnabled then begin ConstrainStartLineBytePos(Value); @@ -2294,6 +2312,8 @@ var s: string; {$ENDIF} begin + FLeftCharPos := -1; + FRightCharPos := -1; if FEnabled then begin FStickyAutoExtend := False; @@ -2424,6 +2444,20 @@ begin if Result <> BytePos then debugln(['Selection needed byte adjustment Line=', Line, ' BytePos=', BytePos, ' Result=', Result]); end; +function TSynEditSelection.GetColumnEndBytePos(ALinePos: Integer): integer; +begin + FInternalCaret.Invalidate; + FInternalCaret.LineCharPos := Point(GetColumnRightCharPos, ALinePos); + Result := FInternalCaret.BytePos; +end; + +function TSynEditSelection.GetColumnStartBytePos(ALinePos: Integer): integer; +begin + FInternalCaret.Invalidate; + FInternalCaret.LineCharPos := Point(GetColumnLeftCharPos, ALinePos); + Result := FInternalCaret.BytePos; +end; + function TSynEditSelection.GetFirstLineBytePos: TPoint; begin if IsBackwardSel then @@ -2445,6 +2479,34 @@ begin Result := (LastLineBytePos.x > 1) or ((FActiveSelectionMode = smLine) and FForceSingleLineSelected); end; +function TSynEditSelection.GetColumnLeftCharPos: Integer; +begin + if FLeftCharPos < 0 then begin + FInternalCaret.Invalidate; + FInternalCaret.LineBytePos := FirstLineBytePos; + FLeftCharPos := FInternalCaret.CharPos; + FInternalCaret.LineBytePos := LastLineBytePos; + FRightCharPos := FInternalCaret.CharPos; + if FLeftCharPos > FRightCharPos then + SwapInt(FLeftCharPos, FRightCharPos); + end; + Result := FLeftCharPos; +end; + +function TSynEditSelection.GetColumnRightCharPos: Integer; +begin + if FLeftCharPos < 0 then begin + FInternalCaret.Invalidate; + FInternalCaret.LineBytePos := FirstLineBytePos; + FLeftCharPos := FInternalCaret.CharPos; + FInternalCaret.LineBytePos := LastLineBytePos; + FRightCharPos := FInternalCaret.CharPos; + if FLeftCharPos > FRightCharPos then + SwapInt(FLeftCharPos, FRightCharPos); + end; + Result := FRightCharPos; +end; + procedure TSynEditSelection.SetAutoExtend(AValue: Boolean); begin if FAutoExtend = AValue then Exit;