PageRenderTime 145ms CodeModel.GetById 53ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 0ms

/components/synedit/syneditmousecmds.pp

http://github.com/graemeg/lazarus
Pascal | 1101 lines | 899 code | 147 blank | 55 comment | 72 complexity | 124b89d15b41c580c057cc6c9a35f3d4 MD5 | raw file
   1{ Mouse Command Configuration for SynEdit
   2
   3  Copyright (C) 2009 Martn Friebe
   4
   5  The contents of this file are subject to the Mozilla Public License
   6  Version 1.1 (the "License"); you may not use this file except in compliance
   7  with the License. You may obtain a copy of the License at
   8  http://www.mozilla.org/MPL/
   9
  10  Software distributed under the License is distributed on an "AS IS" basis,
  11  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  12  the specific language governing rights and limitations under the License.
  13
  14  Alternatively, the contents of this file may be used under the terms of the
  15  GNU General Public License Version 2 or later (the "GPL"), in which case
  16  the provisions of the GPL are applicable instead of those above.
  17  If you wish to allow use of your version of this file only under the terms
  18  of the GPL and not to allow others to use your version of this file
  19  under the MPL, indicate your decision by deleting the provisions above and
  20  replace them with the notice and other provisions required by the GPL.
  21  If you do not delete the provisions above, a recipient may use your version
  22  of this file under either the MPL or the GPL.
  23
  24  A copy of the GNU General Public License is available on the World Wide Web
  25  at <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing
  26  to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  27  MA 02111-1307, USA.
  28
  29}
  30
  31unit SynEditMouseCmds;
  32
  33{$I synedit.inc}
  34
  35interface
  36
  37uses
  38  LazSynEditMouseCmdsTypes, Classes, Controls, SysUtils, SynEditStrConst, SynEditPointClasses,
  39  SynEditKeyCmds, Dialogs, LCLProc, Menus;
  40
  41type
  42
  43  TSynEditorMouseOption = (
  44    emUseMouseActions,         // Enable mouse actions
  45    emAltSetsColumnMode,       // Allows to activate "column" selection mode, if <Alt> key is pressed and text is being selected with mouse
  46    emDragDropEditing,         // Allows to drag-and-drop text blocks within the control
  47    emRightMouseMovesCursor,   // When clicking with the right mouse button, for a popup menu, move the caret to clicked position
  48    emDoubleClickSelectsLine,  // Selects entire line with double-click, otherwise double-click selects only current word
  49    emShowCtrlMouseLinks,      // Pressing <Ctrl> key (SYNEDIT_LINK_MODIFIER) will highlight the word under mouse cursor
  50    emCtrlWheelZoom            // Allows to zoom editor by <Ctrl+MouseWheel> commands
  51  );
  52  TSynEditorMouseOptions = set of TSynEditorMouseOption;
  53
  54  TSynEditorMouseCommand = type word;
  55  TSynEditorMouseCommandOpt = type word;
  56  TSynMouseButton = LazSynEditMouseCmdsTypes.TSynMouseButton;
  57  TSynMAClickCount = (ccSingle, ccDouble, ccTriple, ccQuad, ccAny);
  58  TSynMAClickDir = (cdUp, cdDown);
  59  TSynMAUpRestriction = ( // Restrict cdUp
  60    crLastDownPos,                     // check if the lasth MouseDown had same Pos (as in would have triggered the same command)
  61    crLastDownPosSameLine,             // check if the last dow
  62    crLastDownPosSearchAll,            // allow to find downclick at lower priority or parent list
  63    crLastDownButton, crLastDownShift, // check if the lasth MouseDown had same Button / Shift
  64    crAllowFallback  // If action is restricted, continue search for up action in (fallback, or parent list)
  65  );
  66  TSynMAUpRestrictions = set of TSynMAUpRestriction;
  67  ESynMouseCmdError = class(Exception);
  68
  69const
  70  crRestrictAll = [crLastDownPos, crLastDownPosSameLine, crLastDownButton, crLastDownShift];
  71
  72  mbXLeft      =  LazSynEditMouseCmdsTypes.mbLeft;
  73  mbXRight     =  LazSynEditMouseCmdsTypes.mbRight;
  74  mbXMiddle    =  LazSynEditMouseCmdsTypes.mbMiddle;
  75  mbXExtra1    =  LazSynEditMouseCmdsTypes.mbExtra1;
  76  mbXExtra2    =  LazSynEditMouseCmdsTypes.mbExtra2;
  77  mbXWheelUp   =  LazSynEditMouseCmdsTypes.mbWheelUp;
  78  mbXWheelDown =  LazSynEditMouseCmdsTypes.mbWheelDown;
  79
  80  SynMouseButtonMap: Array [TMouseButton] of TSynMouseButton =
  81    (mbXLeft, mbXRight, mbXMiddle, mbXExtra1, mbXExtra2);
  82
  83  SynMouseButtonBackMap: Array [TSynMouseButton] of TMouseButton =
  84    (Controls.mbLeft, Controls.mbRight, Controls.mbMiddle,
  85     Controls.mbExtra1, Controls.mbExtra2,
  86     Controls.mbLeft, Controls.mbLeft);
  87
  88type
  89
  90  // Mouse actions to be handled *after* paintlock
  91  TSynEditMouseActionResult = record
  92    DoPopUpEvent: Boolean;               // Trigger OnContextPopUp, only valid if PopUpMenu is set
  93    PopUpEventX, PopUpEventY: Integer;
  94    PopUpMenu: TPopupMenu;               // PopupMenu to Display (must be outside PaintLock)
  95  end;
  96
  97  TSynEditMouseActionInfo = record
  98    NewCaret: TSynEditCaret;
  99    Button: TSynMouseButton;
 100    Shift: TShiftState;
 101    MouseX, MouseY, WheelDelta: Integer;
 102    CCount: TSynMAClickCount;
 103    Dir: TSynMAClickDir;
 104    CaretDone: Boolean; // Return Value
 105    IgnoreUpClick: Boolean;
 106    ActionResult: TSynEditMouseActionResult;
 107  end;
 108
 109  { TSynEditMouseAction }
 110
 111  TSynEditMouseAction = class(TCollectionItem)
 112  private
 113    FButtonUpRestrictions: TSynMAUpRestrictions;
 114    FClickDir: TSynMAClickDir;
 115    FIgnoreUpClick: Boolean;
 116    FOption: TSynEditorMouseCommandOpt;
 117    FOption2: Integer;
 118    FPriority: TSynEditorMouseCommandOpt;
 119    FShift, FShiftMask: TShiftState;
 120    FButton: TSynMouseButton;
 121    FClickCount: TSynMAClickCount;
 122    FCommand: TSynEditorMouseCommand;
 123    FMoveCaret: Boolean;
 124    procedure SetButton(const AValue: TSynMouseButton);
 125    procedure SetButtonUpRestrictions(AValue: TSynMAUpRestrictions);
 126    procedure SetClickCount(const AValue: TSynMAClickCount);
 127    procedure SetClickDir(AValue: TSynMAClickDir);
 128    procedure SetCommand(const AValue: TSynEditorMouseCommand);
 129    procedure SetIgnoreUpClick(AValue: Boolean);
 130    procedure SetMoveCaret(const AValue: Boolean);
 131    procedure SetOption(const AValue: TSynEditorMouseCommandOpt);
 132    procedure SetOption2(AValue: Integer);
 133    procedure SetPriority(const AValue: TSynEditorMouseCommandOpt);
 134    procedure SetShift(const AValue: TShiftState);
 135    procedure SetShiftMask(const AValue: TShiftState);
 136  protected
 137    function GetDisplayName: string; override;
 138  public
 139    procedure Assign(Source: TPersistent); override;
 140    procedure Clear;
 141    function IsMatchingShiftState(AShift: TShiftState): Boolean;
 142    function IsMatchingClick(ABtn: TSynMouseButton; ACCount: TSynMAClickCount;
 143                             ACDir: TSynMAClickDir): Boolean;
 144    function IsFallback: Boolean;
 145    function Conflicts(Other: TSynEditMouseAction): Boolean;
 146    function Equals(Other: TSynEditMouseAction; IgnoreCmd: Boolean = False): Boolean; reintroduce;
 147  published
 148    property Shift: TShiftState read FShift write SetShift                      default [];
 149    property ShiftMask: TShiftState read FShiftMask write SetShiftMask          default [];
 150    property Button: TSynMouseButton read FButton write SetButton               default mbXLeft;
 151    property ClickCount: TSynMAClickCount read FClickCount write SetClickCount  default ccSingle;
 152    property ClickDir: TSynMAClickDir read FClickDir write SetClickDir          default cdUp;
 153    property ButtonUpRestrictions: TSynMAUpRestrictions
 154             read FButtonUpRestrictions write SetButtonUpRestrictions           default [];
 155    property Command: TSynEditorMouseCommand read FCommand write SetCommand;
 156    property MoveCaret: Boolean read FMoveCaret write SetMoveCaret              default False;
 157    property IgnoreUpClick: Boolean read FIgnoreUpClick write SetIgnoreUpClick  default False; // only for mouse down
 158    property Option: TSynEditorMouseCommandOpt read FOption write SetOption     default 0;
 159    property Option2: Integer read FOption2 write SetOption2                    default 0;
 160    // Priority: 0 = highest / MaxInt = lowest
 161    property Priority: TSynEditorMouseCommandOpt read FPriority write SetPriority default 0;
 162  end;
 163
 164  { TSynEditMouseActions }
 165
 166  TSynEditMouseActions = class(TCollection)
 167  private
 168    FOwner: TPersistent;
 169    FAssertLock: Integer;
 170    function GetItem(Index: Integer): TSynEditMouseAction;
 171    procedure SetItem(Index: Integer; const AValue: TSynEditMouseAction);
 172  protected
 173    function GetOwner: TPersistent; override;
 174    procedure Update(Item: TCollectionItem); override;
 175  public
 176    constructor Create(AOwner: TPersistent);
 177    function Add: TSynEditMouseAction;
 178    procedure Assign(Source: TPersistent); override;
 179    procedure AssertNoConflict(MAction: TSynEditMouseAction);
 180    function Equals(Other: TSynEditMouseActions): Boolean; reintroduce;
 181    function FindCommand(AnInfo: TSynEditMouseActionInfo;
 182                         APrevious: TSynEditMouseAction = nil): TSynEditMouseAction;
 183    procedure ResetDefaults; virtual;
 184    procedure IncAssertLock;
 185    procedure DecAssertLock;
 186    function  IndexOf(MAction: TSynEditMouseAction;
 187                      IgnoreCmd: Boolean = False): Integer;
 188    procedure AddCommand(const ACmd: TSynEditorMouseCommand;
 189             const AMoveCaret: Boolean;
 190             const AButton: TSynMouseButton; const AClickCount: TSynMAClickCount;
 191             const ADir: TSynMAClickDir; const AShift, AShiftMask: TShiftState;
 192             const AOpt: TSynEditorMouseCommandOpt = 0;
 193             const APrior: Integer = 0;
 194             const AOpt2: integer = 0;
 195             const AIgnoreUpClick: Boolean = False); overload;
 196    procedure AddCommand(const ACmd: TSynEditorMouseCommand;
 197             const AMoveCaret: Boolean;
 198             const AButton: TSynMouseButton; const AClickCount: TSynMAClickCount;
 199             const ADir: TSynMAClickDir; const AnUpRestrict: TSynMAUpRestrictions;
 200             const AShift, AShiftMask: TShiftState;
 201             const AOpt: TSynEditorMouseCommandOpt = 0;
 202             const APrior: Integer = 0;
 203             const AOpt2: integer = 0;
 204             const AIgnoreUpClick: Boolean = False); overload;
 205  public
 206    property Items[Index: Integer]: TSynEditMouseAction read GetItem
 207      write SetItem; default;
 208  end;
 209
 210  { TSynEditMouseInternalActions }
 211
 212  TSynEditMouseInternalActions = class(TSynEditMouseActions)
 213  private
 214    FOptions, FInternOptions: TSynEditorMouseOptions;
 215    FUserActions: TSynEditMouseActions;
 216    procedure SetOptions(AValue: TSynEditorMouseOptions);
 217    procedure SetUserActions(AValue: TSynEditMouseActions);
 218  protected
 219    procedure InitForOptions(AnOptions: TSynEditorMouseOptions); virtual;
 220  public
 221    constructor Create(AOwner: TPersistent);
 222    destructor Destroy; override;
 223    procedure ResetDefaults; override;
 224    procedure ResetUserActions;
 225    function  GetActionsForOptions(AnOptions: TSynEditorMouseOptions): TSynEditMouseActions;
 226    property  Options: TSynEditorMouseOptions read FOptions write SetOptions;
 227    property  UserActions: TSynEditMouseActions read FUserActions write SetUserActions;
 228  end;
 229
 230
 231  TSynEditMouseActionHandler = function(AnActionList: TSynEditMouseActions;
 232    var AnInfo: TSynEditMouseActionInfo): Boolean of object;
 233
 234  // Called by SynEdit
 235  // Should Call "HandleActionProc" for each ActionList it want's to check
 236  TSynEditMouseActionSearchProc = function(var AnInfo: TSynEditMouseActionInfo;
 237    HandleActionProc: TSynEditMouseActionHandler): Boolean of object;
 238
 239  // Called by "HandleActionProc", if an Action was found in the list
 240  TSynEditMouseActionExecProc = function(AnAction: TSynEditMouseAction;
 241    var AnInfo: TSynEditMouseActionInfo): Boolean of object;
 242
 243  { TSynEditMouseActionSearchList }
 244
 245  TSynEditMouseActionSearchList = Class(TMethodList)
 246  public
 247    function CallSearchHandlers(var AnInfo: TSynEditMouseActionInfo;
 248                         HandleActionProc: TSynEditMouseActionHandler): Boolean;
 249  end;
 250
 251  { TSynEditMouseActionExecList }
 252
 253  TSynEditMouseActionExecList = Class(TMethodList)
 254  public
 255    function CallExecHandlers(AnAction: TSynEditMouseAction;
 256                                  var AnInfo: TSynEditMouseActionInfo): Boolean;
 257  end;
 258
 259const
 260  // EditorMouseCommands
 261
 262  emcNone                     =  TSynEditorMouseCommand(0);
 263  emcStartSelections          =  TSynEditorMouseCommand(1);    // Start BlockSelection (Default Left Mouse Btn)
 264  emcStartColumnSelections    =  TSynEditorMouseCommand(3);    // Column BlockSelection (Default Alt - Left Mouse Btn)
 265  emcStartLineSelections      =  TSynEditorMouseCommand(4);    // Line BlockSelection (Default Alt - Left Mouse Btn)
 266  emcStartLineSelectionsNoneEmpty =  TSynEditorMouseCommand(5);    // Line BlockSelection (Default Alt - Left Mouse Btn)
 267
 268  emcSelectWord               =  TSynEditorMouseCommand(6);
 269  emcSelectLine               =  TSynEditorMouseCommand(7);
 270  emcSelectPara               =  TSynEditorMouseCommand(8);
 271
 272  emcStartDragMove            =  TSynEditorMouseCommand(9);
 273  emcPasteSelection           = TSynEditorMouseCommand(10);
 274  emcMouseLink                = TSynEditorMouseCommand(11);
 275
 276  emcContextMenu              = TSynEditorMouseCommand(12);
 277
 278  emcOnMainGutterClick        = TSynEditorMouseCommand(13);    // OnGutterClick
 279
 280  emcCodeFoldCollaps          = TSynEditorMouseCommand(14);
 281  emcCodeFoldExpand           = TSynEditorMouseCommand(15);
 282  emcCodeFoldContextMenu      = TSynEditorMouseCommand(16);
 283
 284  emcSynEditCommand           = TSynEditorMouseCommand(17);    // Key-Commands
 285
 286  emcWheelScrollDown          = TSynEditorMouseCommand(18);
 287  emcWheelScrollUp            = TSynEditorMouseCommand(19);
 288
 289  emcWheelVertScrollDown      = TSynEditorMouseCommand(20);
 290  emcWheelVertScrollUp        = TSynEditorMouseCommand(21);
 291  emcWheelHorizScrollDown     = TSynEditorMouseCommand(22);
 292  emcWheelHorizScrollUp       = TSynEditorMouseCommand(23);
 293
 294  emcWheelZoomOut             = TSynEditorMouseCommand(24);
 295  emcWheelZoomIn              = TSynEditorMouseCommand(25);
 296  emcWheelZoomNorm            = TSynEditorMouseCommand(26);
 297
 298  emcStartSelectTokens        =  TSynEditorMouseCommand(27);    // Start BlockSelection, word/token wise
 299  emcStartSelectWords         =  TSynEditorMouseCommand(28);    // Start BlockSelection, wordwise
 300  emcStartSelectLines         =  TSynEditorMouseCommand(29);    // Start BlockSelection, linewise (but not line mode)
 301
 302  emcOverViewGutterGotoMark   = TSynEditorMouseCommand(30);
 303  emcOverViewGutterScrollTo   = TSynEditorMouseCommand(31);
 304
 305  emcMax = 31;
 306
 307  emcPluginFirstSyncro     = 19000;
 308  emcPluginFirstMultiCaret = 19010;
 309  emcPluginFirst = 20000;
 310
 311  // Options
 312  emcoSelectionStart          = TSynEditorMouseCommandOpt(0);
 313  emcoSelectionContinue       = TSynEditorMouseCommandOpt(1);
 314
 315  emcoSelectLineSmart         =  TSynEditorMouseCommandOpt(0);
 316  emcoSelectLineFull          =  TSynEditorMouseCommandOpt(1);
 317  emcoMouseLinkShow           =  TSynEditorMouseCommandOpt(0);
 318  emcoMouseLinkHide           =  TSynEditorMouseCommandOpt(1);
 319
 320  emcoNotDragedSetCaretOnUp   = TSynEditorMouseCommandOpt(0);
 321  emcoNotDragedNoCaretOnUp    = TSynEditorMouseCommandOpt(1);
 322
 323  emcoCodeFoldCollapsOne      = TSynEditorMouseCommandOpt(0);
 324  emcoCodeFoldCollapsAll      = TSynEditorMouseCommandOpt(1);
 325  emcoCodeFoldCollapsAtCaret  = TSynEditorMouseCommandOpt(2);
 326  emcoCodeFoldCollapsPreCaret = TSynEditorMouseCommandOpt(3);
 327  emcoCodeFoldExpandOne       = TSynEditorMouseCommandOpt(0);
 328  emcoCodeFoldExpandAll       = TSynEditorMouseCommandOpt(1);
 329
 330  // menu, and caret move
 331  emcoSelectionCaretMoveNever     = TSynEditorMouseCommandOpt(0);
 332  emcoSelectionCaretMoveOutside   = TSynEditorMouseCommandOpt(1); // click is outside selected area
 333  emcoSelectionCaretMoveAlways    = TSynEditorMouseCommandOpt(2);
 334
 335  emcoWheelScrollSystem         = TSynEditorMouseCommandOpt(0); // Opt2 > 0 ==> percentage
 336  emcoWheelScrollLines          = TSynEditorMouseCommandOpt(1); // Opt2 > 0 ==> amount of lines
 337  emcoWheelScrollPages          = TSynEditorMouseCommandOpt(2); // Opt2 > 0 ==> percentage
 338  emcoWheelScrollPagesLessOne   = TSynEditorMouseCommandOpt(3); // Opt2 > 0 ==> percentage
 339
 340type
 341  TMouseCmdNameAndOptProcs = function(emc: TSynEditorMouseCommand): String;
 342
 343// Plugins don't know of other plugins, so they need to map the codes
 344// Plugins all start at ecPluginFirst (overlapping)
 345// If ask by SynEdit they add an offset
 346
 347// Return the next offset
 348function AllocatePluginMouseRange(Count: Integer; OffsetOnly: Boolean = False): integer;
 349
 350function MouseCommandName(emc: TSynEditorMouseCommand): String;
 351function MouseCommandConfigName(emc: TSynEditorMouseCommand): String;
 352
 353function SynMouseCmdToIdent(SynMouseCmd: Longint; var Ident: String): Boolean;
 354function IdentToSynMouseCmd(const Ident: string; var SynMouseCmd: Longint): Boolean;
 355procedure GetEditorMouseCommandValues(Proc: TGetStrProc);
 356
 357procedure RegisterMouseCmdIdentProcs(IdentToIntFn: TIdentToInt; IntToIdentFn: TIntToIdent);
 358procedure RegisterExtraGetEditorMouseCommandValues(AProc: TGetEditorCommandValuesProc);
 359
 360procedure RegisterMouseCmdNameAndOptProcs(ANamesProc: TMouseCmdNameAndOptProcs; AOptProc: TMouseCmdNameAndOptProcs = nil);
 361
 362const
 363  SYNEDIT_LINK_MODIFIER = {$IFDEF LCLcarbon}ssMeta{$ELSE}ssCtrl{$ENDIF};
 364
 365implementation
 366
 367const
 368  SynMouseCommandNames: array [0..30] of TIdentMapEntry = (
 369    (Value: emcNone;                  Name: 'emcNone'),
 370    (Value: emcStartSelections;       Name: 'emcStartSelections'),
 371    (Value: emcStartColumnSelections; Name: 'emcStartColumnSelections'),
 372    (Value: emcStartLineSelections;   Name: 'emcStartLineSelections'),
 373    (Value: emcStartLineSelectionsNoneEmpty;   Name: 'emcStartLineSelectionsNoneEmpty'),
 374
 375    (Value: emcSelectWord;            Name: 'emcSelectWord'),
 376    (Value: emcSelectLine;            Name: 'emcSelectLine'),
 377    (Value: emcSelectPara;            Name: 'emcSelectPara'),
 378
 379    (Value: emcStartDragMove;         Name: 'emcStartDragMove'),
 380    (Value: emcPasteSelection;        Name: 'emcPasteSelection'),
 381    (Value: emcMouseLink;             Name: 'emcMouseLink'),
 382
 383    (Value: emcContextMenu;           Name: 'emcContextMenu'),
 384
 385    (Value: emcOnMainGutterClick;     Name: 'emcOnMainGutterClick'),
 386
 387    (Value: emcCodeFoldCollaps;       Name: 'emcCodeFoldCollaps'),
 388    (Value: emcCodeFoldExpand;        Name: 'emcCodeFoldExpand'),
 389    (Value: emcCodeFoldContextMenu;   Name: 'emcCodeFoldContextMenu'),
 390
 391    (Value: emcSynEditCommand;        Name: 'emcSynEditCommand'),
 392
 393    (Value: emcWheelScrollDown;       Name: 'emcWheelScrollDown'),
 394    (Value: emcWheelScrollUp;         Name: 'emcWheelScrollUp'),
 395    (Value: emcWheelVertScrollDown;   Name: 'emcWheelVertScrollDown'),
 396    (Value: emcWheelVertScrollUp;     Name: 'emcWheelVertScrollUp'),
 397    (Value: emcWheelHorizScrollDown;  Name: 'emcWheelHorizScrollDown'),
 398    (Value: emcWheelHorizScrollUp;    Name: 'emcWheelHorizScrollUp'),
 399
 400    (Value: emcWheelZoomOut;          Name: 'emcWheelZoomOut'),
 401    (Value: emcWheelZoomIn;           Name: 'emcWheelZoomIn'),
 402    (Value: emcWheelZoomNorm;         Name: 'emcWheelZoomNorm'),
 403
 404    (Value: emcStartSelectTokens;     Name: 'emcStartSelectTokens'),
 405    (Value: emcStartSelectWords;      Name: 'emcStartSelectWords'),
 406    (Value: emcStartSelectLines;      Name: 'emcStartSelectLines'),
 407
 408    (Value: emcOverViewGutterGotoMark;Name: 'emcOverViewGutterGotoMark'),
 409    (Value: emcOverViewGutterScrollTo;Name: 'emcOverViewGutterScrollTo')
 410
 411  );
 412
 413var
 414  ExtraIdentToIntFn: Array of TIdentToInt = nil;
 415  ExtraIntToIdentFn: Array of TIntToIdent = nil;
 416  ExtraGetEditorCommandValues: Array of TGetEditorCommandValuesProc = nil;
 417  ExtraMouseCmdNameFn: Array of TMouseCmdNameAndOptProcs = nil;
 418  ExtraMouseCmdOptFn: Array of TMouseCmdNameAndOptProcs = nil;
 419
 420function AllocatePluginMouseRange(Count: Integer; OffsetOnly: Boolean = False): integer;
 421const
 422  CurOffset : integer = 0;
 423begin
 424  Result := CurOffset;
 425  inc(CurOffset, Count);
 426  if not OffsetOnly then
 427    inc(Result, emcPluginFirst);
 428end;
 429
 430function MouseCommandName(emc: TSynEditorMouseCommand): String;
 431var
 432  i: Integer;
 433begin
 434  case emc of
 435    emcNone:                  Result := SYNS_emcNone;
 436    emcStartSelections:       Result := SYNS_emcStartSelection;
 437    emcStartColumnSelections: Result := SYNS_emcStartColumnSelections;
 438    emcStartLineSelections:   Result := SYNS_emcStartLineSelections;
 439    emcStartLineSelectionsNoneEmpty: Result := SYNS_emcStartLineSelectionsNoneEmpty;
 440    emcSelectWord:            Result := SYNS_emcSelectWord;
 441    emcSelectLine:            Result := SYNS_emcSelectLine;
 442    emcSelectPara:            Result := SYNS_emcSelectPara;
 443    emcStartDragMove:         Result := SYNS_emcStartDragMove;
 444    emcPasteSelection:        Result := SYNS_emcPasteSelection;
 445    emcMouseLink:             Result := SYNS_emcMouseLink;
 446    emcContextMenu:           Result := SYNS_emcContextMenu;
 447
 448    emcOnMainGutterClick:     Result := SYNS_emcBreakPointToggle;
 449
 450    emcCodeFoldCollaps:       Result := SYNS_emcCodeFoldCollaps;
 451    emcCodeFoldExpand:        Result := SYNS_emcCodeFoldExpand;
 452    emcCodeFoldContextMenu:   Result := SYNS_emcCodeFoldContextMenu;
 453
 454    emcSynEditCommand:        Result := SYNS_emcSynEditCommand;
 455
 456    emcWheelScrollDown:       Result := SYNS_emcWheelScrollDown;
 457    emcWheelScrollUp:         Result := SYNS_emcWheelScrollUp;
 458    emcWheelHorizScrollDown:  Result := SYNS_emcWheelHorizScrollDown;
 459    emcWheelHorizScrollUp:    Result := SYNS_emcWheelHorizScrollUp;
 460    emcWheelVertScrollDown:   Result := SYNS_emcWheelVertScrollDown;
 461    emcWheelVertScrollUp:     Result := SYNS_emcWheelVertScrollUp;
 462
 463    emcWheelZoomOut:          Result := SYNS_emcWheelZoomOut;
 464    emcWheelZoomIn:           Result := SYNS_emcWheelZoomIn;
 465    emcWheelZoomNorm:         Result := SYNS_emcWheelZoomNorm;
 466
 467    emcStartSelectTokens:     Result := SYNS_emcStartSelectTokens;
 468    emcStartSelectWords:      Result := SYNS_emcStartSelectWords;
 469    emcStartSelectLines:      Result := SYNS_emcStartSelectLines;
 470
 471    emcOverViewGutterGotoMark: Result := SYNS_emcOverViewGutterGotoMark;
 472    emcOverViewGutterScrollTo: Result := SYNS_emcOverViewGutterScrollTo;
 473
 474    else begin
 475      Result := '';
 476      i := 0;
 477      while (i < length(ExtraMouseCmdNameFn)) and (Result = '') do begin
 478        Result := ExtraMouseCmdNameFn[i](emc);
 479        inc(i);
 480      end;
 481    end;
 482  end;
 483end;
 484
 485function MouseCommandConfigName(emc: TSynEditorMouseCommand): String;
 486var
 487  i: Integer;
 488begin
 489  case emc of
 490    emcStartSelections,
 491    emcStartColumnSelections,
 492    emcStartLineSelections,
 493    emcStartLineSelectionsNoneEmpty:   Result := SYNS_emcSelection_opt;
 494    emcSelectLine:            Result := SYNS_emcSelectLine_opt;
 495    emcMouseLink:             Result := SYNS_emcMouseLink_opt;
 496    emcStartDragMove:         Result := SYNS_emcStartDragMove_opt;
 497    emcCodeFoldCollaps:       Result := SYNS_emcCodeFoldCollaps_opt;
 498    emcCodeFoldExpand:        Result := SYNS_emcCodeFoldExpand_opt;
 499    emcContextMenu:           Result := SYNS_emcContextMenuCaretMove_opt;
 500    emcWheelScrollDown..emcWheelVertScrollUp:
 501                              Result := SYNS_emcWheelScroll_opt;
 502    else begin
 503      Result := '';
 504      i := 0;
 505      while (i < length(ExtraMouseCmdOptFn)) and (Result = '') do begin
 506        Result := ExtraMouseCmdOptFn[i](emc);
 507        inc(i);
 508      end;
 509    end;
 510  end;
 511end;
 512
 513function SynMouseCmdToIdent(SynMouseCmd: Longint; var Ident: String): Boolean;
 514var
 515  i: Integer;
 516begin
 517  Ident := '';
 518  Result := IntToIdent(SynMouseCmd, Ident, SynMouseCommandNames);
 519  i := 0;
 520  while (i < length(ExtraIntToIdentFn)) and (not Result) do begin
 521    Result := ExtraIntToIdentFn[i](SynMouseCmd, Ident);
 522    inc(i);
 523  end;
 524end;
 525
 526function IdentToSynMouseCmd(const Ident: string; var SynMouseCmd: Longint): Boolean;
 527var
 528  i: Integer;
 529begin
 530  SynMouseCmd := 0;
 531  Result := IdentToInt(Ident, SynMouseCmd, SynMouseCommandNames);
 532  i := 0;
 533  while (i < length(ExtraIdentToIntFn)) and (not Result) do begin
 534    Result := ExtraIdentToIntFn[i](Ident, SynMouseCmd);
 535    inc(i);
 536  end;
 537end;
 538
 539procedure GetEditorMouseCommandValues(Proc: TGetStrProc);
 540var
 541  i: Integer;
 542begin
 543  for i := Low(SynMouseCommandNames) to High(SynMouseCommandNames) do
 544    Proc(SynMouseCommandNames[I].Name);
 545  i := 0;
 546  while (i < length(ExtraGetEditorCommandValues)) do begin
 547    ExtraGetEditorCommandValues[i](Proc);
 548    inc(i);
 549  end;
 550end;
 551
 552procedure RegisterMouseCmdIdentProcs(IdentToIntFn: TIdentToInt; IntToIdentFn: TIntToIdent);
 553var
 554  i: Integer;
 555begin
 556  i := length(ExtraIdentToIntFn);
 557  SetLength(ExtraIdentToIntFn, i + 1);
 558  ExtraIdentToIntFn[i] := IdentToIntFn;
 559  i := length(ExtraIntToIdentFn);
 560  SetLength(ExtraIntToIdentFn, i + 1);
 561  ExtraIntToIdentFn[i] := IntToIdentFn;
 562end;
 563
 564procedure RegisterExtraGetEditorMouseCommandValues(AProc: TGetEditorCommandValuesProc);
 565var
 566  i: Integer;
 567begin
 568  i := length(ExtraGetEditorCommandValues);
 569  SetLength(ExtraGetEditorCommandValues, i + 1);
 570  ExtraGetEditorCommandValues[i] := AProc;
 571end;
 572
 573procedure RegisterMouseCmdNameAndOptProcs(ANamesProc: TMouseCmdNameAndOptProcs;
 574  AOptProc: TMouseCmdNameAndOptProcs);
 575var
 576  i: Integer;
 577begin
 578  i := length(ExtraMouseCmdNameFn);
 579  SetLength(ExtraMouseCmdNameFn, i + 1);
 580  ExtraMouseCmdNameFn[i] := ANamesProc;
 581  if AOptProc = nil then
 582    exit;
 583  i := length(ExtraMouseCmdOptFn);
 584  SetLength(ExtraMouseCmdOptFn, i + 1);
 585  ExtraMouseCmdOptFn[i] := AOptProc;
 586end;
 587
 588{ TSynEditMouseInternalActions }
 589
 590procedure TSynEditMouseInternalActions.SetOptions(AValue: TSynEditorMouseOptions);
 591begin
 592  FOptions := AValue;
 593  if emUseMouseActions in FOptions then exit;
 594
 595  AValue := AValue - [emUseMouseActions];
 596  if (FInternOptions = AValue) and (Count > 0) then exit;
 597  FInternOptions := AValue;
 598  InitForOptions(FInternOptions);
 599end;
 600
 601procedure TSynEditMouseInternalActions.SetUserActions(AValue: TSynEditMouseActions);
 602begin
 603  if AValue =nil then
 604    FUserActions.Clear
 605  else
 606    FUserActions.Assign(AValue);
 607end;
 608
 609procedure TSynEditMouseInternalActions.InitForOptions(AnOptions: TSynEditorMouseOptions);
 610begin
 611  Clear;
 612end;
 613
 614constructor TSynEditMouseInternalActions.Create(AOwner: TPersistent);
 615begin
 616  FOptions := [];
 617  FUserActions := TSynEditMouseActions.Create(AOwner);
 618  inherited Create(AOwner);
 619end;
 620
 621destructor TSynEditMouseInternalActions.Destroy;
 622begin
 623  FreeAndNil(FUserActions);
 624  inherited Destroy;
 625end;
 626
 627procedure TSynEditMouseInternalActions.ResetDefaults;
 628begin
 629  InitForOptions(FOptions);
 630end;
 631
 632procedure TSynEditMouseInternalActions.ResetUserActions;
 633begin
 634  if emUseMouseActions in FOptions then begin
 635    if (FInternOptions <> FOptions - [emUseMouseActions]) or (Count = 0) then begin
 636      FInternOptions := FOptions - [emUseMouseActions];
 637      InitForOptions(FInternOptions);
 638    end;
 639    FUserActions.Assign(Self);
 640  end
 641  else begin
 642    FUserActions.Clear;
 643  end;
 644end;
 645
 646function TSynEditMouseInternalActions.GetActionsForOptions(AnOptions: TSynEditorMouseOptions): TSynEditMouseActions;
 647begin
 648  Options := AnOptions;
 649  if emUseMouseActions in FOptions then
 650    Result := FUserActions
 651  else
 652    Result := Self;
 653end;
 654
 655{ TSynEditMouseAction }
 656
 657procedure TSynEditMouseAction.SetButton(const AValue: TSynMouseButton);
 658begin
 659  if FButton = AValue then exit;
 660  FButton := AValue;
 661  if Collection <> nil then
 662    TSynEditMouseActions(Collection).AssertNoConflict(self);
 663
 664  if FButton in [mbXWheelUp, mbXWheelDown] then
 665    ClickDir := cdDown;
 666end;
 667
 668procedure TSynEditMouseAction.SetButtonUpRestrictions(AValue: TSynMAUpRestrictions);
 669begin
 670  if FButtonUpRestrictions = AValue then Exit;
 671  FButtonUpRestrictions := AValue;
 672  if Collection <> nil then
 673    TSynEditMouseActions(Collection).AssertNoConflict(self);
 674end;
 675
 676procedure TSynEditMouseAction.SetClickCount(const AValue: TSynMAClickCount);
 677begin
 678  if FClickCount = AValue then exit;
 679  FClickCount := AValue;
 680  if Collection <> nil then
 681    TSynEditMouseActions(Collection).AssertNoConflict(self);
 682end;
 683
 684procedure TSynEditMouseAction.SetClickDir(AValue: TSynMAClickDir);
 685begin
 686  if FButton in [mbXWheelUp, mbXWheelDown] then
 687    AValue := cdDown;
 688  if FClickDir = AValue then exit;
 689  FClickDir := AValue;
 690  if Collection <> nil then
 691    TSynEditMouseActions(Collection).AssertNoConflict(self);
 692end;
 693
 694procedure TSynEditMouseAction.SetCommand(const AValue: TSynEditorMouseCommand);
 695begin
 696  if FCommand = AValue then exit;
 697  FCommand := AValue;
 698  if Collection <> nil then
 699    TSynEditMouseActions(Collection).AssertNoConflict(self);
 700end;
 701
 702procedure TSynEditMouseAction.SetIgnoreUpClick(AValue: Boolean);
 703begin
 704  if FIgnoreUpClick = AValue then Exit;
 705  FIgnoreUpClick := AValue;
 706  if Collection <> nil then
 707    TSynEditMouseActions(Collection).AssertNoConflict(self);
 708end;
 709
 710procedure TSynEditMouseAction.SetMoveCaret(const AValue: Boolean);
 711begin
 712  if FMoveCaret = AValue then exit;
 713  FMoveCaret := AValue;
 714  if Collection <> nil then
 715    TSynEditMouseActions(Collection).AssertNoConflict(self);
 716end;
 717
 718procedure TSynEditMouseAction.SetOption(const AValue: TSynEditorMouseCommandOpt);
 719begin
 720  if FOption = AValue then exit;
 721  FOption := AValue;
 722  if Collection <> nil then
 723    TSynEditMouseActions(Collection).AssertNoConflict(self);
 724end;
 725
 726procedure TSynEditMouseAction.SetOption2(AValue: Integer);
 727begin
 728  if FOption2 = AValue then Exit;
 729  FOption2 := AValue;
 730  if Collection <> nil then
 731    TSynEditMouseActions(Collection).AssertNoConflict(self);
 732end;
 733
 734procedure TSynEditMouseAction.SetPriority(const AValue: TSynEditorMouseCommandOpt);
 735begin
 736  if FPriority = AValue then exit;
 737  FPriority := AValue;
 738  if Collection <> nil then
 739    TSynEditMouseActions(Collection).AssertNoConflict(self);
 740end;
 741
 742procedure TSynEditMouseAction.SetShift(const AValue: TShiftState);
 743begin
 744  if FShift = AValue then exit;
 745  FShift := AValue;
 746  if Collection <> nil then
 747    TSynEditMouseActions(Collection).AssertNoConflict(self);
 748end;
 749
 750procedure TSynEditMouseAction.SetShiftMask(const AValue: TShiftState);
 751begin
 752  if FShiftMask = AValue then exit;
 753  FShiftMask := AValue;
 754  if Collection <> nil then
 755    TSynEditMouseActions(Collection).AssertNoConflict(self);
 756end;
 757
 758function TSynEditMouseAction.GetDisplayName: string;
 759begin
 760  Result := MouseCommandName(FCommand);
 761end;
 762
 763procedure TSynEditMouseAction.Assign(Source: TPersistent);
 764begin
 765  if Source is TSynEditMouseAction then
 766  begin
 767    FCommand    := TSynEditMouseAction(Source).Command;
 768    FClickCount := TSynEditMouseAction(Source).ClickCount;
 769    FClickDir   := TSynEditMouseAction(Source).ClickDir;
 770    FButtonUpRestrictions := TSynEditMouseAction(Source).ButtonUpRestrictions;
 771    FButton     := TSynEditMouseAction(Source).Button;
 772    FShift      := TSynEditMouseAction(Source).Shift;
 773    FShiftMask  := TSynEditMouseAction(Source).ShiftMask;
 774    FMoveCaret  := TSynEditMouseAction(Source).MoveCaret;
 775    FIgnoreUpClick := TSynEditMouseAction(Source).IgnoreUpClick;
 776    FOption     := TSynEditMouseAction(Source).FOption;
 777    FOption2    := TSynEditMouseAction(Source).FOption2;
 778    FPriority   := TSynEditMouseAction(Source).Priority;
 779  end else
 780    inherited Assign(Source);
 781  if Collection <> nil then
 782    TSynEditMouseActions(Collection).AssertNoConflict(self);
 783end;
 784
 785procedure TSynEditMouseAction.Clear;
 786begin
 787  FCommand    := 0;
 788  FClickCount := ccSingle;
 789  FClickDir   := cdUp;
 790  FButton     := mbXLeft;
 791  FShift      := [];
 792  FShiftMask  := [];
 793  FMoveCaret  := False;
 794  FOption     := 0;
 795  FPriority   := 0;
 796  FIgnoreUpClick := False;
 797end;
 798
 799function TSynEditMouseAction.IsMatchingShiftState(AShift: TShiftState): Boolean;
 800begin
 801  Result := AShift * FShiftMask = FShift;
 802end;
 803
 804function TSynEditMouseAction.IsMatchingClick(ABtn: TSynMouseButton; ACCount: TSynMAClickCount;
 805  ACDir: TSynMAClickDir): Boolean;
 806begin
 807  Result := (Button     = ABtn)
 808        and ((ClickCount = ACCount) or (ClickCount = ccAny))
 809        and (ClickDir   = ACDir)
 810end;
 811
 812function TSynEditMouseAction.IsFallback: Boolean;
 813begin
 814  Result := FShiftMask = [];
 815end;
 816
 817function TSynEditMouseAction.Conflicts(Other: TSynEditMouseAction): Boolean;
 818begin
 819  If (Other = nil) or (Other = self) then exit(False);
 820  Result := (Other.Button     = self.Button)
 821        and ((Other.ClickCount = self.ClickCount)
 822             or (self.ClickCount = ccAny) or (Other.ClickCount = ccAny))
 823        and (Other.ClickDir   = self.ClickDir)
 824        and (Other.Shift * self.ShiftMask = self.Shift * Other.ShiftMask)
 825        and ((Other.Command   <> self.Command) or  // Only conflicts, if Command differs
 826             (Other.MoveCaret <> self.MoveCaret) or
 827             (Other.IgnoreUpClick <> self.IgnoreUpClick) or
 828             (Other.Option    <> self.Option) or
 829             (Other.Option2   <> self.Option2) )
 830        and not(Other.IsFallback xor self.IsFallback)
 831        and (Other.Priority   = self.Priority);
 832end;
 833
 834function TSynEditMouseAction.Equals(Other: TSynEditMouseAction;
 835  IgnoreCmd: Boolean = False): Boolean;
 836begin
 837  Result := (Other.Button     = self.Button)
 838        and (Other.ClickCount = self.ClickCount)
 839        and (Other.ClickDir   = self.ClickDir)
 840        and (Other.ButtonUpRestrictions   = self.ButtonUpRestrictions)
 841        and (Other.Shift      = self.Shift)
 842        and (Other.ShiftMask  = self.ShiftMask)
 843        and (Other.Priority   = self.Priority)
 844        and ((Other.Command   = self.Command) or IgnoreCmd)
 845        and ((Other.Option    = self.Option) or IgnoreCmd)
 846        and ((Other.Option2   = self.Option2) or IgnoreCmd)
 847        and ((Other.MoveCaret = self.MoveCaret) or IgnoreCmd)
 848        and ((Other.IgnoreUpClick = self.IgnoreUpClick) or IgnoreCmd);
 849end;
 850
 851{ TSynEditMouseActions }
 852
 853function TSynEditMouseActions.GetItem(Index: Integer): TSynEditMouseAction;
 854begin
 855 Result := TSynEditMouseAction(inherited GetItem(Index));
 856end;
 857
 858procedure TSynEditMouseActions.SetItem(Index: Integer; const AValue: TSynEditMouseAction);
 859begin
 860  inherited SetItem(Index, AValue);
 861end;
 862
 863function TSynEditMouseActions.GetOwner: TPersistent;
 864begin
 865  Result := FOwner;
 866end;
 867
 868procedure TSynEditMouseActions.Update(Item: TCollectionItem);
 869var
 870  i: Integer;
 871  Err : ESynMouseCmdError;
 872begin
 873  inherited Update(Item);
 874  i := Count - 1;
 875  Err := nil;
 876  while i > 0 do begin
 877    try
 878      AssertNoConflict(Items[i]);
 879    except
 880      on E : ESynMouseCmdError do begin
 881        Delete(i);
 882        if assigned(Owner) and (csDesigning in TComponent(Owner).ComponentState)
 883        then
 884          MessageDlg(SYNS_EDuplicateShortCut, E.Message + LineEnding + Items[i].DisplayName,
 885                     mtWarning, [mbOK], '')
 886        else
 887          Err := E;
 888        //if not(assigned(Owner) and (csLoading in TComponent(Owner).ComponentState))
 889        //then
 890        //  raise E;
 891      end;
 892    end;
 893    dec(i);
 894  end;
 895  if assigned(Err) then
 896    raise Err;
 897end;
 898
 899constructor TSynEditMouseActions.Create(AOwner: TPersistent);
 900begin
 901  inherited Create(TSynEditMouseAction);
 902  FOwner := AOwner;
 903  FAssertLock := 0;
 904end;
 905
 906function TSynEditMouseActions.Add: TSynEditMouseAction;
 907begin
 908  Result := TSynEditMouseAction(inherited Add);
 909end;
 910
 911procedure TSynEditMouseActions.Assign(Source: TPersistent);
 912var
 913  i: Integer;
 914begin
 915  if Source is TSynEditMouseActions then
 916  begin
 917    Clear;
 918    BeginUpdate;
 919    for i := 0 to TSynEditMouseActions(Source).Count-1 do
 920      Add.Assign(TSynEditMouseActions(Source)[i]);
 921    EndUpdate;
 922  end
 923  else
 924    inherited Assign(Source);
 925end;
 926
 927procedure TSynEditMouseActions.AssertNoConflict(MAction: TSynEditMouseAction);
 928var
 929  i: Integer;
 930begin
 931  if (FAssertLock > 0) or (UpdateCount > 0) then exit;
 932  for i := 0 to Count-1 do begin
 933    if Items[i].Conflicts(MAction) then
 934      raise ESynMouseCmdError.Create(SYNS_EDuplicateShortCut);
 935  end;
 936end;
 937
 938function TSynEditMouseActions.Equals(Other: TSynEditMouseActions): Boolean;
 939var
 940  i: Integer;
 941begin
 942  Result := False;
 943  if Count <> Other.Count then exit;
 944
 945  for i := 0 to Count - 1 do
 946    if Other.IndexOf(Items[i]) < 0 then
 947      exit;
 948  Result := True;
 949end;
 950
 951function TSynEditMouseActions.FindCommand(AnInfo: TSynEditMouseActionInfo;
 952  APrevious: TSynEditMouseAction = nil): TSynEditMouseAction;
 953var
 954  i, MinPriority: Integer;
 955  act, found, fback: TSynEditMouseAction;
 956begin
 957  MinPriority := 0;
 958  if assigned(APrevious) then
 959    MinPriority := APrevious.Priority + 1;
 960  fback := nil;
 961  found := nil;
 962  for i := 0 to Count-1 do begin
 963    act := Items[i];
 964    if act.Priority < MinPriority then
 965      continue;
 966
 967    if act.IsMatchingClick(AnInfo.Button, AnInfo.CCount, AnInfo.Dir) and
 968       act.IsMatchingShiftState(AnInfo.Shift)
 969    then begin
 970      if act.IsFallback then begin
 971        if (fback = nil) or (act.Priority < fback.Priority) then
 972          fback := act;
 973      end
 974      else begin
 975        if (found = nil) or (act.Priority < found.Priority) then
 976          found := act;
 977      end;
 978    end;
 979  end;
 980  if found <> nil then begin
 981    if (fback <> nil) and (fback.Priority < found.Priority) then
 982      Result := fback
 983    else
 984      Result := found;
 985  end
 986  else if fback <> nil then
 987    Result := fback
 988  else
 989    Result := nil;
 990end;
 991
 992procedure TSynEditMouseActions.AddCommand(const ACmd: TSynEditorMouseCommand;
 993  const AMoveCaret: Boolean; const AButton: TSynMouseButton;
 994  const AClickCount: TSynMAClickCount; const ADir: TSynMAClickDir;
 995  const AShift, AShiftMask: TShiftState; const AOpt: TSynEditorMouseCommandOpt = 0;
 996  const APrior: Integer = 0; const AOpt2: integer = 0; const AIgnoreUpClick: Boolean = False);
 997begin
 998  AddCommand(ACmd, AMoveCaret, AButton, AClickCount, ADir, [], AShift, AShiftMask, AOpt, APrior,
 999    AOpt2, AIgnoreUpClick);
