SynEdit: Add key-bindings for column-mode-selection (ALT-Shift-Cursor*). Issue #13238. (Based on a patch by dmitry boyarintsev)

git-svn-id: trunk@18908 -
This commit is contained in:
martin 2009-03-07 12:20:26 +00:00
parent 1929a0bdbf
commit 72776045a9
6 changed files with 165 additions and 32 deletions

View File

@ -5806,9 +5806,14 @@ begin
IncPaintLock;
bCaretAdjust := FCaret.AdjustToNextChar;
try
if Command in [ecColSelLeft..ecColSelEditorBottom] then
FBlockSelection.ActiveSelectionMode := smColumn
else
FBlockSelection.ActiveSelectionMode := FBlockSelection.SelectionMode;
case Command of
// horizontal caret movement or selection
ecLeft, ecSelLeft:
ecLeft, ecSelLeft, ecColSelLeft:
begin
{$IFDEF SYN_LAZARUS}
if (eoCaretSkipsSelection in Options2) and (Command=ecLeft)
@ -5816,9 +5821,9 @@ begin
CaretXY:=LogicalToPhysicalPos(BlockBegin);
end else
{$ENDIF}
MoveCaretHorz(-1, Command = ecSelLeft);
MoveCaretHorz(-1, Command in [ecSelLeft, ecColSelLeft]);
end;
ecRight, ecSelRight:
ecRight, ecSelRight, ecColSelRight:
begin
{$IFDEF SYN_LAZARUS}
if (eoCaretSkipsSelection in Options2) and (Command=ecRight)
@ -5826,41 +5831,41 @@ begin
CaretXY:=LogicalToPhysicalPos(BlockEnd);
end else
{$ENDIF}
MoveCaretHorz(1, Command = ecSelRight);
MoveCaretHorz(1, Command in [ecSelRight, ecColSelRight]);
end;
ecPageLeft, ecSelPageLeft:
ecPageLeft, ecSelPageLeft, ecColSelPageLeft:
begin
MoveCaretHorz(-CharsInWindow, Command = ecSelPageLeft);
MoveCaretHorz(-CharsInWindow, Command in [ecSelPageLeft, ecColSelPageLeft]);
end;
ecPageRight, ecSelPageRight:
ecPageRight, ecSelPageRight, ecColSelPageRight:
begin
MoveCaretHorz(CharsInWindow, Command = ecSelPageRight);
MoveCaretHorz(CharsInWindow, Command in [ecSelPageRight, ecColSelPageRight]);
end;
ecLineStart, ecSelLineStart:
DoHomeKey(Command=ecSelLineStart);
ecLineStart, ecSelLineStart, ecColSelLineStart:
DoHomeKey(Command in [ecSelLineStart, ecColSelLineStart]);
{begin
MoveCaretAndSelectionPhysical(CaretXY,Point(1, CaretY),
Command = ecSelLineStart);
fLastCaretX := CaretX;
end;}
ecLineEnd, ecSelLineEnd:
DoEndKey(Command=ecSelLineEnd);
ecLineEnd, ecSelLineEnd, ecColSelLineEnd:
DoEndKey(Command in [ecSelLineEnd, ecColSelLineEnd]);
// vertical caret movement or selection
ecUp, ecSelUp:
ecUp, ecSelUp, ecColSelUp:
begin
MoveCaretVert(-1, Command = ecSelUp);
MoveCaretVert(-1, Command in [ecSelUp, ecColSelUp]);
{$IFNDEF SYN_LAZARUS}
Update;
{$ENDIF}
end;
ecDown, ecSelDown:
ecDown, ecSelDown, ecColSelDown:
begin
MoveCaretVert(1, Command = ecSelDown);
MoveCaretVert(1, Command in [ecSelDown, ecColSelDown]);
{$IFNDEF SYN_LAZARUS}
Update;
{$ENDIF}
end;
ecPageUp, ecSelPageUp, ecPageDown, ecSelPageDown:
ecPageUp, ecSelPageUp, ecPageDown, ecSelPageDown, ecColSelPageUp, ecColSelPageDown:
begin
{$IFDEF SYN_LAZARUS}
counter := fLinesInWindow;
@ -5877,20 +5882,20 @@ begin
{$ELSE}
TopLine := TopLine + counter;
{$ENDIF}
MoveCaretVert(counter, Command in [ecSelPageUp, ecSelPageDown]);
MoveCaretVert(counter, Command in [ecSelPageUp, ecSelPageDown, ecColSelPageUp, ecColSelPageDown]);
Update;
end;
ecPageTop, ecSelPageTop:
ecPageTop, ecSelPageTop, ecColSelPageTop:
begin
{$IFDEF SYN_LAZARUS}
MoveCaretAndSelectionPhysical
{$ELSE}
MoveCaretAndSelection
{$ENDIF}
(CaretXY, Point(CaretX, TopLine), Command = ecSelPageTop);
(CaretXY, Point(CaretX, TopLine), Command in [ecSelPageTop, ecColSelPageTop]);
Update;
end;
ecPageBottom, ecSelPageBottom:
ecPageBottom, ecSelPageBottom, ecColSelPageBottom:
begin
CaretNew := Point(CaretX, ScreenRowToRow(LinesInWindow - 1));
{$IFDEF SYN_LAZARUS}
@ -5898,20 +5903,20 @@ begin
{$ELSE}
MoveCaretAndSelection
{$ENDIF}
(CaretXY, CaretNew, Command = ecSelPageBottom);
(CaretXY, CaretNew, Command in [ecSelPageBottom, ecColSelPageBottom]);
Update;
end;
ecEditorTop, ecSelEditorTop:
ecEditorTop, ecSelEditorTop, ecColSelEditorTop:
begin
{$IFDEF SYN_LAZARUS}
MoveCaretAndSelectionPhysical
{$ELSE}
MoveCaretAndSelection
{$ENDIF}
(CaretXY, Point(1, 1), Command = ecSelEditorTop);
(CaretXY, Point(1, 1), Command in [ecSelEditorTop, ecColSelEditorTop]);
Update;
end;
ecEditorBottom, ecSelEditorBottom:
ecEditorBottom, ecSelEditorBottom, ecColSelEditorBottom:
begin
{$IFDEF SYN_LAZARUS}
CaretNew := Point(1, FFoldedLinesView.ViewPosToTextIndex(FFoldedLinesView.Count)+1);
@ -5926,7 +5931,7 @@ begin
{$ELSE}
CaretXY,
{$ENDIF}
CaretNew, Command = ecSelEditorBottom);
CaretNew, Command in [ecSelEditorBottom, ecColSelEditorBottom]);
Update;
end;
// goto special line / column position
@ -7630,7 +7635,8 @@ begin
FCaret.ForcePastEOL := True;
if SelectionCommand then begin
//debugln('TCustomSynEdit.MoveCaretHorz A CaretXY=',dbgs(CaretXY),' NewCaret=',dbgs(NewCaret));
if not SelAvail then SetBlockBegin(PhysicalToLogicalPos(CaretXY));
if not FBlockSelection.SelCanContinue(FCaret) then
SetBlockBegin(PhysicalToLogicalPos(CaretXY));
SetBlockEnd(FInternalCaret.LineBytePos);
//debugln('TCustomSynEdit.MoveCaretHorz B BB=',dbgs(BlockBegin),' BE=',dbgs(BlockEnd));
AquirePrimarySelection;
@ -7696,6 +7702,7 @@ var
NewCaret: TPoint;
OldCaret: TPoint;
SaveLastCaretX: LongInt;
SelContinue: Boolean;
begin
OldCaret:=CaretXY;
NewCaret:=OldCaret;
@ -7705,11 +7712,12 @@ begin
NewCaret.X:=fLastCaretX;
IncPaintLock;
SaveLastCaretX:=fLastCaretX;
SelContinue := FBlockSelection.SelCanContinue(FCaret);
CaretXY:=NewCaret;
fLastCaretX:=SaveLastCaretX;
// set caret and block begin / end
if SelectionCommand then begin
if not SelAvail then begin
if not SelContinue then begin
OldCaret := PhysicalToLogicalPos(OldCaret);
if (OldCaret.X > Length(FTheLinesView[OldCaret.Y-1]) + 1) and
not(eoScrollPastEol in Options) then

