SYnEdit: multi caret, paint - started keep caret-x / lock trim-space

git-svn-id: trunk@48283 -
This commit is contained in:
martin 2015-03-12 02:38:21 +00:00
parent 5e1973260e
commit 192eb7981a
2 changed files with 138 additions and 31 deletions

View File

@ -340,6 +340,7 @@ type
property SkipTabs: Boolean read FSkipTabs write SetSkipTabs; property SkipTabs: Boolean read FSkipTabs write SetSkipTabs;
property AllowPastEOL: Boolean read FAllowPastEOL write SetAllowPastEOL; property AllowPastEOL: Boolean read FAllowPastEOL write SetAllowPastEOL;
property KeepCaretX: Boolean read FKeepCaretX write SetKeepCaretX; property KeepCaretX: Boolean read FKeepCaretX write SetKeepCaretX;
property KeepCaretXPos: Integer read FLastCharPos write FLastCharPos;
property MaxLeftChar: TMaxLeftCharFunc read FMaxLeftChar write FMaxLeftChar; property MaxLeftChar: TMaxLeftCharFunc read FMaxLeftChar write FMaxLeftChar;
end; end;

View File

@ -14,7 +14,7 @@ interface
uses uses
Classes, SysUtils, SynEdit, SynEditPointClasses, SynEditKeyCmds, SynEditTypes, Classes, SysUtils, SynEdit, SynEditPointClasses, SynEditKeyCmds, SynEditTypes,
LazSynTextArea, SynEditMiscProcs, LazSynEditText, SynEditMiscClasses, SynEditMouseCmds, LazSynTextArea, SynEditMiscProcs, LazSynEditText, SynEditMiscClasses, SynEditMouseCmds,
SynEditStrConst, SynEditStrConst, SynEditTextTrimmer,
{$IfDef SynMultiCaretDebug} LazLoggerBase, {$ELSE} LazLoggerDummy, {$ENDIF} {$IfDef SynMultiCaretDebug} LazLoggerBase, {$ELSE} LazLoggerDummy, {$ENDIF}
LCLType, Controls, Graphics, Clipbrd; LCLType, Controls, Graphics, Clipbrd;
@ -97,6 +97,7 @@ type
function FindEqOrNextCaretRawIdx(X, Y, Offs: Integer; LowIdx: integer = -1; HighIdx: integer = -1): Integer; function FindEqOrNextCaretRawIdx(X, Y, Offs: Integer; LowIdx: integer = -1; HighIdx: integer = -1): Integer;
function GetCaret(Index: Integer): TPoint; inline; function GetCaret(Index: Integer): TPoint; inline;
function GetCaretFull(Index: Integer): TLogCaretPoint; inline; function GetCaretFull(Index: Integer): TLogCaretPoint; inline;
function GetCaretKeepX(Index: Integer): Integer; inline;
function GetCaretOffs(Index: Integer): Integer; inline; function GetCaretOffs(Index: Integer): Integer; inline;
function GetCaretX(Index: Integer): Integer; inline; function GetCaretX(Index: Integer): Integer; inline;
function GetCaretY(Index: Integer): Integer; inline; function GetCaretY(Index: Integer): Integer; inline;
@ -105,6 +106,7 @@ type
function GetVisual(Index: Integer): TSynPluginMultiCaretVisual; inline; function GetVisual(Index: Integer): TSynPluginMultiCaretVisual; inline;
procedure SetCaret(Index: Integer; AValue: TPoint); inline; procedure SetCaret(Index: Integer; AValue: TPoint); inline;
procedure SetCaretFull(Index: Integer; AValue: TLogCaretPoint); inline; procedure SetCaretFull(Index: Integer; AValue: TLogCaretPoint); inline;
procedure SetCaretKeepX(Index: Integer; AValue: Integer); inline;
procedure SetCaretOffs(Index: Integer; AValue: Integer); inline; procedure SetCaretOffs(Index: Integer; AValue: Integer); inline;
procedure SetCaretX(Index: Integer; AValue: Integer); inline; procedure SetCaretX(Index: Integer; AValue: Integer); inline;
procedure SetCaretY(Index: Integer; AValue: Integer); inline; procedure SetCaretY(Index: Integer; AValue: Integer); inline;
@ -115,7 +117,7 @@ type
procedure AdjustAfterChange(RawIndex: Integer); procedure AdjustAfterChange(RawIndex: Integer);
public public
constructor Create; constructor Create;
function AddCaret(X, Y, Offs: Integer; flags: TCaretFlags = []): Integer; function AddCaret(X, Y, Offs: Integer; flags: TCaretFlags = []; PhysX: Integer = -1): Integer;
procedure RemoveCaret(Index: Integer); procedure RemoveCaret(Index: Integer);
procedure Clear(AFreeVisual: Boolean = False); procedure Clear(AFreeVisual: Boolean = False);
function Count: Integer; function Count: Integer;
@ -130,6 +132,7 @@ type
property CaretFull[Index: Integer]: TLogCaretPoint read GetCaretFull write SetCaretFull; property CaretFull[Index: Integer]: TLogCaretPoint read GetCaretFull write SetCaretFull;
property CaretX[Index: Integer]: Integer read GetCaretX write SetCaretX; property CaretX[Index: Integer]: Integer read GetCaretX write SetCaretX;
property CaretOffs[Index: Integer]: Integer read GetCaretOffs write SetCaretOffs; property CaretOffs[Index: Integer]: Integer read GetCaretOffs write SetCaretOffs;
property CaretKeepX[Index: Integer]: Integer read GetCaretKeepX write SetCaretKeepX;
property CaretY[Index: Integer]: Integer read GetCaretY write SetCaretY; property CaretY[Index: Integer]: Integer read GetCaretY write SetCaretY;
property Visual[Index: Integer]: TSynPluginMultiCaretVisual read GetVisual write SetVisual; property Visual[Index: Integer]: TSynPluginMultiCaretVisual read GetVisual write SetVisual;
property Flags[Index: Integer]: TCaretFlags read GetFlags; property Flags[Index: Integer]: TCaretFlags read GetFlags;
@ -173,7 +176,7 @@ type
function CreateVisual: TSynPluginMultiCaretVisual; virtual; function CreateVisual: TSynPluginMultiCaretVisual; virtual;
function GetVisual: TSynPluginMultiCaretVisual; function GetVisual: TSynPluginMultiCaretVisual;
protected protected
function AddCaret(X, Y, Offs: Integer; flags: TCaretFlags = []): Integer; function AddCaret(X, Y, Offs: Integer; flags: TCaretFlags = []; PhysX: Integer = -1): Integer;
procedure RemoveCaret(Index: Integer); procedure RemoveCaret(Index: Integer);
procedure UpdateCaretsPos; procedure UpdateCaretsPos;
procedure ClearCarets; procedure ClearCarets;
@ -238,12 +241,16 @@ type
FMouseActions: TSynPluginMultiCaretMouseActions; FMouseActions: TSynPluginMultiCaretMouseActions;
FSelY1, FSelY2, FSelX: Integer; FSelY1, FSelY2, FSelX: Integer;
FColSelDoneY1, FColSelDoneY2, FColSelDonePhysX: Integer; FColSelDoneY1, FColSelDoneY2, FColSelDonePhysX: Integer;
FSpaceTrimmerLocked: Boolean;
procedure RemoveCaretsInSelection; procedure RemoveCaretsInSelection;
procedure SetActiveMode(AValue: TSynPluginMultiCaretMode); procedure SetActiveMode(AValue: TSynPluginMultiCaretMode);
procedure SetDefaultColumnSelectMode(AValue: TSynPluginMultiCaretDefaultMode); procedure SetDefaultColumnSelectMode(AValue: TSynPluginMultiCaretDefaultMode);
procedure SetDefaultMode(AValue: TSynPluginMultiCaretDefaultMode); procedure SetDefaultMode(AValue: TSynPluginMultiCaretDefaultMode);
procedure SetSkipCaretAtSel; procedure SetSkipCaretAtSel;
procedure LockSpaceTrimmer; // Todo: per line lock / reverse: trimmer should ask / add event for trimmer via caretObj
procedure UnLockSpaceTrimmer;
protected protected
function LogPhysConvertor: TSynLogicalPhysicalConvertor; inline; function LogPhysConvertor: TSynLogicalPhysicalConvertor; inline;
function PhysicalToLogical(AIndex, AColumn: Integer; out AColOffset: Integer; function PhysicalToLogical(AIndex, AColumn: Integer; out AColOffset: Integer;
@ -488,7 +495,8 @@ end;
function TSynPluginMultiCaretList.FindEqOrNextCaretRawIdx(X, Y, Offs: Integer; function TSynPluginMultiCaretList.FindEqOrNextCaretRawIdx(X, Y, Offs: Integer;
LowIdx: integer; HighIdx: integer): Integer; LowIdx: integer; HighIdx: integer): Integer;
var var
l, h: Integer; l, h: integer;
cp: ^TCaretData;
begin begin
if LowIdx < 0 if LowIdx < 0
then l := FLowIndex then l := FLowIndex
@ -503,6 +511,30 @@ begin
end; end;
Result := (l + h) div 2; Result := (l + h) div 2;
// FPC does not optimize the repeated array access
while (h > l) do begin
cp := @FCarets[Result];
if (cp^.y > y) or
( (cp^.y = y) and
( (cp^.x > x) or
((cp^.x = x) and (cp^.offs >= Offs))
)
)
then
h := Result
else
l := Result + 1;
Result := cardinal(l + h) div 2;
end;
cp := @FCarets[Result];
if (cp^.y < y) or
( (cp^.y = y) and
(cp^.x < x) or
((cp^.x = x) and (cp^.offs < Offs))
)
then
inc(Result);
(*
while (h > l) do begin while (h > l) do begin
if (FCarets[Result].y > y) or if (FCarets[Result].y > y) or
( (FCarets[Result].y = y) and ( (FCarets[Result].y = y) and
@ -523,6 +555,7 @@ begin
) )
then then
inc(Result); inc(Result);
//*)
end; end;
function TSynPluginMultiCaretList.GetCaret(Index: Integer): TPoint; function TSynPluginMultiCaretList.GetCaret(Index: Integer): TPoint;
@ -542,6 +575,13 @@ begin
Result.Offs := FCarets[Index].offs; Result.Offs := FCarets[Index].offs;
end; end;
function TSynPluginMultiCaretList.GetCaretKeepX(Index: Integer): Integer;
begin
Index := Index + FLowIndex;
assert((Index>=FLowIndex) and (Index <= FHighIndex), 'TSynPluginMultiCaretList.GetCaretX: (Index>=FLowIndex) and (Index <= FHighIndex)');
Result := FCarets[Index].KeepX;
end;
function TSynPluginMultiCaretList.GetCaretOffs(Index: Integer): Integer; function TSynPluginMultiCaretList.GetCaretOffs(Index: Integer): Integer;
begin begin
Index := Index + FLowIndex; Index := Index + FLowIndex;
@ -607,6 +647,14 @@ begin
AdjustAfterChange(Index); AdjustAfterChange(Index);
end; end;
procedure TSynPluginMultiCaretList.SetCaretKeepX(Index: Integer; AValue: Integer);
begin
Index := Index + FLowIndex;
assert((Index>=FLowIndex) and (Index <= FHighIndex), 'TSynPluginMultiCaretList.SetCaretX: (Index>=FLowIndex) and (Index <= FHighIndex)');
//if FCarets[Index].KeepX = AValue then exit;
FCarets[Index].KeepX := AValue;
end;
procedure TSynPluginMultiCaretList.SetCaretOffs(Index: Integer; AValue: Integer); procedure TSynPluginMultiCaretList.SetCaretOffs(Index: Integer; AValue: Integer);
begin begin
Index := Index + FLowIndex; Index := Index + FLowIndex;
@ -747,7 +795,8 @@ begin
FMainCaretIndex := -1; FMainCaretIndex := -1;
end; end;
function TSynPluginMultiCaretList.AddCaret(X, Y, Offs: Integer; flags: TCaretFlags): Integer; function TSynPluginMultiCaretList.AddCaret(X, Y, Offs: Integer; flags: TCaretFlags;
PhysX: Integer): Integer;
var var
NewCarets: Array of TCaretData; NewCarets: Array of TCaretData;
Len, AddLen, i, Middle: Integer; Len, AddLen, i, Middle: Integer;
@ -761,6 +810,7 @@ begin
FCarets[Result].Flags := flags - [cfMainCaret]; FCarets[Result].Flags := flags - [cfMainCaret];
if cfMainCaret in flags then if cfMainCaret in flags then
FMainCaretIndex := Result; FMainCaretIndex := Result;
// TODO maybe update PhysX;
Result := Result - FLowIndex; Result := Result - FLowIndex;
exit; exit;
end; end;
@ -820,6 +870,7 @@ begin
FCarets[Result].x := x; FCarets[Result].x := x;
FCarets[Result].offs := Offs; FCarets[Result].offs := Offs;
FCarets[Result].y := y; FCarets[Result].y := y;
FCarets[Result].KeepX := PhysX;
FCarets[Result].Visual := nil; FCarets[Result].Visual := nil;
FCarets[Result].Flags := flags - [cfMainCaret, cfAddDuplicate]; FCarets[Result].Flags := flags - [cfMainCaret, cfAddDuplicate];
@ -1206,11 +1257,12 @@ begin
Result := TLazSynSurfaceManager(PaintArea).TextArea; Result := TLazSynSurfaceManager(PaintArea).TextArea;
end; end;
function TSynPluginMultiCaretBase.AddCaret(X, Y, Offs: Integer; flags: TCaretFlags): Integer; function TSynPluginMultiCaretBase.AddCaret(X, Y, Offs: Integer; flags: TCaretFlags;
PhysX: Integer): Integer;
var var
y1, y2: Integer; y1, y2: Integer;
begin begin
Result := Carets.AddCaret(x,y, Offs, flags); Result := Carets.AddCaret(x,y, Offs, flags, PhysX);
if cfNoneVisual in flags then if cfNoneVisual in flags then
exit; exit;
@ -1473,8 +1525,12 @@ procedure TSynCustomPluginMultiCaret.SetActiveMode(AValue: TSynPluginMultiCaretM
begin begin
if FActiveMode = AValue then Exit; if FActiveMode = AValue then Exit;
FActiveMode := AValue; FActiveMode := AValue;
if FActiveMode = mcmNoCarets then if FActiveMode = mcmNoCarets then begin
ClearCarets; ClearCarets;
UnLockSpaceTrimmer;
end
else
LockSpaceTrimmer;
end; end;
procedure TSynCustomPluginMultiCaret.SetDefaultColumnSelectMode(AValue: TSynPluginMultiCaretDefaultMode); procedure TSynCustomPluginMultiCaret.SetDefaultColumnSelectMode(AValue: TSynPluginMultiCaretDefaultMode);
@ -1497,6 +1553,38 @@ begin
FSelX := SelectionObj.FirstLineBytePos.x; FSelX := SelectionObj.FirstLineBytePos.x;
end; end;
procedure TSynCustomPluginMultiCaret.LockSpaceTrimmer;
var
b: TSynEditStrings;
begin
if FSpaceTrimmerLocked then exit;
FSpaceTrimmerLocked := True;
b := ViewedTextBuffer;
while b <> nil do begin
if b is TSynEditStringTrimmingList then TSynEditStringTrimmingList(b).Lock;
if b is TSynEditStringsLinked then
b := TSynEditStringsLinked(b).NextLines
else
b := nil;
end;
end;
procedure TSynCustomPluginMultiCaret.UnLockSpaceTrimmer;
var
b: TSynEditStrings;
begin
if not FSpaceTrimmerLocked then exit;
FSpaceTrimmerLocked := False;
b := ViewedTextBuffer;
while b <> nil do begin
if b is TSynEditStringTrimmingList then TSynEditStringTrimmingList(b).UnLock;
if b is TSynEditStringsLinked then
b := TSynEditStringsLinked(b).NextLines
else
b := nil;
end;
end;
function TSynCustomPluginMultiCaret.LogPhysConvertor: TSynLogicalPhysicalConvertor; function TSynCustomPluginMultiCaret.LogPhysConvertor: TSynLogicalPhysicalConvertor;
begin begin
Result := ViewedTextBuffer.LogPhysConvertor; Result := ViewedTextBuffer.LogPhysConvertor;
@ -1563,7 +1651,7 @@ end;
procedure TSynCustomPluginMultiCaret.DoCleared; procedure TSynCustomPluginMultiCaret.DoCleared;
begin begin
inherited DoCleared; inherited DoCleared;
FActiveMode := mcmNoCarets; ActiveMode := mcmNoCarets;
Exclude(FStateFlags, sfCreateCaretAtCurrentPos); Exclude(FStateFlags, sfCreateCaretAtCurrentPos);
FColSelDoneY1 := -1; FColSelDoneY1 := -1;
FColSelDoneY2 := -2; FColSelDoneY2 := -2;
@ -1588,7 +1676,7 @@ begin
exit; exit;
end; end;
if (FStateFlags * [sfProcessingCmd, sfExtendingColumnSel] <> []) or if (FStateFlags * [sfProcessingCmd, sfExtendingColumnSel] <> []) or
(FActiveMode = mcmAddingCarets) (ActiveMode = mcmAddingCarets)
then then
exit; exit;
@ -1611,7 +1699,7 @@ procedure TSynCustomPluginMultiCaret.DoSelectionChanged(Sender: TObject);
CurCar := Carets.CaretFull[i]; CurCar := Carets.CaretFull[i];
end; end;
if (CurCar.x <> XLog) or (CurCar.Offs <> Offs) or (CurCar.y <> StartY) then if (CurCar.x <> XLog) or (CurCar.Offs <> Offs) or (CurCar.y <> StartY) then
AddCaret(XLog, StartY, Offs); // TODO: pass "i-1" as KnowIndexOfCaretBefore (limit bin search) AddCaret(XLog, StartY, Offs, [], PhysX); // TODO: pass "i-1" as KnowIndexOfCaretBefore (limit bin search)
inc(StartY); inc(StartY);
end; end;
end; end;
@ -1682,6 +1770,7 @@ begin
if (CurCaret.X = XLog) and (CurCaret.Offs = Offs) then begin if (CurCaret.X = XLog) and (CurCaret.Offs = Offs) then begin
CurCaret.X := PhysicalToLogical(ToIdx(CurCaret.Y), XPhys, CurCaret.Offs); CurCaret.X := PhysicalToLogical(ToIdx(CurCaret.Y), XPhys, CurCaret.Offs);
Carets.CaretFull[i] := CurCaret; Carets.CaretFull[i] := CurCaret;
Carets.CaretKeepX[i] := XPhys;
end; end;
inc(i); inc(i);
if i >= CaretsCount then if i >= CaretsCount then
@ -1719,8 +1808,8 @@ begin
if i >= 0 then if i >= 0 then
Carets.RemoveCaret(i); Carets.RemoveCaret(i);
if FActiveMode = mcmNoCarets then if ActiveMode = mcmNoCarets then
FActiveMode := DefaultColumnSelectMode; ActiveMode := DefaultColumnSelectMode;
end; end;
procedure TSynCustomPluginMultiCaret.DoBeforeSetSelText(Sender: TObject; AMode: TSynSelectionMode; procedure TSynCustomPluginMultiCaret.DoBeforeSetSelText(Sender: TObject; AMode: TSynSelectionMode;
@ -1752,14 +1841,14 @@ begin
ecPluginMultiCaretSetCaret: begin ecPluginMultiCaretSetCaret: begin
if Carets.FindCaretIdx(CaretObj.BytePos, CaretObj.LinePos, CaretObj.BytePosOffset) < 0 then if Carets.FindCaretIdx(CaretObj.BytePos, CaretObj.LinePos, CaretObj.BytePosOffset) < 0 then
include(FStateFlags, sfCreateCaretAtCurrentPos); include(FStateFlags, sfCreateCaretAtCurrentPos);
FActiveMode := mcmAddingCarets; ActiveMode := mcmAddingCarets;
end; end;
ecPluginMultiCaretUnsetCaret: begin ecPluginMultiCaretUnsetCaret: begin
exclude(FStateFlags, sfCreateCaretAtCurrentPos); exclude(FStateFlags, sfCreateCaretAtCurrentPos);
i := Carets.FindCaretIdx(CaretObj.BytePos, CaretObj.LinePos, CaretObj.BytePosOffset); i := Carets.FindCaretIdx(CaretObj.BytePos, CaretObj.LinePos, CaretObj.BytePosOffset);
if i >= 0 then if i >= 0 then
RemoveCaret(i); RemoveCaret(i);
FActiveMode := mcmAddingCarets; ActiveMode := mcmAddingCarets;
end; end;
ecPluginMultiCaretToggleCaret: begin ecPluginMultiCaretToggleCaret: begin
i := Carets.FindCaretIdx(CaretObj.BytePos, CaretObj.LinePos, CaretObj.BytePosOffset); i := Carets.FindCaretIdx(CaretObj.BytePos, CaretObj.LinePos, CaretObj.BytePosOffset);
@ -1771,7 +1860,7 @@ begin
else begin else begin
include(FStateFlags, sfCreateCaretAtCurrentPos); include(FStateFlags, sfCreateCaretAtCurrentPos);
end; end;
FActiveMode := mcmAddingCarets; ActiveMode := mcmAddingCarets;
end; end;
ecPluginMultiCaretClearAll: begin ecPluginMultiCaretClearAll: begin
ClearCarets; ClearCarets;
@ -1779,8 +1868,8 @@ begin
SelectionObj.Clear; // clear invisibel selection SelectionObj.Clear; // clear invisibel selection
end; end;
ecPluginMultiCaretModeCancelOnMove: FActiveMode := mcmCancelOnCaretMove; ecPluginMultiCaretModeCancelOnMove: ActiveMode := mcmCancelOnCaretMove;
ecPluginMultiCaretModeMoveAll: FActiveMode := mcmMoveAllCarets; ecPluginMultiCaretModeMoveAll: ActiveMode := mcmMoveAllCarets;
else else
Handled := False; Handled := False;
end; end;
@ -1793,12 +1882,13 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
procedure ExecCommandRepeated; procedure ExecCommandRepeated;
var var
c, i, y: Integer; c, i, y: Integer;
p: TPoint; p: TLogCaretPoint;
begin begin
Handled := True; Handled := True;
Editor.BeginUpdate(True); Editor.BeginUpdate(True);
try try
c := AddCaret(Editor.LogicalCaretXY.x, Editor.CaretY, CaretObj.BytePosOffset, [cfMainCaret, cfNoneVisual {, cfAddDuplicate}]); c := AddCaret(Editor.LogicalCaretXY.x, Editor.CaretY, CaretObj.BytePosOffset,
[cfMainCaret, cfNoneVisual {, cfAddDuplicate}], CaretObj.KeepCaretXPos);
// Execute Command at current caret pos // Execute Command at current caret pos
Include(FStateFlags, sfProcessingMain); Include(FStateFlags, sfProcessingMain);
@ -1816,7 +1906,7 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
while i > 0 do begin while i > 0 do begin
dec(i); dec(i);
if i = c then continue; if i = c then continue;
p := Carets.Caret[i]; p := Carets.CaretFull[i];
if y > p.y then y := p.y; if y > p.y then y := p.y;
if (sfSkipCaretsAtSelection in FStateFlags) and (y >= FSelY1) and if (sfSkipCaretsAtSelection in FStateFlags) and (y >= FSelY1) and
(y = p.y) and (FSelX = p.x) (y = p.y) and (FSelX = p.x)
@ -1824,13 +1914,19 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
dec(y); dec(y);
continue; continue;
end; end;
Editor.LogicalCaretXY := p; CaretObj.FullLogicalPos := p;
//j := Carets.CaretKeepX[i];
//if j > 0 then
// CaretObj.KeepCaretXPos := j;
Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]); Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]);
Carets.CaretFull[i] := CaretObj.FullLogicalPos;
Carets.CaretKeepX[i] := -1;
end; end;
CaretObj.DecForcePastEOL; CaretObj.DecForcePastEOL;
if Carets.MainCaretIndex >= 0 then begin if Carets.MainCaretIndex >= 0 then begin
CaretObj.FullLogicalPos := Carets.CaretFull[Carets.MainCaretIndex]; CaretObj.FullLogicalPos := Carets.CaretFull[Carets.MainCaretIndex];
//CaretObj.KeepCaretXPos := Carets.CaretKeepX[Carets.MainCaretIndex];
RemoveCaret(Carets.MainCaretIndex); RemoveCaret(Carets.MainCaretIndex);
end end
else else
@ -1842,7 +1938,7 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
procedure ExecCaretMoveRepeated; procedure ExecCaretMoveRepeated;
var var
i,j: Integer; i, j, k, xk: Integer;
c: TLogCaretPoint; c: TLogCaretPoint;
begin begin
Handled := True; Handled := True;
@ -1853,6 +1949,7 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
Include(FStateFlags, sfProcessingMain); Include(FStateFlags, sfProcessingMain);
Editor.CommandProcessor(Command, AChar, data, [hcfInit, hcfFinish]); Editor.CommandProcessor(Command, AChar, data, [hcfInit, hcfFinish]);
c := CaretObj.FullLogicalPos; c := CaretObj.FullLogicalPos;
xk := CaretObj.KeepCaretXPos;
Exclude(FStateFlags, sfProcessingMain); Exclude(FStateFlags, sfProcessingMain);
// Repeat command // Repeat command
@ -1866,8 +1963,12 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
j := CaretsCount; j := CaretsCount;
while i < j do begin while i < j do begin
CaretObj.FullLogicalPos := Carets.CaretFull[i]; CaretObj.FullLogicalPos := Carets.CaretFull[i];
k := Carets.CaretKeepX[i];
if k > 0 then
CaretObj.KeepCaretXPos := k;
Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]); Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]);
Carets.CaretFull[i] := CaretObj.FullLogicalPos; Carets.CaretFull[i] := CaretObj.FullLogicalPos;
Carets.CaretKeepX[i] := CaretObj.KeepCaretXPos;
inc(i); inc(i);
end; end;
end; end;
@ -1878,8 +1979,12 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
while i > 0 do begin while i > 0 do begin
dec(i); dec(i);
CaretObj.FullLogicalPos := Carets.CaretFull[i]; CaretObj.FullLogicalPos := Carets.CaretFull[i];
k := Carets.CaretKeepX[i];
if k > 0 then
CaretObj.KeepCaretXPos := k;
Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]); Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]);
Carets.CaretFull[i] := CaretObj.FullLogicalPos; Carets.CaretFull[i] := CaretObj.FullLogicalPos;
Carets.CaretKeepX[i] := CaretObj.KeepCaretXPos;
end; end;
end; end;
end; end;
@ -1887,6 +1992,7 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
finally finally
FCarets.DecMergeLock; FCarets.DecMergeLock;
CaretObj.FullLogicalPos := c; CaretObj.FullLogicalPos := c;
CaretObj.KeepCaretXPos := xk;
MergeAndRemoveCarets; MergeAndRemoveCarets;
Editor.EndUpdate; Editor.EndUpdate;
end; end;
@ -1895,8 +2001,8 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
procedure StartEditing; procedure StartEditing;
begin begin
Include(FStateFlags, sfProcessingCmd); Include(FStateFlags, sfProcessingCmd);
if (FActiveMode = mcmAddingCarets) and (not Editor.ReadOnly) then if (ActiveMode = mcmAddingCarets) and (not Editor.ReadOnly) then
FActiveMode := DefaultMode; ActiveMode := DefaultMode;
end; end;
var var
@ -1988,12 +2094,12 @@ begin
Include(FStateFlags, sfExtendingColumnSel); Include(FStateFlags, sfExtendingColumnSel);
end; end;
ecLeft..ecHalfWordRight: begin ecLeft..ecHalfWordRight: begin
if FActiveMode = mcmMoveAllCarets then begin if ActiveMode = mcmMoveAllCarets then begin
Include(FStateFlags, sfProcessingCmd); Include(FStateFlags, sfProcessingCmd);
ExecCaretMoveRepeated; ExecCaretMoveRepeated;
end end
else else
if FActiveMode = mcmAddingCarets then if ActiveMode = mcmAddingCarets then
Include(FStateFlags, sfProcessingCmd) Include(FStateFlags, sfProcessingCmd)
else else
ClearCarets; ClearCarets;
@ -2042,9 +2148,9 @@ begin
AddCaret(AnInfo.NewCaret.BytePos, AnInfo.NewCaret.LinePos, AnInfo.NewCaret.BytePosOffset); AddCaret(AnInfo.NewCaret.BytePos, AnInfo.NewCaret.LinePos, AnInfo.NewCaret.BytePosOffset);
end; end;
if CaretsCount > 0 then if CaretsCount > 0 then
FActiveMode := DefaultMode ActiveMode := DefaultMode
else else
FActiveMode := mcmNoCarets; ActiveMode := mcmNoCarets;
exclude(FStateFlags, sfCreateCaretAtCurrentPos); exclude(FStateFlags, sfCreateCaretAtCurrentPos);
end; end;
end; end;
@ -2079,8 +2185,8 @@ end;
procedure TSynCustomPluginMultiCaret.AddCaretAtLogPos(X, Y, Offs: Integer); procedure TSynCustomPluginMultiCaret.AddCaretAtLogPos(X, Y, Offs: Integer);
begin begin
AddCaret(x, y, Offs); AddCaret(x, y, Offs);
if FActiveMode = mcmNoCarets then if ActiveMode = mcmNoCarets then
FActiveMode := FDefaultMode; ActiveMode := FDefaultMode;
end; end;
initialization initialization