{ ***************************************************************************** See the file COPYING.modifiedLGPL.txt, included in this distribution, for details about the license. ***************************************************************************** Abstract: Defines interface to source editors. } unit SrcEditorIntf; {$mode objfpc}{$H+} interface uses Classes, // LCL LCLType, Forms, Controls, Graphics, ComCtrls, // LazUtils Laz2_XMLCfg, LazStringUtils, // BuildIntf ProjectIntf, // IdeIntf IDECommands; type TSourceMarklingType = ( smtHint, // something is unusual or awkward smtNote, // something could be wrong or is not optimized smtWarning, // something is probably wrong or likely to fail smtError // something is definitely wrong ); { TSourceMarklingProducer } TSourceMarklingProducer = class(TComponent) public procedure InvalidateAllFiles; procedure InvalidateFile(aFilename: string); function GetMarklings(aFilename: string; out FreeList, FreeMarklings: boolean): TFPList; virtual; abstract; end; { TSourceMarkling } TSourceMarkling = class private FColumn: integer; FProducer: TSourceMarklingProducer; FId: integer; FLine: integer; fType: TSourceMarklingType; public constructor Create(aProducer: TSourceMarklingProducer; TheID, aLine, aColumn: integer; aType: TSourceMarklingType); property Producer: TSourceMarklingProducer read FProducer; property Id: integer read FId; property Line: integer read FLine; property Column: integer read FColumn; property TheType: TSourceMarklingType read fType; end; type TSrcEditSearchOption = ( sesoMatchCase, sesoWholeWord, sesoBackwards, sesoEntireScope, sesoSelectedOnly, sesoReplace, sesoReplaceAll, sesoPrompt, sesoRegExpr, sesoMultiLine ); TSrcEditSearchOptions = set of TSrcEditSearchOption; TSrcEditReplaceAction = (seraCancel, seraSkip, seraReplace, seraReplaceAll); TSrcEditProjectUpdateNeeded = (sepuNewShared, sepuChangedHighlighter); TSrcEditProjectUpdatesNeeded = set of TSrcEditProjectUpdateNeeded; { TSourceEditorInterface } TSourceEditorInterface = class protected function GetBlockBegin: TPoint; virtual; abstract; function GetBlockEnd: TPoint; virtual; abstract; function GetCodeToolsBuffer: TObject; virtual; abstract; function GetCursorScreenXY: TPoint; virtual; abstract; function GetCursorTextXY: TPoint; virtual; abstract; function GetEditorControl: TWinControl; virtual; abstract; function GetFileName: string; virtual; abstract; function GetLines: TStrings; virtual; abstract; function GetLineText: string; virtual; abstract; function GetLinesInWindow: Integer; virtual; abstract; function GetModified: Boolean; virtual; abstract; function GetPageCaption: string; virtual; abstract; function GetPageName: string; virtual; abstract; function GetReadOnly: Boolean; virtual; abstract; function GetSelection: string; virtual; abstract; function GetSelEnd: Integer; virtual; abstract; function GetSelStart: Integer; virtual; abstract; function GetSourceText: string; virtual; abstract; function GetTopLine: Integer; virtual; abstract; procedure SetBlockBegin(const AValue: TPoint); virtual; abstract; procedure SetBlockEnd(const AValue: TPoint); virtual; abstract; procedure SetCursorScreenXY(const AValue: TPoint); virtual; abstract; procedure SetCursorTextXY(const AValue: TPoint); virtual; abstract; procedure SetLines(const AValue: TStrings); virtual; abstract; procedure SetLineText(const AValue: string); virtual; abstract; procedure SetModified(const NewValue: Boolean); virtual; abstract; procedure SetReadOnly(const AValue: Boolean); virtual; abstract; procedure SetSelection(const AValue: string); virtual; abstract; procedure SetSelEnd(const AValue: Integer); virtual; abstract; procedure SetSelStart(const AValue: Integer); virtual; abstract; procedure SetSourceText(const AValue: string); virtual; abstract; procedure SetTopLine(const AValue: Integer); virtual; abstract; public // selections function SelectionAvailable: boolean; virtual; abstract; function GetText(OnlySelection: boolean): string; virtual; abstract; procedure SelectText(LineNum, CharStart, LineNum2, CharEnd: Integer); procedure SelectText(const StartPos, EndPos: TPoint); virtual; abstract; procedure InsertLine(StartLine: Integer; const NewText: String; aKeepMarks: Boolean = False); virtual; abstract; procedure ReplaceLines(StartLine, EndLine: integer; const NewText: string; aKeepMarks: Boolean = False); virtual; abstract; procedure ReplaceText(const StartPos, EndPos: TPoint; const NewText: string); procedure AskReplace(Sender: TObject; const ASearch, AReplace: string; Line, Column: integer; out Action: TSrcEditReplaceAction); virtual; abstract; procedure CopyToClipboard; virtual; abstract; procedure CutToClipboard; virtual; abstract; function GetBookMark(BookMark: Integer; out X, Y: Integer): Boolean; virtual; abstract; function GetBookMark(BookMark: Integer; out X, Y, ALeft, ATop: Integer): Boolean; virtual; abstract; procedure SetBookMark(BookMark: Integer; X, Y: Integer; AnLeft: Integer = -1; AnTop: Integer = -1); virtual; abstract; // screen and text position mapping function LineCount: Integer; virtual; abstract; function TextToScreenPosition(const Position: TPoint): TPoint; virtual; abstract; // aka byte to glyph function ScreenToTextPosition(const Position: TPoint): TPoint; virtual; abstract; // aka glyph to byte // characters and pixels function WidthInChars: Integer; virtual; abstract; function HeightInLines: Integer; virtual; abstract; function CharWidth: integer; virtual; abstract; function CursorInPixel: TPoint; virtual; abstract; function ScreenToPixelPosition(const Position: TPoint): TPoint; virtual; abstract;// ScreenXY to pixel in EditorControl. // To get the desktop pixel coords use: // with SourceEditorWindow.ActiveEditor do // DesktopXY:=EditorControl.ClientToScreen(ScreenToPixelPosition(ScreenXY)); // update procedure BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; virtual; abstract; procedure EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; virtual; abstract; procedure BeginUpdate; virtual; abstract; // block painting procedure EndUpdate; virtual; abstract; procedure IncreaseIgnoreCodeBufferLock; virtual; abstract; procedure DecreaseIgnoreCodeBufferLock; virtual; abstract; procedure UpdateCodeBuffer; virtual; abstract;// copy the source from EditorComponent to the codetools function NeedsUpdateCodeBuffer: boolean; virtual; abstract;// needs UpdateCodeBuffer // search and replace function SearchReplace(const ASearch, AReplace: string; SearchOptions: TSrcEditSearchOptions): integer; virtual; abstract; // context function GetProjectFile: TLazProjectFile; virtual; abstract; procedure UpdateProjectFile(AnUpdates: TSrcEditProjectUpdatesNeeded = []); virtual; abstract; function GetDesigner(LoadForm: boolean): TIDesigner; virtual; abstract; // editor commands procedure DoEditorExecuteCommand(EditorCommand: word); virtual; abstract; // move/copy to another SourceEditorWindow procedure MoveToWindow(AWindowIndex: Integer); virtual; abstract; procedure CopyToWindow(AWindowIndex: Integer); virtual; abstract; // function DebugToSourceLine(aLinePos: Integer): Integer; virtual; abstract; public property BlockBegin: TPoint read GetBlockBegin write SetBlockBegin; property BlockEnd: TPoint read GetBlockEnd write SetBlockEnd; property CodeToolsBuffer: TObject read GetCodeToolsBuffer; property CursorScreenXY: TPoint read GetCursorScreenXY write SetCursorScreenXY; // glyph/character,line coord, both 1-based property CursorTextXY: TPoint read GetCursorTextXY write SetCursorTextXY; // byte,line coord, both 1-based property EditorControl: TWinControl read GetEditorControl;// normally TSynEdit property FileName: string read GetFileName; property Lines: TStrings read GetLines write SetLines;// the whole file property CurrentLineText: string read GetLineText write SetLineText;// source of current line property PageCaption: string read GetPageCaption;// the beatified unit name with modifiers ('*', '#') as it is shown in tab caption property PageName: string read GetPageName;// the beatified unit name property ReadOnly: Boolean read GetReadOnly write SetReadOnly; property Selection: string read GetSelection write SetSelection; // setting selection is undoable property SelEnd: Integer read GetSelEnd write SetSelEnd; property SelStart: Integer read GetSelStart write SetSelStart; property SourceText: string read GetSourceText write SetSourceText;// the whole file, raw format, writing clears undo list property TopLine: Integer read GetTopLine write SetTopLine;// first visible line property LinesInWindow: Integer read GetLinesInWindow; property Modified: Boolean read GetModified write SetModified; end; { TSourceEditorCompletionPlugin } TSourceEditorCompletionPlugin = class(TComponent) public procedure Init(SrcEdit: TSourceEditorInterface; JumpToError: boolean; var Handled, Abort: boolean; var Prefix: string; var BoxX, BoxY: integer); virtual; abstract; // check if this plugin is responsible function Collect(List: TStrings): boolean; virtual; abstract; // collect values procedure Cancel; virtual; abstract; // completion was cancelled procedure Complete(var Value: string; SourceValue: string; var SourceStart, SourceEnd: TPoint; KeyChar: TUTF8Char; Shift: TShiftState); virtual; abstract; // execute completion procedure IndexChanged(Position: integer); virtual; abstract; procedure PrefixChanged(const NewPrefix: string; var NewIndex: integer; var s: TStrings); virtual; abstract; procedure CompletePrefix(var Prefix: string); virtual; abstract; function HasCustomPaint: boolean; virtual; procedure PaintItem(const {%H-}AKey: string; {%H-}ACanvas: TCanvas; {%H-}X, {%H-}Y: integer; {%H-}ItemSelected: boolean; {%H-}Index: integer); virtual; function MeasureItem(const {%H-}AKey: string; {%H-}ACanvas: TCanvas; {%H-}ItemSelected: boolean; {%H-}Index: integer): TPoint; virtual; end; TSourceEditorStatusPanelInterface = class; TDrawSourceEditPanelEvent = procedure(APanel: TSourceEditorStatusPanelInterface; ACanvas: TCanvas; const Rect: TRect) of object; { TSourceEditorStatusPanelInterface } TSourceEditorStatusPanelInterface = class private FOnClick: TNotifyEvent; FOnContextPopup: TContextPopupEvent; FOnDoubleClick: TNotifyEvent; FOnDrawPanel: TDrawSourceEditPanelEvent; FOwner: TClass; FTag: PtrUInt; FOnDestroy: TNotifyEvent; FOnResize: TNotifyEvent; protected function GetAlignment: TAlignment; virtual; abstract; function GetBevel: TStatusPanelBevel; virtual; abstract; function GetBidiMode: TBiDiMode; virtual; abstract; function GetHeight: integer; virtual; abstract; function GetScreenBounds: TRect;virtual; abstract; function GetText: string; virtual; abstract; function GetVisible: boolean; virtual; abstract; function GetWidth: integer; virtual; abstract; procedure SetAlignment(AValue: TAlignment); virtual; abstract; procedure SetBevel(AValue: TStatusPanelBevel); virtual; abstract; procedure SetBidiMode(AValue: TBiDiMode); virtual; abstract; procedure SetText(AValue: string); virtual; abstract; procedure SetOnDrawPanel(AValue: TDrawSourceEditPanelEvent); virtual; procedure SetVisible(AValue: boolean); virtual; abstract; public constructor Create(AnOwner: TClass; ATag: PtrUInt); property Owner: TClass read FOwner; property Tag: PtrUInt read FTag; property Alignment: TAlignment read GetAlignment write SetAlignment; property Bevel: TStatusPanelBevel read GetBevel write SetBevel; property BidiMode: TBiDiMode read GetBidiMode write SetBidiMode; property Text: string read GetText write SetText; property Visible: boolean read GetVisible write SetVisible; function RequestWidth(AWidth: Integer): Integer; virtual; abstract; property Height: integer read GetHeight; property Width: integer read GetWidth; property ScreenBounds: TRect read GetScreenBounds; property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy; property OnResize: TNotifyEvent read FOnResize write FOnResize; property OnClick: TNotifyEvent read FOnClick write FOnClick; property OnDoubleClick: TNotifyEvent read FOnDoubleClick write FOnDoubleClick; property OnContextPopup: TContextPopupEvent read FOnContextPopup write FOnContextPopup; property OnDrawPanel: TDrawSourceEditPanelEvent read FOnDrawPanel write SetOnDrawPanel; // change draw mode end; { TSourceEditorWindowInterface } TSourceEditorWindowInterface = class(TForm) protected function GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; virtual; abstract; function GetActiveEditor: TSourceEditorInterface; virtual; abstract; function GetBaseCaption: String; virtual; abstract; function GetCompletionPlugins(Index: integer): TSourceEditorCompletionPlugin; virtual; abstract; function GetItems(Index: integer): TSourceEditorInterface; virtual; abstract; procedure SetActiveEditor(const AValue: TSourceEditorInterface); virtual; abstract; procedure SetBaseCaption(AValue: String); virtual; abstract; function GetWindowID: Integer; virtual; abstract; function GetStatusPanel(AnOwner: TClass; AnIdx: integer): TSourceEditorStatusPanelInterface; virtual; abstract; function GetStatusPanelTagged(AnOwner: TClass; ATag: PtrUInt; AnIdx: integer): TSourceEditorStatusPanelInterface; virtual; abstract; public procedure IncUpdateLock; virtual; abstract; procedure DecUpdateLock; virtual; abstract; function IndexOfEditorInShareWith(AnOtherEditor: TSourceEditorInterface): Integer; virtual; abstract; function SourceEditorIntfWithFilename(const Filename: string): TSourceEditorInterface; virtual; abstract; property ActiveEditor: TSourceEditorInterface read GetActiveEditor write SetActiveEditor; function Count: integer; virtual; abstract; property Items[Index: integer]: TSourceEditorInterface read GetItems; default; property ActiveCompletionPlugin: TSourceEditorCompletionPlugin read GetActiveCompletionPlugin; // The number in the Form.Caption minus 1 (0-based), if multiple Win are open property WindowID: Integer read GetWindowID; // Editor Page Caption update procedure AddUpdateEditorPageCaptionHandler(AEvent: TNotifyEvent; const AsLast: Boolean = True); virtual; abstract; procedure RemoveUpdateEditorPageCaptionHandler(AEvent: TNotifyEvent); virtual; abstract; procedure AddControlToEditor(aSourceEditor : TSourceEditorInterface; aControl : TControl; aAlign : TAlign); virtual; abstract; property BaseCaption: String read GetBaseCaption write SetBaseCaption; function AddStatusPanel(AnOwner: TClass; ATag: PtrUInt = 0): TSourceEditorStatusPanelInterface; virtual; abstract; function StatusPanelCount(AnOwner: TClass): integer; virtual; abstract; function StatusPanelTaggedCount(AnOwner: TClass; ATag: PtrUInt): integer; virtual; abstract; property StatusPanel[AnOwner: TClass; AnIdx: integer]: TSourceEditorStatusPanelInterface read GetStatusPanel; property StatusPanelTagged[AnOwner: TClass; ATag: PtrUInt; AnIdx: integer]: TSourceEditorStatusPanelInterface read GetStatusPanelTagged; end; TSemChangeReason = ( semWindowCreate, // Called after creation of a Window semWindowDestroy, // Called after removal of a Window semWindowActivate, // Window is now ActiveSourceWindow (does not vave to be focused) semWindowFocused, // The window became the active win of the application semWindowShow, // Called after a Window is shown semWindowHide, // Called after a Window is hidden semEditorCreate, // Called after a new editor was created and added to list semEditorDestroy, // Called when an Editor is destroyed / after it is removed fron the list of editors semEditorOptsChanged, // Called when EditorOptions changed / called with TIDEEditorOptions as Sender semEditorActivate, // Editor is ActiveEditor semEditorStatus, // any status change of the editor (Caret, Selection, topline, ...) semEditorMouseDown, semEditorMouseUp, semEditorMoved, // Called when moved to a new window semEditorCloned, // Called when cloned to a new window. semEditorReConfigured // Called when the configuration of an editor changes ); TSemSelectionMode = ( semsmNormal, semsmLine, semsmColumn, semsmCurrent); TSemCopyPasteAction = ( semcaContinue, // normal paste with specials like folding semcaPlainText, // paste as normal text, ignore folding and other specials semcaAbort // cancel, use this if you handled the paste yourself ); // ToDo: use the right clipboard TSemCopyPasteEvent = procedure(Sender: TSourceEditorInterface; var AText: String; var AMode: TSemSelectionMode; ALogStartPos: TPoint; var AnAction: TSemCopyPasteAction) of object; TSemBeautyFlag = ( sembfNotBreakDots ); TSemBeautyFlags = set of TSemBeautyFlag; { TSourceEditorManagerInterface } TSourceEditorManagerInterface = class(TComponent) protected function GetActiveSourceWindow: TSourceEditorWindowInterface; virtual; abstract; procedure SetActiveSourceWindow(const AValue: TSourceEditorWindowInterface); virtual; abstract; function GetSourceWindows(Index: integer): TSourceEditorWindowInterface; virtual; abstract; function GetActiveEditor: TSourceEditorInterface; virtual; abstract; procedure SetActiveEditor(const AValue: TSourceEditorInterface); virtual; abstract; function GetSourceEditors(Index: integer): TSourceEditorInterface; virtual; abstract; function GetUniqueSourceEditors(Index: integer): TSourceEditorInterface; virtual; abstract; function GetMarklingProducers(Index: integer): TSourceMarklingProducer; virtual; abstract; function GetShowTabs: Boolean; virtual; abstract; procedure SetShowTabs(const AShowTabs: Boolean); virtual; abstract; public // List of SourceEditorWindows function SourceWindowWithEditor(const AEditor: TSourceEditorInterface): TSourceEditorWindowInterface; virtual; abstract; function IndexOfSourceWindowWithID(const AnID: Integer): Integer; virtual; abstract; procedure ShowActiveWindowOnTop(Focus: Boolean = False); virtual; abstract; function SourceWindowCount: integer; virtual; abstract; property SourceWindows[Index: integer]: TSourceEditorWindowInterface read GetSourceWindows; property ActiveSourceWindow: TSourceEditorWindowInterface read GetActiveSourceWindow write SetActiveSourceWindow; // List of SourceEditors (accross all Windows) function SourceEditorIntfWithFilename(const Filename: string): TSourceEditorInterface; virtual; abstract; // first hit, there might be more function SourceEditorCount: integer; virtual; abstract; property SourceEditors[Index: integer]: TSourceEditorInterface read GetSourceEditors; property ActiveEditor: TSourceEditorInterface read GetActiveEditor write SetActiveEditor; // List of unique SourceEditors (excluding DualView) function UniqueSourceEditorCount: integer; virtual; abstract; property UniqueSourceEditors[Index: integer]: TSourceEditorInterface read GetUniqueSourceEditors; // Editor Preferences function GetEditorControlSettings(EditControl: TControl): boolean; virtual; abstract; function GetHighlighterSettings(Highlighter: TObject): boolean; virtual; abstract; // Messages procedure ClearErrorLines; virtual; abstract; // General source functions function Beautify(const Src: string; const Flags: TSemBeautyFlags = []): string; virtual; abstract; protected // Completion Plugins function GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; virtual; abstract; function GetCompletionBoxPosition: integer; virtual; abstract; function GetCompletionPlugins(Index: integer): TSourceEditorCompletionPlugin; virtual; abstract; function GetDefaultSynCompletionForm: TCustomForm; virtual; abstract; function GetSynCompletionLinesInWindow: integer; virtual; abstract; procedure SetSynCompletionLinesInWindow(LineCnt: integer); virtual; abstract; public // Completion Plugins function CompletionPluginCount: integer; virtual; abstract; property CompletionPlugins[Index: integer]: TSourceEditorCompletionPlugin read GetCompletionPlugins; property DefaultSynCompletionForm: TCustomForm read GetDefaultSynCompletionForm; property SynCompletionLinesInWindow: integer read GetSynCompletionLinesInWindow write SetSynCompletionLinesInWindow; procedure DeactivateCompletionForm; virtual; abstract; property ActiveCompletionPlugin: TSourceEditorCompletionPlugin read GetActiveCompletionPlugin; property CompletionBoxPosition: integer read GetCompletionBoxPosition; procedure RegisterCompletionPlugin(Plugin: TSourceEditorCompletionPlugin); virtual; abstract; procedure UnregisterCompletionPlugin(Plugin: TSourceEditorCompletionPlugin); virtual; abstract; public procedure RegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); virtual; abstract; procedure UnRegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); virtual; abstract; procedure RegisterCopyPasteEvent(AHandler: TSemCopyPasteEvent); virtual; abstract; procedure UnRegisterCopyPasteEvent(AHandler: TSemCopyPasteEvent); virtual; abstract; public // source marklings function MarklingProducerCount: integer; virtual; abstract; property MarklingProducers[Index: integer]: TSourceMarklingProducer read GetMarklingProducers; procedure RegisterMarklingProducer(aProducer: TSourceMarklingProducer); virtual; abstract; procedure UnregisterMarklingProducer(aProducer: TSourceMarklingProducer); virtual; abstract; procedure InvalidateMarklingsOfAllFiles(aProducer: TSourceMarklingProducer); virtual; abstract; procedure InvalidateMarklings(aProducer: TSourceMarklingProducer; aFilename: string); virtual; abstract; property ShowTabs: Boolean read GetShowTabs write SetShowTabs; end; var SourceEditorManagerIntf: TSourceEditorManagerInterface=nil; // set by the IDE type TEditorMacroState = (emStopped, emRecording, emPlaying, emRecPaused); // msPaused = paused recording TEditorMacro = class; { TEditorMacroKeyBinding } TEditorMacroKeyBinding = class protected FOwner: TEditorMacro; function GetIdeCmd: TIDECommand; virtual; public constructor Create(AOwner: TEditorMacro); virtual; procedure WriteToXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract; procedure ReadFromXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract; procedure MacroNameChanged; virtual; // must be called by sub-class of TEditorMacro property IdeCmd: TIDECommand read GetIdeCmd; // TKeyCommandRelation function ShortCutAsText: String; virtual; end; TEditorMacroKeyBindingClass = class of TEditorMacroKeyBinding; { TEditorMacro "aEditor: TWinControl" must be TCustomSynEdit } TEditorMacro = class private FOnChange: TNotifyEvent; FOnStateChange: TNotifyEvent; procedure SetMacroNameFull(AValue: String); procedure SetOnChange(AValue: TNotifyEvent); protected procedure DoChanged; procedure DoStateChanged; // (Un)setActivated: Must be called, whenever the state changes procedure SetActivated; procedure UnsetActivated; function IsActivated: Boolean; procedure CheckStateAndActivated; function GetMacroName: String; virtual; abstract; procedure SetMacroName(AValue: string); virtual; abstract; function GetState: TEditorMacroState; virtual; abstract; function GetErrorMsg: String; virtual; function GetDefaultKeyBinding: TEditorMacroKeyBinding; function GetKeyBinding: TEditorMacroKeyBinding; virtual; abstract; procedure DoRecordMacro(aEditor: TWinControl); virtual; abstract; procedure DoPlaybackMacro(aEditor: TWinControl); virtual; abstract; procedure DoStop; virtual; abstract; procedure DoPause; virtual; abstract; procedure DoResume; virtual; abstract; public constructor Create(aOwner: TComponent); virtual; abstract; procedure AssignEventsFrom(AMacroRecorder: TEditorMacro); virtual; abstract; procedure WriteToXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract; procedure ReadFromXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract; function GetAsSource: String; virtual; abstract; procedure SetFromSource(const AText: String); virtual; abstract; procedure RecordMacro(aEditor: TWinControl); procedure PlaybackMacro(aEditor: TWinControl); procedure Stop; procedure Pause; procedure Resume; procedure Clear; virtual; abstract; function IsEmpty: Boolean; virtual; abstract; function IsInvalid: Boolean; virtual; abstract; function IsRecording(AnEditor: TWinControl): Boolean; virtual; abstract; property MacroName: String read GetMacroName write SetMacroNameFull; property State: TEditorMacroState read GetState; property ErrorMsg: String read GetErrorMsg; property OnStateChange: TNotifyEvent read FOnStateChange write FOnStateChange; property OnChange: TNotifyEvent read FOnChange write FOnChange; // Name, body property KeyBinding: TEditorMacroKeyBinding read GetKeyBinding; end; TEditorMacroClass = class of TEditorMacro; var // EditorMacroForRecording: // Used to record new Macros. On Completion it will be assigned to a player-macro EditorMacroForRecording: TEditorMacro = nil; // set by SourceEditor // ActiveEditorMacro: // Will be set whenever a macro is playing/recording. Ensures only one Macro is active ActiveEditorMacro: TEditorMacro = nil; DefaultBindingClass: TEditorMacroKeyBindingClass = nil; EditorMacroPlayerClass: TEditorMacroClass = nil; function GetMacroListViewerWarningText: String; procedure SetMacroListViewerWarningText(AValue: String); function GetMacroListViewerWarningChanged: TNotifyProcedure; procedure SetMacroListViewerWarningChanged(AValue: TNotifyProcedure); property MacroListViewerWarningText: string read GetMacroListViewerWarningText write SetMacroListViewerWarningText; property MacroListViewerWarningChanged: TNotifyProcedure read GetMacroListViewerWarningChanged write SetMacroListViewerWarningChanged; type { TIDEInteractiveStringValue } TIDEInteractiveStringValue = class(TPersistent) private FValue: string; published property Value: string read FValue write FValue; end; { TIDETemplateParser } TIDETemplateParser = class protected function GetSrcPosition: Integer; virtual; abstract; function GetDestPosition: Integer; virtual; abstract; function GetDestPosX: Integer; virtual; abstract; function GetDestPosY: Integer; virtual; abstract; function GetSrcTemplate: String; virtual; abstract; function GetDestTemplate: String; virtual; abstract; public property SrcTemplate: String read GetSrcTemplate; property DestTemplate: String read GetDestTemplate; property SrcPosition: Integer read GetSrcPosition; property DestPosition: Integer read GetDestPosition; property DestPosX: Integer read GetDestPosX; // logical, byte position property DestPosY: Integer read GetDestPosY; end; { TIDECodeMacro - templates for sources, invoked by Ctrl-j } TIDECodeMacroGetValueProc = function(const Parameter: string; InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface; var Value, ErrorMsg: string): boolean; TIDECodeMacroGetValueMethod = function(const Parameter: string; InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface; var Value, ErrorMsg: string): boolean of object; TIDECodeMacroGetValueExProc = function(const Parameter: string; InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface; var Value, ErrorMsg: string; TemplateParser: TIDETemplateParser): boolean; TIDECodeMacroGetValueExMethod = function(const Parameter: string; InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface; var Value, ErrorMsg: string; TemplateParser: TIDETemplateParser): boolean of object; TIDECodeMacro = class private FInteractive: boolean; FInteractiveValueClass: TPersistentClass; FLongDescription: string; FName: string; FOnGetValueMethod: TIDECodeMacroGetValueMethod; FOnGetValueProc: TIDECodeMacroGetValueProc; FOnGetValueExMethod: TIDECodeMacroGetValueExMethod; FOnGetValueExProc: TIDECodeMacroGetValueExProc; FShortDescription: string; protected procedure Init; virtual; public constructor Create(const TheName: string); property Name: string read FName; property ShortDescription: string read FShortDescription write FShortDescription; property LongDescription: string read FLongDescription write FLongDescription; property OnGetValueProc: TIDECodeMacroGetValueProc read FOnGetValueProc write FOnGetValueProc; property OnGetValueMethod: TIDECodeMacroGetValueMethod read FOnGetValueMethod write FOnGetValueMethod; property OnGetValueExProc: TIDECodeMacroGetValueExProc read FOnGetValueExProc write FOnGetValueExProc; property OnGetValueExMethod: TIDECodeMacroGetValueExMethod read FOnGetValueExMethod write FOnGetValueExMethod; function GetValue(const Parameter: string; InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface; out Value, ErrorMsg: string; TemplateParser: TIDETemplateParser = nil): boolean; virtual; property Interactive: boolean read FInteractive write FInteractive; property InteractiveValueClass: TPersistentClass read FInteractiveValueClass write FInteractiveValueClass; end; { TIDECodeMacros } TIDECodeMacros = class protected function GetItems(Index: integer): TIDECodeMacro; virtual; abstract; public property Items[Index: integer]: TIDECodeMacro read GetItems; default; function Count: integer; virtual; abstract; function Add(Macro: TIDECodeMacro): integer; virtual; abstract; function FindByName(const AName: string): TIDECodeMacro; virtual; abstract; function CreateUniqueName(const AName: string): string; virtual; abstract; end; var IDECodeMacros: TIDECodeMacros = nil; // set by the IDE function RegisterCodeMacro(const Name: string; const ShortDescription, LongDescription: string; OnGetValueProc: TIDECodeMacroGetValueProc; OnGetValueMethod: TIDECodeMacroGetValueMethod): TIDECodeMacro; function RegisterCodeMacroEx(const Name: string; const ShortDescription, LongDescription: string; OnGetValueProc: TIDECodeMacroGetValueExProc; OnGetValueMethod: TIDECodeMacroGetValueExMethod): TIDECodeMacro; { SearchInFile to search in a file. This can be interactively or without user interaction. If the file is open in the source editor, changes will be added to the undo history. } type TIDESearchInTextAddMatch = procedure(const Filename: string; const StartPos, EndPos: TPoint; const Lines: string) of object; { TIDESearchInTextProgress } TIDESearchInTextProgress = class private FAbort: boolean; FOnAddMatch: TIDESearchInTextAddMatch; protected procedure SetAbort(const AValue: boolean); virtual; public property Abort: boolean read FAbort write SetAbort; property OnAddMatch: TIDESearchInTextAddMatch read FOnAddMatch write FOnAddMatch; end; TIDESearchInTextFunction = function(const TheFileName: string; var TheText: string;// if TheFileName='' then use TheText SearchFor, ReplaceText: string; Flags: TSrcEditSearchOptions; var Prompt: boolean; Progress: TIDESearchInTextProgress = nil): TModalResult; TBookmarkNumRange = 0..9; var IDESearchInText: TIDESearchInTextFunction = nil;// set by the IDE implementation function RegisterCodeMacro(const Name: string; const ShortDescription, LongDescription: string; OnGetValueProc: TIDECodeMacroGetValueProc; OnGetValueMethod: TIDECodeMacroGetValueMethod): TIDECodeMacro; var NewName: String; begin NewName:=IDECodeMacros.CreateUniqueName(Name); Result:=TIDECodeMacro.Create(NewName); Result.ShortDescription:=LineBreaksToSystemLineBreaks(ShortDescription); Result.LongDescription:=LineBreaksToSystemLineBreaks(LongDescription); Result.OnGetValueProc:=OnGetValueProc; Result.OnGetValueMethod:=OnGetValueMethod; IDECodeMacros.Add(Result); end; function RegisterCodeMacroEx(const Name: string; const ShortDescription, LongDescription: string; OnGetValueProc: TIDECodeMacroGetValueExProc; OnGetValueMethod: TIDECodeMacroGetValueExMethod): TIDECodeMacro; var NewName: String; begin NewName:=IDECodeMacros.CreateUniqueName(Name); Result:=TIDECodeMacro.Create(NewName); Result.ShortDescription:=LineBreaksToSystemLineBreaks(ShortDescription); Result.LongDescription:=LineBreaksToSystemLineBreaks(LongDescription); Result.OnGetValueExProc:=OnGetValueProc; Result.OnGetValueExMethod:=OnGetValueMethod; IDECodeMacros.Add(Result); end; { TEditorMacroKeyBinding } function TEditorMacroKeyBinding.GetIdeCmd: TIDECommand; begin Result :=nil; end; procedure TEditorMacroKeyBinding.MacroNameChanged; begin // end; constructor TEditorMacroKeyBinding.Create(AOwner: TEditorMacro); begin FOwner := AOwner; end; function TEditorMacroKeyBinding.ShortCutAsText: String; begin Result := ''; end; procedure TEditorMacro.CheckStateAndActivated; begin if (State = emStopped) then begin if IsActivated then UnsetActivated; end else if not IsActivated then SetActivated; end; function TEditorMacro.GetDefaultKeyBinding: TEditorMacroKeyBinding; begin Result := DefaultBindingClass.Create(Self); end; procedure TEditorMacro.SetMacroNameFull(AValue: String); begin SetMacroName(AValue); if KeyBinding <> nil then KeyBinding.MacroNameChanged; end; procedure TEditorMacro.SetOnChange(AValue: TNotifyEvent); begin if FOnChange=AValue then Exit; FOnChange:=AValue; end; function TEditorMacro.GetErrorMsg: String; begin Result := ''; end; procedure TEditorMacro.DoChanged; begin if Assigned(FOnChange) then FOnChange(Self); end; procedure TEditorMacro.DoStateChanged; begin if Assigned(FOnStateChange) then FOnStateChange(Self); end; procedure TEditorMacro.SetActivated; begin Assert(ActiveEditorMacro=nil, 'TEditorMacro.SetActivated: There already is an active Macro'); ActiveEditorMacro := self; end; procedure TEditorMacro.UnsetActivated; begin Assert(ActiveEditorMacro=self, 'TEditorMacro.SetActivated: This is not the active Macro'); ActiveEditorMacro := nil; end; function TEditorMacro.IsActivated: Boolean; begin Result := ActiveEditorMacro = self; end; procedure TEditorMacro.RecordMacro(aEditor: TWinControl); begin SetActivated; DoRecordMacro(aEditor); CheckStateAndActivated; end; procedure TEditorMacro.PlaybackMacro(aEditor: TWinControl); begin SetActivated; DoPlaybackMacro(aEditor); CheckStateAndActivated; end; procedure TEditorMacro.Stop; begin DoStop; CheckStateAndActivated; end; procedure TEditorMacro.Pause; begin DoPause; CheckStateAndActivated; end; procedure TEditorMacro.Resume; begin DoResume; CheckStateAndActivated; end; var FMacroListViewerWarningText: String; FMacroListViewerWarningChanged: TNotifyProcedure; function GetMacroListViewerWarningText: String; begin Result := FMacroListViewerWarningText; end; procedure SetMacroListViewerWarningText(AValue: String); begin FMacroListViewerWarningText := AValue; if FMacroListViewerWarningChanged <> nil then FMacroListViewerWarningChanged(nil); end; function GetMacroListViewerWarningChanged: TNotifyProcedure; begin Result := FMacroListViewerWarningChanged; end; procedure SetMacroListViewerWarningChanged(AValue: TNotifyProcedure); begin FMacroListViewerWarningChanged := AValue; if (FMacroListViewerWarningChanged <> nil) and (FMacroListViewerWarningText <> '') then FMacroListViewerWarningChanged(nil); end; { TEditorMacro } { TSourceEditorInterface } procedure TSourceEditorInterface.SelectText(LineNum, CharStart, LineNum2, CharEnd: Integer); begin SelectText(Point(CharStart,LineNum),Point(CharEnd,LineNum2)); end; procedure TSourceEditorInterface.ReplaceText(const StartPos, EndPos: TPoint; const NewText: string); begin BeginUpdate; BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorInterface.ReplaceText'){$ENDIF}; try SelectText(StartPos,EndPos); CursorTextXY:=StartPos; Selection:=NewText; finally EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorInterface.ReplaceText'){$ENDIF}; EndUpdate; end; end; { TIDECodeMacro } procedure TIDECodeMacro.Init; begin FInteractiveValueClass:=TIDEInteractiveStringValue; end; constructor TIDECodeMacro.Create(const TheName: string); begin FName:=TheName; FShortDescription:=FName; FLongDescription:=FName; end; function TIDECodeMacro.GetValue(const Parameter: string; InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface; out Value, ErrorMsg: string; TemplateParser: TIDETemplateParser = nil): boolean; begin Value:=Parameter; ErrorMsg:=''; if Assigned(OnGetValueProc) then Result:=OnGetValueProc(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg) else if Assigned(OnGetValueMethod) then Result:=OnGetValueMethod(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg) else if Assigned(OnGetValueExProc) then Result:=OnGetValueExProc(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg, TemplateParser) else if Assigned(OnGetValueExMethod) then Result:=OnGetValueExMethod(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg, TemplateParser) else Result:=true; end; { TIDESearchInTextProgress } procedure TIDESearchInTextProgress.SetAbort(const AValue: boolean); begin if FAbort=AValue then exit; fAbort:=AValue; end; { TSourceEditorCompletionPlugin } function TSourceEditorCompletionPlugin.HasCustomPaint: boolean; begin Result:=false; end; procedure TSourceEditorCompletionPlugin.PaintItem(const AKey: string; ACanvas: TCanvas; X, Y: integer; ItemSelected: boolean; Index: integer); begin // this is called if HasCustomPaint returns true end; function TSourceEditorCompletionPlugin.MeasureItem(const AKey: string; ACanvas: TCanvas; ItemSelected: boolean; Index: integer): TPoint; begin // this is called if HasCustomPaint returns true Result:=Point(0,0); end; { TSourceEditorStatusPanelInterface } procedure TSourceEditorStatusPanelInterface.SetOnDrawPanel( AValue: TDrawSourceEditPanelEvent); begin if FOnDrawPanel = AValue then Exit; FOnDrawPanel := AValue; end; constructor TSourceEditorStatusPanelInterface.Create(AnOwner: TClass; ATag: PtrUInt); begin FOwner := AnOwner; FTag := ATag; inherited Create; end; { TSourceMarkling } constructor TSourceMarkling.Create(aProducer: TSourceMarklingProducer; TheID, aLine, aColumn: integer; aType: TSourceMarklingType); begin FProducer:=aProducer; FLine:=aLine; FColumn:=aColumn; FId:=TheID; fType:=aType; end; { TSourceMarklingProducer } procedure TSourceMarklingProducer.InvalidateAllFiles; begin SourceEditorManagerIntf.InvalidateMarklingsOfAllFiles(Self); end; procedure TSourceMarklingProducer.InvalidateFile(aFilename: string); begin SourceEditorManagerIntf.InvalidateMarklings(Self,aFilename); end; end.