View File

@ -96,6 +96,7 @@ const
ecSelection = 100; // Add this to ecXXX command to get equivalent
// command, but with selection enabled. This is not
// a command itself.
// Same as commands above, except they affect selection, too
ecSelLeft = ecLeft + ecSelection;
ecSelRight = ecRight + ecSelection;
@ -115,6 +116,26 @@ const
ecSelEditorBottom = ecEditorBottom + ecSelection;
ecSelGotoXY = ecGotoXY + ecSelection; // Data = PPoint
// Allow access to column mode selection
ecColumnSelection = ecSelection+50;
ecColSelLeft = ecLeft + ecColumnSelection;
ecColSelRight = ecRight + ecColumnSelection;
ecColSelUp = ecUp + ecColumnSelection;
ecColSelDown = ecDown + ecColumnSelection;
ecColSelLineStart = ecLineStart + ecColumnSelection;
ecColSelLineEnd = ecLineEnd + ecColumnSelection;
ecColSelPageUp = ecPageUp + ecColumnSelection;
ecColSelPageDown = ecPageDown + ecColumnSelection;
ecColSelPageLeft = ecPageLeft + ecColumnSelection;
ecColSelPageRight = ecPageRight + ecColumnSelection;
ecColSelPageTop = ecPageTop + ecColumnSelection;
ecColSelPageBottom = ecPageBottom + ecColumnSelection;
ecColSelEditorTop = ecEditorTop + ecColumnSelection;
ecColSelEditorBottom = ecEditorBottom + ecColumnSelection;
ecSelectAll = 199; // Select entire contents of editor, cursor to end
ecCopy = 201; // Copy selection to clipboard
@ -967,6 +988,19 @@ begin
AddKey(ecTab, VK_TAB, []);
AddKey(ecShiftTab, VK_TAB, [ssShift]);
AddKey(ecMatchBracket, ord('B'), [ssCtrl,ssShift]);
AddKey(ecColSelUp, VK_UP, [ssAlt, ssShift]);
AddKey(ecColSelDown, VK_DOWN, [ssAlt, ssShift]);
AddKey(ecColSelLeft, VK_LEFT, [ssAlt, ssShift]);
AddKey(ecColSelRight, VK_RIGHT, [ssAlt, ssShift]);
AddKey(ecColSelPageDown, VK_NEXT, [ssAlt, ssShift]);
AddKey(ecColSelPageBottom, VK_NEXT, [ssAlt, ssShift,ssCtrl]);
AddKey(ecColSelPageUp, VK_PRIOR, [ssAlt, ssShift]);
AddKey(ecColSelPageTop, VK_PRIOR, [ssAlt, ssShift,ssCtrl]);
AddKey(ecColSelLineStart, VK_HOME, [ssAlt, ssShift]);
AddKey(ecColSelLineEnd, VK_END, [ssAlt, ssShift]);
AddKey(ecColSelEditorTop, VK_HOME, [ssAlt, ssShift,ssCtrl]);
AddKey(ecColSelEditorBottom, VK_END, [ssAlt, ssShift,ssCtrl]);
end;
procedure TSynEditKeyStrokes.SetItem(Index: Integer; Value: TSynEditKeyStroke);