1000end;
1001
1002procedure TSynEditMouseActions.AddCommand(const ACmd: TSynEditorMouseCommand;
1003  const AMoveCaret: Boolean; const AButton: TSynMouseButton;
1004  const AClickCount: TSynMAClickCount; const ADir: TSynMAClickDir;
1005  const AnUpRestrict: TSynMAUpRestrictions; const AShift, AShiftMask: TShiftState;
1006  const AOpt: TSynEditorMouseCommandOpt; const APrior: Integer; const AOpt2: integer;
1007  const AIgnoreUpClick: Boolean);
1008var
1009  new: TSynEditMouseAction;
1010begin
1011  inc(FAssertLock);
1012  try
1013    new := Add;
1014    with new do begin
1015      Command := ACmd;
1016      MoveCaret := AMoveCaret;
1017      Button := AButton;
1018      ClickCount := AClickCount;
1019      ClickDir := ADir;
1020      ButtonUpRestrictions := AnUpRestrict;
1021      Shift := AShift;
1022      ShiftMask := AShiftMask;
1023      Option := AOpt;
1024      Priority := APrior;
1025      Option2 := AOpt2;
1026      IgnoreUpClick := AIgnoreUpClick;
1027    end;
1028  finally
1029    dec(FAssertLock);
1030  end;
1031  try
1032    AssertNoConflict(new);
1033  except
1034    Delete(Count-1);
1035    raise;
1036  end;
1037end;
1038
1039procedure TSynEditMouseActions.ResetDefaults;
1040begin
1041  Clear;
1042end;
1043
1044procedure TSynEditMouseActions.IncAssertLock;
1045begin
1046  inc(FAssertLock);
1047end;
1048
1049procedure TSynEditMouseActions.DecAssertLock;
1050begin
1051  dec(FAssertLock);
1052end;
1053
1054function TSynEditMouseActions.IndexOf(MAction: TSynEditMouseAction;
1055  IgnoreCmd: Boolean = False): Integer;
1056begin
1057  Result := Count - 1;
1058  while Result >= 0 do begin
1059    if Items[Result].Equals(MAction, IgnoreCmd) then exit;
1060    Dec(Result);
1061  end;
1062end;
1063
1064{ TSynEditMouseActionSearchList }
1065
1066function TSynEditMouseActionSearchList.CallSearchHandlers(var AnInfo: TSynEditMouseActionInfo;
1067  HandleActionProc: TSynEditMouseActionHandler): Boolean;
1068var
1069  i: LongInt;
1070begin
1071  i:=Count;
1072  Result := False;
1073  while NextDownIndex(i) and (not Result) do
1074    Result := TSynEditMouseActionSearchProc(Items[i])(AnInfo, HandleActionProc);
1075end;
1076
1077{ TSynEditMouseActionExecList }
1078
1079function TSynEditMouseActionExecList.CallExecHandlers(AnAction: TSynEditMouseAction;
1080  var AnInfo: TSynEditMouseActionInfo): Boolean;
1081var
1082  i: LongInt;
1083begin
1084  i:=Count;
1085  Result := False;
1086  while NextDownIndex(i) and (not Result) do
1087    Result := TSynEditMouseActionExecProc(Items[i])(AnAction, AnInfo);
1088end;
1089
1090initialization
1091  RegisterIntegerConsts(TypeInfo(TSynEditorMouseCommand), @IdentToSynMouseCmd, @SynMouseCmdToIdent);
1092
1093finalization
1094  ExtraIdentToIntFn := nil;
1095  ExtraIntToIdentFn := nil;
1096  ExtraGetEditorCommandValues := nil;
1097  ExtraMouseCmdNameFn := nil;
1098  ExtraMouseCmdOptFn := nil;
1099
1100end.
1101