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
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.

View File

@ -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;