diff --git a/components/synedit/synedit.pp b/components/synedit/synedit.pp index d04cb6b4f9..0cd8316b86 100644 --- a/components/synedit/synedit.pp +++ b/components/synedit/synedit.pp @@ -148,6 +148,13 @@ type var Handled: boolean; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer; HandlerData: pointer) of object; + THookedCommandFlag = ( + hcfInit, // run before On[User]CommandProcess (outside UndoBlock / should not do execution) + hcfPreExec, // Run before CommandProcessor (unless handled by On[User]CommandProcess) + hcfPostExec, // Run after CommandProcessor (unless handled by On[User]CommandProcess) + hcfFinish // Run at the very end + ); + THookedCommandFlags = set of THookedCommandFlag; THookedKeyTranslationEvent = procedure(Sender: TObject; Code: word; SState: TShiftState; var Data: pointer; var IsStartOfCombo: boolean; @@ -772,10 +779,8 @@ type procedure MBCSGetSelRangeInLineWhenColumnSelectionMode(const s: string; var ColFrom, ColTo: Integer); {$ENDIF} - procedure NotifyHookedCommandHandlers(AfterProcessing: boolean; - var Command: TSynEditorCommand; - var AChar: TUTF8Char; - Data: pointer); virtual; + procedure NotifyHookedCommandHandlers(var Command: TSynEditorCommand; + var AChar: TUTF8Char; Data: pointer; ATime: THookedCommandFlag); virtual; function NextWordLogicalPos(ABoundary: TLazSynWordBoundary = swbWordBegin; WordEndForDelete : Boolean = false): TPoint; function PrevWordLogicalPos(ABoundary: TLazSynWordBoundary = swbWordBegin): TPoint; procedure RecalcCharExtent; @@ -943,7 +948,7 @@ type procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure RegisterCommandHandler(AHandlerProc: THookedCommandEvent; - AHandlerData: pointer); + AHandlerData: pointer; AFlags: THookedCommandFlags = [hcfPreExec, hcfPostExec]); procedure UnregisterCommandHandler(AHandlerProc: THookedCommandEvent); procedure RegisterMouseActionSearchHandler(AHandlerProc: TSynEditMouseActionSearchProc); @@ -1315,11 +1320,12 @@ type THookedCommandHandlerEntry = class(TObject) private - fEvent: THookedCommandEvent; - fData: pointer; + FEvent: THookedCommandEvent; + FData: pointer; + FFlags: THookedCommandFlags; function Equals(AEvent: THookedCommandEvent): boolean; reintroduce; public - constructor Create(AEvent: THookedCommandEvent; AData: pointer); + constructor Create(AEvent: THookedCommandEvent; AData: pointer; AFlags: THookedCommandFlags); end; @@ -1506,12 +1512,13 @@ end; { THookedCommandHandlerEntry } -constructor THookedCommandHandlerEntry.Create(AEvent: THookedCommandEvent; - AData: pointer); +constructor THookedCommandHandlerEntry.Create(AEvent: THookedCommandEvent; AData: pointer; + AFlags: THookedCommandFlags); begin inherited Create; fEvent := AEvent; fData := AData; + FFlags := AFlags; end; function THookedCommandHandlerEntry.Equals(AEvent: THookedCommandEvent): boolean; @@ -5795,6 +5802,7 @@ begin {$ENDIF} // first the program event handler gets a chance to process the command InitialCmd := Command; + NotifyHookedCommandHandlers(Command, AChar, Data, hcfInit); DoOnProcessCommand(Command, AChar, Data); if Command <> ecNone then begin try @@ -5808,14 +5816,14 @@ begin // notify hooked command handlers before the command is executed inside of // the class if Command <> ecNone then - NotifyHookedCommandHandlers(FALSE, Command, AChar, Data); + NotifyHookedCommandHandlers(Command, AChar, Data, hcfPreExec); // internal command handler if (Command <> ecNone) and (Command < ecUserFirst) then ExecuteCommand(Command, AChar, Data); // notify hooked command handlers after the command was executed inside of // the class if Command <> ecNone then - NotifyHookedCommandHandlers(TRUE, Command, AChar, Data); + NotifyHookedCommandHandlers(Command, AChar, Data, hcfPostExec); if Command <> ecNone then DoOnCommandProcessed(Command, AChar, Data); @@ -5835,6 +5843,7 @@ begin {$ENDIF} end; end; + NotifyHookedCommandHandlers(Command, AChar, Data, hcfFinish); end; procedure TCustomSynEdit.ExecuteCommand(Command: TSynEditorCommand; @@ -8387,8 +8396,8 @@ begin Result := 0; end; -procedure TCustomSynEdit.RegisterCommandHandler(AHandlerProc: - THookedCommandEvent; AHandlerData: pointer); +procedure TCustomSynEdit.RegisterCommandHandler(AHandlerProc: THookedCommandEvent; + AHandlerData: pointer; AFlags: THookedCommandFlags); begin if not Assigned(AHandlerProc) then begin {$IFDEF SYN_DEVELOPMENT_CHECKS} @@ -8400,7 +8409,7 @@ begin fHookedCommandHandlers := TList.Create; if FindHookedCmdEvent(AHandlerProc) = -1 then fHookedCommandHandlers.Add(THookedCommandHandlerEntry.Create( - AHandlerProc, AHandlerData)) + AHandlerProc, AHandlerData, AFlags)) else {$IFDEF SYN_DEVELOPMENT_CHECKS} raise Exception.CreateFmt('Event handler (%p, %p) already registered', @@ -8471,9 +8480,8 @@ begin TSynStatusChangedHandlerList(FStatusChangedList).Remove(AStatusChangeProc); end; -procedure TCustomSynEdit.NotifyHookedCommandHandlers(AfterProcessing: boolean; - var Command: TSynEditorCommand; - var AChar: TUTF8Char; Data: pointer); +procedure TCustomSynEdit.NotifyHookedCommandHandlers(var Command: TSynEditorCommand; + var AChar: TUTF8Char; Data: pointer; ATime: THookedCommandFlag); var Handled: boolean; i: integer; @@ -8482,10 +8490,11 @@ begin Handled := FALSE; for i := 0 to GetHookedCommandHandlersCount - 1 do begin Entry := THookedCommandHandlerEntry(fHookedCommandHandlers[i]); + if not(ATime in Entry.FFlags) then continue; // NOTE: Command should NOT be set to ecNone, because this might interfere // with other handlers. Set Handled to False instead (and check its value // to not process the command twice). - Entry.fEvent(Self, AfterProcessing, Handled, Command, AChar, Data, + Entry.fEvent(Self, ATime in [hcfPostExec, hcfFinish], Handled, Command, AChar, Data, Entry.fData); end; if Handled then diff --git a/components/synedit/syneditplugins.pas b/components/synedit/syneditplugins.pas index 5bac9a2aa9..689122c146 100644 --- a/components/synedit/syneditplugins.pas +++ b/components/synedit/syneditplugins.pas @@ -129,7 +129,7 @@ type published property ShortCut: TShortCut read fShortCut write SetShortCut stored IsShortCutStored; - end; + end deprecated; { use TAbstractSynCompletion for non-visual completion } @@ -149,10 +149,10 @@ type public procedure AddEditor(aEditor: TCustomSynEdit); property CurrentString: String read fCurrentString write SetCurrentString; - end; + end deprecated; -function NewPluginCommand: TSynEditorCommand; -procedure ReleasePluginCommand(aCmd: TSynEditorCommand); +function NewPluginCommand: TSynEditorCommand; deprecated; +procedure ReleasePluginCommand(aCmd: TSynEditorCommand); deprecated; implementation @@ -169,22 +169,13 @@ uses {$ENDIF} SynEditStrConst; -const - ecPluginBase = 64000; - -var - gCurrentCommand: integer; - function NewPluginCommand: TSynEditorCommand; begin - Result := TSynEditorCommand(gCurrentCommand); - Inc( gCurrentCommand ); + Result := ecPluginFirst + AllocatePluginKeyRange(1); end; procedure ReleasePluginCommand(aCmd: TSynEditorCommand); begin - if aCmd = Pred( gCurrentCommand ) then - gCurrentCommand := aCmd; end; { TLazSynMultiEditPlugin } @@ -374,7 +365,8 @@ end; constructor TAbstractSynSingleHookPlugin.Create(aOwner: TComponent); begin inherited; - fCommandID := NewPluginCommand; + // TODO: subclasses should implement per class, not per instance + fCommandID := ecPluginFirst + AllocatePluginKeyRange(1); fShortCut := DefaultShortCut; end; @@ -387,7 +379,7 @@ destructor TAbstractSynSingleHookPlugin.Destroy; begin if Executing then Cancel; - ReleasePluginCommand( CommandID ); + //ReleasePluginCommand( CommandID ); inherited; end; @@ -582,7 +574,4 @@ begin inherited AddEditor(aEditor); end; -initialization - gCurrentCommand := ecPluginBase; - end. diff --git a/components/synedit/synmacrorecorder.pas b/components/synedit/synmacrorecorder.pas index 9c68a60f60..13497db2d8 100644 --- a/components/synedit/synmacrorecorder.pas +++ b/components/synedit/synmacrorecorder.pas @@ -518,7 +518,7 @@ var begin if AfterProcessing then begin - if (Sender = fCurrentEditor) and (State = msRecording) and (not Handled) then + if (Sender = fCurrentEditor) and (State = msRecording) and (Command <> ecNone) then begin iEvent := CreateMacroEvent( Command ); iEvent.Initialize( Command, aChar, Data );