1 {
2  *****************************************************************************
3   See the file COPYING.modifiedLGPL.txt, included in this distribution,
4   for details about the license.
5  *****************************************************************************
6 
7  Abstract:
8    Interface unit for IDE commands.
9    IDE commands are functions like open file, save, build, ... .
10 
11    Every command can have up to two shortcuts. For example:
12      ecCopy: two shortcuts: Ctrl+C and Ctrl+Insert
13      ecDeleteChar: one shortcut: Delete
14      ecInsertDateTime: no shortcut
15 
16    Commands are sorted into categories. For example:
17      ecCopy is in the category 'Selection'.
18      This is only to help the user find commands.
19 
20    Scopes:
21      A command can work globally or only in some IDE windows.
22      For example: When the user presses a key in the source editor, the IDE
23        first searches in all commands with the Scope IDECmdScopeSrcEdit.
24        Then it will search in all commands without scope.
25 }
26 unit IDECommands;
27 
28 {$mode objfpc}{$H+}
29 
30 interface
31 
32 uses
33   Classes, SysUtils,
34   // LCL
35   LCLProc, LCLType, LCLIntf, Forms, Menus,
36   // LazUtils
37   LazMethodList, LazLoggerBase,
38   // IdeIntf
39   PropEdits, IDEImagesIntf;
40 
41 const
42   { editor commands constants. see syneditkeycmds.pp for more
43 
44    These values can change from version to version, so DO NOT save them to file!
45 
46    To add one static key do the following:
47      1. Add a constant with a unique value in the list below.
48      2. Update IDEEditorCommandStrs to define a name (used for configs)
49      3. Add it to GetDefaultKeyForCommand to define the default keys+shiftstates
50      4. Add it to EditorCommandToDescriptionString to define the description
51      5. Add it to TKeyCommandRelationList.DefineCommandCategories to define the category.
52   }
53   ecNone                    = 0;
54 
55   ecFirstLazarus            = 1001;  // syneditkeycmds.ecUserFirst = 1001;
56 
57   // search
58   ecFind                    = ecFirstLazarus + 1;
59   ecFindAgain               = ecFirstLazarus + 2;
60   ecFindNext                = ecFindAgain;
61   ecFindPrevious            = ecFirstLazarus + 3;
62   ecReplace                 = ecFirstLazarus + 4;
63   ecIncrementalFind         = ecFirstLazarus + 5;
64   ecFindProcedureDefinition = ecFirstLazarus + 6;
65   ecFindProcedureMethod     = ecFirstLazarus + 7;
66   ecGotoLineNumber          = ecFirstLazarus + 8;
67   ecFindNextWordOccurrence  = ecFirstLazarus + 9;
68   ecFindPrevWordOccurrence  = ecFirstLazarus + 10;
69   ecFindInFiles             = ecFirstLazarus + 11;
70   ecJumpBack                = ecFirstLazarus + 12;
71   ecJumpForward             = ecFirstLazarus + 13;
72   ecAddJumpPoint            = ecFirstLazarus + 14;
73   ecViewJumpHistory         = ecFirstLazarus + 15;
74   ecJumpToNextError         = ecFirstLazarus + 16;
75   ecJumpToPrevError         = ecFirstLazarus + 17;
76   ecProcedureList           = ecFirstLazarus + 18;
77 
78   // search code
79   ecFindDeclaration         = ecFirstLazarus + 20;
80   ecFindBlockOtherEnd       = ecFirstLazarus + 21;
81   ecFindBlockStart          = ecFirstLazarus + 22;
82   ecOpenFileAtCursor        = ecFirstLazarus + 23;
83   ecGotoIncludeDirective    = ecFirstLazarus + 24;
84   ecJumpToInterface         = ecFirstLazarus + 25;
85   ecJumpToInterfaceUses     = ecFirstLazarus + 26;
86   ecJumpToImplementation    = ecFirstLazarus + 27;
87   ecJumpToImplementationUses= ecFirstLazarus + 28;
88   ecJumpToInitialization    = ecFirstLazarus + 29;
89   ecJumpToProcedureHeader   = ecFirstLazarus + 30;
90   ecJumpToProcedureBegin    = ecFirstLazarus + 31;
91 
92   // edit selection
93   ecSelectionUpperCase      = ecFirstLazarus + 50;
94   ecSelectionLowerCase      = ecFirstLazarus + 51;
95   ecSelectionSwapCase       = ecFirstLazarus + 52;
96   ecSelectionTabs2Spaces    = ecFirstLazarus + 53;
97   ecSelectionEnclose        = ecFirstLazarus + 54;
98   ecSelectionComment        = ecFirstLazarus + 55;
99   ecSelectionUncomment      = ecFirstLazarus + 56;
100   ecSelectionSort           = ecFirstLazarus + 57;
101   ecSelectionBreakLines     = ecFirstLazarus + 58;
102   ecSelectToBrace           = ecFirstLazarus + 59;
103   ecSelectCodeBlock         = ecFirstLazarus + 60;
104   ecSelectWord              = ecFirstLazarus + 61;
105   ecSelectLine              = ecFirstLazarus + 62;
106   ecSelectParagraph         = ecFirstLazarus + 63;
107   ecSelectionEncloseIFDEF   = ecFirstLazarus + 64;
108   ecToggleComment           = ecFirstLazarus + 65;
109 
110   // insert text
111   ecInsertCharacter         = ecFirstLazarus + 70;
112   ecInsertGUID              = ecFirstLazarus + 71;
113   ecInsertFilename          = ecFirstLazarus + 72;
114   ecInsertUserName          = ecFirstLazarus + 73;
115   ecInsertDateTime          = ecFirstLazarus + 74;
116   ecInsertChangeLogEntry    = ecFirstLazarus + 75;
117   ecInsertCVSAuthor         = ecFirstLazarus + 76;
118   ecInsertCVSDate           = ecFirstLazarus + 77;
119   ecInsertCVSHeader         = ecFirstLazarus + 78;
120   ecInsertCVSID             = ecFirstLazarus + 79;
121   ecInsertCVSLog            = ecFirstLazarus + 80;
122   ecInsertCVSName           = ecFirstLazarus + 81;
123   ecInsertCVSRevision       = ecFirstLazarus + 82;
124   ecInsertCVSSource         = ecFirstLazarus + 83;
125   ecInsertGPLNotice         = ecFirstLazarus + 84;
126   ecInsertGPLNoticeTranslated = ecFirstLazarus + 85;
127   ecInsertLGPLNotice        = ecFirstLazarus + 86;
128   ecInsertLGPLNoticeTranslated = ecFirstLazarus + 87;
129   ecInsertModifiedLGPLNotice= ecFirstLazarus + 88;
130   ecInsertModifiedLGPLNoticeTranslated = ecFirstLazarus + 89;
131   ecInsertMITNotice         = ecFirstLazarus + 90;
132   ecInsertMITNoticeTranslated = ecFirstLazarus + 91;
133 
134   // source tools
135   ecWordCompletion          = ecFirstLazarus + 100;
136   ecCompleteCode            = ecFirstLazarus + 101;
137   ecIdentCompletion         = ecFirstLazarus + 102;
138   ecSyntaxCheck             = ecFirstLazarus + 103;
139   ecGuessUnclosedBlock      = ecFirstLazarus + 104;
140   ecGuessMisplacedIFDEF     = ecFirstLazarus + 105;
141   ecConvertDFM2LFM          = ecFirstLazarus + 106;
142   ecCheckLFM                = ecFirstLazarus + 107;
143   ecConvertDelphiUnit       = ecFirstLazarus + 108;
144   ecConvertDelphiProject    = ecFirstLazarus + 109;
145   ecConvertDelphiPackage    = ecFirstLazarus + 110;
146   ecConvertEncoding         = ecFirstLazarus + 111;
147   ecMakeResourceString      = ecFirstLazarus + 112;
148   ecDiff                    = ecFirstLazarus + 113;
149   ecExtractProc             = ecFirstLazarus + 114;
150   ecFindIdentifierRefs      = ecFirstLazarus + 115;
151   ecRenameIdentifier        = ecFirstLazarus + 116;
152   ecInvertAssignment        = ecFirstLazarus + 117;
153   ecShowCodeContext         = ecFirstLazarus + 118;
154   ecShowAbstractMethods     = ecFirstLazarus + 119;
155   ecRemoveEmptyMethods      = ecFirstLazarus + 120;
156   ecRemoveUnusedUnits       = ecFirstLazarus + 121;
157   ecUseUnit                 = ecFirstLazarus + 122;
158   ecFindOverloads           = ecFirstLazarus + 123;
159   ecFindUsedUnitRefs        = ecFirstLazarus + 124;
160   ecCompleteCodeInteractive = ecFirstLazarus + 125;
161 
162   // file menu
163   ecNew                     = ecFirstLazarus + 201;
164   ecNewUnit                 = ecFirstLazarus + 202;
165   ecNewForm                 = ecFirstLazarus + 203;
166   ecOpen                    = ecFirstLazarus + 205;
167   ecRevert                  = ecFirstLazarus + 206;
168   ecSave                    = ecFirstLazarus + 207;
169   ecSaveAs                  = ecFirstLazarus + 208;
170   ecSaveAll                 = ecFirstLazarus + 209;
171   ecClose                   = ecFirstLazarus + 210;
172   ecCloseAll                = ecFirstLazarus + 211;
173   ecCleanDirectory          = ecFirstLazarus + 212;
174   ecRestart                 = ecFirstLazarus + 213;
175   ecQuit                    = ecFirstLazarus + 214;
176   ecOpenUnit                = ecFirstLazarus + 215;
177 
178   // edit menu
179   ecMultiPaste              = ecFirstLazarus + 230;
180 
181   // IDE navigation
182   ecToggleFormUnit          = ecFirstLazarus + 301;
183   ecToggleObjectInsp        = ecFirstLazarus + 302;
184   ecToggleSourceEditor      = ecFirstLazarus + 303;
185   ecToggleCodeExpl          = ecFirstLazarus + 304;
186   ecToggleFPDocEditor       = ecFirstLazarus + 305;
187   ecToggleMessages          = ecFirstLazarus + 306;
188   ecToggleWatches           = ecFirstLazarus + 307;
189   ecToggleBreakPoints       = ecFirstLazarus + 308;
190   ecToggleDebuggerOut       = ecFirstLazarus + 309;
191   ecViewUnitDependencies    = ecFirstLazarus + 312;
192   ecViewUnitInfo            = ecFirstLazarus + 313;
193   ecToggleLocals            = ecFirstLazarus + 314;
194   ecToggleCallStack         = ecFirstLazarus + 315;
195   ecToggleSearchResults     = ecFirstLazarus + 316;
196   ecViewAnchorEditor        = ecFirstLazarus + 317;
197   ecViewTabOrder            = ecFirstLazarus + 318;
198   ecToggleCodeBrowser       = ecFirstLazarus + 319;
199   ecToggleCompPalette       = ecFirstLazarus + 320;
200   ecToggleIDESpeedBtns      = ecFirstLazarus + 321;
201   ecViewComponents          = ecFirstLazarus + 322;
202   ecToggleRestrictionBrowser= ecFirstLazarus + 323;
203   ecViewTodoList            = ecFirstLazarus + 324;
204   ecToggleRegisters         = ecFirstLazarus + 325;
205   ecToggleAssembler         = ecFirstLazarus + 326;
206   ecToggleDebugEvents       = ecFirstLazarus + 327;
207   ecViewPseudoTerminal      = ecFirstLazarus + 328;
208   ecViewThreads             = ecFirstLazarus + 329;
209   ecViewHistory             = ecFirstLazarus + 460;
210   ecViewMacroList           = ecFirstLazarus + 461;
211 
212   // sourcenotebook commands
213   ecNextEditor              = ecFirstLazarus + 330;
214   ecPrevEditor              = ecFirstLazarus + 331;
215   ecMoveEditorLeft          = ecFirstLazarus + 332;
216   ecMoveEditorRight         = ecFirstLazarus + 333;
217   ecToggleBreakPoint        = ecFirstLazarus + 334;
218   ecRemoveBreakPoint        = ecFirstLazarus + 335;
219   ecMoveEditorLeftmost      = ecFirstLazarus + 336;
220   ecMoveEditorRightmost     = ecFirstLazarus + 337;
221 
222   ecNextSharedEditor        = ecFirstLazarus + 338;
223   ecPrevSharedEditor        = ecFirstLazarus + 339;
224 
225   ecNextWindow              = ecFirstLazarus + 340;
226   ecPrevWindow              = ecFirstLazarus + 341;
227   ecMoveEditorNextWindow    = ecFirstLazarus + 342;
228   ecMoveEditorPrevWindow    = ecFirstLazarus + 343;
229   ecMoveEditorNewWindow     = ecFirstLazarus + 344;
230   ecCopyEditorNextWindow    = ecFirstLazarus + 345;
231   ecCopyEditorPrevWindow    = ecFirstLazarus + 346;
232   ecCopyEditorNewWindow     = ecFirstLazarus + 347;
233   ecPrevEditorInHistory     = ecFirstLazarus + 348;
234   ecNextEditorInHistory     = ecFirstLazarus + 349;
235 
236   ecGotoEditor1             = ecFirstLazarus + 350;
237   ecGotoEditor2             = ecGotoEditor1 + 1;
238   ecGotoEditor3             = ecGotoEditor2 + 1;
239   ecGotoEditor4             = ecGotoEditor3 + 1;
240   ecGotoEditor5             = ecGotoEditor4 + 1;
241   ecGotoEditor6             = ecGotoEditor5 + 1;
242   ecGotoEditor7             = ecGotoEditor6 + 1;
243   ecGotoEditor8             = ecGotoEditor7 + 1;
244   ecGotoEditor9             = ecGotoEditor8 + 1;
245   ecGotoEditor0             = ecGotoEditor9 + 1;
246 
247   ecLockEditor              = ecFirstLazarus + 370;
248 
249   // marker
250   ecSetFreeBookmark         = ecFirstLazarus + 381;
251   ecPrevBookmark            = ecFirstLazarus + 382;
252   ecNextBookmark            = ecFirstLazarus + 383;
253   ecClearBookmarkForFile    = ecFirstLazarus + 384;
254   ecClearAllBookmark        = ecFirstLazarus + 385;
255 
256   ecGotoBookmarks           = ecFirstLazarus + 386;
257   ecToggleBookmarks         = ecFirstLazarus + 387;
258 
259   // Macro
260   ecSynMacroRecord          = ecFirstLazarus + 390;
261   ecSynMacroPlay            = ecFirstLazarus + 391;
262 
263   // run menu
264   ecCompile                 = ecFirstLazarus + 400;
265   ecBuild                   = ecFirstLazarus + 401;
266   ecQuickCompile            = ecFirstLazarus + 402;
267   ecCleanUpAndBuild         = ecFirstLazarus + 403;
268   ecBuildManyModes          = ecFirstLazarus + 404;
269   ecAbortBuild              = ecFirstLazarus + 405;
270   ecRunWithoutDebugging     = ecFirstLazarus + 409;
271   ecRun                     = ecFirstLazarus + 410;
272   ecPause                   = ecFirstLazarus + 411;
273   ecStepInto                = ecFirstLazarus + 412;
274   ecStepOver                = ecFirstLazarus + 413;
275   ecRunToCursor             = ecFirstLazarus + 414;
276   ecStopProgram             = ecFirstLazarus + 415;
277   ecResetDebugger           = ecFirstLazarus + 416;
278   ecRunParameters           = ecFirstLazarus + 417;
279   ecBuildFile               = ecFirstLazarus + 431;
280   ecRunFile                 = ecFirstLazarus + 432;
281   ecConfigBuildFile         = ecFirstLazarus + 433;
282   ecInspect                 = ecFirstLazarus + 440;
283   ecEvaluate                = ecFirstLazarus + 441;
284   ecAddWatch                = ecFirstLazarus + 442;
285   ecShowExecutionPoint      = ecFirstLazarus + 443;
286   ecStepOut                 = ecFirstLazarus + 444;
287   ecStepIntoInstr           = ecFirstLazarus + 445;
288   ecStepOverInstr           = ecFirstLazarus + 446;
289   ecStepIntoContext         = ecFirstLazarus + 447;
290   ecStepOverContext         = ecFirstLazarus + 448;
291   ecAddBpSource             = ecFirstLazarus + 449;
292   ecAddBpAddress            = ecFirstLazarus + 450;
293   ecAddBpDataWatch          = ecFirstLazarus + 451;
294   ecAttach                  = ecFirstLazarus + 452;
295   ecDetach                  = ecFirstLazarus + 453;
296 
297   // 460++ : used for ecViewHistory (debugger) / ecViewMacroList
298 
299   // project menu
300   ecNewProject              = ecFirstLazarus + 500;
301   ecNewProjectFromFile      = ecFirstLazarus + 501;
302   ecOpenProject             = ecFirstLazarus + 502;
303   ecCloseProject            = ecFirstLazarus + 503;
304   ecSaveProject             = ecFirstLazarus + 504;
305   ecSaveProjectAs           = ecFirstLazarus + 505;
306   ecPublishProject          = ecFirstLazarus + 506;
307   ecProjectInspector        = ecFirstLazarus + 507;
308   ecAddCurUnitToProj        = ecFirstLazarus + 508;
309   ecRemoveFromProj          = ecFirstLazarus + 509;
310   ecViewProjectUnits        = ecFirstLazarus + 510;
311   ecViewProjectForms        = ecFirstLazarus + 511;
312   ecViewProjectSource       = ecFirstLazarus + 512;
313   ecProjectOptions          = ecFirstLazarus + 513;
314   ecProjectChangeBuildMode  = ecFirstLazarus + 514;
315   ecProjectResaveFormsWithI18n = ecFirstLazarus + 515;
316 
317   // package menu
318   ecOpenPackage             = ecFirstLazarus + 600;
319   ecOpenPackageFile         = ecFirstLazarus + 601;
320   ecOpenPackageOfCurUnit    = ecFirstLazarus + 602;
321   ecAddCurFileToPkg         = ecFirstLazarus + 603;
322   ecNewPkgComponent         = ecFirstLazarus + 604;
323   ecPackageGraph            = ecFirstLazarus + 605;
324   ecPackageLinks            = ecFirstLazarus + 606;
325   ecEditInstallPkgs         = ecFirstLazarus + 607;
326   ecConfigCustomComps       = ecFirstLazarus + 608;
327   ecNewPackage              = ecFirstLazarus + 609;
328 
329   // custom tools menu
330   ecExtToolFirst            = ecFirstLazarus + 700;
331   ecExtToolLast             = ecFirstLazarus + 799;
332 
333   // tools menu
334   ecEnvironmentOptions      = ecFirstLazarus + 820;
335   ecRescanFPCSrcDir         = ecFirstLazarus + 821;
336   ecEditCodeTemplates       = ecFirstLazarus + 822;
337   ecCodeToolsDefinesEd      = ecFirstLazarus + 823;
338 
339   ecExtToolSettings         = ecFirstLazarus + 824;
340   ecManageDesktops          = ecFirstLazarus + 825;
341   ecManageExamples          = ecFirstLazarus + 826;
342   ecConfigBuildLazarus      = ecFirstLazarus + 830;
343   ecBuildLazarus            = ecFirstLazarus + 831;
344   ecBuildAdvancedLazarus    = ecFirstLazarus + 832;
345 
346   // window menu
347   ecManageSourceEditors     = ecFirstLazarus + 840;
348 
349   // help menu
350   ecAboutLazarus            = ecFirstLazarus + 900;
351   ecOnlineHelp              = ecFirstLazarus + 901;
352   ecContextHelp             = ecFirstLazarus + 903;
353   ecEditContextHelp         = ecFirstLazarus + 904;
354   ecReportingBug            = ecFirstLazarus + 905;
355   ecFocusHint               = ecFirstLazarus + 906;
356   ecSmartHint               = ecFirstLazarus + 907;
357 
358   // designer
359   ecDesignerCopy            = ecFirstLazarus + 1000;
360   ecDesignerCut             = ecFirstLazarus + 1001;
361   ecDesignerPaste           = ecFirstLazarus + 1002;
362   ecDesignerSelectParent    = ecFirstLazarus + 1003;
363   ecDesignerMoveToFront     = ecFirstLazarus + 1004;
364   ecDesignerMoveToBack      = ecFirstLazarus + 1005;
365   ecDesignerForwardOne      = ecFirstLazarus + 1006;
366   ecDesignerBackOne         = ecFirstLazarus + 1007;
367   ecDesignerToggleNonVisComps= ecFirstLazarus + 1008;
368 
369 
370   (* SynEdit Plugins
371      Define fixed values for the IDE. Must be mapped to plugincommands,
372      when assigned to KeyMap.
373      Offsets are defined in KeyMapping
374      See: TKeyCommandRelationList.AssignTo
375   *)
376   ecFirstPlugin = ecFirstLazarus +  5000; // 6001
377   ecLastPlugin = ecFirstLazarus +  6000; // 6001
378   // custom commands
379   ecLazarusLast             = ecLastPlugin;
380 
381   // TSynPluginTemplateEdit - In cell
382   ecIdePTmplEdNextCell           = ecFirstPlugin +  0;
383   ecIdePTmplEdNextCellSel        = ecFirstPlugin +  1;
384   ecIdePTmplEdNextCellRotate     = ecFirstPlugin +  2;
385   ecIdePTmplEdNextCellSelRotate  = ecFirstPlugin +  3;
386   ecIdePTmplEdPrevCell           = ecFirstPlugin +  4;
387   ecIdePTmplEdPrevCellSel        = ecFirstPlugin +  5;
388   ecIdePTmplEdCellHome           = ecFirstPlugin +  6;
389   ecIdePTmplEdCellEnd            = ecFirstPlugin +  7;
390   ecIdePTmplEdCellSelect         = ecFirstPlugin +  8;
391   ecIdePTmplEdFinish             = ecFirstPlugin +  9;
392   ecIdePTmplEdEscape             = ecFirstPlugin + 10;
393   ecIdePTmplEdNextFirstCell           = ecFirstPlugin + 11;
394   ecIdePTmplEdNextFirstCellSel        = ecFirstPlugin + 12;
395   ecIdePTmplEdNextFirstCellRotate     = ecFirstPlugin + 13;
396   ecIdePTmplEdNextFirstCellSelRotate  = ecFirstPlugin + 14;
397   ecIdePTmplEdPrevFirstCell           = ecFirstPlugin + 15;
398   ecIdePTmplEdPrevFirstCellSel        = ecFirstPlugin + 16;
399 
400   // TSynPluginTemplateEdit - Out off Cell
401   ecIdePTmplEdOutNextCell           = ecFirstPlugin +  20;
402   ecIdePTmplEdOutNextCellSel        = ecFirstPlugin +  21;
403   ecIdePTmplEdOutNextCellRotate     = ecFirstPlugin +  22;
404   ecIdePTmplEdOutNextCellSelRotate  = ecFirstPlugin +  23;
405   ecIdePTmplEdOutPrevCell           = ecFirstPlugin +  24;
406   ecIdePTmplEdOutPrevCellSel        = ecFirstPlugin +  25;
407   ecIdePTmplEdOutCellHome           = ecFirstPlugin +  26;
408   ecIdePTmplEdOutCellEnd            = ecFirstPlugin +  27;
409   ecIdePTmplEdOutCellSelect         = ecFirstPlugin +  28;
410   ecIdePTmplEdOutFinish             = ecFirstPlugin +  29;
411   ecIdePTmplEdOutEscape             = ecFirstPlugin +  30;
412   ecIdePTmplEdOutNextFirstCell           = ecFirstPlugin + 31;
413   ecIdePTmplEdOutNextFirstCellSel        = ecFirstPlugin + 32;
414   ecIdePTmplEdOutNextFirstCellRotate     = ecFirstPlugin + 33;
415   ecIdePTmplEdOutNextFirstCellSelRotate  = ecFirstPlugin + 34;
416   ecIdePTmplEdOutPrevFirstCell           = ecFirstPlugin + 35;
417   ecIdePTmplEdOutPrevFirstCellSel        = ecFirstPlugin + 36;
418 
419   // TSynPluginSyncroEdit - in celll
420   ecIdePSyncroEdNextCell           = ecFirstPlugin +  50;
421   ecIdePSyncroEdNextCellSel        = ecFirstPlugin +  51;
422   ecIdePSyncroEdPrevCell           = ecFirstPlugin +  52;
423   ecIdePSyncroEdPrevCellSel        = ecFirstPlugin +  53;
424   ecIdePSyncroEdCellHome           = ecFirstPlugin +  54;
425   ecIdePSyncroEdCellEnd            = ecFirstPlugin +  55;
426   ecIdePSyncroEdCellSelect         = ecFirstPlugin +  56;
427   ecIdePSyncroEdEscape             = ecFirstPlugin +  57;
428   ecIdePSyncroEdNextFirstCell      = ecFirstPlugin +  58;
429   ecIdePSyncroEdNextFirstCellSel   = ecFirstPlugin +  59;
430   ecIdePSyncroEdPrevFirstCell      = ecFirstPlugin +  60;
431   ecIdePSyncroEdPrevFirstCellSel   = ecFirstPlugin +  61;
432 
433   // TSynPluginSyncroEdit - Out off cell
434   ecIdePSyncroEdOutNextCell           = ecFirstPlugin +  70;
435   ecIdePSyncroEdOutNextCellSel        = ecFirstPlugin +  71;
436   ecIdePSyncroEdOutPrevCell           = ecFirstPlugin +  72;
437   ecIdePSyncroEdOutPrevCellSel        = ecFirstPlugin +  73;
438   ecIdePSyncroEdOutCellHome           = ecFirstPlugin +  74;
439   ecIdePSyncroEdOutCellEnd            = ecFirstPlugin +  75;
440   ecIdePSyncroEdOutCellSelect         = ecFirstPlugin +  76;
441   ecIdePSyncroEdOutEscape             = ecFirstPlugin +  77;
442   ecIdePSyncroEdOutNextFirstCell      = ecFirstPlugin +  78;
443   ecIdePSyncroEdOutNextFirstCellSel   = ecFirstPlugin +  79;
444   ecIdePSyncroEdOutPrevFirstCell      = ecFirstPlugin +  80;
445   ecIdePSyncroEdOutPrevFirstCellSel   = ecFirstPlugin +  81;
446 
447   // TSynPluginSyncroEdit - selecting
448   ecIdePSyncroEdSelStart              = ecFirstPlugin +  90;
449 
450 
451 type
452   TIDECommand = class;
453   TIDECommandCategory = class;
454   TIDESpecialCommand = class;
455   TIDESpecialCommands = class;
456 
457   TNotifyProcedure = procedure(Sender: TObject);
458 
459   { TIDECommandScope
460     A TIDECommandScope defines a set of IDE windows that will share the same
461     IDE commands. An IDE command can be valid in several scopes at the same
462     time. }
463 
464   { TIDECommandScope }
465 
466   TIDECommandScope = class(TPersistent)
467   private
468     FName: string;
469     FIDEWindowClasses: TFPList;// list of TCustomFormClass
470     FCategories: TFPList;
GetCategoriesnull471     function GetCategories(Index: integer): TIDECommandCategory;
GetIDEWindowClassesnull472     function GetIDEWindowClasses(Index: integer): TCustomFormClass;
473   public
474     constructor Create(const TheName: string);
475     destructor Destroy; override;
476     procedure AddWindowClass(AWindowClass: TCustomFormClass);
477     procedure RemoveWindowClass(AWindowClass: TCustomFormClass);
IDEWindowClassCountnull478     function IDEWindowClassCount: integer;
CategoryCountnull479     function CategoryCount: integer;
HasIDEWindowClassnull480     function HasIDEWindowClass(AWindowClass: TCustomFormClass): boolean;
Intersectsnull481     function Intersects(AScope: TIDECommandScope): boolean;
482     procedure WriteDebugReport;
483   public
484     property Name: string read FName;
485     property IDEWindowClasses[Index: integer]: TCustomFormClass read GetIDEWindowClasses;
486     property Categories[Index: integer]: TIDECommandCategory read GetCategories;
487   end;
488 
489   { TIDECommandScopes }
490 
491   TIDECommandScopes = class(TPersistent)
492   private
493     FItems: TFPList;
GetItemsnull494     function GetItems(Index: integer): TIDECommandScope;
495   public
496     constructor Create;
497     destructor Destroy; override;
498     procedure Clear;
499     procedure Add(NewItem: TIDECommandScope);
IndexOfnull500     function IndexOf(AnItem: TIDECommandScope): Integer;
IndexByNamenull501     function IndexByName(const AName: string): Integer;
FindByNamenull502     function FindByName(const AName: string): TIDECommandScope;
CreateUniqueNamenull503     function CreateUniqueName(const AName: string): string;
Countnull504     function Count: integer;
505   public
506     property Items[Index: integer]: TIDECommandScope read GetItems;
507   end;
508 
509 
510   { TIDEShortCut }
511 
512   TIDEShortCut = record
513     Key1: word;
514     Shift1: TShiftState;
515     Key2: word;
516     Shift2: TShiftState;
517   end;
518   PIDEShortCut = ^TIDEShortCut;
519 
520   { TIDECommandCategory - list of TKeyCommandRelation/TIDECommand
521     TIDECommandCategory is used to divide the commands in handy packets }
522 
523   TIDECommandCategory = class(TList)
524   private
525     procedure SetDescription(const AValue: string);
526   protected
527     FDescription: string;
528     FName: string;
529     FParent: TIDECommandCategory;
530     FScope: TIDECommandScope;
531     procedure SetScope(const AValue: TIDECommandScope);
532   public
533     destructor Destroy; override;
ScopeIntersectsnull534     function ScopeIntersects(AScope: TIDECommandScope): boolean;
535     procedure WriteScopeDebugReport;
536     procedure DoOnUpdate;
537   public
538     property Name: string read FName;
539     property Description: string read FDescription write SetDescription;
540     property Parent: TIDECommandCategory read FParent;
541     procedure Delete(Index: Integer); virtual;
542     property Scope: TIDECommandScope read FScope write SetScope;
543   end;
544 
545 
546   { TIDECommand }
547   { class for storing the keys of a single command (shortcut-command relationship) }
548   TIDECommand = class
549   private
550     FCategory: TIDECommandCategory;
551     FCommand: word;
552     FLocalizedName: string;
553     FName: String;
554     FOnExecute: TNotifyEvent;
555     FOnExecuteProc: TNotifyProcedure;
556     FShortcutA: TIDEShortCut;
557     FShortcutB: TIDEShortCut;
558     FOnUpdateMethod: TNotifyEvent;
559     FOnUpdateProc: TNotifyProcedure;
560     FUsers: TIDESpecialCommands;
561 
GetUsernull562     function GetUser(Index: Integer): TIDESpecialCommand;
GetUserCountnull563     function GetUserCount: Integer;
564     procedure SetOnExecute(const aOnExecute: TNotifyEvent);
565     procedure SetOnExecuteProc(const aOnExecuteProc: TNotifyProcedure);
566     procedure SetEnabled(const AEnabled: Boolean);
567     procedure SetCaption(const ACaption: string);
568     procedure SetHint(const AHint: string);
569   protected
GetLocalizedNamenull570     function GetLocalizedName: string; virtual;
571     procedure SetLocalizedName(const AValue: string); virtual;
572     procedure SetCategory(const AValue: TIDECommandCategory); virtual;
573     procedure SetShortcutA(const AValue: TIDEShortCut); virtual;
574     procedure SetShortcutB(const AValue: TIDEShortCut); virtual;
575     procedure Change;
576     procedure Init; virtual;
577   public
AsShortCutnull578     function AsShortCut: TShortCut; virtual;
579     constructor Create(TheCategory: TIDECommandCategory;
580               const TheName, TheLocalizedName: String; TheCommand: word;
581               const TheShortcutA, TheShortcutB: TIDEShortCut;
582               const ExecuteMethod: TNotifyEvent; const ExecuteProc: TNotifyProcedure);
583     constructor Create(TheCategory: TIDECommandCategory;
584               const TheName, TheLocalizedName: String; TheCommand: word);
585     constructor Create(ACommand: TIDECommand; ACategory: TIDECommandCategory);
586     destructor Destroy; override;
587     procedure Assign(ACommand: TIDECommand);
IsEqualnull588     function IsEqual(ACommand: TIDECommand): boolean;
589   public
590     DefaultShortcutA: TIDEShortCut;
591     DefaultShortcutB: TIDEShortCut;
592     procedure ClearShortcutA;
593     procedure ClearShortcutB;
GetCategoryAndNamenull594     function GetCategoryAndName: string;
Executenull595     function Execute(Sender: TObject): boolean;
596     procedure UserAdded(const aUser: TIDESpecialCommand);
597     procedure UserRemoved(const aUser: TIDESpecialCommand);
598     procedure DoOnUpdate; overload;
599     procedure DoOnUpdate(Sender: TObject); overload;
600   public
601     property Enabled: Boolean write SetEnabled;
602     property Caption: string write SetCaption;
603     property Hint: string write SetHint;
604     // don't add Visible property here - it is not generic. Tool buttons should never be hidden programmatically
605   public
606     property Name: String read FName;
607     property Command: word read FCommand;// see the ecXXX constants above
608     property LocalizedName: string read GetLocalizedName write SetLocalizedName;
609     property Category: TIDECommandCategory read FCategory write SetCategory;
610     property ShortcutA: TIDEShortCut read FShortcutA write SetShortcutA;
611     property ShortcutB: TIDEShortCut read FShortcutB write SetShortcutB;
612     property OnExecute: TNotifyEvent read FOnExecute write SetOnExecute;
613     property OnExecuteProc: TNotifyProcedure read FOnExecuteProc write SetOnExecuteProc;
614     property OnUpdate: TNotifyEvent read FOnUpdateMethod write FOnUpdateMethod;
615     property OnUpdateProc: TNotifyProcedure read FOnUpdateProc write FOnUpdateProc;
616 
617     property Users[Index: Integer]: TIDESpecialCommand read GetUser;
618     property UserCount: Integer read GetUserCount;
619   end;
620 
621 
622   { TIDECommands }
623 
624   TIDECommands = class
625   private
626     FCustomUpdateEvents: TMethodList;
627     FDontExecuteUpdateEventsUntil: QWord;
628 
629     procedure ApplicationOnIdle({%H-}Sender: TObject; var {%H-}Done: Boolean);
630   protected
631     function GetCategory(Index: integer): TIDECommandCategory; virtual; abstract;
632   public
633     constructor Create;
634     destructor Destroy; override;
635 
636     function FindIDECommand(ACommand: word): TIDECommand; virtual; abstract;
637     function CreateCategory(Parent: TIDECommandCategory;
638                             const Name, Description: string;
639                             Scope: TIDECommandScope = nil): TIDECommandCategory; virtual; abstract;
640     function CreateCommand(Category: TIDECommandCategory;
641                            const Name, Description: string;
642                            const TheShortcutA, TheShortcutB: TIDEShortCut;
643                            const OnExecuteMethod: TNotifyEvent = nil;
644                            const OnExecuteProc: TNotifyProcedure = nil
645                            ): TIDECommand; virtual; abstract;
646     function FindCategoryByName(const CategoryName: string): TIDECommandCategory; virtual; abstract;
647     function FindCommandByName(const CommandName: string): TIDECommand; virtual; abstract;
648     function FindCommandsByShortCut(const ShortCutMask: TIDEShortCut;
649             IDEWindowClass: TCustomFormClass = nil): TFPList; virtual; abstract; // list of TIDECommand
650     function RemoveShortCut(ShortCutMask: TIDEShortCut;
651             IDEWindowClass: TCustomFormClass = nil): Integer; virtual; abstract;
652     function CategoryCount: integer; virtual; abstract;
653   public
654     procedure StartUpdateEvents;
655     procedure StopUpdateEvents;
656 
657     procedure ExecuteUpdateEvents;
658     procedure CancelPostponeUpdateEvents;
659     procedure PostponeUpdateEvents;
660 
661     procedure AddCustomUpdateEvent(const aEvent: TNotifyEvent);
662     procedure RemoveCustomUpdateEvent(const aEvent: TNotifyEvent);
663   public
664     property Categories[Index: integer]: TIDECommandCategory read GetCategory;
665   end;
666 
667   // MenuItem and ButtonCommand inherit from SpecialCommand.
668 
669   TGetHintCaptionEvent = procedure(Sender: TObject; var ACaption, AHint: string) of object;
670 
671   TIDESpecialCommand = class(TPersistent)
672   private
673     FCommand: TIDECommand;
674     FName: string;
675     FCaption: string;
676     FEnabled: Boolean;
677     FChecked: Boolean;
678     FHint: string;
679     FImageIndex: Integer;
680     FOnClickMethod: TNotifyEvent;
681     FOnClickProc: TNotifyProcedure;
682     FOnRequestCaption: TGetHintCaptionEvent;
683     FSyncProperties: Boolean;
684     FBlockSync: Integer;
685   protected
686     function SyncAvailable: Boolean; virtual;
687     function GetCaption: string; virtual;
688     procedure SetCommand(const AValue: TIDECommand); virtual;
689     procedure SetName(const aName: string); virtual;
690     procedure SetCaption(aCaption: string); virtual;
691     procedure SetEnabled(const aEnabled: Boolean); virtual;
692     procedure SetChecked(const aChecked: Boolean); virtual;
693     procedure SetHint(const aHint: string); virtual;
694     procedure SetImageIndex(const aImageIndex: Integer); virtual;
695     procedure SetOnClickMethod(const aOnClick: TNotifyEvent); virtual;
696     procedure SetOnClickProc(const aOnClickProc: TNotifyProcedure); virtual;
697     procedure SetOnRequestCaption(
698       const aOnRequestCaptionHint: TGetHintCaptionEvent); virtual;
699     procedure SetResourceName(const aResourceName: string); virtual;
700     procedure ShortCutsUpdated(const {%H-}aShortCut, {%H-}aShortCutKey2: TShortCut); virtual;
701   public
702     constructor Create(const aName: string); virtual;
703     destructor Destroy; override;
704   public
705     procedure DoOnClick; overload;
706     procedure DoOnClick(Sender: TObject); virtual; overload;
707     function DoOnRequestCaption(Sender: TObject): Boolean; virtual;
708 
709     procedure BlockSync;
710     procedure UnblockSync;
711   public
712     function GetCaptionWithShortCut: String; virtual;
713     function GetHintOrCaptionWithShortCut: String; virtual;
714     function GetShortcut: String; virtual;
715 
716     property Command: TIDECommand read FCommand write SetCommand;
717     property SyncProperties: Boolean read FSyncProperties write FSyncProperties;
718     property Name: string read FName write SetName;
719     property Caption: string read GetCaption write SetCaption;
720     property Hint: string read FHint write SetHint;
721     property Enabled: Boolean read FEnabled write SetEnabled;
722     property Checked: Boolean read FChecked write SetChecked;
723     property ImageIndex: Integer read FImageIndex write SetImageIndex;
724     property ResourceName: string write SetResourceName;
725     // don't add Visible property here - it is not generic. Tool buttons should never be hidden programmatically
726 
727     property OnClick: TNotifyEvent read FOnClickMethod write SetOnClickMethod;
728     property OnClickProc: TNotifyProcedure read FOnClickProc write SetOnClickProc;
729     property OnRequestCaptionHint: TGetHintCaptionEvent read FOnRequestCaption write SetOnRequestCaption;
730   end;
731 
732   TIDESpecialCommandEnumerator = class
733   private
734     FList: TIDESpecialCommands;
735     FPosition: Integer;
736   public
737     constructor Create(AButtons: TIDESpecialCommands);
GetCurrentnull738     function GetCurrent: TIDESpecialCommand;
MoveNextnull739     function MoveNext: Boolean;
740     property Current: TIDESpecialCommand read GetCurrent;
741   end;
742 
743   TIDESpecialCommands = class
744   private
745     FList: TFPList;
GetCountnull746     function GetCount: Integer;
GetItemsnull747     function GetItems(Index: Integer): TIDESpecialCommand;
748   public
749     constructor Create;
750     destructor Destroy; override;
751   public
GetEnumeratornull752     function GetEnumerator: TIDESpecialCommandEnumerator;
753     procedure Add(const aUser: TIDESpecialCommand);
754     procedure Remove(const aUser: TIDESpecialCommand);
755 
756     property Count: Integer read GetCount;
757     property Items[Index: Integer]: TIDESpecialCommand read GetItems; default;
758   end;
759 
760 
761 
762 const
763   CleanIDEShortCut: TIDEShortCut =
764     (Key1: VK_UNKNOWN; Shift1: []; Key2: VK_UNKNOWN; Shift2: []);
765 
IDEShortCutnull766 function IDEShortCut(Key1: word; Shift1: TShiftState;
767   Key2: word = VK_UNKNOWN; Shift2: TShiftState = []): TIDEShortCut;
768 
769 
770 type
771   TExecuteIDEShortCut =
772     procedure(Sender: TObject; var Key: word; Shift: TShiftState;
773               IDEWindowClass: TCustomFormClass) of object;
endernull774   TExecuteIDECommand = function(Sender: TObject; Command: word): boolean of object;
775 
776 var
777   OnExecuteIDEShortCut: TExecuteIDEShortCut;
778   OnExecuteIDECommand: TExecuteIDECommand;
779 
780 procedure ExecuteIDEShortCut(Sender: TObject; var Key: word; Shift: TShiftState;
781   IDEWindowClass: TCustomFormClass);
782 procedure ExecuteIDEShortCut(Sender: TObject; var Key: word; Shift: TShiftState);
ExecuteIDECommandnull783 function ExecuteIDECommand(Sender: TObject; Command: word): boolean;
IsValidIDECommandKeynull784 function IsValidIDECommandKey(Key: word): boolean;
785 
786 var
787   // will be set by the IDE
788   IDECommandList: TIDECommands;
789   IDECommandScopes: TIDECommandScopes = nil;
790 var
791   IDECmdScopeSrcEdit: TIDECommandScope;
792   IDECmdScopeSrcEditOnly: TIDECommandScope;
793   IDECmdScopeSrcEditOnlyMultiCaret: TIDECommandScope;
794   IDECmdScopeSrcEditOnlyTmplEdit: TIDECommandScope;
795   IDECmdScopeSrcEditOnlyTmplEditOff: TIDECommandScope;
796   IDECmdScopeSrcEditOnlySyncroEditSel: TIDECommandScope;
797   IDECmdScopeSrcEditOnlySyncroEdit: TIDECommandScope;
798   IDECmdScopeSrcEditOnlySyncroEditOff: TIDECommandScope;
799   IDECmdScopeDesignerOnly: TIDECommandScope;
800   IDECmdScopeObjectInspectorOnly: TIDECommandScope;
801 
802 const
803   CommandCategoryToolMenuName = 'ToolMenu';
804   CommandCategoryCustomName = 'Custom';
805   CommandCategoryTextEditingName = 'text editing commands';
806   CommandCategoryViewName = 'ViewMenu';
807   CommandCategoryCodeTools = 'CodeTools';
808 
809 // register a new IDE command category (i.e. set of commands)
RegisterIDECommandCategorynull810 function RegisterIDECommandCategory(Parent: TIDECommandCategory;
811                           const Name, Description: string): TIDECommandCategory;
812 
813 // register a new IDE command (i.e. a shortcut, IDE function)
functionnull814 function RegisterIDECommand(Category: TIDECommandCategory;
815   const Name, Description: string;
816   const OnExecuteMethod: TNotifyEvent = nil;
817   const OnExecuteProc: TNotifyProcedure = nil): TIDECommand;
RegisterIDECommandnull818 function RegisterIDECommand(Category: TIDECommandCategory;
819   const Name, Description: string; Key1: word; Shift1: TShiftState;
820   const OnExecuteMethod: TNotifyEvent = nil;
821   const OnExecuteProc: TNotifyProcedure = nil): TIDECommand;
RegisterIDECommandnull822 function RegisterIDECommand(Category: TIDECommandCategory;
823   const Name, Description: string; const ShortCut1: TIDEShortCut;
824   const OnExecuteMethod: TNotifyEvent = nil;
825   const OnExecuteProc: TNotifyProcedure = nil): TIDECommand;
RegisterIDECommandnull826 function RegisterIDECommand(Category: TIDECommandCategory;
827   const Name, Description: string;
828   const ShortCut1, ShortCut2: TIDEShortCut;
829   const OnExecuteMethod: TNotifyEvent = nil;
830   const OnExecuteProc: TNotifyProcedure = nil): TIDECommand;
831 
832 // register a new IDE command scope (i.e. a set of windows)
RegisterIDECommandScopenull833 function RegisterIDECommandScope(const Name: string): TIDECommandScope;
834 
835 procedure CreateStandardIDECommandScopes;
836 
837 
CompareIDEShortCutsnull838 function CompareIDEShortCuts(Data1, Data2: Pointer): integer;
CompareIDEShortCutKey1snull839 function CompareIDEShortCutKey1s(Data1, Data2: Pointer): integer;
IdentToIDECommandnull840 function IdentToIDECommand(const Ident: string; var Cmd: longint): boolean;
IDECommandToIdentnull841 function IDECommandToIdent(Cmd: longint; var Ident: string): boolean;
IDECommandToIdentnull842 function IDECommandToIdent(Cmd: longint): string;
843 procedure GetIDEEditorCommandValues(Proc: TGetStrProc);
844 
845 implementation
846 
IDEShortCutnull847 function IDEShortCut(Key1: word; Shift1: TShiftState;
848   Key2: word; Shift2: TShiftState): TIDEShortCut;
849 begin
850   Result.Key1:=Key1;
851   Result.Shift1:=Shift1;
852   Result.Key2:=Key2;
853   Result.Shift2:=Shift2;
854 end;
855 
856 procedure ExecuteIDEShortCut(Sender: TObject; var Key: word; Shift: TShiftState;
857   IDEWindowClass: TCustomFormClass);
858 begin
859   if (OnExecuteIDECommand<>nil) and (Key<>VK_UNKNOWN) then
860     OnExecuteIDEShortCut(Sender,Key,Shift,IDEWindowClass);
861 end;
862 
863 procedure ExecuteIDEShortCut(Sender: TObject; var Key: word;
864   Shift: TShiftState);
865 begin
866   OnExecuteIDEShortCut(Sender,Key,Shift,nil);
867 end;
868 
ExecuteIDECommandnull869 function ExecuteIDECommand(Sender: TObject; Command: word): boolean;
870 begin
871   if (OnExecuteIDECommand<>nil) and (Command<>0) then
872     Result:=OnExecuteIDECommand(Sender,Command)
873   else
874     Result:=false;
875 end;
876 
IsValidIDECommandKeynull877 function IsValidIDECommandKey(Key: word): boolean;
878 begin
879   case Key of
880   VK_UNDEFINED,VK_UNKNOWN,
881   VK_CONTROL,VK_LCONTROL,VK_RCONTROL,
882   VK_SHIFT,VK_LSHIFT,VK_RSHIFT,
883   VK_LBUTTON,VK_MBUTTON,VK_RBUTTON,
884   VK_LWIN,VK_RWIN:
885     exit(false);
886   end;
887   Result:=true;
888 end;
889 
890 procedure CreateStandardIDECommandScopes;
891 begin
892   IDECommandScopes:=TIDECommandScopes.Create;
893   IDECmdScopeSrcEdit:=RegisterIDECommandScope('SourceEditor');
894   IDECmdScopeSrcEditOnly:=RegisterIDECommandScope('SourceEditorOnly');
895   IDECmdScopeSrcEditOnlyMultiCaret:=RegisterIDECommandScope('IDECmdScopeSrcEditOnlyMultiCaret');
896   IDECmdScopeSrcEditOnlyTmplEdit:=RegisterIDECommandScope('SourceEditorOnlyTemplateEdit');
897   IDECmdScopeSrcEditOnlyTmplEditOff:=RegisterIDECommandScope('SourceEditorOnlyTemplateEditOff');
898   IDECmdScopeSrcEditOnlySyncroEditSel:=RegisterIDECommandScope('SourceEditorOnlySyncroEditSel');
899   IDECmdScopeSrcEditOnlySyncroEdit:=RegisterIDECommandScope('SourceEditorOnlySyncroEdit');
900   IDECmdScopeSrcEditOnlySyncroEditOff:=RegisterIDECommandScope('SourceEditorOnlySyncroEdit');
901   IDECmdScopeDesignerOnly:=RegisterIDECommandScope('DesignerOnly');
902   IDECmdScopeObjectInspectorOnly:=RegisterIDECommandScope('ObjectInspectorOnly');
903 end;
904 
905 type
906 // in fpc 2.3.1 TShiftState is declared with {$packset 1}
907 {$IF sizeof(TShiftState)=2}
908   TShiftStateInt = word;
909 {$ELSE}
910   TShiftStateInt = integer;
911 {$ENDIF}
912 
CompareIDEShortCutsnull913 function CompareIDEShortCuts(Data1, Data2: Pointer): integer;
914 var
915   ShortCut1: PIDEShortCut absolute Data1;
916   ShortCut2: PIDEShortCut absolute Data2;
917 begin
918   if ShortCut1^.Key1>ShortCut2^.Key1 then
919     Result:=1
920   else if ShortCut1^.Key1<ShortCut2^.Key1 then
921     Result:=-1
922   else if TShiftStateInt(ShortCut1^.Shift1)>TShiftStateInt(ShortCut2^.Shift1) then
923     Result:=1
924   else if TShiftStateInt(ShortCut1^.Shift1)<TShiftStateInt(ShortCut2^.Shift1) then
925     Result:=-1
926   else if ShortCut1^.Key2>ShortCut2^.Key2 then
927     Result:=1
928   else if ShortCut1^.Key2<ShortCut2^.Key2 then
929     Result:=-1
930   else if TShiftStateInt(ShortCut1^.Shift2)>TShiftStateInt(ShortCut2^.Shift2) then
931     Result:=1
932   else if TShiftStateInt(ShortCut1^.Shift2)<TShiftStateInt(ShortCut2^.Shift2) then
933     Result:=-1
934   else
935     Result:=0;
936 end;
937 
CompareIDEShortCutKey1snull938 function CompareIDEShortCutKey1s(Data1, Data2: Pointer): integer;
939 var
940   ShortCut1: PIDEShortCut;
941   ShortCut2: PIDEShortCut;
942 begin
943   ShortCut1:=PIDEShortCut(Data1);
944   ShortCut2:=PIDEShortCut(Data2);
945   if ShortCut1^.Key1>ShortCut2^.Key1 then
946     Result:=1
947   else if ShortCut1^.Key1<ShortCut2^.Key1 then
948     Result:=-1
949   else if TShiftStateInt(ShortCut1^.Shift1)>TShiftStateInt(ShortCut2^.Shift1) then
950     Result:=1
951   else if TShiftStateInt(ShortCut1^.Shift1)<TShiftStateInt(ShortCut2^.Shift1) then
952     Result:=-1
953   else
954     Result:=0;
955 end;
956 
RegisterIDECommandCategorynull957 function RegisterIDECommandCategory(Parent: TIDECommandCategory;
958   const Name, Description: string): TIDECommandCategory;
959 begin
960   Result:=IDECommandList.CreateCategory(Parent,Name,Description);
961 end;
962 
RegisterIDECommandnull963 function RegisterIDECommand(Category: TIDECommandCategory;
964   const Name, Description: string;
965   const OnExecuteMethod: TNotifyEvent = nil;
966   const OnExecuteProc: TNotifyProcedure = nil): TIDECommand;
967 begin
968   Result:=RegisterIDECommand(Category,Name,Description,IDEShortCut(VK_UNKNOWN,[]),
969                              OnExecuteMethod,OnExecuteProc);
970 end;
971 
RegisterIDECommandnull972 function RegisterIDECommand(Category: TIDECommandCategory;
973   const Name, Description: string;
974   Key1: word; Shift1: TShiftState;
975   const OnExecuteMethod: TNotifyEvent;
976   const OnExecuteProc: TNotifyProcedure): TIDECommand;
977 begin
978   Result:=RegisterIDECommand(Category,Name,Description,IDEShortCut(Key1,Shift1),
979                              OnExecuteMethod,OnExecuteProc);
980 end;
981 
RegisterIDECommandnull982 function RegisterIDECommand(Category: TIDECommandCategory;
983   const Name, Description: string;  const ShortCut1: TIDEShortCut;
984   const OnExecuteMethod: TNotifyEvent;
985   const OnExecuteProc: TNotifyProcedure): TIDECommand;
986 begin
987   Result:=RegisterIDECommand(Category,Name,Description,
988                              ShortCut1,IDEShortCut(VK_UNKNOWN,[]),
989                              OnExecuteMethod,OnExecuteProc);
990 end;
991 
RegisterIDECommandnull992 function RegisterIDECommand(Category: TIDECommandCategory;
993   const Name, Description: string;
994   const ShortCut1, ShortCut2: TIDEShortCut;
995   const OnExecuteMethod: TNotifyEvent;
996   const OnExecuteProc: TNotifyProcedure): TIDECommand;
997 begin
998   Result:=IDECommandList.CreateCommand(Category,Name,Description,
999                                        ShortCut1,ShortCut2,OnExecuteMethod,
1000                                        OnExecuteProc);
1001 end;
1002 
RegisterIDECommandScopenull1003 function RegisterIDECommandScope(const Name: string): TIDECommandScope;
1004 begin
1005   Result:=TIDECommandScope.Create(Name);
1006   IDECommandScopes.Add(Result);
1007 end;
1008 
1009 { TIDECommandScope }
1010 
GetCategoriesnull1011 function TIDECommandScope.GetCategories(Index: integer): TIDECommandCategory;
1012 begin
1013   Result:=TIDECommandCategory(FCategories[Index]);
1014 end;
1015 
TIDECommandScope.GetIDEWindowClassesnull1016 function TIDECommandScope.GetIDEWindowClasses(Index: integer): TCustomFormClass;
1017 begin
1018   Result:=TCustomFormClass(FIDEWindowClasses[Index]);
1019 end;
1020 
1021 constructor TIDECommandScope.Create(const TheName: string);
1022 begin
1023   FName:=TheName;
1024   FIDEWindowClasses:=TFPList.Create;
1025   FCategories:=TFPList.Create;
1026 end;
1027 
1028 destructor TIDECommandScope.Destroy;
1029 var
1030   i: Integer;
1031 begin
1032   for i:=FCategories.Count-1 downto 0 do
1033     Categories[i].Scope:=nil;
1034   FreeAndNil(FIDEWindowClasses);
1035   FreeAndNil(FCategories);
1036   inherited Destroy;
1037 end;
1038 
1039 procedure TIDECommandScope.AddWindowClass(AWindowClass: TCustomFormClass);
1040 begin
1041   if FIDEWindowClasses.IndexOf(AWindowClass)>=0 then
1042     RaiseGDBException('TIDECommandScope.AddWindowClass');
1043   FIDEWindowClasses.Add(AWindowClass);
1044 end;
1045 
1046 procedure TIDECommandScope.RemoveWindowClass(AWindowClass: TCustomFormClass);
1047 begin
1048   FIDEWindowClasses.Remove(AWindowClass);
1049 end;
1050 
TIDECommandScope.IDEWindowClassCountnull1051 function TIDECommandScope.IDEWindowClassCount: integer;
1052 begin
1053   Result:=FIDEWindowClasses.Count;
1054 end;
1055 
CategoryCountnull1056 function TIDECommandScope.CategoryCount: integer;
1057 begin
1058   Result:=FCategories.Count;
1059 end;
1060 
TIDECommandScope.HasIDEWindowClassnull1061 function TIDECommandScope.HasIDEWindowClass(AWindowClass: TCustomFormClass): boolean;
1062 var
1063   i: Integer;
1064 begin
1065   if AWindowClass<>nil then begin
1066     for i:=0 to FIDEWindowClasses.Count-1 do begin
1067       if (FIDEWindowClasses[i]=nil)
1068       or AWindowClass.InheritsFrom(TCustomFormClass(FIDEWindowClasses[i])) then
1069         exit(true);
1070     end;
1071   end else begin
1072     if FIDEWindowClasses.IndexOf(nil)>=0 then
1073       exit(true);
1074   end;
1075   Result:=false;
1076 end;
1077 
Intersectsnull1078 function TIDECommandScope.Intersects(AScope: TIDECommandScope): boolean;
1079 var
1080   i: Integer;
1081   CurClass: TCustomFormClass;
1082 begin
1083   if AScope=nil then
1084     Result:=true
1085   else begin
1086     for i:=0 to FIDEWindowClasses.Count-1 do begin
1087       CurClass:=TCustomFormClass(FIDEWindowClasses[i]);
1088       if (CurClass=nil)
1089       or (AScope.FIDEWindowClasses.IndexOf(FIDEWindowClasses[i])>=0) then
1090         exit(true);
1091     end;
1092     Result:=false;
1093   end;
1094 end;
1095 
1096 procedure TIDECommandScope.WriteDebugReport;
1097 var
1098   i: Integer;
1099 begin
1100   debugln('TIDECommandScope.WriteDebugReport ',Name);
1101   for i:=0 to FIDEWindowClasses.Count-1 do begin
1102     if FIDEWindowClasses[i]=nil then
1103       debugln('  ',dbgs(i),'/',dbgs(FIDEWindowClasses.Count),' nil')
1104     else
1105       debugln('  ',dbgs(i),'/',dbgs(FIDEWindowClasses.Count),' ',TClass(FIDEWindowClasses[i]).ClassName);
1106   end;
1107 end;
1108 
1109 { TIDECommandScopes }
1110 
TIDECommandScopes.GetItemsnull1111 function TIDECommandScopes.GetItems(Index: integer): TIDECommandScope;
1112 begin
1113   Result:=TIDECommandScope(FItems[Index]);
1114 end;
1115 
1116 constructor TIDECommandScopes.Create;
1117 begin
1118   FItems:=TFPList.Create;
1119 end;
1120 
1121 destructor TIDECommandScopes.Destroy;
1122 begin
1123   Clear;
1124   FItems.Free;
1125   inherited Destroy;
1126 end;
1127 
1128 procedure TIDECommandScopes.Clear;
1129 var
1130   i: Integer;
1131 begin
1132   for i:=0 to FItems.Count-1 do Items[i].Free;
1133   FItems.Clear;
1134 end;
1135 
1136 procedure TIDECommandScopes.Add(NewItem: TIDECommandScope);
1137 begin
1138   NewItem.fName:=CreateUniqueName(NewItem.Name);
1139   FItems.Add(NewItem);
1140 end;
1141 
IndexOfnull1142 function TIDECommandScopes.IndexOf(AnItem: TIDECommandScope): Integer;
1143 begin
1144   Result:=FItems.IndexOf(AnItem);
1145 end;
1146 
IndexByNamenull1147 function TIDECommandScopes.IndexByName(const AName: string): Integer;
1148 begin
1149   Result:=Count-1;
1150   while (Result>=0) and (CompareText(AName,Items[Result].Name)<>0) do
1151     dec(Result);
1152 end;
1153 
TIDECommandScopes.FindByNamenull1154 function TIDECommandScopes.FindByName(const AName: string): TIDECommandScope;
1155 var
1156   i: LongInt;
1157 begin
1158   i:=IndexByName(AName);
1159   if i>=0 then
1160     Result:=Items[i]
1161   else
1162     Result:=nil;
1163 end;
1164 
TIDECommandScopes.CreateUniqueNamenull1165 function TIDECommandScopes.CreateUniqueName(const AName: string): string;
1166 begin
1167   Result:=AName;
1168   if IndexByName(Result)<0 then exit;
1169   Result:=CreateFirstIdentifier(Result);
1170   while IndexByName(Result)>=0 do
1171     Result:=CreateNextIdentifier(Result);
1172 end;
1173 
TIDECommandScopes.Countnull1174 function TIDECommandScopes.Count: integer;
1175 begin
1176   Result:=FItems.Count;
1177 end;
1178 
1179 { TIDECommandCategory }
1180 
1181 procedure TIDECommandCategory.SetDescription(const AValue: string);
1182 begin
1183   if FDescription=AValue then exit;
1184   FDescription:=AValue;
1185 end;
1186 
1187 procedure TIDECommandCategory.SetScope(const AValue: TIDECommandScope);
1188 begin
1189   if FScope=AValue then exit;
1190   if FScope<>nil then
1191     FScope.FCategories.Remove(Self);
1192   FScope:=AValue;
1193   if FScope<>nil then
1194     FScope.FCategories.Add(Self);
1195 end;
1196 
1197 destructor TIDECommandCategory.Destroy;
1198 begin
1199   Scope:=nil;
1200   inherited Destroy;
1201 end;
1202 
1203 procedure TIDECommandCategory.DoOnUpdate;
1204 var
1205   i: Integer;
1206 begin
1207   for i := 0 to Count-1 do
1208     TIDECommand(Items[i]).DoOnUpdate;
1209 end;
1210 
ScopeIntersectsnull1211 function TIDECommandCategory.ScopeIntersects(AScope: TIDECommandScope): boolean;
1212 begin
1213   if (Scope=nil) or (AScope=nil) then
1214     Result:=true
1215   else
1216     Result:=Scope.Intersects(AScope);
1217 end;
1218 
1219 procedure TIDECommandCategory.WriteScopeDebugReport;
1220 begin
1221   debugln('TIDECommandCategory.WriteScopeDebugReport ',Name,'=',Description);
1222   if Scope<>nil then
1223     Scope.WriteDebugReport
1224   else
1225     debugln('  Scope=nil');
1226 end;
1227 
1228 procedure TIDECommandCategory.Delete(Index: Integer);
1229 begin
1230   inherited Delete(Index);
1231 end;
1232 
1233 { TIDECommand }
1234 
1235 procedure TIDECommand.SetShortcutA(const AValue: TIDEShortCut);
1236 begin
1237   if CompareIDEShortCuts(@FShortcutA,@AValue)=0 then exit;
1238   FShortcutA:=AValue;
1239   //DebugLn('TIDECommand.SetShortcutA ',dbgs(Assigned(OnChange)),' ',Name);
1240   Change;
1241 end;
1242 
1243 procedure TIDECommand.SetShortcutB(const AValue: TIDEShortCut);
1244 begin
1245   if CompareIDEShortCuts(@FShortcutB,@AValue)=0 then exit;
1246   FShortcutB:=AValue;
1247   //DebugLn('TIDECommand.SetShortcutB ',dbgs(Assigned(OnChange)),' ',Name);
1248   Change;
1249 end;
1250 
1251 procedure TIDECommand.UserAdded(const aUser: TIDESpecialCommand);
1252 begin
1253   FUsers.Add(aUser);
1254 end;
1255 
1256 procedure TIDECommand.UserRemoved(const aUser: TIDESpecialCommand);
1257 begin
1258   FUsers.Remove(aUser);
1259 end;
1260 
1261 procedure TIDECommand.Change;
1262 var
1263   xUser: TIDESpecialCommand;
1264 begin
1265   for xUser in FUsers do
1266   begin
1267     xUser.ShortCutsUpdated(KeyToShortCut(ShortcutA.Key1,ShortcutA.Shift1),
1268                            KeyToShortCut(ShortcutA.Key2,ShortcutA.Shift2));
1269   end;
1270 end;
1271 
1272 procedure TIDECommand.Init;
1273 begin
1274   //
1275 end;
1276 
GetLocalizedNamenull1277 function TIDECommand.GetLocalizedName: string;
1278 begin
1279   if FLocalizedName<>'' then
1280     Result:=FLocalizedName
1281   else
1282     Result:=Name;
1283 end;
1284 
TIDECommand.GetUsernull1285 function TIDECommand.GetUser(Index: Integer): TIDESpecialCommand;
1286 begin
1287   Result := FUsers[Index];
1288 end;
1289 
TIDECommand.GetUserCountnull1290 function TIDECommand.GetUserCount: Integer;
1291 begin
1292   Result := FUsers.Count;
1293 end;
1294 
1295 procedure TIDECommand.SetLocalizedName(const AValue: string);
1296 begin
1297   if FLocalizedName=AValue then exit;
1298   FLocalizedName:=AValue;
1299   //DebugLn('TIDECommand.SetLocalizedName ',dbgs(Assigned(OnChange)),' ',Name);
1300   Change;
1301 end;
1302 
1303 procedure TIDECommand.SetOnExecute(const aOnExecute: TNotifyEvent);
1304 var
1305   xUser: TIDESpecialCommand;
1306 begin
1307   if CompareMethods(TMethod(FOnExecute), TMethod(aOnExecute)) then Exit;
1308   FOnExecute := aOnExecute;
1309   for xUser in FUsers do
1310     if xUser.SyncProperties then
1311     begin
1312       xUser.BlockSync;
1313       try
1314         xUser.OnClick := aOnExecute;
1315       finally
1316         xUser.UnblockSync;
1317       end;
1318     end;
1319 end;
1320 
1321 procedure TIDECommand.SetOnExecuteProc(const aOnExecuteProc: TNotifyProcedure);
1322 var
1323   xUser: TIDESpecialCommand;
1324 begin
1325   if FOnExecuteProc = aOnExecuteProc then Exit;
1326   FOnExecuteProc := aOnExecuteProc;
1327   for xUser in FUsers do
1328     if xUser.SyncProperties then
1329     begin
1330       xUser.BlockSync;
1331       try
1332         xUser.OnClickProc := aOnExecuteProc;
1333       finally
1334         xUser.UnblockSync;
1335       end;
1336     end;
1337 end;
1338 
1339 procedure TIDECommand.SetCategory(const AValue: TIDECommandCategory);
1340 begin
1341   if FCategory=AValue then exit;
1342   // unbind
1343   if Category<>nil then
1344     Category.Remove(Self);
1345   // bind
1346   fCategory:=AValue;
1347   if Category<>nil then
1348     Category.Add(Self);
1349   //DebugLn('TIDECommand.SetCategory ',dbgs(Assigned(OnChange)),' ',Name);
1350   Change;
1351 end;
1352 
1353 procedure TIDECommand.SetEnabled(const AEnabled: Boolean);
1354 var
1355   xUser: TIDESpecialCommand;
1356 begin
1357   for xUser in FUsers do
1358     if xUser.SyncProperties then
1359     begin
1360       xUser.BlockSync;
1361       try
1362         xUser.Enabled := AEnabled;
1363       finally
1364         xUser.UnblockSync;
1365       end;
1366     end;
1367 end;
1368 
1369 procedure TIDECommand.SetHint(const AHint: string);
1370 var
1371   xUser: TIDESpecialCommand;
1372 begin
1373   for xUser in FUsers do
1374     if xUser.SyncProperties then
1375     begin
1376       xUser.BlockSync;
1377       try
1378         xUser.Hint := AHint;
1379       finally
1380         xUser.UnblockSync;
1381       end;
1382     end;
1383 end;
1384 
TIDECommand.AsShortCutnull1385 function TIDECommand.AsShortCut: TShortCut;
1386 var
1387   CurKey: TIDEShortCut;
1388 begin
1389   if (ShortcutA.Key1<>VK_UNKNOWN) and (ShortcutA.Key2=VK_UNKNOWN) then
1390     CurKey:=ShortcutA
1391   else if (ShortcutB.Key1<>VK_UNKNOWN) and (ShortcutB.Key2=VK_UNKNOWN) then
1392     CurKey:=ShortcutB
1393   else
1394     CurKey:=CleanIDEShortCut;
1395   Result:=CurKey.Key1;
1396   if ssCtrl in CurKey.Shift1 then
1397     Result:=Result+scCtrl;
1398   if ssShift in CurKey.Shift1 then
1399     Result:=Result+scShift;
1400   if ssAlt in CurKey.Shift1 then
1401     Result:=Result+scAlt;
1402 end;
1403 
1404 constructor TIDECommand.Create(TheCategory: TIDECommandCategory;
1405   const TheName, TheLocalizedName: String; TheCommand: word;
1406   const TheShortcutA, TheShortcutB: TIDEShortCut;
1407   const ExecuteMethod: TNotifyEvent;
1408   const ExecuteProc: TNotifyProcedure);
1409 begin
1410   FUsers:=TIDESpecialCommands.Create;
1411   fCommand:=TheCommand;
1412   fName:=TheName;
1413   FLocalizedName:=TheLocalizedName;
1414   fShortcutA:=TheShortcutA;
1415   fShortcutB:=TheShortcutB;
1416   DefaultShortcutA:=ShortcutA;
1417   DefaultShortcutB:=ShortcutB;
1418   Category:=TheCategory;
1419   FOnExecute:=ExecuteMethod;
1420   FOnExecuteProc:=ExecuteProc;
1421   //DebugLn('TIDECommand.Create Name=',Name,' ',ShortCutToText(AsShortCut),' ',dbgs(Pointer(Self)));
1422   Init;
1423 end;
1424 
1425 constructor TIDECommand.Create(TheCategory: TIDECommandCategory;
1426   const TheName, TheLocalizedName: String; TheCommand: word);
1427 begin
1428   Create(TheCategory, TheName, TheLocalizedName, TheCommand,
1429          CleanIDEShortCut, CleanIDEShortCut, Nil, Nil);
1430 end;
1431 
1432 constructor TIDECommand.Create(ACommand: TIDECommand; ACategory: TIDECommandCategory);
1433 begin
1434   Create(ACategory, ACommand.Name, ACommand.LocalizedName, ACommand.Command,
1435     ACommand.ShortcutA, ACommand.ShortcutB, ACommand.OnExecute, ACommand.OnExecuteProc);
1436 end;
1437 
1438 destructor TIDECommand.Destroy;
1439 begin
1440   if Category <> nil then
1441     Category := nil;
1442   FUsers.Free;
1443   inherited Destroy;
1444 end;
1445 
1446 procedure TIDECommand.DoOnUpdate(Sender: TObject);
1447 begin
1448   if Assigned(FOnUpdateProc) then
1449     FOnUpdateProc(Sender);
1450   if Assigned(FOnUpdateMethod) then
1451     FOnUpdateMethod(Sender);
1452 end;
1453 
1454 procedure TIDECommand.DoOnUpdate;
1455 begin
1456   DoOnUpdate(Self);
1457 end;
1458 
1459 procedure TIDECommand.Assign(ACommand: TIDECommand);
1460 begin
1461   if IsEqual(ACommand) then exit;
1462   //DebugLn('TIDECommand.Assign ',dbgs(Assigned(OnChange)),' ',Name,' ');
1463   FShortcutA:=ACommand.FShortcutA;
1464   FShortcutB:=ACommand.FShortcutB;
1465   Change;
1466 end;
1467 
TIDECommand.IsEqualnull1468 function TIDECommand.IsEqual(ACommand: TIDECommand): boolean;
1469 begin
1470   Result:=(CompareIDEShortCuts(@FShortcutA,@ACommand.FShortcutA)=0)
1471           and (CompareIDEShortCuts(@FShortcutB,@ACommand.FShortcutB)=0);
1472 end;
1473 
1474 procedure TIDECommand.SetCaption(const ACaption: string);
1475 var
1476   xUser: TIDESpecialCommand;
1477 begin
1478   for xUser in FUsers do
1479     if xUser.SyncProperties then
1480     begin
1481       xUser.BlockSync;
1482       try
1483         xUser.Caption := ACaption;
1484       finally
1485         xUser.UnblockSync;
1486       end;
1487     end;
1488 end;
1489 
1490 procedure TIDECommand.ClearShortcutA;
1491 begin
1492   ShortcutA:=CleanIDEShortCut;
1493 end;
1494 
1495 procedure TIDECommand.ClearShortcutB;
1496 begin
1497   ShortcutB:=CleanIDEShortCut;
1498 end;
1499 
TIDECommand.GetCategoryAndNamenull1500 function TIDECommand.GetCategoryAndName: string;
1501 begin
1502   Result:='"'+GetLocalizedName+'"';
1503   if Category<>nil then
1504     Result:='"'+Category.Description+'" -> '+Result;
1505 end;
1506 
TIDECommand.Executenull1507 function TIDECommand.Execute(Sender: TObject): boolean;
1508 begin
1509   Result:=false;
1510   if Assigned(OnExecute) then begin
1511     Result:=true;
1512     OnExecute(Sender);
1513   end else
1514   if Assigned(OnExecuteProc) then begin
1515     Result:=true;
1516     OnExecuteProc(Sender);
1517   end;
1518 end;
1519 
1520 { TIDECommands }
1521 
1522 procedure TIDECommands.AddCustomUpdateEvent(const aEvent: TNotifyEvent);
1523 begin
1524   FCustomUpdateEvents.Add(TMethod(aEvent));
1525 end;
1526 
1527 procedure TIDECommands.ApplicationOnIdle(Sender: TObject; var Done: Boolean);
1528 begin
1529   if (FDontExecuteUpdateEventsUntil > 0) and (GetTickCount64 < FDontExecuteUpdateEventsUntil) then
1530     Exit;
1531 
1532   ExecuteUpdateEvents;
1533   FDontExecuteUpdateEventsUntil := 0;
1534 end;
1535 
1536 constructor TIDECommands.Create;
1537 begin
1538   inherited Create;
1539 
1540   FCustomUpdateEvents := TMethodList.Create;
1541 end;
1542 
1543 destructor TIDECommands.Destroy;
1544 begin
1545   FCustomUpdateEvents.Free;
1546   inherited Destroy;
1547 end;
1548 
1549 procedure TIDECommands.ExecuteUpdateEvents;
1550 var
1551   i: Integer;
1552 begin
1553   if not Application.Active or
1554      (ActivePopupMenu <> nil) or//no popup menus
1555      (Application.ModalLevel > 0) or//no modal windows
1556      not IsWindowEnabled(Application.MainForm.Handle)//main IDE must be enabled
1557   then
1558     Exit;
1559 
1560   FCustomUpdateEvents.CallNotifyEvents(Self);
1561   for i := 0 to CategoryCount-1 do
1562     Categories[i].DoOnUpdate;
1563 end;
1564 
1565 procedure TIDECommands.CancelPostponeUpdateEvents;
1566 begin
1567   FDontExecuteUpdateEventsUntil := 0;
1568 end;
1569 
1570 procedure TIDECommands.PostponeUpdateEvents;
1571 begin
1572   FDontExecuteUpdateEventsUntil := GetTickCount64 + 500;
1573 end;
1574 
1575 procedure TIDECommands.RemoveCustomUpdateEvent(const aEvent: TNotifyEvent);
1576 begin
1577   FCustomUpdateEvents.Remove(TMethod(aEvent));
1578 end;
1579 
1580 procedure TIDECommands.StartUpdateEvents;
1581 begin
1582   Application.AddOnIdleHandler(@ApplicationOnIdle, False);
1583 end;
1584 
1585 procedure TIDECommands.StopUpdateEvents;
1586 begin
1587   Application.RemoveOnIdleHandler(@ApplicationOnIdle);
1588 end;
1589 
1590 { TIDESpecialCommand }
1591 
1592 constructor TIDESpecialCommand.Create(const aName: string);
1593 begin
1594   inherited Create;
1595 
1596   FSyncProperties:=true;
1597   FName := aName;
1598   FEnabled:=true;
1599   FImageIndex:=-1;
1600 end;
1601 
1602 procedure TIDESpecialCommand.BlockSync;
1603 begin
1604   Inc(FBlockSync);
1605 end;
1606 
1607 destructor TIDESpecialCommand.Destroy;
1608 begin
1609   if Assigned(FCommand) then
1610     FCommand.UserRemoved(Self);
1611   inherited Destroy;
1612 end;
1613 
1614 procedure TIDESpecialCommand.DoOnClick(Sender: TObject);
1615 begin
1616   if Assigned(FOnClickProc) then
1617     FOnClickProc(Sender)
1618   else
1619   if Assigned(FOnClickMethod) then
1620     FOnClickMethod(Sender);
1621 end;
1622 
1623 procedure TIDESpecialCommand.DoOnClick;
1624 begin
1625   DoOnClick(Self);
1626 end;
1627 
DoOnRequestCaptionnull1628 function TIDESpecialCommand.DoOnRequestCaption(Sender: TObject): Boolean;
1629 var
1630   xCaption, xHint: string;
1631 begin
1632   Result := Assigned(FOnRequestCaption);
1633   if Result then
1634   begin
1635     xCaption := Caption;
1636     xHint := Hint;
1637     FOnRequestCaption(Sender, xCaption, xHint);
1638     Caption := xCaption;
1639     Hint := xHint;
1640   end;
1641 end;
1642 
TIDESpecialCommand.GetCaptionnull1643 function TIDESpecialCommand.GetCaption: string;
1644 begin
1645   if FCaption<>'' then
1646     Result:=FCaption
1647   else if (FCommand<>nil) and (FCommand.LocalizedName<>'') then
1648     Result:=FCommand.LocalizedName
1649   else
1650     Result:=FName;
1651 end;
1652 
TIDESpecialCommand.GetCaptionWithShortCutnull1653 function TIDESpecialCommand.GetCaptionWithShortCut: String;
1654 begin
1655   Result := Caption;
1656   DeleteAmpersands(Result);
1657   Result := Result + GetShortcut;
1658 end;
1659 
GetHintOrCaptionWithShortCutnull1660 function TIDESpecialCommand.GetHintOrCaptionWithShortCut: String;
1661 begin
1662   if Hint <> '' then
1663     Result := Hint
1664   else
1665     Result := Caption;
1666   DeleteAmpersands(Result);
1667   Result := Result + GetShortcut;
1668 end;
1669 
GetShortcutnull1670 function TIDESpecialCommand.GetShortcut: String;
1671 begin
1672   Result := '';
1673   if Assigned(FCommand) then
1674     Result := ShortCutToText(FCommand.AsShortCut);
1675   if Result <> '' then
1676     Result := ' (' + Result + ')';
1677 end;
1678 
1679 procedure TIDESpecialCommand.SetCaption(aCaption: string);
1680 var
1681   xUser: TIDESpecialCommand;
1682 begin
1683   if FCaption=aCaption then Exit;
1684   FCaption := aCaption;
1685   if (FCommand<> nil) and SyncAvailable then
1686     for xUser in FCommand.FUsers do
1687       if (xUser <> Self) and xUser.SyncProperties then
1688       begin
1689         xUser.BlockSync;
1690         try
1691           xUser.Caption:=aCaption;
1692         finally
1693           xUser.UnblockSync;
1694         end;
1695       end;
1696 end;
1697 
1698 procedure TIDESpecialCommand.SetChecked(const aChecked: Boolean);
1699 var
1700   xUser: TIDESpecialCommand;
1701 begin
1702   if FChecked=aChecked then Exit;
1703   FChecked := aChecked;
1704   if (FCommand<> nil) and SyncAvailable then
1705     for xUser in FCommand.FUsers do
1706       if (xUser <> Self) and xUser.SyncProperties then
1707       begin
1708         xUser.BlockSync;
1709         try
1710           xUser.Checked:=aChecked;
1711         finally
1712           xUser.UnblockSync;
1713         end;
1714       end;
1715 end;
1716 
1717 procedure TIDESpecialCommand.SetCommand(const AValue: TIDECommand);
1718 begin
1719   if FCommand = AValue then
1720     Exit;
1721   FCommand := AValue;
1722   if FCommand <> nil then
1723   begin
1724     if (FCommand.OnExecute=nil) and (OnClick<>nil) then
1725       FCommand.OnExecute := OnClick
1726     else
1727     if (OnClick=nil) and (FCommand.OnExecute<>nil) then
1728       OnClick := FCommand.OnExecute;
1729 
1730     if (FCommand.OnExecuteProc=nil) and (OnClickProc<>nil) then
1731       FCommand.OnExecuteProc := OnClickProc
1732     else
1733     if (OnClickProc=nil) and (FCommand.OnExecuteProc<>nil) then
1734       OnClickProc := FCommand.OnExecuteProc;
1735 
1736     FCommand.UserAdded(Self);
1737     FCommand.Change;
1738   end;
1739 end;
1740 
1741 procedure TIDESpecialCommand.SetEnabled(const aEnabled: Boolean);
1742 var
1743   xUser: TIDESpecialCommand;
1744 begin
1745   if FEnabled=aEnabled then Exit;
1746   FEnabled := aEnabled;
1747   if (FCommand<> nil) and SyncAvailable then
1748     for xUser in FCommand.FUsers do
1749       if (xUser <> Self) and xUser.SyncProperties then
1750       begin
1751         xUser.BlockSync;
1752         try
1753           xUser.Enabled:=aEnabled;
1754         finally
1755           xUser.UnblockSync;
1756         end;
1757       end;
1758 end;
1759 
1760 procedure TIDESpecialCommand.SetHint(const aHint: string);
1761 var
1762   xUser: TIDESpecialCommand;
1763 begin
1764   if FHint=aHint then Exit;
1765   FHint := aHint;
1766   if (FCommand<> nil) and SyncAvailable then
1767     for xUser in FCommand.FUsers do
1768       if (xUser <> Self) and xUser.SyncProperties then
1769       begin
1770         xUser.BlockSync;
1771         try
1772           xUser.Hint:=aHint;
1773         finally
1774           xUser.UnblockSync;
1775         end;
1776       end;
1777 end;
1778 
1779 procedure TIDESpecialCommand.SetImageIndex(const aImageIndex: Integer);
1780 var
1781   xUser: TIDESpecialCommand;
1782 begin
1783   if FImageIndex=aImageIndex then Exit;
1784   FImageIndex := aImageIndex;
1785   if (FCommand<> nil) and SyncAvailable then
1786     for xUser in FCommand.FUsers do
1787       if (xUser <> Self) and xUser.SyncProperties then
1788       begin
1789         xUser.BlockSync;
1790         try
1791           xUser.ImageIndex:=aImageIndex;
1792         finally
1793           xUser.UnblockSync;
1794         end;
1795       end;
1796 end;
1797 
1798 procedure TIDESpecialCommand.SetName(const aName: string);
1799 begin
1800   FName := aName;
1801 end;
1802 
1803 procedure TIDESpecialCommand.SetOnClickMethod(const aOnClick: TNotifyEvent);
1804 begin
1805   if CompareMethods(TMethod(FOnClickMethod), TMethod(aOnClick)) then Exit;
1806   FOnClickMethod := aOnClick;
1807   if (FCommand<> nil) and SyncAvailable then
1808     FCommand.OnExecute:=aOnClick;
1809 end;
1810 
1811 procedure TIDESpecialCommand.SetOnClickProc(const aOnClickProc: TNotifyProcedure);
1812 begin
1813   if FOnClickProc = aOnClickProc then Exit;
1814   FOnClickProc := aOnClickProc;
1815   if (FCommand<> nil) and SyncAvailable then
1816     FCommand.OnExecuteProc:=aOnClickProc;
1817 end;
1818 
1819 procedure TIDESpecialCommand.SetOnRequestCaption(
1820   const aOnRequestCaptionHint: TGetHintCaptionEvent);
1821 var
1822   xUser: TIDESpecialCommand;
1823 begin
1824   if FOnRequestCaption = aOnRequestCaptionHint then Exit;
1825   FOnRequestCaption := aOnRequestCaptionHint;
1826   if (FCommand<> nil) and SyncAvailable then
1827     for xUser in FCommand.FUsers do
1828       if (xUser <> Self) and xUser.SyncProperties then
1829       begin
1830         xUser.BlockSync;
1831         try
1832           xUser.OnRequestCaptionHint:=aOnRequestCaptionHint;
1833         finally
1834           xUser.UnblockSync;
1835         end;
1836       end;
1837 end;
1838 
1839 procedure TIDESpecialCommand.SetResourceName(const aResourceName: string);
1840 begin
1841   if aResourceName <> '' then
1842     ImageIndex := IDEImages.LoadImage(aResourceName)
1843   else
1844     ImageIndex := -1;
1845 end;
1846 
1847 procedure TIDESpecialCommand.ShortCutsUpdated(const aShortCut,
1848   aShortCutKey2: TShortCut);
1849 begin
1850   //nothing here, override in descendants
1851 end;
1852 
TIDESpecialCommand.SyncAvailablenull1853 function TIDESpecialCommand.SyncAvailable: Boolean;
1854 begin
1855   Result := FSyncProperties and (FBlockSync=0);
1856 end;
1857 
1858 procedure TIDESpecialCommand.UnblockSync;
1859 begin
1860   Dec(FBlockSync);
1861 end;
1862 
1863 { TIDESpecialCommandEnumerator }
1864 
1865 constructor TIDESpecialCommandEnumerator.Create(AButtons: TIDESpecialCommands);
1866 begin
1867   inherited Create;
1868   FList := AButtons;
1869   FPosition := -1;
1870 end;
1871 
GetCurrentnull1872 function TIDESpecialCommandEnumerator.GetCurrent: TIDESpecialCommand;
1873 begin
1874   Result := TIDESpecialCommand(FList[FPosition]);
1875 end;
1876 
TIDESpecialCommandEnumerator.MoveNextnull1877 function TIDESpecialCommandEnumerator.MoveNext: Boolean;
1878 begin
1879   Inc(FPosition);
1880   Result := FPosition < FList.Count;
1881 end;
1882 
1883 { TIDESpecialCommands }
1884 
1885 procedure TIDESpecialCommands.Add(const aUser: TIDESpecialCommand);
1886 begin
1887   FList.Add(aUser);
1888 end;
1889 
1890 constructor TIDESpecialCommands.Create;
1891 begin
1892   inherited Create;
1893   FList := TFPList.Create;
1894 end;
1895 
1896 destructor TIDESpecialCommands.Destroy;
1897 var
1898   I: Integer;
1899 begin
1900   for I := 0 to Count-1 do
1901     Items[I].FCommand := nil;
1902   FList.Free;
1903   inherited Destroy;
1904 end;
1905 
GetCountnull1906 function TIDESpecialCommands.GetCount: Integer;
1907 begin
1908   Result := FList.Count;
1909 end;
1910 
GetEnumeratornull1911 function TIDESpecialCommands.GetEnumerator: TIDESpecialCommandEnumerator;
1912 begin
1913   Result := TIDESpecialCommandEnumerator.Create(Self);
1914 end;
1915 
TIDESpecialCommands.GetItemsnull1916 function TIDESpecialCommands.GetItems(Index: Integer): TIDESpecialCommand;
1917 begin
1918   Result := TIDESpecialCommand(FList[Index]);
1919 end;
1920 
1921 procedure TIDESpecialCommands.Remove(const aUser: TIDESpecialCommand);
1922 begin
1923   FList.Remove(aUser);
1924 end;
1925 
1926 const
1927   IDEEditorCommandStrs: array[0..319] of TIdentMapEntry = (
1928   // search
1929     (Value: ecFind;                                   Name: 'ecFind'),
1930     (Value: ecFindAgain;                              Name: 'ecFindAgain'),
1931     (Value: ecFindNext;                               Name: 'ecFindNext'),
1932     (Value: ecFindPrevious;                           Name: 'ecFindPrevious'),
1933     (Value: ecReplace;                                Name: 'ecReplace'),
1934     (Value: ecIncrementalFind;                        Name: 'ecIncrementalFind'),
1935     (Value: ecFindProcedureDefinition;                Name: 'ecFindProcedureDefinition'),
1936     (Value: ecFindProcedureMethod;                    Name: 'ecFindProcedureMethod'),
1937     (Value: ecGotoLineNumber;                         Name: 'ecGotoLineNumber'),
1938     (Value: ecFindNextWordOccurrence;                 Name: 'ecFindNextWordOccurrence'),
1939     (Value: ecFindPrevWordOccurrence;                 Name: 'ecFindPrevWordOccurrence'),
1940     (Value: ecFindInFiles;                            Name: 'ecFindInFiles'),
1941     (Value: ecJumpBack;                               Name: 'ecJumpBack'),
1942     (Value: ecJumpForward;                            Name: 'ecJumpForward'),
1943     (Value: ecAddJumpPoint;                           Name: 'ecAddJumpPoint'),
1944     (Value: ecViewJumpHistory;                        Name: 'ecViewJumpHistory'),
1945     (Value: ecJumpToNextError;                        Name: 'ecJumpToNextError'),
1946     (Value: ecJumpToPrevError;                        Name: 'ecJumpToPrevError'),
1947     (Value: ecProcedureList;                          Name: 'ecProcedureList'),
1948 
1949   // search code
1950     (Value: ecFindDeclaration;                        Name: 'ecFindDeclaration'),
1951     (Value: ecFindBlockOtherEnd;                      Name: 'ecFindBlockOtherEnd'),
1952     (Value: ecFindBlockStart;                         Name: 'ecFindBlockStart'),
1953     (Value: ecOpenFileAtCursor;                       Name: 'ecOpenFileAtCursor'),
1954     (Value: ecGotoIncludeDirective;                   Name: 'ecGotoIncludeDirective'),
1955     (Value: ecJumpToInterface;                        Name: 'ecJumpToInterface'),
1956     (Value: ecJumpToInterfaceUses;                    Name: 'ecJumpToInterfaceUses'),
1957     (Value: ecJumpToImplementation;                   Name: 'ecJumpToImplementation'),
1958     (Value: ecJumpToImplementationUses;               Name: 'ecJumpToImplementationUses'),
1959     (Value: ecJumpToInitialization;                   Name: 'ecJumpToInitialization'),
1960 
1961   // edit selection
1962     (Value: ecSelectionUpperCase;                     Name: 'ecSelectionUpperCase'),
1963     (Value: ecSelectionLowerCase;                     Name: 'ecSelectionLowerCase'),
1964     (Value: ecSelectionSwapCase;                      Name: 'ecSelectionSwapCase'),
1965     (Value: ecSelectionTabs2Spaces;                   Name: 'ecSelectionTabs2Spaces'),
1966     (Value: ecSelectionEnclose;                       Name: 'ecSelectionEnclose'),
1967     (Value: ecSelectionComment;                       Name: 'ecSelectionComment'),
1968     (Value: ecSelectionUncomment;                     Name: 'ecSelectionUncomment'),
1969     (Value: ecSelectionSort;                          Name: 'ecSelectionSort'),
1970     (Value: ecSelectionBreakLines;                    Name: 'ecSelectionBreakLines'),
1971     (Value: ecSelectToBrace;                          Name: 'ecSelectToBrace'),
1972     (Value: ecSelectCodeBlock;                        Name: 'ecSelectCodeBlock'),
1973     (Value: ecSelectWord;                             Name: 'ecSelectWord'),
1974     (Value: ecSelectLine;                             Name: 'ecSelectLine'),
1975     (Value: ecSelectParagraph;                        Name: 'ecSelectParagraph'),
1976     (Value: ecSelectionEncloseIFDEF;                  Name: 'ecSelectionEncloseIFDEF'),
1977     (Value: ecToggleComment;                          Name: 'ecToggleComment'),
1978 
1979   // insert text
1980     (Value: ecInsertCharacter;                        Name: 'ecInsertCharacter'),
1981     (Value: ecInsertGUID;                             Name: 'ecInsertGUID'),
1982     (Value: ecInsertFilename;                         Name: 'ecInsertFilename'),
1983     (Value: ecInsertUserName;                         Name: 'ecInsertUserName'),
1984     (Value: ecInsertDateTime;                         Name: 'ecInsertDateTime'),
1985     (Value: ecInsertChangeLogEntry;                   Name: 'ecInsertChangeLogEntry'),
1986     (Value: ecInsertCVSAuthor;                        Name: 'ecInsertCVSAuthor'),
1987     (Value: ecInsertCVSDate;                          Name: 'ecInsertCVSDate'),
1988     (Value: ecInsertCVSHeader;                        Name: 'ecInsertCVSHeader'),
1989     (Value: ecInsertCVSID;                            Name: 'ecInsertCVSID'),
1990     (Value: ecInsertCVSLog;                           Name: 'ecInsertCVSLog'),
1991     (Value: ecInsertCVSName;                          Name: 'ecInsertCVSName'),
1992     (Value: ecInsertCVSRevision;                      Name: 'ecInsertCVSRevision'),
1993     (Value: ecInsertCVSSource;                        Name: 'ecInsertCVSSource'),
1994     (Value: ecInsertGPLNotice;                        Name: 'ecInsertGPLNotice'),
1995     (Value: ecInsertGPLNoticeTranslated;              Name: 'ecInsertGPLNoticeTranslated'),
1996     (Value: ecInsertLGPLNotice;                       Name: 'ecInsertLGPLNotice'),
1997     (Value: ecInsertLGPLNoticeTranslated;             Name: 'ecInsertLGPLNoticeTranslated'),
1998     (Value: ecInsertModifiedLGPLNotice;               Name: 'ecInsertModifiedLGPLNotice'),
1999     (Value: ecInsertModifiedLGPLNoticeTranslated;     Name: 'ecInsertModifiedLGPLNoticeTranslated'),
2000     (Value: ecInsertMITNotice;                        Name: 'ecInsertMITNotice'),
2001     (Value: ecInsertMITNoticeTranslated;              Name: 'ecInsertMITNoticeTranslated'),
2002 
2003   // source tools
2004     (Value: ecWordCompletion;                         Name: 'ecWordCompletion'),
2005     (Value: ecCompleteCode;                           Name: 'ecCompleteCode'),
2006     (Value: ecIdentCompletion;                        Name: 'ecIdentCompletion'),
2007     (Value: ecSyntaxCheck;                            Name: 'ecSyntaxCheck'),
2008     (Value: ecGuessUnclosedBlock;                     Name: 'ecGuessUnclosedBlock'),
2009     (Value: ecGuessMisplacedIFDEF;                    Name: 'ecGuessMisplacedIFDEF'),
2010     (Value: ecConvertDFM2LFM;                         Name: 'ecConvertDFM2LFM'),
2011     (Value: ecCheckLFM;                               Name: 'ecCheckLFM'),
2012     (Value: ecConvertDelphiUnit;                      Name: 'ecConvertDelphiUnit'),
2013     (Value: ecConvertDelphiProject;                   Name: 'ecConvertDelphiProject'),
2014     (Value: ecConvertDelphiPackage;                   Name: 'ecConvertDelphiPackage'),
2015     (Value: ecConvertEncoding;                        Name: 'ecConvertEncoding'),
2016     (Value: ecMakeResourceString;                     Name: 'ecMakeResourceString'),
2017     (Value: ecDiff;                                   Name: 'ecDiff'),
2018     (Value: ecExtractProc;                            Name: 'ecExtractProc'),
2019     (Value: ecFindIdentifierRefs;                     Name: 'ecFindIdentifierRefs'),
2020     (Value: ecRenameIdentifier;                       Name: 'ecRenameIdentifier'),
2021     (Value: ecInvertAssignment;                       Name: 'ecInvertAssignment'),
2022     (Value: ecShowCodeContext;                        Name: 'ecShowCodeContext'),
2023     (Value: ecShowAbstractMethods;                    Name: 'ecShowAbstractMethods'),
2024     (Value: ecRemoveEmptyMethods;                     Name: 'ecRemoveEmptyMethods'),
2025     (Value: ecRemoveUnusedUnits;                      Name: 'ecRemoveUnusedUnits'),
2026     (Value: ecUseUnit;                                Name: 'ecUseUnit'),
2027     (Value: ecFindOverloads;                          Name: 'ecFindOverloads'),
2028     (Value: ecFindUsedUnitRefs;                       Name: 'ecFindUsedUnitRefs'),
2029     (Value: ecCompleteCodeInteractive;                Name: 'ecCompleteCodeInteractive'),
2030 
2031   // file menu
2032     (Value: ecNew;                                    Name: 'ecNew'),
2033     (Value: ecNewUnit;                                Name: 'ecNewUnit'),
2034     (Value: ecNewForm;                                Name: 'ecNewForm'),
2035     (Value: ecOpen;                                   Name: 'ecOpen'),
2036     (Value: ecRevert;                                 Name: 'ecRevert'),
2037     (Value: ecSave;                                   Name: 'ecSave'),
2038     (Value: ecSaveAs;                                 Name: 'ecSaveAs'),
2039     (Value: ecSaveAll;                                Name: 'ecSaveAll'),
2040     (Value: ecClose;                                  Name: 'ecClose'),
2041     (Value: ecCloseAll;                               Name: 'ecCloseAll'),
2042     (Value: ecCleanDirectory;                         Name: 'ecCleanDirectory'),
2043     (Value: ecRestart;                                Name: 'ecRestart'),
2044     (Value: ecQuit;                                   Name: 'ecQuit'),
2045 
2046   // edit menu
2047     (Value: ecMultiPaste;                             Name: 'ecMultiPaste'),
2048 
2049   // IDE navigation
2050     (Value: ecToggleFormUnit;                         Name: 'ecToggleFormUnit'),
2051     (Value: ecToggleObjectInsp;                       Name: 'ecToggleObjectInsp'),
2052     (Value: ecToggleSourceEditor;                     Name: 'ecToggleSourceEditor'),
2053     (Value: ecToggleCodeExpl;                         Name: 'ecToggleCodeExpl'),
2054     (Value: ecToggleFPDocEditor;                      Name: 'ecToggleFPDocEditor'),
2055     (Value: ecToggleMessages;                         Name: 'ecToggleMessages'),
2056     (Value: ecToggleWatches;                          Name: 'ecToggleWatches'),
2057     (Value: ecToggleBreakPoints;                      Name: 'ecToggleBreakPoints'),
2058     (Value: ecToggleDebuggerOut;                      Name: 'ecToggleDebuggerOut'),
2059     (Value: ecViewUnitDependencies;                   Name: 'ecViewUnitDependencies'),
2060     (Value: ecViewUnitInfo;                           Name: 'ecViewUnitInfo'),
2061     (Value: ecToggleLocals;                           Name: 'ecToggleLocals'),
2062     (Value: ecToggleCallStack;                        Name: 'ecToggleCallStack'),
2063     (Value: ecToggleSearchResults;                    Name: 'ecToggleSearchResults'),
2064     (Value: ecViewAnchorEditor;                       Name: 'ecViewAnchorEditor'),
2065     (Value: ecViewTabOrder;                           Name: 'ecViewTabOrder'),
2066     (Value: ecToggleCodeBrowser;                      Name: 'ecToggleCodeBrowser'),
2067     (Value: ecToggleCompPalette;                      Name: 'ecToggleCompPalette'),
2068     (Value: ecToggleIDESpeedBtns;                     Name: 'ecToggleIDESpeedBtns'),
2069     (Value: ecViewComponents;                         Name: 'ecViewComponents'),
2070     (Value: ecToggleRestrictionBrowser;               Name: 'ecToggleRestrictionBrowser'),
2071     (Value: ecViewTodoList;                           Name: 'ecViewTodoList'),
2072     (Value: ecToggleRegisters;                        Name: 'ecToggleRegisters'),
2073     (Value: ecToggleAssembler;                        Name: 'ecToggleAssembler'),
2074     (Value: ecToggleDebugEvents;                      Name: 'ecToggleDebugEvents'),
2075     (Value: ecViewPseudoTerminal;                     Name: 'ecViewPseudoTerminal'),
2076     (Value: ecViewThreads;                            Name: 'ecViewThreads'),
2077     (Value: ecViewHistory;                            Name: 'ecViewHistory'),
2078     (Value: ecViewMacroList;                          Name: 'ecViewMacroList'),
2079 
2080   // sourcenotebook commands
2081     (Value: ecNextEditor;                             Name: 'ecNextEditor'),
2082     (Value: ecPrevEditor;                             Name: 'ecPrevEditor'),
2083     (Value: ecMoveEditorLeft;                         Name: 'ecMoveEditorLeft'),
2084     (Value: ecMoveEditorRight;                        Name: 'ecMoveEditorRight'),
2085     (Value: ecToggleBreakPoint;                       Name: 'ecToggleBreakPoint'),
2086     (Value: ecRemoveBreakPoint;                       Name: 'ecRemoveBreakPoint'),
2087     (Value: ecMoveEditorLeftmost;                     Name: 'ecMoveEditorLeftmost'),
2088     (Value: ecMoveEditorRightmost;                    Name: 'ecMoveEditorRightmost'),
2089 
2090     (Value: ecNextSharedEditor;                       Name: 'ecNextSharedEditor'),
2091     (Value: ecPrevSharedEditor;                       Name: 'ecPrevSharedEditor'),
2092 
2093     (Value: ecNextWindow;                             Name: 'ecNextWindow'),
2094     (Value: ecPrevWindow;                             Name: 'ecPrevWindow'),
2095     (Value: ecMoveEditorNextWindow;                   Name: 'ecMoveEditorNextWindow'),
2096     (Value: ecMoveEditorPrevWindow;                   Name: 'ecMoveEditorPrevWindow'),
2097     (Value: ecMoveEditorNewWindow;                    Name: 'ecMoveEditorNewWindow'),
2098     (Value: ecCopyEditorNextWindow;                   Name: 'ecCopyEditorNextWindow'),
2099     (Value: ecCopyEditorPrevWindow;                   Name: 'ecCopyEditorPrevWindow'),
2100     (Value: ecCopyEditorNewWindow;                    Name: 'ecCopyEditorNewWindow'),
2101     (Value: ecPrevEditorInHistory;                    Name: 'ecPrevEditorInHistory'),
2102     (Value: ecNextEditorInHistory;                    Name: 'ecNextEditorInHistory'),
2103 
2104     (Value: ecGotoEditor1;                            Name: 'ecGotoEditor1'),
2105     (Value: ecGotoEditor2;                            Name: 'ecGotoEditor2'),
2106     (Value: ecGotoEditor3;                            Name: 'ecGotoEditor3'),
2107     (Value: ecGotoEditor4;                            Name: 'ecGotoEditor4'),
2108     (Value: ecGotoEditor5;                            Name: 'ecGotoEditor5'),
2109     (Value: ecGotoEditor6;                            Name: 'ecGotoEditor6'),
2110     (Value: ecGotoEditor7;                            Name: 'ecGotoEditor7'),
2111     (Value: ecGotoEditor8;                            Name: 'ecGotoEditor8'),
2112     (Value: ecGotoEditor9;                            Name: 'ecGotoEditor9'),
2113     (Value: ecGotoEditor0;                            Name: 'ecGotoEditor0'),
2114 
2115     (Value: ecLockEditor;                             Name: 'ecLockEditor'),
2116 
2117   // marker
2118     (Value: ecSetFreeBookmark;                        Name: 'ecSetFreeBookmark'),
2119     (Value: ecPrevBookmark;                           Name: 'ecPrevBookmark'),
2120     (Value: ecNextBookmark;                           Name: 'ecNextBookmark'),
2121     (Value: ecClearBookmarkForFile;                   Name: 'ecClearBookmarkForFile'),
2122     (Value: ecClearAllBookmark;                       Name: 'ecClearAllBookmark'),
2123     (Value: ecGotoBookmarks;                          Name: 'ecGotoBookmarks'),
2124     (Value: ecToggleBookmarks;                        Name: 'ecToggleBookmarks'),
2125 
2126   // Macro
2127     (Value: ecSynMacroRecord;                         Name: 'ecSynMacroRecord'),
2128     (Value: ecSynMacroPlay;                           Name: 'ecSynMacroPlay'),
2129 
2130   // run menu
2131     (Value: ecCompile;                                Name: 'ecCompile'),
2132     (Value: ecBuild;                                  Name: 'ecBuild'),
2133     (Value: ecQuickCompile;                           Name: 'ecQuickCompile'),
2134     (Value: ecCleanUpAndBuild;                        Name: 'ecCleanUpAndBuild'),
2135     (Value: ecAbortBuild;                             Name: 'ecAbortBuild'),
2136     (Value: ecRunWithoutDebugging;                    Name: 'ecRunWithoutDebugging'),
2137     (Value: ecRun;                                    Name: 'ecRun'),
2138     (Value: ecPause;                                  Name: 'ecPause'),
2139     (Value: ecStepInto;                               Name: 'ecStepInto'),
2140     (Value: ecStepOver;                               Name: 'ecStepOver'),
2141     (Value: ecRunToCursor;                            Name: 'ecRunToCursor'),
2142     (Value: ecStopProgram;                            Name: 'ecStopProgram'),
2143     (Value: ecResetDebugger;                          Name: 'ecResetDebugger'),
2144     (Value: ecRunParameters;                          Name: 'ecRunParameters'),
2145     (Value: ecBuildFile;                              Name: 'ecBuildFile'),
2146     (Value: ecRunFile;                                Name: 'ecRunFile'),
2147     (Value: ecConfigBuildFile;                        Name: 'ecConfigBuildFile'),
2148     (Value: ecInspect;                                Name: 'ecInspect'),
2149     (Value: ecEvaluate;                               Name: 'ecEvaluate'),
2150     (Value: ecAddWatch;                               Name: 'ecAddWatch'),
2151     (Value: ecShowExecutionPoint;                     Name: 'ecShowExecutionPoint'),
2152     (Value: ecStepOut;                                Name: 'ecStepOut'),
2153     (Value: ecStepIntoInstr;                          Name: 'ecStepIntoInstr'),
2154     (Value: ecStepOverInstr;                          Name: 'ecStepOverInstr'),
2155     (Value: ecStepIntoContext;                        Name: 'ecStepIntoContext'),
2156     (Value: ecStepOverContext;                        Name: 'ecStepOverContext'),
2157     (Value: ecAddBpSource;                            Name: 'ecAddBpSource'),
2158     (Value: ecAddBpAddress;                           Name: 'ecAddBpAddress'),
2159     (Value: ecAddBpDataWatch;                         Name: 'ecAddBpDataWatch'),
2160     (Value: ecAttach;                                 Name: 'ecAttach'),
2161     (Value: ecDetach;                                 Name: 'ecDetach'),
2162 
2163   // 460++ : used for ecViewHistory (debugger) / ecViewMacroList
2164 
2165   // project menu
2166     (Value: ecNewProject;                             Name: 'ecNewProject'),
2167     (Value: ecNewProjectFromFile;                     Name: 'ecNewProjectFromFile'),
2168     (Value: ecOpenProject;                            Name: 'ecOpenProject'),
2169     (Value: ecCloseProject;                           Name: 'ecCloseProject'),
2170     (Value: ecSaveProject;                            Name: 'ecSaveProject'),
2171     (Value: ecSaveProjectAs;                          Name: 'ecSaveProjectAs'),
2172     (Value: ecPublishProject;                         Name: 'ecPublishProject'),
2173     (Value: ecProjectInspector;                       Name: 'ecProjectInspector'),
2174     (Value: ecAddCurUnitToProj;                       Name: 'ecAddCurUnitToProj'),
2175     (Value: ecRemoveFromProj;                         Name: 'ecRemoveFromProj'),
2176     (Value: ecViewProjectUnits;                       Name: 'ecViewProjectUnits'),
2177     (Value: ecViewProjectForms;                       Name: 'ecViewProjectForms'),
2178     (Value: ecViewProjectSource;                      Name: 'ecViewProjectSource'),
2179     (Value: ecProjectOptions;                         Name: 'ecProjectOptions'),
2180     (Value: ecProjectChangeBuildMode;                 Name: 'ecProjectChangeBuildMode'),
2181     (Value: ecProjectResaveFormsWithI18n;             Name: 'ecProjectResaveFormsWithI18n'),
2182 
2183   // package menu
2184     (Value: ecOpenPackage;                            Name: 'ecOpenPackage'),
2185     (Value: ecOpenPackageFile;                        Name: 'ecOpenPackageFile'),
2186     (Value: ecOpenPackageOfCurUnit;                   Name: 'ecOpenPackageOfCurUnit'),
2187     (Value: ecAddCurFileToPkg;                        Name: 'ecAddCurFileToPkg'),
2188     (Value: ecNewPkgComponent;                        Name: 'ecNewPkgComponent'),
2189     //(Value: ecAddCurUnitToPkg;                        Name: 'ecAddCurUnitToPkg'),
2190     (Value: ecPackageGraph;                           Name: 'ecPackageGraph'),
2191     (Value: ecEditInstallPkgs;                        Name: 'ecEditInstallPkgs'),
2192     (Value: ecConfigCustomComps;                      Name: 'ecConfigCustomComps'),
2193     (Value: ecNewPackage;                             Name: 'ecNewPackage'),
2194 
2195   // custom tools menu
2196     (Value: ecExtToolFirst;                           Name: 'ecExtToolFirst'),
2197     (Value: ecExtToolLast;                            Name: 'ecExtToolLast'),
2198 
2199   // tools menu
2200     (Value: ecEnvironmentOptions;                     Name: 'ecEnvironmentOptions'),
2201     (Value: ecManageDesktops;                         Name: 'ecManageDesktops'),
2202     (Value: ecRescanFPCSrcDir;                        Name: 'ecRescanFPCSrcDir'),
2203     (Value: ecEditCodeTemplates;                      Name: 'ecEditCodeTemplates'),
2204     (Value: ecCodeToolsDefinesEd;                     Name: 'ecCodeToolsDefinesEd'),
2205 
2206     (Value: ecExtToolSettings;                        Name: 'ecExtToolSettings'),
2207     (Value: ecManageExamples;                         Name: 'ecManageExamples'),
2208     (Value: ecConfigBuildLazarus;                     Name: 'ecConfigBuildLazarus'),
2209     (Value: ecBuildLazarus;                           Name: 'ecBuildLazarus'),
2210     (Value: ecBuildAdvancedLazarus;                   Name: 'ecBuildAdvancedLazarus'),
2211 
2212   // window menu
2213     (Value: ecManageSourceEditors;                          Name: 'ecWindowManager'),
2214 
2215   // help menu
2216     (Value: ecAboutLazarus;                           Name: 'ecAboutLazarus'),
2217     (Value: ecOnlineHelp;                             Name: 'ecOnlineHelp'),
2218     (Value: ecContextHelp;                            Name: 'ecContextHelp'),
2219     (Value: ecEditContextHelp;                        Name: 'ecEditContextHelp'),
2220     (Value: ecReportingBug;                           Name: 'ecReportingBug'),
2221     (Value: ecFocusHint;                              Name: 'ecFocusHint'),
2222     (Value: ecSmartHint;                              Name: 'ecSmartHint'),
2223 
2224   // designer
2225     (Value: ecDesignerCopy;                           Name: 'ecDesignerCopy'),
2226     (Value: ecDesignerCut;                            Name: 'ecDesignerCut'),
2227     (Value: ecDesignerPaste;                          Name: 'ecDesignerPaste'),
2228     (Value: ecDesignerSelectParent;                   Name: 'ecDesignerSelectParent'),
2229     (Value: ecDesignerMoveToFront;                    Name: 'ecDesignerMoveToFront'),
2230     (Value: ecDesignerMoveToBack;                     Name: 'ecDesignerMoveToBack'),
2231     (Value: ecDesignerForwardOne;                     Name: 'ecDesignerForwardOne'),
2232     (Value: ecDesignerBackOne;                        Name: 'ecDesignerBackOne'),
2233     (Value: ecDesignerToggleNonVisComps;              Name: 'ecDesignerToggleNonVisComps'),
2234 
2235   // TSynPluginTemplateEdit - In cell
2236     (Value: ecIdePTmplEdNextCell;                     Name: 'ecIdePTmplEdNextCell'),
2237     (Value: ecIdePTmplEdNextCellSel;                  Name: 'ecIdePTmplEdNextCellSel'),
2238     (Value: ecIdePTmplEdNextCellRotate;               Name: 'ecIdePTmplEdNextCellRotate'),
2239     (Value: ecIdePTmplEdNextCellSelRotate;            Name: 'ecIdePTmplEdNextCellSelRotate'),
2240     (Value: ecIdePTmplEdPrevCell;                     Name: 'ecIdePTmplEdPrevCell'),
2241     (Value: ecIdePTmplEdPrevCellSel;                  Name: 'ecIdePTmplEdPrevCellSel'),
2242     (Value: ecIdePTmplEdCellHome;                     Name: 'ecIdePTmplEdCellHome'),
2243     (Value: ecIdePTmplEdCellEnd;                      Name: 'ecIdePTmplEdCellEnd'),
2244     (Value: ecIdePTmplEdCellSelect;                   Name: 'ecIdePTmplEdCellSelect'),
2245     (Value: ecIdePTmplEdFinish;                       Name: 'ecIdePTmplEdFinish'),
2246     (Value: ecIdePTmplEdEscape;                       Name: 'ecIdePTmplEdEscape'),
2247     (Value: ecIdePTmplEdNextFirstCell;                Name: 'ecIdePTmplEdNextFirstCell'),
2248     (Value: ecIdePTmplEdNextFirstCellSel;             Name: 'ecIdePTmplEdNextFirstCellSel'),
2249     (Value: ecIdePTmplEdNextFirstCellRotate;          Name: 'ecIdePTmplEdNextFirstCellRotate'),
2250     (Value: ecIdePTmplEdNextFirstCellSelRotate;       Name: 'ecIdePTmplEdNextFirstCellSelRotate'),
2251     (Value: ecIdePTmplEdPrevFirstCell;                Name: 'ecIdePTmplEdPrevFirstCell'),
2252     (Value: ecIdePTmplEdPrevFirstCellSel;             Name: 'ecIdePTmplEdPrevFirstCellSel'),
2253 
2254   // TSynPluginTemplateEdit - Out off Cell
2255     (Value: ecIdePTmplEdOutNextCell;                  Name: 'ecIdePTmplEdOutNextCell'),
2256     (Value: ecIdePTmplEdOutNextCellSel;               Name: 'ecIdePTmplEdOutNextCellSel'),
2257     (Value: ecIdePTmplEdOutNextCellRotate;            Name: 'ecIdePTmplEdOutNextCellRotate'),
2258     (Value: ecIdePTmplEdOutNextCellSelRotate;         Name: 'ecIdePTmplEdOutNextCellSelRotate'),
2259     (Value: ecIdePTmplEdOutPrevCell;                  Name: 'ecIdePTmplEdOutPrevCell'),
2260     (Value: ecIdePTmplEdOutPrevCellSel;               Name: 'ecIdePTmplEdOutPrevCellSel'),
2261     (Value: ecIdePTmplEdOutCellHome;                  Name: 'ecIdePTmplEdOutCellHome'),
2262     (Value: ecIdePTmplEdOutCellEnd;                   Name: 'ecIdePTmplEdOutCellEnd'),
2263     (Value: ecIdePTmplEdOutCellSelect;                Name: 'ecIdePTmplEdOutCellSelect'),
2264     (Value: ecIdePTmplEdOutFinish;                    Name: 'ecIdePTmplEdOutFinish'),
2265     (Value: ecIdePTmplEdOutEscape;                    Name: 'ecIdePTmplEdOutEscape'),
2266     (Value: ecIdePTmplEdOutNextFirstCell;             Name: 'ecIdePTmplEdOutNextFirstCell'),
2267     (Value: ecIdePTmplEdOutNextFirstCellSel;          Name: 'ecIdePTmplEdOutNextFirstCellSel'),
2268     (Value: ecIdePTmplEdOutNextFirstCellRotate;       Name: 'ecIdePTmplEdOutNextFirstCellRotate'),
2269     (Value: ecIdePTmplEdOutNextFirstCellSelRotate;    Name: 'ecIdePTmplEdOutNextFirstCellSelRotate'),
2270     (Value: ecIdePTmplEdOutPrevFirstCell;             Name: 'ecIdePTmplEdOutPrevFirstCell'),
2271     (Value: ecIdePTmplEdOutPrevFirstCellSel;          Name: 'ecIdePTmplEdOutPrevFirstCellSel'),
2272 
2273   // TSynPluginSyncroEdit - in celll
2274     (Value: ecIdePSyncroEdNextCell;                   Name: 'ecIdePSyncroEdNextCell'),
2275     (Value: ecIdePSyncroEdNextCellSel;                Name: 'ecIdePSyncroEdNextCellSel'),
2276     (Value: ecIdePSyncroEdPrevCell;                   Name: 'ecIdePSyncroEdPrevCell'),
2277     (Value: ecIdePSyncroEdPrevCellSel;                Name: 'ecIdePSyncroEdPrevCellSel'),
2278     (Value: ecIdePSyncroEdCellHome;                   Name: 'ecIdePSyncroEdCellHome'),
2279     (Value: ecIdePSyncroEdCellEnd;                    Name: 'ecIdePSyncroEdCellEnd'),
2280     (Value: ecIdePSyncroEdCellSelect;                 Name: 'ecIdePSyncroEdCellSelect'),
2281     (Value: ecIdePSyncroEdEscape;                     Name: 'ecIdePSyncroEdEscape'),
2282     (Value: ecIdePSyncroEdNextFirstCell;              Name: 'ecIdePSyncroEdNextFirstCell'),
2283     (Value: ecIdePSyncroEdNextFirstCellSel;           Name: 'ecIdePSyncroEdNextFirstCellSel'),
2284     (Value: ecIdePSyncroEdPrevFirstCell;              Name: 'ecIdePSyncroEdPrevFirstCell'),
2285     (Value: ecIdePSyncroEdPrevFirstCellSel;           Name: 'ecIdePSyncroEdPrevFirstCellSel'),
2286 
2287   // TSynPluginSyncroEdit - Out off cell
2288     (Value: ecIdePSyncroEdOutNextCell;                Name: 'ecIdePSyncroEdOutNextCell'),
2289     (Value: ecIdePSyncroEdOutNextCellSel;             Name: 'ecIdePSyncroEdOutNextCellSel'),
2290     (Value: ecIdePSyncroEdOutPrevCell;                Name: 'ecIdePSyncroEdOutPrevCell'),
2291     (Value: ecIdePSyncroEdOutPrevCellSel;             Name: 'ecIdePSyncroEdOutPrevCellSel'),
2292     (Value: ecIdePSyncroEdOutCellHome;                Name: 'ecIdePSyncroEdOutCellHome'),
2293     (Value: ecIdePSyncroEdOutCellEnd;                 Name: 'ecIdePSyncroEdOutCellEnd'),
2294     (Value: ecIdePSyncroEdOutCellSelect;              Name: 'ecIdePSyncroEdOutCellSelect'),
2295     (Value: ecIdePSyncroEdOutEscape;                  Name: 'ecIdePSyncroEdOutEscape'),
2296     (Value: ecIdePSyncroEdOutNextFirstCell;           Name: 'ecIdePSyncroEdOutNextFirstCell'),
2297     (Value: ecIdePSyncroEdOutNextFirstCellSel;        Name: 'ecIdePSyncroEdOutNextFirstCellSel'),
2298     (Value: ecIdePSyncroEdOutPrevFirstCell;           Name: 'ecIdePSyncroEdOutPrevFirstCell'),
2299     (Value: ecIdePSyncroEdOutPrevFirstCellSel;        Name: 'ecIdePSyncroEdOutPrevFirstCellSel'),
2300 
2301   // TSynPluginSyncroEdit - selecting
2302     (Value: ecIdePSyncroEdSelStart; Name: 'ecIdePSyncroEdSelStart')
2303   );
2304 
IdentToIDECommandnull2305 function IdentToIDECommand(const Ident: string; var Cmd: longint): boolean;
2306 begin
2307   Result := IdentToInt(Ident, Cmd, IDEEditorCommandStrs);
2308 end;
2309 
IDECommandToIdentnull2310 function IDECommandToIdent(Cmd: longint; var Ident: string): boolean;
2311 begin
2312   Result := IntToIdent(Cmd, Ident, IDEEditorCommandStrs);
2313 end;
2314 
IDECommandToIdentnull2315 function IDECommandToIdent(Cmd: longint): string;
2316 begin
2317   Result := '';
2318   if not IDECommandToIdent(Cmd, Result) then
2319     raise Exception.CreateFmt('IDECommandToIdent: command %d not found', [Cmd]);
2320 end;
2321 
2322 procedure GetIDEEditorCommandValues(Proc: TGetStrProc);
2323 var
2324   i: integer;
2325 begin
2326   for i := Low(IDEEditorCommandStrs) to High(IDEEditorCommandStrs) do
2327     Proc(IDEEditorCommandStrs[I].Name);
2328 end;
2329 
2330 end.
2331 
2332