mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-08 05:37:23 +01:00
SYnEdit: multi caret, IDE integration, and refactor
git-svn-id: trunk@48395 -
This commit is contained in:
parent
6e3dd69f06
commit
5e498c6211
@ -149,8 +149,8 @@ const
|
|||||||
ecColSelEditorBottom = ecEditorBottom + ecColumnSelection;
|
ecColSelEditorBottom = ecEditorBottom + ecColumnSelection;
|
||||||
ecColSelLineTextStart= ecLineTextStart + ecColumnSelection;
|
ecColSelLineTextStart= ecLineTextStart + ecColumnSelection;
|
||||||
|
|
||||||
ecSelColCmdRangeStart = ecLeft + ecColumnSelection;
|
ecSelColCmdRangeStart = ecColumnSelection;
|
||||||
ecSelColCmdRangeEnd = ecLeft + ecColumnSelection + 48; // 1 less for ecSelectAll
|
ecSelColCmdRangeEnd = ecColumnSelection + 48; // 1 less for ecSelectAll
|
||||||
|
|
||||||
|
|
||||||
ecSelectAll = 199; // Select entire contents of editor, cursor to end
|
ecSelectAll = 199; // Select entire contents of editor, cursor to end
|
||||||
|
|||||||
@ -39,6 +39,24 @@ const
|
|||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
TSynMultiCaretCommandAction = (
|
||||||
|
ccaDefaultAction, // build in default, if any
|
||||||
|
ccaNoneRepeatCommand, // Run Command (onc), clear carets IF any changes (text,selection,main-caret)
|
||||||
|
ccaRepeatCommand, // Repeat the command for each caret
|
||||||
|
ccaRepeatCommandPerLine, // Repeat the command for the first caret on each line
|
||||||
|
ccaClearCarets, // Always Clear all carets
|
||||||
|
ccaAdjustCarets // Run the command once (for main-caret), keep and adjust all carets
|
||||||
|
);
|
||||||
|
TSynMultiCaretCommandFlag = ( // for extension
|
||||||
|
ccfDummy // do not use
|
||||||
|
);
|
||||||
|
TSynMultiCaretCommandFlags = set of TSynMultiCaretCommandFlag;
|
||||||
|
|
||||||
|
TSynMultiCaretBeforeCommand = procedure(Sender: TObject;
|
||||||
|
ACommand: TSynEditorCommand;
|
||||||
|
var AnAction: TSynMultiCaretCommandAction;
|
||||||
|
var AFlags: TSynMultiCaretCommandFlags) of object;
|
||||||
|
|
||||||
TLogCaretPointArray = Array of TLogCaretPoint;
|
TLogCaretPointArray = Array of TLogCaretPoint;
|
||||||
TSynPluginMultiCaretVisualList = class;
|
TSynPluginMultiCaretVisualList = class;
|
||||||
|
|
||||||
@ -151,6 +169,7 @@ type
|
|||||||
FIterationDoneCount: Integer;
|
FIterationDoneCount: Integer;
|
||||||
FLowCaret, FHighCaret: PCaretData; // used in AdjustAfterChange
|
FLowCaret, FHighCaret: PCaretData; // used in AdjustAfterChange
|
||||||
FIteratoreMode: (mciNone, mciUp, mciDown);
|
FIteratoreMode: (mciNone, mciUp, mciDown);
|
||||||
|
function GetCurrentCaretFlags: TCaretFlags; inline;
|
||||||
function GetCurrentCaretFull: TLogCaretPoint; inline;
|
function GetCurrentCaretFull: TLogCaretPoint; inline;
|
||||||
function GetCurrentCaretKeepX: Integer; inline;
|
function GetCurrentCaretKeepX: Integer; inline;
|
||||||
procedure SetCurrentCaretFull(AValue: TLogCaretPoint); inline;
|
procedure SetCurrentCaretFull(AValue: TLogCaretPoint); inline;
|
||||||
@ -163,10 +182,14 @@ type
|
|||||||
function IterateNextUp: Boolean; inline;
|
function IterateNextUp: Boolean; inline;
|
||||||
procedure StartIteratorAtLast;
|
procedure StartIteratorAtLast;
|
||||||
function IterateNextDown: Boolean; inline;
|
function IterateNextDown: Boolean; inline;
|
||||||
|
function CanPeekCaret(AIndexOffset: Integer): Boolean; inline;
|
||||||
|
function PeekCaretY(AIndexOffset: Integer): Integer; inline;
|
||||||
|
function PeekCaretFull(AIndexOffset: Integer): TLogCaretPoint; inline;
|
||||||
//procedure AbortIterator;
|
//procedure AbortIterator;
|
||||||
|
|
||||||
property CurrentCaretFull: TLogCaretPoint read GetCurrentCaretFull write SetCurrentCaretFull;
|
property CurrentCaretFull: TLogCaretPoint read GetCurrentCaretFull write SetCurrentCaretFull;
|
||||||
property CurrentCaretKeepX: Integer read GetCurrentCaretKeepX write SetCurrentCaretKeepX;
|
property CurrentCaretKeepX: Integer read GetCurrentCaretKeepX write SetCurrentCaretKeepX;
|
||||||
|
property CurrentCaretFlags: TCaretFlags read GetCurrentCaretFlags;
|
||||||
//property CurrentCaret: TPoint read GetCurrentCaret write SetCurrentCaret;
|
//property CurrentCaret: TPoint read GetCurrentCaret write SetCurrentCaret;
|
||||||
//property CurrentCaretX: Integer read GetCurrentCaretX write SetCurrentCaretX;
|
//property CurrentCaretX: Integer read GetCurrentCaretX write SetCurrentCaretX;
|
||||||
//property CurrentCaretOffs: Integer read GetCurrentCaretOffs write SetCurrentCaretOffs;
|
//property CurrentCaretOffs: Integer read GetCurrentCaretOffs write SetCurrentCaretOffs;
|
||||||
@ -196,7 +219,8 @@ type
|
|||||||
function GetTextArea: TLazSynTextArea;
|
function GetTextArea: TLazSynTextArea;
|
||||||
procedure DoTextSizeChanged(Sender: TObject);
|
procedure DoTextSizeChanged(Sender: TObject);
|
||||||
procedure DoBoundsChanged(Sender: TObject);
|
procedure DoBoundsChanged(Sender: TObject);
|
||||||
procedure MergeAndRemoveCarets;
|
procedure MergeAndRemoveCarets(AForce: Boolean = False);
|
||||||
|
function IsCaretMergeRequested: Boolean;
|
||||||
procedure DoEditorPaintEvent(Sender: TObject; EventType: TSynPaintEvent;
|
procedure DoEditorPaintEvent(Sender: TObject; EventType: TSynPaintEvent;
|
||||||
const prcClip: TRect);
|
const prcClip: TRect);
|
||||||
procedure DoEditorScrollEvent(Sender: TObject; EventType: TSynScrollEvent; dx,
|
procedure DoEditorScrollEvent(Sender: TObject; EventType: TSynScrollEvent; dx,
|
||||||
@ -256,7 +280,8 @@ type
|
|||||||
TSynPluginMultiCaretDefaultMode = mcmCancelOnCaretMove..mcmMoveAllCarets;
|
TSynPluginMultiCaretDefaultMode = mcmCancelOnCaretMove..mcmMoveAllCarets;
|
||||||
|
|
||||||
TSynPluginMultiCaretStateFlag = (
|
TSynPluginMultiCaretStateFlag = (
|
||||||
sfProcessingCmd, sfProcessingMain,
|
sfProcessingCmd, sfProcessingMain, sfProcessingRepeat,
|
||||||
|
sfNoChangeIndicator,
|
||||||
sfExtendingColumnSel, sfSkipCaretsAtSelection,
|
sfExtendingColumnSel, sfSkipCaretsAtSelection,
|
||||||
sfCreateCaretAtCurrentPos,
|
sfCreateCaretAtCurrentPos,
|
||||||
sfSkipSelChanged, sfSkipCaretChanged,
|
sfSkipSelChanged, sfSkipCaretChanged,
|
||||||
@ -293,13 +318,16 @@ type
|
|||||||
FDefaultMode: TSynPluginMultiCaretDefaultMode;
|
FDefaultMode: TSynPluginMultiCaretDefaultMode;
|
||||||
FEnableWithColumnSelection: Boolean;
|
FEnableWithColumnSelection: Boolean;
|
||||||
FKeyStrokes: TSynPluginMultiCaretKeyStrokes;
|
FKeyStrokes: TSynPluginMultiCaretKeyStrokes;
|
||||||
|
FOnBeforeCommand: TSynMultiCaretBeforeCommand;
|
||||||
FStateFlags: TSynPluginMultiCaretStateFlags;
|
FStateFlags: TSynPluginMultiCaretStateFlags;
|
||||||
FMouseActions: TSynPluginMultiCaretMouseActions;
|
FMouseActions: TSynPluginMultiCaretMouseActions;
|
||||||
FSelY1, FSelY2, FSelX: Integer;
|
FSelY1, FSelY2, FSelX: Integer;
|
||||||
FColSelDoneY1, FColSelDoneY2, FColSelDonePhysX: Integer;
|
FColSelDoneY1, FColSelDoneY2, FColSelDonePhysX: Integer;
|
||||||
FSpaceTrimmerLocked: Boolean;
|
FSpaceTrimmerLocked: Boolean;
|
||||||
FForeignPaintLock: Integer;
|
FForeignPaintLock, FNestedCommandProcessor: Integer;
|
||||||
|
|
||||||
|
function GetIsInMainExecution: Boolean;
|
||||||
|
function GetIsInRepeatExecution: Boolean;
|
||||||
procedure RemoveCaretsInSelection;
|
procedure RemoveCaretsInSelection;
|
||||||
procedure SetActiveMode(AValue: TSynPluginMultiCaretMode);
|
procedure SetActiveMode(AValue: TSynPluginMultiCaretMode);
|
||||||
procedure SetDefaultColumnSelectMode(AValue: TSynPluginMultiCaretDefaultMode);
|
procedure SetDefaultColumnSelectMode(AValue: TSynPluginMultiCaretDefaultMode);
|
||||||
@ -354,12 +382,16 @@ type
|
|||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure AddCaretAtLogPos(X, Y, Offs: Integer);
|
procedure AddCaretAtLogPos(X, Y, Offs: Integer);
|
||||||
|
property IsInMainExecution: Boolean read GetIsInMainExecution;
|
||||||
|
property IsInRepeatExecution: Boolean read GetIsInRepeatExecution;
|
||||||
property MouseActions: TSynPluginMultiCaretMouseActions read FMouseActions;
|
property MouseActions: TSynPluginMultiCaretMouseActions read FMouseActions;
|
||||||
property KeyStrokes: TSynPluginMultiCaretKeyStrokes read FKeyStrokes;
|
property KeyStrokes: TSynPluginMultiCaretKeyStrokes read FKeyStrokes;
|
||||||
property EnableWithColumnSelection: Boolean read FEnableWithColumnSelection write FEnableWithColumnSelection default True;
|
property EnableWithColumnSelection: Boolean read FEnableWithColumnSelection write FEnableWithColumnSelection default True;
|
||||||
property ActiveMode: TSynPluginMultiCaretMode read FActiveMode write SetActiveMode;
|
property ActiveMode: TSynPluginMultiCaretMode read FActiveMode write SetActiveMode;
|
||||||
property DefaultMode: TSynPluginMultiCaretDefaultMode read FDefaultMode write SetDefaultMode default mcmMoveAllCarets;
|
property DefaultMode: TSynPluginMultiCaretDefaultMode read FDefaultMode write SetDefaultMode default mcmMoveAllCarets;
|
||||||
property DefaultColumnSelectMode: TSynPluginMultiCaretDefaultMode read FDefaultColumnSelectMode write SetDefaultColumnSelectMode default mcmCancelOnCaretMove;
|
property DefaultColumnSelectMode: TSynPluginMultiCaretDefaultMode
|
||||||
|
read FDefaultColumnSelectMode write SetDefaultColumnSelectMode default mcmCancelOnCaretMove;
|
||||||
|
property OnBeforeCommand: TSynMultiCaretBeforeCommand read FOnBeforeCommand write FOnBeforeCommand;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TSynPluginMultiCaret = class(TSynCustomPluginMultiCaret)
|
TSynPluginMultiCaret = class(TSynCustomPluginMultiCaret)
|
||||||
@ -369,6 +401,7 @@ type
|
|||||||
property EnableWithColumnSelection;
|
property EnableWithColumnSelection;
|
||||||
property DefaultMode;
|
property DefaultMode;
|
||||||
property DefaultColumnSelectMode;
|
property DefaultColumnSelectMode;
|
||||||
|
property OnBeforeCommand;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -805,9 +838,10 @@ begin
|
|||||||
if (Result <= FHighIndex) and (FCarets[Result].x = x) and (FCarets[Result].y = y) and
|
if (Result <= FHighIndex) and (FCarets[Result].x = x) and (FCarets[Result].y = y) and
|
||||||
(FCarets[Result].offs = Offs) and not(cfAddDuplicate in flags)
|
(FCarets[Result].offs = Offs) and not(cfAddDuplicate in flags)
|
||||||
then begin
|
then begin
|
||||||
FCarets[Result].Flags := flags - [cfMainCaret];
|
if cfMainCaret in flags then begin
|
||||||
if cfMainCaret in flags then
|
|
||||||
FMainCaretIndex := Result;
|
FMainCaretIndex := Result;
|
||||||
|
FCarets[Result].Flags := flags + [cfMainCaret];
|
||||||
|
end;
|
||||||
// TODO maybe update PhysX;
|
// TODO maybe update PhysX;
|
||||||
Result := Result - FLowIndex;
|
Result := Result - FLowIndex;
|
||||||
exit;
|
exit;
|
||||||
@ -870,7 +904,7 @@ begin
|
|||||||
FCarets[Result].y := y;
|
FCarets[Result].y := y;
|
||||||
FCarets[Result].KeepX := PhysX;
|
FCarets[Result].KeepX := PhysX;
|
||||||
FCarets[Result].Visual := nil;
|
FCarets[Result].Visual := nil;
|
||||||
FCarets[Result].Flags := flags - [cfMainCaret, cfAddDuplicate];
|
FCarets[Result].Flags := flags - [cfAddDuplicate];
|
||||||
|
|
||||||
if cfMainCaret in flags then
|
if cfMainCaret in flags then
|
||||||
FMainCaretIndex := Result;
|
FMainCaretIndex := Result;
|
||||||
@ -1082,6 +1116,11 @@ begin
|
|||||||
Result.Offs := FCurrenCaret^.offs;
|
Result.Offs := FCurrenCaret^.offs;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSynPluginMultiCaretList.GetCurrentCaretFlags: TCaretFlags;
|
||||||
|
begin
|
||||||
|
Result := FCurrenCaret^.Flags;
|
||||||
|
end;
|
||||||
|
|
||||||
function TSynPluginMultiCaretList.GetCurrentCaretKeepX: Integer;
|
function TSynPluginMultiCaretList.GetCurrentCaretKeepX: Integer;
|
||||||
begin
|
begin
|
||||||
Result := FCurrenCaret^.KeepX;
|
Result := FCurrenCaret^.KeepX;
|
||||||
@ -1285,6 +1324,26 @@ begin
|
|||||||
until False;
|
until False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSynPluginMultiCaretList.CanPeekCaret(AIndexOffset: Integer): Boolean;
|
||||||
|
begin
|
||||||
|
if AIndexOffset < 0 then
|
||||||
|
Result := FCurrenCaret + AIndexOffset >= FLowCaret
|
||||||
|
else
|
||||||
|
Result := FCurrenCaret + AIndexOffset <= FHighCaret;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynPluginMultiCaretList.PeekCaretY(AIndexOffset: Integer): Integer;
|
||||||
|
begin
|
||||||
|
Result := (FCurrenCaret+AIndexOffset)^.y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynPluginMultiCaretList.PeekCaretFull(AIndexOffset: Integer): TLogCaretPoint;
|
||||||
|
begin
|
||||||
|
Result.X := (FCurrenCaret+AIndexOffset)^.x;
|
||||||
|
Result.Y := (FCurrenCaret+AIndexOffset)^.y;
|
||||||
|
Result.Offs := (FCurrenCaret+AIndexOffset)^.offs;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TSynPluginMultiCaretBase }
|
{ TSynPluginMultiCaretBase }
|
||||||
|
|
||||||
procedure TSynPluginMultiCaretBase.DoBoundsChanged(Sender: TObject);
|
procedure TSynPluginMultiCaretBase.DoBoundsChanged(Sender: TObject);
|
||||||
@ -1303,11 +1362,11 @@ begin
|
|||||||
UpdateCaretsPos;
|
UpdateCaretsPos;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynPluginMultiCaretBase.MergeAndRemoveCarets;
|
procedure TSynPluginMultiCaretBase.MergeAndRemoveCarets(AForce: Boolean);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if FPaintLock > 0 then begin
|
if (FPaintLock > 0) and (not AForce) then begin
|
||||||
include(FPaintLockFlags, plfMergeCarets);
|
include(FPaintLockFlags, plfMergeCarets);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -1318,6 +1377,11 @@ begin
|
|||||||
Carets.RemoveCaret(i);
|
Carets.RemoveCaret(i);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSynPluginMultiCaretBase.IsCaretMergeRequested: Boolean;
|
||||||
|
begin
|
||||||
|
Result := plfMergeCarets in FPaintLockFlags;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSynPluginMultiCaretBase.DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePos,
|
procedure TSynPluginMultiCaretBase.DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePos,
|
||||||
aCount, aLineBrkCnt: Integer; aText: String);
|
aCount, aLineBrkCnt: Integer; aText: String);
|
||||||
begin
|
begin
|
||||||
@ -1843,6 +1907,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSynCustomPluginMultiCaret.GetIsInMainExecution: Boolean;
|
||||||
|
begin
|
||||||
|
Result := sfProcessingMain in FStateFlags;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynCustomPluginMultiCaret.GetIsInRepeatExecution: Boolean;
|
||||||
|
begin
|
||||||
|
Result := sfProcessingRepeat in FStateFlags;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSynCustomPluginMultiCaret.SetActiveMode(AValue: TSynPluginMultiCaretMode);
|
procedure TSynCustomPluginMultiCaret.SetActiveMode(AValue: TSynPluginMultiCaretMode);
|
||||||
begin
|
begin
|
||||||
if FActiveMode = AValue then Exit;
|
if FActiveMode = AValue then Exit;
|
||||||
@ -2041,13 +2115,14 @@ begin
|
|||||||
|
|
||||||
|
|
||||||
inherited DoLinesEdited(Sender, aLinePos, aBytePos, aCount, aLineBrkCnt, aText);
|
inherited DoLinesEdited(Sender, aLinePos, aBytePos, aCount, aLineBrkCnt, aText);
|
||||||
Exclude(FStateFlags, sfCreateCaretAtCurrentPos);
|
FStateFlags := FStateFlags - [sfCreateCaretAtCurrentPos, sfSkipCaretsAtSelection, sfNoChangeIndicator];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynCustomPluginMultiCaret.DoCaretChanged(Sender: TObject);
|
procedure TSynCustomPluginMultiCaret.DoCaretChanged(Sender: TObject);
|
||||||
var
|
var
|
||||||
p: TLogCaretPoint;
|
p: TLogCaretPoint;
|
||||||
begin
|
begin
|
||||||
|
Exclude(FStateFlags, sfNoChangeIndicator);
|
||||||
if (sfCreateCaretAtCurrentPos in FStateFlags) then begin
|
if (sfCreateCaretAtCurrentPos in FStateFlags) then begin
|
||||||
p := CaretObj.OldFullLogicalPos;
|
p := CaretObj.OldFullLogicalPos;
|
||||||
AddCaret(p.x, p.y, p.Offs);
|
AddCaret(p.x, p.y, p.Offs);
|
||||||
@ -2110,6 +2185,7 @@ var
|
|||||||
SelFirstY, SelLastY, CurY: Integer;
|
SelFirstY, SelLastY, CurY: Integer;
|
||||||
CurCaret: TLogCaretPoint;
|
CurCaret: TLogCaretPoint;
|
||||||
begin
|
begin
|
||||||
|
Exclude(FStateFlags, sfNoChangeIndicator);
|
||||||
if (FStateFlags * [sfProcessingCmd, sfSkipSelChanged] <> []) or
|
if (FStateFlags * [sfProcessingCmd, sfSkipSelChanged] <> []) or
|
||||||
(FForeignPaintLock > 0)
|
(FForeignPaintLock > 0)
|
||||||
then exit;
|
then exit;
|
||||||
@ -2196,17 +2272,29 @@ end;
|
|||||||
|
|
||||||
procedure TSynCustomPluginMultiCaret.DoBeforeSetSelText(Sender: TObject; AMode: TSynSelectionMode;
|
procedure TSynCustomPluginMultiCaret.DoBeforeSetSelText(Sender: TObject; AMode: TSynSelectionMode;
|
||||||
ANewText: PChar);
|
ANewText: PChar);
|
||||||
|
var
|
||||||
|
skip: Boolean;
|
||||||
begin
|
begin
|
||||||
SelectionObj.RemoveBeforeSetSelTextHandler(@DoBeforeSetSelText);
|
SelectionObj.RemoveBeforeSetSelTextHandler(@DoBeforeSetSelText);
|
||||||
|
|
||||||
|
// only here if selectionexists and is smColumn;
|
||||||
|
skip := //Editor.SelAvail and (SelectionObj.ActiveSelectionMode = smColumn) and
|
||||||
|
not(eoPersistentBlock in Editor.Options2);
|
||||||
|
if skip then
|
||||||
|
SetSkipCaretAtSel;
|
||||||
|
|
||||||
RemoveCaretsInSelection;
|
RemoveCaretsInSelection;
|
||||||
SelectionObj.SelText := '';
|
SelectionObj.SelText := '';
|
||||||
|
|
||||||
if Carets.MainCaretIndex >= 0 then begin
|
if Carets.MainCaretIndex >= 0 then begin
|
||||||
Editor.LogicalCaretXY := Carets.Caret[Carets.MainCaretIndex];
|
Editor.LogicalCaretXY := Carets.Caret[Carets.MainCaretIndex];
|
||||||
FSelX := Carets.Caret[Carets.MainCaretIndex].x;
|
FSelX := Carets.Caret[Carets.MainCaretIndex].x;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert(False, 'TSynCustomPluginMultiCaret.ProcessAllSynCommand: Maincaret index not found');
|
assert(False, 'TSynCustomPluginMultiCaret.ProcessAllSynCommand: Maincaret index not found');
|
||||||
|
|
||||||
|
if skip then
|
||||||
|
Include(FStateFlags, sfSkipCaretsAtSelection); // restore the flag
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSynCustomPluginMultiCaret.ProcessMySynCommand(Sender: TObject;
|
procedure TSynCustomPluginMultiCaret.ProcessMySynCommand(Sender: TObject;
|
||||||
@ -2261,50 +2349,79 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
|
|||||||
var Handled: boolean; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer;
|
var Handled: boolean; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer;
|
||||||
HandlerData: pointer);
|
HandlerData: pointer);
|
||||||
|
|
||||||
procedure ExecCommandRepeated;
|
procedure ExecCommandRepeated(AOnePerLine: Boolean = False);
|
||||||
var
|
var
|
||||||
c, i, y: Integer;
|
i, y: Integer;
|
||||||
p: TLogCaretPoint;
|
p: TLogCaretPoint;
|
||||||
|
skip, noChange, SelAvail, IsUser: Boolean;
|
||||||
|
MainY: Integer;
|
||||||
begin
|
begin
|
||||||
Handled := True;
|
Handled := True;
|
||||||
Editor.BeginUpdate(True);
|
Editor.BeginUpdate(True);
|
||||||
|
FCarets.IncMergeLock;
|
||||||
try
|
try
|
||||||
c := AddCaret(Editor.LogicalCaretXY.x, Editor.CaretY, CaretObj.BytePosOffset,
|
AddCaret(Editor.LogicalCaretXY.x, Editor.CaretY, CaretObj.BytePosOffset,
|
||||||
[cfMainCaret, cfNoneVisual {, cfAddDuplicate}], CaretObj.KeepCaretXPos);
|
[cfMainCaret, cfNoneVisual {, cfAddDuplicate}], CaretObj.KeepCaretXPos);
|
||||||
|
|
||||||
// Execute Command at current caret pos
|
// Execute Command at current caret pos
|
||||||
Include(FStateFlags, sfProcessingMain);
|
Include(FStateFlags, sfProcessingMain);
|
||||||
|
Include(FStateFlags, sfNoChangeIndicator);
|
||||||
if Editor.SelAvail and (SelectionObj.ActiveSelectionMode = smColumn) then
|
if Editor.SelAvail and (SelectionObj.ActiveSelectionMode = smColumn) then
|
||||||
SelectionObj.AddBeforeSetSelTextHandler(@DoBeforeSetSelText);
|
SelectionObj.AddBeforeSetSelTextHandler(@DoBeforeSetSelText);
|
||||||
Editor.CommandProcessor(Command, AChar, data, [hcfInit, hcfFinish]);
|
Editor.CommandProcessor(Command, AChar, data, [hcfInit, hcfFinish]);
|
||||||
SelectionObj.RemoveBeforeSetSelTextHandler(@DoBeforeSetSelText);
|
SelectionObj.RemoveBeforeSetSelTextHandler(@DoBeforeSetSelText);
|
||||||
Exclude(FStateFlags, sfProcessingMain);
|
Exclude(FStateFlags, sfProcessingMain);
|
||||||
// if there was no change, then do not re-exec ?
|
noChange := sfNoChangeIndicator in FStateFlags;
|
||||||
|
Exclude(FStateFlags, sfNoChangeIndicator);
|
||||||
|
|
||||||
|
if noChange then begin
|
||||||
|
if Carets.MainCaretIndex >= 0 then
|
||||||
|
RemoveCaret(Carets.MainCaretIndex)
|
||||||
|
else
|
||||||
|
assert(False, 'TSynCustomPluginMultiCaret.ProcessAllSynCommand: Maincaret index not found');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
// Repeat command
|
// Repeat command
|
||||||
|
Include(FStateFlags, sfProcessingRepeat);
|
||||||
CaretObj.IncForcePastEOL;
|
CaretObj.IncForcePastEOL;
|
||||||
i := CaretsCount;
|
skip := sfSkipCaretsAtSelection in FStateFlags;
|
||||||
|
MainY := CaretObj.LinePos;
|
||||||
|
SelAvail := Editor.SelAvail;
|
||||||
|
IsUser := Command >= ecUserFirst;
|
||||||
|
|
||||||
y := FSelY2;
|
y := FSelY2;
|
||||||
while i > 0 do begin
|
Carets.StartIteratorAtLast;
|
||||||
dec(i);
|
while Carets.IterateNextDown do begin
|
||||||
if i = c then continue;
|
if cfMainCaret in Carets.CurrentCaretFlags then
|
||||||
p := Carets.CaretFull[i];
|
continue;
|
||||||
|
p := Carets.CurrentCaretFull;
|
||||||
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 (skip) and (y >= FSelY1) and
|
||||||
(y = p.y) and (FSelX = p.x)
|
(y = p.y) and (FSelX = p.x)
|
||||||
then begin
|
then begin
|
||||||
dec(y);
|
dec(y);
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
|
if AOnePerLine and
|
||||||
|
( (p.y = MainY) or
|
||||||
|
( Carets.CanPeekCaret(-1) and (Carets.PeekCaretY(-1) = p.y) ) )
|
||||||
|
then
|
||||||
|
continue;
|
||||||
|
|
||||||
CaretObj.FullLogicalPos := p;
|
CaretObj.FullLogicalPos := p;
|
||||||
//j := Carets.CaretKeepX[i];
|
if IsUser and not SelAvail then
|
||||||
//if j > 0 then
|
SelectionObj.StartLineBytePos := Point(p.x, p.y);
|
||||||
// CaretObj.KeepCaretXPos := j;
|
i := Carets.CurrentCaretKeepX;
|
||||||
|
if i > 0 then
|
||||||
|
CaretObj.KeepCaretXPos := i;
|
||||||
Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]);
|
Editor.CommandProcessor(Command, AChar, nil, [hcfInit, hcfFinish]);
|
||||||
Carets.CaretFull[i] := CaretObj.FullLogicalPos;
|
Carets.CurrentCaretFull := CaretObj.FullLogicalPos;
|
||||||
Carets.CaretKeepX[i] := -1;
|
Carets.CurrentCaretKeepX := -1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
CaretObj.DecForcePastEOL;
|
CaretObj.DecForcePastEOL;
|
||||||
|
Exclude(FStateFlags, sfProcessingRepeat);
|
||||||
|
|
||||||
if Carets.MainCaretIndex >= 0 then begin
|
if Carets.MainCaretIndex >= 0 then begin
|
||||||
CaretObj.FullLogicalPos := Carets.CaretFull[Carets.MainCaretIndex];
|
CaretObj.FullLogicalPos := Carets.CaretFull[Carets.MainCaretIndex];
|
||||||
@ -2314,6 +2431,9 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
|
|||||||
else
|
else
|
||||||
assert(False, 'TSynCustomPluginMultiCaret.ProcessAllSynCommand: Maincaret index not found');
|
assert(False, 'TSynCustomPluginMultiCaret.ProcessAllSynCommand: Maincaret index not found');
|
||||||
finally
|
finally
|
||||||
|
Exclude(FStateFlags, sfSkipCaretsAtSelection);
|
||||||
|
FCarets.DecMergeLock;
|
||||||
|
MergeAndRemoveCarets;
|
||||||
Editor.EndUpdate;
|
Editor.EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -2335,8 +2455,7 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
|
|||||||
Exclude(FStateFlags, sfProcessingMain);
|
Exclude(FStateFlags, sfProcessingMain);
|
||||||
|
|
||||||
// Repeat command
|
// Repeat command
|
||||||
// TODO lock sorting, and sort at end only
|
Include(FStateFlags, sfProcessingRepeat);
|
||||||
// TODO: ecPageTop ecLineTextStart moves both dir.
|
|
||||||
case Command of
|
case Command of
|
||||||
ecLeft, ecUp, ecWordLeft, ecLineStart, ecPageUp, ecPageLeft,
|
ecLeft, ecUp, ecWordLeft, ecLineStart, ecPageUp, ecPageLeft,
|
||||||
ecPageTop, ecLineTextStart, ecWordEndLeft, ecHalfWordLeft:
|
ecPageTop, ecLineTextStart, ecWordEndLeft, ecHalfWordLeft:
|
||||||
@ -2367,6 +2486,7 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Exclude(FStateFlags, sfProcessingRepeat);
|
||||||
|
|
||||||
finally
|
finally
|
||||||
FCarets.DecMergeLock;
|
FCarets.DecMergeLock;
|
||||||
@ -2386,35 +2506,86 @@ procedure TSynCustomPluginMultiCaret.ProcessAllSynCommand(Sender: TObject; After
|
|||||||
|
|
||||||
var
|
var
|
||||||
ClipHelper: TSynClipboardStream;
|
ClipHelper: TSynClipboardStream;
|
||||||
|
Action: TSynMultiCaretCommandAction;
|
||||||
|
Flags: TSynMultiCaretCommandFlags;
|
||||||
begin
|
begin
|
||||||
// hcfInit / hcfFinish
|
// hcfFinish
|
||||||
if (sfProcessingCmd in FStateFlags) or (CaretsCount = 0) then
|
|
||||||
exit;
|
|
||||||
if AfterProcessing then begin
|
if AfterProcessing then begin
|
||||||
//if sfExtendingColumnSel in FStateFlags then
|
if (FNestedCommandProcessor > 0) then begin
|
||||||
// HandleNewColSelection;
|
dec(FNestedCommandProcessor);
|
||||||
Exclude(FStateFlags, sfExtendingColumnSel);
|
|
||||||
UpdateCaretsPos;
|
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if Handled then exit;
|
|
||||||
|
|
||||||
|
FStateFlags := FStateFlags - [sfProcessingCmd, sfSkipUndoCarets, sfExtendingColumnSel];
|
||||||
|
if (CaretsCount = 0) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if IsCaretMergeRequested then
|
||||||
|
MergeAndRemoveCarets(True); // is case of several commands in one paintlock
|
||||||
|
UpdateCaretsPos;
|
||||||
|
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
// hcfInit
|
||||||
(* use Editor.CommandProcessor(... SkipInit=[hcfInit, hcfFinish])
|
(* use Editor.CommandProcessor(... SkipInit=[hcfInit, hcfFinish])
|
||||||
command is already initialized / prevent macro recorder from recording again.
|
command is already initialized / prevent macro recorder from recording again.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
try
|
if (sfProcessingCmd in FStateFlags) then
|
||||||
|
inc(FNestedCommandProcessor);
|
||||||
|
if (sfProcessingCmd in FStateFlags) or (CaretsCount = 0) then
|
||||||
|
exit;
|
||||||
|
if Handled then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
|
||||||
|
case Command of
|
||||||
|
ecCopy, ecCut: Action := ccaNoneRepeatCommand;
|
||||||
|
ecGotoMarker0..ecGotoMarker9: Action := ccaClearCarets;
|
||||||
|
ecSelectAll: Action := ccaClearCarets;
|
||||||
|
else
|
||||||
|
if Command >= ecUserFirst then
|
||||||
|
Action := ccaNoneRepeatCommand
|
||||||
|
else
|
||||||
|
Action := ccaDefaultAction;
|
||||||
|
end;
|
||||||
|
Flags := [];
|
||||||
|
if FOnBeforeCommand <> nil then
|
||||||
|
FOnBeforeCommand(Self, Command, Action, Flags);
|
||||||
|
|
||||||
|
case Action of
|
||||||
|
//ccaDefaultAction: ;
|
||||||
|
ccaNoneRepeatCommand: begin
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
ccaRepeatCommand: begin
|
||||||
|
StartEditing;
|
||||||
|
ExecCommandRepeated;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
ccaRepeatCommandPerLine: begin
|
||||||
|
StartEditing;
|
||||||
|
ExecCommandRepeated(True);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
ccaClearCarets: begin
|
||||||
|
ClearCarets;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
ccaAdjustCarets: begin
|
||||||
|
Include(FStateFlags, sfProcessingCmd);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
case Command of
|
case Command of
|
||||||
// TODO: delete and smColumn -- only delete once
|
// TODO: delete and smColumn -- only delete once
|
||||||
ecDeleteLastChar..ecDeleteLine,
|
ecDeleteLastChar..ecDeleteLine,
|
||||||
ecLineBreak..ecChar:
|
ecLineBreak..ecChar:
|
||||||
begin
|
begin
|
||||||
StartEditing;
|
StartEditing;
|
||||||
if ((Command = ecDeleteChar) or (Command = ecDeleteLastChar)) and
|
|
||||||
Editor.SelAvail and (SelectionObj.ActiveSelectionMode = smColumn) and
|
|
||||||
not(eoPersistentBlock in Editor.Options2)
|
|
||||||
then
|
|
||||||
SetSkipCaretAtSel;
|
|
||||||
if Editor.ReadOnly then exit;
|
if Editor.ReadOnly then exit;
|
||||||
ExecCommandRepeated;
|
ExecCommandRepeated;
|
||||||
end;
|
end;
|
||||||
@ -2444,10 +2615,8 @@ begin
|
|||||||
begin
|
begin
|
||||||
StartEditing;
|
StartEditing;
|
||||||
if Editor.ReadOnly then exit;
|
if Editor.ReadOnly then exit;
|
||||||
|
if (eoTabIndent in Editor.Options) and Editor.SelAvail then begin
|
||||||
if (eoTabIndent in Editor.Options) and Editor.SelAvail and
|
if (SelectionObj.ActiveSelectionMode = smColumn) then begin
|
||||||
(SelectionObj.ActiveSelectionMode = smColumn)
|
|
||||||
then begin
|
|
||||||
// no indent for column mode, when multicaret
|
// no indent for column mode, when multicaret
|
||||||
Editor.BeginUpdate(True);
|
Editor.BeginUpdate(True);
|
||||||
try
|
try
|
||||||
@ -2464,6 +2633,9 @@ begin
|
|||||||
Editor.EndUpdate;
|
Editor.EndUpdate;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
else // exec once and adjust
|
||||||
|
exit;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
ExecCommandRepeated;
|
ExecCommandRepeated;
|
||||||
end;
|
end;
|
||||||
@ -2493,25 +2665,16 @@ begin
|
|||||||
Editor.CommandProcessor(Command, AChar, data, [hcfInit, hcfFinish]);
|
Editor.CommandProcessor(Command, AChar, data, [hcfInit, hcfFinish]);
|
||||||
Handled := True;
|
Handled := True;
|
||||||
end;
|
end;
|
||||||
ecCopy,
|
|
||||||
ecScrollUp..ecScrollRight,
|
|
||||||
ecInsertMode..ecToggleMode,
|
|
||||||
ecNormalSelect, ecLineSelect,
|
|
||||||
ecSetMarker0..ecSetMarker9,
|
|
||||||
ecToggleMarker0..ecToggleMarker9,
|
|
||||||
EcFoldLevel1..EcFoldLevel9, EcFoldLevel0, EcFoldCurrent,
|
|
||||||
ecGotFocus, ecLostFocus
|
|
||||||
:
|
|
||||||
; // Ignore, if no changes occur
|
|
||||||
ecPluginFirstMultiCaret..ecPluginLastMultiCaret: ; // ignore and handle in hcfPreExec
|
ecPluginFirstMultiCaret..ecPluginLastMultiCaret: ; // ignore and handle in hcfPreExec
|
||||||
else
|
else
|
||||||
ClearCarets;
|
begin
|
||||||
|
StartEditing;
|
||||||
|
if Editor.ReadOnly then exit;
|
||||||
|
ExecCommandRepeated;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Exclude(FStateFlags, sfSkipCaretsAtSelection);
|
//Exclude(FStateFlags, sfSkipCaretsAtSelection);
|
||||||
finally
|
|
||||||
FStateFlags := FStateFlags - [sfProcessingCmd, sfSkipUndoCarets];
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TSynCustomPluginMultiCaret.MaybeHandleMouseAction(var AnInfo: TSynEditMouseActionInfo;
|
function TSynCustomPluginMultiCaret.MaybeHandleMouseAction(var AnInfo: TSynEditMouseActionInfo;
|
||||||
|
|||||||
@ -183,7 +183,7 @@ type
|
|||||||
FAreaMarkupEnabled: Boolean;
|
FAreaMarkupEnabled: Boolean;
|
||||||
FMarkupEnabled: Boolean;
|
FMarkupEnabled: Boolean;
|
||||||
FEnabled: Boolean;
|
FEnabled: Boolean;
|
||||||
FEditing: Boolean;
|
FEditing: Boolean; // In ApplyChangeList, edit actions are caused by the plugin itself
|
||||||
FPaintLock: Integer;
|
FPaintLock: Integer;
|
||||||
FOwnPaintLock: Integer;
|
FOwnPaintLock: Integer;
|
||||||
FTextBufferChanging: Boolean;
|
FTextBufferChanging: Boolean;
|
||||||
|
|||||||
@ -766,16 +766,15 @@ begin
|
|||||||
|
|
||||||
RunCmdSeq([ecChar], ['A']);
|
RunCmdSeq([ecChar], ['A']);
|
||||||
TestIsCaretLogAndFullText('', 2, 6, LocalText1A);
|
TestIsCaretLogAndFullText('', 2, 6, LocalText1A);
|
||||||
|
TestExtraCaretPos('', 4, [2,2, 2,3, 2,4, 2,5]);
|
||||||
|
|
||||||
RunCmdSeq([ecDeleteLastChar], []);
|
RunCmdSeq([ecDeleteLastChar], []);
|
||||||
TestIsCaretLogAndFullText('', 1, 6, LocalText1);
|
TestIsCaretLogAndFullText('', 1, 6, LocalText1);
|
||||||
// 4 extra carets + main caret
|
TestExtraCaretPos('', 4, [1,2, 1,3, 1,4, 1,5]);
|
||||||
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
|
||||||
|
|
||||||
RunCmdSeq([ecDeleteLastChar], []);
|
RunCmdSeq([ecDeleteLastChar], []);
|
||||||
TestIsCaretLogAndFullText('', 6, 1, LocalText1Del);
|
TestIsCaretLogAndFullText('', 6, 1, LocalText1Del);
|
||||||
// 4 extra carets + main caret
|
TestExtraCaretPos('', 4, [2,1, 3,1, 4,1, 5,1]);
|
||||||
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
|
||||||
|
|
||||||
RunCmdSeq([ecDeleteLastChar], []);
|
RunCmdSeq([ecDeleteLastChar], []);
|
||||||
TestIsCaretLogAndFullText('', 1, 1, LocalText1Del, [1, '6']);
|
TestIsCaretLogAndFullText('', 1, 1, LocalText1Del, [1, '6']);
|
||||||
@ -1129,12 +1128,63 @@ procedure TTestMultiCaret.TabKey;
|
|||||||
Result[6] := '7g';
|
Result[6] := '7g';
|
||||||
Result[7] := '';
|
Result[7] := '';
|
||||||
end;
|
end;
|
||||||
|
function LocalText1AfterIndent: TStringArray;
|
||||||
|
begin
|
||||||
|
SetLength(Result, 8);
|
||||||
|
Result[0] := '1a';
|
||||||
|
Result[1] := ' 2b';
|
||||||
|
Result[2] := ' 3c';
|
||||||
|
Result[3] := ' 4d';
|
||||||
|
Result[4] := '5e';
|
||||||
|
Result[5] := '6f';
|
||||||
|
Result[6] := '7g';
|
||||||
|
Result[7] := '';
|
||||||
|
end;
|
||||||
begin
|
begin
|
||||||
PushBaseName('ZERO width selection -- WITH eoTabIndent');
|
PushBaseName('WITH eoTabIndent');
|
||||||
ReCreateEdit;
|
FOptAdd := [eoTabIndent];
|
||||||
SynEdit.Options := SynEdit.Options + [eoTabIndent] - [eoTabsToSpaces, eoSmartTabs, eoTrimTrailingSpaces];
|
FOptRemove := [eoTabsToSpaces, eoSmartTabs, eoTrimTrailingSpaces];
|
||||||
SetLines(LocalText1);
|
|
||||||
|
|
||||||
|
PushBaseName('ZERO width selection');
|
||||||
|
ReCreateEdit(LocalText1);
|
||||||
|
SetCaretAndColumnSelect(2,2, 4,0);
|
||||||
|
TestIsCaretLogAndFullText('', 2, 6, LocalText1);
|
||||||
|
|
||||||
|
RunCmdSeq([ecTab], []);
|
||||||
|
TestIsCaretLogAndFullText('', 3, 6, LocalText1Tab);
|
||||||
|
// 4 extra carets + main caret
|
||||||
|
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
||||||
|
|
||||||
|
PopPushBaseName('ONE width selection');
|
||||||
|
ReCreateEdit(LocalText1);
|
||||||
|
SetCaretAndColumnSelect(2,2, 4,1);
|
||||||
|
TestIsCaretLogAndFullText('', 3, 6, LocalText1);
|
||||||
|
|
||||||
|
RunCmdSeq([ecTab], []);
|
||||||
|
TestIsCaretLogAndFullText('', 3, 6, LocalText1TabOver);
|
||||||
|
// 4 extra carets + main caret
|
||||||
|
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
||||||
|
PopBaseName;
|
||||||
|
|
||||||
|
PopPushBaseName('indent selection');
|
||||||
|
ReCreateEdit(LocalText1);
|
||||||
|
SetCaretAndSel(2,2, 2,4);
|
||||||
|
FMultiCaret.AddCaretAtLogPos(3,4,0);
|
||||||
|
FMultiCaret.ActiveMode := mcmMoveAllCarets;
|
||||||
|
|
||||||
|
RunCmdSeq([ecTab], []);
|
||||||
|
TestIsCaretLogAndFullText('', 4, 4, LocalText1AfterIndent);
|
||||||
|
TestExtraCaretPos('', 1, [5,4]);
|
||||||
|
PopBaseName;
|
||||||
|
|
||||||
|
PopBaseName;
|
||||||
|
|
||||||
|
PushBaseName('WITHOUT eoTabIndent');
|
||||||
|
FOptAdd := [];
|
||||||
|
FOptRemove := [eoTabIndent, eoTabsToSpaces, eoSmartTabs, eoTrimTrailingSpaces];
|
||||||
|
|
||||||
|
PushBaseName('ZERO width selection');
|
||||||
|
ReCreateEdit(LocalText1);
|
||||||
SetCaretAndColumnSelect(2,2, 4,0);
|
SetCaretAndColumnSelect(2,2, 4,0);
|
||||||
TestIsCaretLogAndFullText('', 2, 6, LocalText1);
|
TestIsCaretLogAndFullText('', 2, 6, LocalText1);
|
||||||
|
|
||||||
@ -1144,40 +1194,8 @@ begin
|
|||||||
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
||||||
|
|
||||||
|
|
||||||
PopPushBaseName('ONE width selection -- WITH eoTabIndent');
|
PopPushBaseName('ONE width selection');
|
||||||
ReCreateEdit;
|
ReCreateEdit(LocalText1);
|
||||||
SynEdit.Options := SynEdit.Options + [eoTabIndent] - [eoTabsToSpaces, eoSmartTabs, eoTrimTrailingSpaces];
|
|
||||||
SetLines(LocalText1);
|
|
||||||
|
|
||||||
SetCaretAndColumnSelect(2,2, 4,1);
|
|
||||||
TestIsCaretLogAndFullText('', 3, 6, LocalText1);
|
|
||||||
|
|
||||||
RunCmdSeq([ecTab], []);
|
|
||||||
TestIsCaretLogAndFullText('', 3, 6, LocalText1TabOver);
|
|
||||||
// 4 extra carets + main caret
|
|
||||||
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PopPushBaseName('ZERO width selection -- WITHOUT eoTabIndent');
|
|
||||||
ReCreateEdit;
|
|
||||||
SynEdit.Options := SynEdit.Options - [eoTabIndent] - [eoTabsToSpaces, eoSmartTabs, eoTrimTrailingSpaces];
|
|
||||||
SetLines(LocalText1);
|
|
||||||
|
|
||||||
SetCaretAndColumnSelect(2,2, 4,0);
|
|
||||||
TestIsCaretLogAndFullText('', 2, 6, LocalText1);
|
|
||||||
|
|
||||||
RunCmdSeq([ecTab], []);
|
|
||||||
TestIsCaretLogAndFullText('', 3, 6, LocalText1Tab);
|
|
||||||
// 4 extra carets + main caret
|
|
||||||
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
|
||||||
|
|
||||||
|
|
||||||
PopPushBaseName('ONE width selection -- WITHOUT eoTabIndent');
|
|
||||||
ReCreateEdit;
|
|
||||||
SynEdit.Options := SynEdit.Options - [eoTabIndent] - [eoTabsToSpaces, eoSmartTabs, eoTrimTrailingSpaces];
|
|
||||||
SetLines(LocalText1);
|
|
||||||
|
|
||||||
SetCaretAndColumnSelect(2,2, 4,1);
|
SetCaretAndColumnSelect(2,2, 4,1);
|
||||||
TestIsCaretLogAndFullText('', 3, 6, LocalText1);
|
TestIsCaretLogAndFullText('', 3, 6, LocalText1);
|
||||||
|
|
||||||
@ -1185,6 +1203,7 @@ begin
|
|||||||
TestIsCaretLogAndFullText('', 3, 6, LocalText1TabOver);
|
TestIsCaretLogAndFullText('', 3, 6, LocalText1TabOver);
|
||||||
// 4 extra carets + main caret
|
// 4 extra carets + main caret
|
||||||
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
AssertEquals(BaseTestName+'', 4, FMultiCaret.Carets.Count);
|
||||||
|
PopBaseName;
|
||||||
|
|
||||||
PopBaseName;
|
PopBaseName;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@ -54,7 +54,7 @@ uses
|
|||||||
SynEditLines, SynEditStrConst, SynEditTypes, SynEdit, SynRegExpr,
|
SynEditLines, SynEditStrConst, SynEditTypes, SynEdit, SynRegExpr,
|
||||||
SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion,
|
SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion,
|
||||||
SynEditMiscClasses, SynEditMarkupHighAll, SynEditMarks,
|
SynEditMiscClasses, SynEditMarkupHighAll, SynEditMarks,
|
||||||
SynBeautifier,
|
SynBeautifier, SynPluginMultiCaret,
|
||||||
SynPluginSyncronizedEditBase, SourceSynEditor,
|
SynPluginSyncronizedEditBase, SourceSynEditor,
|
||||||
SynExportHTML, SynHighlighterPas, SynEditMarkup, SynEditMarkupIfDef,
|
SynExportHTML, SynHighlighterPas, SynEditMarkup, SynEditMarkupIfDef,
|
||||||
// Intf
|
// Intf
|
||||||
@ -291,6 +291,8 @@ type
|
|||||||
|
|
||||||
procedure UpdateIfDefNodeStates(Force: Boolean = False);
|
procedure UpdateIfDefNodeStates(Force: Boolean = False);
|
||||||
protected
|
protected
|
||||||
|
procedure DoMultiCaretBeforeCommand(Sender: TObject; ACommand: TSynEditorCommand;
|
||||||
|
var AnAction: TSynMultiCaretCommandAction; var AFlags: TSynMultiCaretCommandFlags);
|
||||||
procedure ProcessCommand(Sender: TObject;
|
procedure ProcessCommand(Sender: TObject;
|
||||||
var Command: TSynEditorCommand; var AChar: TUTF8Char; {%H-}Data: pointer);
|
var Command: TSynEditorCommand; var AChar: TUTF8Char; {%H-}Data: pointer);
|
||||||
procedure ProcessUserCommand(Sender: TObject;
|
procedure ProcessUserCommand(Sender: TObject;
|
||||||
@ -3192,6 +3194,37 @@ begin
|
|||||||
FEditor.CaretXY := FTempCaret;
|
FEditor.CaretXY := FTempCaret;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSourceEditor.DoMultiCaretBeforeCommand(Sender: TObject;
|
||||||
|
ACommand: TSynEditorCommand; var AnAction: TSynMultiCaretCommandAction;
|
||||||
|
var AFlags: TSynMultiCaretCommandFlags);
|
||||||
|
begin
|
||||||
|
if (FSourceNoteBook<>nil) and (snIncrementalFind in FSourceNoteBook.States) then begin
|
||||||
|
AnAction := ccaClearCarets;
|
||||||
|
end;
|
||||||
|
|
||||||
|
case ACommand of
|
||||||
|
ecToggleComment:
|
||||||
|
if FEditor.SelAvail then
|
||||||
|
AnAction := ccaAdjustCarets
|
||||||
|
else
|
||||||
|
AnAction := ccaRepeatCommandPerLine; // one per line
|
||||||
|
ecInsertUserName,
|
||||||
|
ecInsertDateTime,
|
||||||
|
ecInsertChangeLogEntry,
|
||||||
|
ecInsertCVSAuthor,
|
||||||
|
ecInsertCVSDate,
|
||||||
|
ecInsertCVSHeader,
|
||||||
|
ecInsertCVSID,
|
||||||
|
ecInsertCVSLog,
|
||||||
|
ecInsertCVSName,
|
||||||
|
ecInsertCVSRevision,
|
||||||
|
ecInsertCVSSource,
|
||||||
|
ecInsertGUID,
|
||||||
|
ecInsertFilename:
|
||||||
|
AnAction := ccaRepeatCommand;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSourceEditor.ProcessCommand(Sender: TObject;
|
procedure TSourceEditor.ProcessCommand(Sender: TObject;
|
||||||
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
||||||
// these are normal commands for synedit (lower than ecUserFirst),
|
// these are normal commands for synedit (lower than ecUserFirst),
|
||||||
@ -3264,7 +3297,7 @@ begin
|
|||||||
|
|
||||||
ecSelEditorTop, ecSelEditorBottom, ecEditorTop, ecEditorBottom:
|
ecSelEditorTop, ecSelEditorBottom, ecEditorTop, ecEditorBottom:
|
||||||
begin
|
begin
|
||||||
if FaOwner<>nil then
|
if (FaOwner<>nil) and (not FEditor.IsInMultiCaretRepeatExecution) then
|
||||||
Manager.AddJumpPointClicked(Self);
|
Manager.AddJumpPointClicked(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -4529,6 +4562,7 @@ Begin
|
|||||||
OnPlaceBookmark := @EditorPlaceBookmark;
|
OnPlaceBookmark := @EditorPlaceBookmark;
|
||||||
OnClearBookmark := @EditorClearBookmark;
|
OnClearBookmark := @EditorClearBookmark;
|
||||||
OnChangeUpdating := @EditorChangeUpdating;
|
OnChangeUpdating := @EditorChangeUpdating;
|
||||||
|
OnMultiCaretBeforeCommand := @DoMultiCaretBeforeCommand;
|
||||||
RegisterMouseActionExecHandler(@EditorHandleMouseAction);
|
RegisterMouseActionExecHandler(@EditorHandleMouseAction);
|
||||||
// IMPORTANT: when you change above, don't forget updating UnbindEditor
|
// IMPORTANT: when you change above, don't forget updating UnbindEditor
|
||||||
Parent := AParent;
|
Parent := AParent;
|
||||||
|
|||||||
@ -233,9 +233,13 @@ type
|
|||||||
function GetHighlightUserWordCount: Integer;
|
function GetHighlightUserWordCount: Integer;
|
||||||
function GetHighlightUserWords(AIndex: Integer): TSourceSynEditMarkupHighlightAllMulti;
|
function GetHighlightUserWords(AIndex: Integer): TSourceSynEditMarkupHighlightAllMulti;
|
||||||
function GetIDEGutterMarks: TIDESynGutterMarks;
|
function GetIDEGutterMarks: TIDESynGutterMarks;
|
||||||
|
function GetIsInMultiCaretMainExecution: Boolean;
|
||||||
|
function GetIsInMultiCaretRepeatExecution: Boolean;
|
||||||
|
function GetOnMultiCaretBeforeCommand: TSynMultiCaretBeforeCommand;
|
||||||
procedure GetTopInfoMarkupForLine(Sender: TObject; {%H-}Line: integer; var Special: boolean;
|
procedure GetTopInfoMarkupForLine(Sender: TObject; {%H-}Line: integer; var Special: boolean;
|
||||||
aMarkup: TSynSelectedColor);
|
aMarkup: TSynSelectedColor);
|
||||||
procedure SetHighlightUserWordCount(AValue: Integer);
|
procedure SetHighlightUserWordCount(AValue: Integer);
|
||||||
|
procedure SetOnMultiCaretBeforeCommand(AValue: TSynMultiCaretBeforeCommand);
|
||||||
procedure SetShowTopInfo(AValue: boolean);
|
procedure SetShowTopInfo(AValue: boolean);
|
||||||
procedure SetTopInfoMarkup(AValue: TSynSelectedColor);
|
procedure SetTopInfoMarkup(AValue: TSynSelectedColor);
|
||||||
procedure DoHighlightChanged(Sender: TSynEditStrings; {%H-}AIndex, {%H-}ACount : Integer);
|
procedure DoHighlightChanged(Sender: TSynEditStrings; {%H-}AIndex, {%H-}ACount : Integer);
|
||||||
@ -271,6 +275,9 @@ type
|
|||||||
procedure SetIfdefNodeState(ALinePos, AstartPos: Integer; AState: TSynMarkupIfdefNodeState);
|
procedure SetIfdefNodeState(ALinePos, AstartPos: Integer; AState: TSynMarkupIfdefNodeState);
|
||||||
property OnIfdefNodeStateRequest: TSynMarkupIfdefStateRequest read FOnIfdefNodeStateRequest write FOnIfdefNodeStateRequest;
|
property OnIfdefNodeStateRequest: TSynMarkupIfdefStateRequest read FOnIfdefNodeStateRequest write FOnIfdefNodeStateRequest;
|
||||||
property MarkupIfDef: TSourceSynEditMarkupIfDef read FMarkupIfDef;
|
property MarkupIfDef: TSourceSynEditMarkupIfDef read FMarkupIfDef;
|
||||||
|
property IsInMultiCaretMainExecution: Boolean read GetIsInMultiCaretMainExecution;
|
||||||
|
property IsInMultiCaretRepeatExecution: Boolean read GetIsInMultiCaretRepeatExecution;
|
||||||
|
property OnMultiCaretBeforeCommand: TSynMultiCaretBeforeCommand read GetOnMultiCaretBeforeCommand write SetOnMultiCaretBeforeCommand;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TIDESynHighlighterPasRangeList = class(TSynHighlighterPasRangeList)
|
TIDESynHighlighterPasRangeList = class(TSynHighlighterPasRangeList)
|
||||||
@ -1509,6 +1516,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TIDESynEditor.SetOnMultiCaretBeforeCommand(AValue: TSynMultiCaretBeforeCommand);
|
||||||
|
begin
|
||||||
|
FMultiCaret.OnBeforeCommand := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TIDESynEditor.SetShowTopInfo(AValue: boolean);
|
procedure TIDESynEditor.SetShowTopInfo(AValue: boolean);
|
||||||
begin
|
begin
|
||||||
if FShowTopInfo = AValue then Exit;
|
if FShowTopInfo = AValue then Exit;
|
||||||
@ -1534,6 +1546,21 @@ begin
|
|||||||
Result := TIDESynGutterMarks(Gutter.Parts.ByClass[TIDESynGutterMarks, 0]);
|
Result := TIDESynGutterMarks(Gutter.Parts.ByClass[TIDESynGutterMarks, 0]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TIDESynEditor.GetIsInMultiCaretMainExecution: Boolean;
|
||||||
|
begin
|
||||||
|
Result := FMultiCaret.IsInMainExecution;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIDESynEditor.GetIsInMultiCaretRepeatExecution: Boolean;
|
||||||
|
begin
|
||||||
|
Result := FMultiCaret.IsInRepeatExecution;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TIDESynEditor.GetOnMultiCaretBeforeCommand: TSynMultiCaretBeforeCommand;
|
||||||
|
begin
|
||||||
|
Result := FMultiCaret.OnBeforeCommand;
|
||||||
|
end;
|
||||||
|
|
||||||
function TIDESynEditor.IsIfdefMarkupActive: Boolean;
|
function TIDESynEditor.IsIfdefMarkupActive: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := FMarkupIfDef.RealEnabled;
|
Result := FMarkupIfDef.RealEnabled;
|
||||||
@ -1610,14 +1637,12 @@ begin
|
|||||||
FUserWordsList := TFPList.Create;
|
FUserWordsList := TFPList.Create;
|
||||||
FTemplateEdit:=TSynPluginTemplateEdit.Create(Self);
|
FTemplateEdit:=TSynPluginTemplateEdit.Create(Self);
|
||||||
FSyncroEdit := TSynPluginSyncroEdit.Create(Self);
|
FSyncroEdit := TSynPluginSyncroEdit.Create(Self);
|
||||||
{$IFnDEF WithoutSynMultiCaret}
|
|
||||||
FMultiCaret := TSynPluginMultiCaret.Create(Self);
|
FMultiCaret := TSynPluginMultiCaret.Create(Self);
|
||||||
FMultiCaret.MouseActions.Clear; // will be added to SynEdit
|
FMultiCaret.MouseActions.Clear; // will be added to SynEdit
|
||||||
FMultiCaret.KeyStrokes.Clear;
|
FMultiCaret.KeyStrokes.Clear;
|
||||||
FMultiCaret.SetCaretTypeSize(ctVerticalLine, 2, 1024, -1, 0, [ccsRelativeHeight]);
|
FMultiCaret.SetCaretTypeSize(ctVerticalLine, 2, 1024, -1, 0, [ccsRelativeHeight]);
|
||||||
FMultiCaret.SetCaretTypeSize(ctBlock, 1024, 1024, 0, 0, [ccsRelativeWidth, ccsRelativeHeight]);
|
FMultiCaret.SetCaretTypeSize(ctBlock, 1024, 1024, 0, 0, [ccsRelativeWidth, ccsRelativeHeight]);
|
||||||
FMultiCaret.Color := $606060;
|
FMultiCaret.Color := $606060;
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
FMarkupForGutterMark := TSynEditMarkupGutterMark.Create(Self, FWordBreaker);
|
FMarkupForGutterMark := TSynEditMarkupGutterMark.Create(Self, FWordBreaker);
|
||||||
TSynEditMarkupManager(MarkupMgr).AddMarkUp(FMarkupForGutterMark);
|
TSynEditMarkupManager(MarkupMgr).AddMarkUp(FMarkupForGutterMark);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user