View File

@ -533,7 +533,7 @@ begin
Accept;
Handled := True;
end;
ecLeft, ecSelLeft:
ecLeft, ecSelLeft, ecColSelLeft:
if CurrentString = '' then
Handled := True;
ecDeleteLastChar:
@ -542,7 +542,7 @@ begin
ecTab:
Accept;
ecDeleteChar,
ecRight, ecSelRight,
ecRight, ecSelRight, ecColSelRight,
ecLostFocus, ecGotFocus:
; {processed on AfterProcessing}
else
@ -555,10 +555,10 @@ begin
ecDeleteChar:
;
ecDeleteLastChar,
ecLeft, ecSelLeft,
ecLeft, ecSelLeft, ecColSelLeft,
ecChar:
CurrentString := GetCurrentEditorString;
ecRight, ecSelRight: begin
ecRight, ecSelRight, ecColSelRight: begin
iString := GetCurrentEditorString;
if iString = '' then
Cancel

View File

@ -106,6 +106,7 @@ type
procedure SetSelTextPrimitive(PasteMode: TSynSelectionMode; Value: PChar;
AddToUndoList: Boolean = false; ChangeReason: TSynChangeReason = crInsert);
function SelAvail: Boolean;
function SelCanContinue(ACaret: TSynEditCaret): Boolean;
function IsBackwardSel: Boolean; // SelStart < SelEnd ?
property Enabled: Boolean read FEnabled write SetEnabled;
property SpacesToTabs: Boolean read FSpacesToTabs write FSpacesToTabs;
@ -1081,6 +1082,13 @@ begin
((FStartLinePos <> FEndLinePos) and (FActiveSelectionMode <> smColumn));
end;
function TSynEditSelection.SelCanContinue(ACaret: TSynEditCaret): Boolean;
begin
if SelAvail then exit(True);
Result := (FActiveSelectionMode = smColumn) and (FEndLinePos = ACaret.LinePos)
and (FEndBytePos = ACaret.BytePos);
end;
function TSynEditSelection.IsBackwardSel: Boolean;
begin
Result := (FStartLinePos > FEndLinePos)

