SynEdit: Use logical pos to mark selection (column mode shows fragmented start/end on double width char)

git-svn-id: trunk@62606 -
This commit is contained in:
martin 2020-02-03 20:23:57 +00:00
parent d5d2ef28f5
commit 0fbdea80f8
2 changed files with 116 additions and 41 deletions

View File

@ -27,7 +27,7 @@ interface
uses uses
Classes, SysUtils, Graphics, Controls, LCLProc, Classes, SysUtils, Graphics, Controls, LCLProc,
SynEditMarkup, SynEditMiscClasses, SynEditPointClasses; SynEditMarkup, SynEditMiscClasses, SynEditPointClasses, SynEditMiscProcs;
type type
@ -150,22 +150,24 @@ begin
nSelStart := 1; nSelStart := 1;
nSelEnd := -1; // line end nSelEnd := -1; // line end
if (FSelection.ActiveSelectionMode = smColumn) then begin if (FSelection.ActiveSelectionMode = smColumn) then begin
p1 := LogicalToPhysicalPos(p1); nSelStart := FSelection.ColumnStartBytePos[aRow];
p2 := LogicalToPhysicalPos(p2); nSelEnd := FSelection.ColumnEndBytePos[aRow];
if (p1.X < p2.X) then begin //p1 := LogicalToPhysicalPos(p1);
nSelStart := p1.X; //p2 := LogicalToPhysicalPos(p2);
nSelEnd := p2.X; //if (p1.X < p2.X) then begin
end else begin // nSelStart := p1.X;
nSelStart := p2.X; // nSelEnd := p2.X;
nSelEnd := p1.X; //end else begin
end; // nSelStart := p2.X;
// nSelEnd := p1.X;
//end;
end else if (FSelection.ActiveSelectionMode = smNormal) then begin end else if (FSelection.ActiveSelectionMode = smNormal) then begin
if p1.y = aRow then begin if p1.y = aRow then begin
p1 := LogicalToPhysicalPos(p1); // p1 := LogicalToPhysicalPos(p1);
nSelStart := p1.x; nSelStart := p1.x;
end; end;
if p2.y = aRow then begin if p2.y = aRow then begin
p2 := LogicalToPhysicalPos(p2); // p2 := LogicalToPhysicalPos(p2);
nSelEnd := p2.x; nSelEnd := p2.x;
end; end;
@ -173,7 +175,7 @@ begin
if FColorTillEol then begin if FColorTillEol then begin
p2.x := Length(Lines[aRow-1]) + 1; p2.x := Length(Lines[aRow-1]) + 1;
p2.y := aRow; p2.y := aRow;
p2 := LogicalToPhysicalPos(p2); // p2 := LogicalToPhysicalPos(p2);
if (nSelEnd = -1) then if (nSelEnd = -1) then
Inc(p2.x, 1); Inc(p2.x, 1);
@ -190,20 +192,24 @@ function TSynEditMarkupSelection.GetMarkupAttributeAtRowCol(const aRow: Integer;
const aStartCol: TLazSynDisplayTokenBound; const AnRtlInfo: TLazSynDisplayRtlInfo): TSynSelectedColor; const aStartCol: TLazSynDisplayTokenBound; const AnRtlInfo: TLazSynDisplayRtlInfo): TSynSelectedColor;
begin begin
result := nil; result := nil;
if AnRtlInfo.IsRtl then begin
if ( ((nSelStart >= aStartCol.Physical) and (nSelStart < AnRtlInfo.PhysRight) ) or if (nSelStart <= aStartCol.Logical) and ((nSelEnd > aStartCol.Logical) or (nSelEnd < 0)) then
(nSelStart <= AnRtlInfo.PhysLeft) Result := MarkupInfo;
) and
( ((nSelEnd < aStartCol.Physical) and (nSelEnd > AnRtlInfo.PhysLeft)) or //if AnRtlInfo.IsRtl then begin
(nSelEnd >= AnRtlInfo.PhysRight) or (nSelEnd < 0)) // if ( ((nSelStart >= aStartCol.Physical) and (nSelStart < AnRtlInfo.PhysRight) ) or
then // (nSelStart <= AnRtlInfo.PhysLeft)
Result := MarkupInfo; // ) and
end else begin // ( ((nSelEnd < aStartCol.Physical) and (nSelEnd > AnRtlInfo.PhysLeft)) or
if (nSelStart <= aStartCol.Physical) and // (nSelEnd >= AnRtlInfo.PhysRight) or (nSelEnd < 0))
((nSelEnd > aStartCol.Physical) or (nSelEnd < 0)) // then
then // Result := MarkupInfo;
Result := MarkupInfo; //end else begin
end; // if (nSelStart <= aStartCol.Physical) and
// ((nSelEnd > aStartCol.Physical) or (nSelEnd < 0))
// then
// Result := MarkupInfo;
//end;
end; end;
procedure TSynEditMarkupSelection.GetNextMarkupColAfterRowCol(const aRow: Integer; procedure TSynEditMarkupSelection.GetNextMarkupColAfterRowCol(const aRow: Integer;
@ -212,20 +218,27 @@ procedure TSynEditMarkupSelection.GetNextMarkupColAfterRowCol(const aRow: Intege
begin begin
ANextLog := -1; ANextLog := -1;
ANextPhys := -1; ANextPhys := -1;
if AnRtlInfo.IsRtl then begin
if (nSelStart < aStartCol.Physical) then if nSelStart > aStartCol.Logical then
ANextPhys := nSelStart; ANextLog := nSelStart
if (nSelEnd < aStartCol.Physical) and (nSelEnd > 0) and else
( (nSelStart >= aStartCol.Physical) or if nSelEnd > aStartCol.Logical then
((nSelStart <= AnRtlInfo.PhysLeft) and (nSelStart > 0)) ) ANextLog := nSelEnd;
then
ANextPhys := nSelEnd; //if AnRtlInfo.IsRtl then begin
end else begin // if (nSelStart < aStartCol.Physical) then
if (nSelStart > aStartCol.Physical) then // ANextPhys := nSelStart;
ANextPhys := nSelStart; // if (nSelEnd < aStartCol.Physical) and (nSelEnd > 0) and
if (nSelEnd > aStartCol.Physical) and (nSelStart <= aStartCol.Physical) then // ( (nSelStart >= aStartCol.Physical) or
ANextPhys := nSelEnd; // ((nSelStart <= AnRtlInfo.PhysLeft) and (nSelStart > 0)) )
end; // 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;
end. end.

View File

@ -121,6 +121,8 @@ type
FAltStartLinePos, FAltStartBytePos: Integer; // 1 based // Alternate, for min selection FAltStartLinePos, FAltStartBytePos: Integer; // 1 based // Alternate, for min selection
FEndLinePos: Integer; // 1 based FEndLinePos: Integer; // 1 based
FEndBytePos: Integer; // 1 based FEndBytePos: Integer; // 1 based
FLeftCharPos: Integer;
FRightCharPos: Integer;
FPersistent: Boolean; FPersistent: Boolean;
FPersistentLock, FWeakPersistentIdx, FStrongPersistentIdx: Integer; FPersistentLock, FWeakPersistentIdx, FStrongPersistentIdx: Integer;
FIgnoreNextCaretMove: Boolean; FIgnoreNextCaretMove: Boolean;
@ -131,9 +133,13 @@ type
FLastCarePos: TPoint; FLastCarePos: TPoint;
FStickyAutoExtend: Boolean; FStickyAutoExtend: Boolean;
function AdjustBytePosToCharacterStart(Line: integer; BytePos: integer): integer; function AdjustBytePosToCharacterStart(Line: integer; BytePos: integer): integer;
function GetColumnEndBytePos(ALinePos: Integer): integer;
function GetColumnStartBytePos(ALinePos: Integer): integer;
function GetFirstLineBytePos: TPoint; function GetFirstLineBytePos: TPoint;
function GetLastLineBytePos: TPoint; function GetLastLineBytePos: TPoint;
function GetLastLineHasSelection: Boolean; function GetLastLineHasSelection: Boolean;
function GetColumnLeftCharPos: Integer;
function GetColumnRightCharPos: Integer;
procedure SetAutoExtend(AValue: Boolean); procedure SetAutoExtend(AValue: Boolean);
procedure SetCaret(const AValue: TSynEditCaret); procedure SetCaret(const AValue: TSynEditCaret);
procedure SetEnabled(const Value : Boolean); procedure SetEnabled(const Value : Boolean);
@ -197,6 +203,12 @@ type
// First and Last Pos are ordered according to the text flow (LTR) // First and Last Pos are ordered according to the text flow (LTR)
property FirstLineBytePos: TPoint read GetFirstLineBytePos; property FirstLineBytePos: TPoint read GetFirstLineBytePos;
property LastLineBytePos: TPoint read GetLastLineBytePos; 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 LastLineHasSelection: Boolean read GetLastLineHasSelection;
property InvalidateLinesMethod : TInvalidateLines write FInvalidateLinesMethod; property InvalidateLinesMethod : TInvalidateLines write FInvalidateLinesMethod;
property Caret: TSynEditCaret read FCaret write SetCaret; property Caret: TSynEditCaret read FCaret write SetCaret;
@ -1858,6 +1870,8 @@ procedure TSynEditSelection.DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBy
var var
empty, back: Boolean; empty, back: Boolean;
begin begin
FLeftCharPos := -1;
FRightCharPos := -1;
if FIsSettingText then exit; if FIsSettingText then exit;
if FPersistent or (FPersistentLock > 0) or if FPersistent or (FPersistentLock > 0) or
((FCaret <> nil) and (not FCaret.Locked)) ((FCaret <> nil) and (not FCaret.Locked))
@ -2232,6 +2246,8 @@ begin
FStickyAutoExtend := False; FStickyAutoExtend := False;
FAltStartLinePos := -1; FAltStartLinePos := -1;
FAltStartBytePos := -1; FAltStartBytePos := -1;
FLeftCharPos := -1;
FRightCharPos := -1;
WasAvail := SelAvail; WasAvail := SelAvail;
ConstrainStartLineBytePos(Value); ConstrainStartLineBytePos(Value);
@ -2262,6 +2278,8 @@ end;
procedure TSynEditSelection.AdjustStartLineBytePos(Value: TPoint); procedure TSynEditSelection.AdjustStartLineBytePos(Value: TPoint);
begin begin
FLeftCharPos := -1;
FRightCharPos := -1;
if FEnabled then begin if FEnabled then begin
ConstrainStartLineBytePos(Value); ConstrainStartLineBytePos(Value);
@ -2294,6 +2312,8 @@ var
s: string; s: string;
{$ENDIF} {$ENDIF}
begin begin
FLeftCharPos := -1;
FRightCharPos := -1;
if FEnabled then begin if FEnabled then begin
FStickyAutoExtend := False; FStickyAutoExtend := False;
@ -2424,6 +2444,20 @@ begin
if Result <> BytePos then debugln(['Selection needed byte adjustment Line=', Line, ' BytePos=', BytePos, ' Result=', Result]); if Result <> BytePos then debugln(['Selection needed byte adjustment Line=', Line, ' BytePos=', BytePos, ' Result=', Result]);
end; 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; function TSynEditSelection.GetFirstLineBytePos: TPoint;
begin begin
if IsBackwardSel then if IsBackwardSel then
@ -2445,6 +2479,34 @@ begin
Result := (LastLineBytePos.x > 1) or ((FActiveSelectionMode = smLine) and FForceSingleLineSelected); Result := (LastLineBytePos.x > 1) or ((FActiveSelectionMode = smLine) and FForceSingleLineSelected);
end; 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); procedure TSynEditSelection.SetAutoExtend(AValue: Boolean);
begin begin
if FAutoExtend = AValue then Exit; if FAutoExtend = AValue then Exit;