SYnEdit: multi caret, IDE integration, and refactor

git-svn-id: trunk@48395 -
This commit is contained in:
martin 2015-03-16 16:42:16 +00:00
parent 6e3dd69f06
commit 5e498c6211
6 changed files with 422 additions and 181 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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