View File

@ -271,6 +271,20 @@ begin
ecSelectionSort: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionBreakLines: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
// column mode selection
ecColSelUp: SetResult(VK_UP, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelDown: SetResult(VK_DOWN, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelLeft: SetResult(VK_LEFT, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelRight: SetResult(VK_RIGHT, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelPageDown: SetResult(VK_NEXT, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelPageBottom: SetResult(VK_NEXT, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
ecColSelPageUp: SetResult(VK_PRIOR, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelPageTop: SetResult(VK_PRIOR, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
ecColSelLineStart: SetResult(VK_HOME, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelLineEnd: SetResult(VK_END, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelEditorTop: SetResult(VK_HOME, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
ecColSelEditorBottom: SetResult(VK_END, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
// editing
ecBlockIndent: SetResult2(VK_I,[ssCtrl],VK_UNKNOWN,[],VK_K,[SSCtrl],VK_I,[]);
ecBlockUnindent: SetResult2(VK_U,[ssCtrl],VK_UNKNOWN,[],VK_K,[SSCtrl],VK_U,[]);
@ -624,6 +638,20 @@ begin
ecSelectionSort: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
ecSelectionBreakLines: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
// column mode selection
ecColSelUp: SetResult(VK_UP, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelDown: SetResult(VK_DOWN, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelLeft: SetResult(VK_LEFT, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelRight: SetResult(VK_RIGHT, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelPageDown: SetResult(VK_NEXT, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelPageBottom: SetResult(VK_NEXT, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelPageUp: SetResult(VK_PRIOR, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelPageTop: SetResult(VK_PRIOR, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelLineStart: SetResult(VK_HOME, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelLineEnd: SetResult(VK_END, [ssAlt, ssShift], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelEditorTop: SetResult(VK_HOME, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
ecColSelEditorBottom: SetResult(VK_END, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[], VK_UNKNOWN,[], VK_UNKNOWN,[]);
// editing
ecBlockIndent: SetResult(VK_K,[ssCtrl],VK_I,[],VK_UNKNOWN,[],VK_UNKNOWN,[]);
ecBlockUnindent: SetResult(VK_K,[ssCtrl],VK_U,[],VK_UNKNOWN,[],VK_UNKNOWN,[]);
@ -1130,6 +1158,20 @@ begin
ecSelectionSort: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionBreakLines: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
// column mode selection
ecColSelUp: SetResult(VK_UP, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelDown: SetResult(VK_DOWN, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelLeft: SetResult(VK_LEFT, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelRight: SetResult(VK_RIGHT, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelPageDown: SetResult(VK_NEXT, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelPageBottom: SetResult(VK_NEXT, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
ecColSelPageUp: SetResult(VK_PRIOR, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelPageTop: SetResult(VK_PRIOR, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
ecColSelLineStart: SetResult(VK_HOME, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelLineEnd: SetResult(VK_END, [ssAlt, ssShift], VK_UNKNOWN,[]);
ecColSelEditorTop: SetResult(VK_HOME, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
ecColSelEditorBottom: SetResult(VK_END, [ssAlt, ssShift,ssCtrl], VK_UNKNOWN,[]);
// editing
ecBlockIndent: SetResult2(VK_I,[ssCtrl],VK_UNKNOWN,[],VK_K,[SSCtrl],VK_I,[]);
ecBlockUnindent: SetResult2(VK_U,[ssCtrl],VK_UNKNOWN,[],VK_K,[SSCtrl],VK_U,[]);
@ -1524,6 +1566,18 @@ begin
ecSelPageBottom : Result:= srkmecSelPageBottom;
ecSelEditorTop : Result:= srkmecSelEditorTop;
ecSelEditorBottom : Result:= srkmecSelEditorBottom;
ecColSelUp : Result:= srkmecColSelUp;
ecColSelDown : Result:= srkmecColSelDown;
ecColSelLeft : Result:= srkmecColSelLeft;
ecColSelRight : Result:= srkmecColSelRight;
ecColSelPageDown : Result:= srkmecColSelPageDown;
ecColSelPageBottom : Result:= srkmecColSelPageBottom;
ecColSelPageUp : Result:= srkmecColSelPageUp;
ecColSelPageTop : Result:= srkmecColSelPageTop;
ecColSelLineStart : Result:= srkmecColSelLineStart;
ecColSelLineEnd : Result:= srkmecColSelLineEnd;
ecColSelEditorTop : Result:= srkmecColSelEditorTop;
ecColSelEditorBottom : Result:= srkmecColSelEditorBottom;
ecSelGotoXY : Result:= srkmecSelGotoXY;
ecSelectAll : Result:= srkmecSelectAll;
ecDeleteLastChar : Result:= srkmecDeleteLastChar;
@ -1990,6 +2044,22 @@ begin
AddDefault(C, 'Select paragraph', lisMenuSelectParagraph, ecSelectParagraph);
AddDefault(C, 'Toggle Current-Word highlight', srkmecToggleMarkupWord, EcToggleMarkupWord);
// column mode selection
C:=Categories[AddCategory('Column Selection',srkmCatColSelection,
IDECmdScopeSrcEditOnly)];
AddDefault(C, 'Column Select Up', srkmecColSelUp, ecColSelUp);
AddDefault(C, 'Column Select Down', srkmecColSelDown, ecColSelDown);
AddDefault(C, 'Column Select Left', srkmecColSelLeft, ecColSelLeft);
AddDefault(C, 'Column Select Right', srkmecColSelRight, ecColSelRight);
AddDefault(C, 'Column Select Page Down', srkmecColSelPageDown, ecColSelPageDown);
AddDefault(C, 'Column Select Page Bottom', srkmecColSelPageBottom, ecColSelPageBottom);
AddDefault(C, 'Column Select Page Up', srkmecColSelPageUp, ecColSelPageUp);
AddDefault(C, 'Column Select Page Top', srkmecColSelPageTop, ecColSelPageTop);
AddDefault(C, 'Column Select Line Start', srkmecColSelLineStart, ecColSelLineStart);
AddDefault(C, 'Column Select Line End', srkmecColSelLineEnd, ecColSelLineEnd);
AddDefault(C, 'Column Select to absolute beginning', srkmecColSelEditorTop, ecColSelEditorTop);
AddDefault(C, 'Column Select to absolute end', srkmecColSelEditorBottom, ecColSelEditorBottom);
// editing - without menu items in the IDE bar
C:=Categories[AddCategory('text editing commands',srkmCatEditing,
IDECmdScopeSrcEditOnly)];

View File

@ -1838,6 +1838,18 @@ resourcestring
srkmecSelPageBottom = 'Select Page Bottom';
srkmecSelEditorTop = 'Select to absolute beginning';
srkmecSelEditorBottom = 'Select to absolute end';
srkmecColSelUp = 'Column Select Up';
srkmecColSelDown = 'Column Select Down';
srkmecColSelLeft = 'Column Select Left';
srkmecColSelRight = 'Column Select Right';
srkmecColSelPageDown = 'Column Select Page Down';
srkmecColSelPageBottom = 'Column Select Page Bottom';
srkmecColSelPageUp = 'Column Select Page Up';
srkmecColSelPageTop = 'Column Select Page Top';
srkmecColSelLineStart = 'Column Select Line Start';
srkmecColSelLineEnd = 'Column Select Line End';
srkmecColSelEditorTop = 'Column Select to absolute beginning';
srkmecColSelEditorBottom = 'Column Select to absolute end';
srkmecSelGotoXY = 'Select Goto XY';
srkmecSelectAll = 'Select All';
srkmecDeleteLastChar = 'Delete Last Char';
@ -2065,6 +2077,7 @@ resourcestring
// Category
srkmCatCursorMoving = 'Cursor moving commands';
srkmCatSelection = 'Text selection commands';
srkmCatColSelection = 'Text column selection commands';
srkmCatEditing = 'Text editing commands';
lisKMDeleteLastChar = 'Delete last char';
srkmCatCmdCmd = 'Command commands';