1{ 2/*************************************************************************** 3 SourceEditor.pp 4 ------------------- 5 6 ***************************************************************************/ 7 8 *************************************************************************** 9 * * 10 * This source is free software; you can redistribute it and/or modify * 11 * it under the terms of the GNU General Public License as published by * 12 * the Free Software Foundation; either version 2 of the License, or * 13 * (at your option) any later version. * 14 * * 15 * This code is distributed in the hope that it will be useful, but * 16 * WITHOUT ANY WARRANTY; without even the implied warranty of * 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 18 * General Public License for more details. * 19 * * 20 * A copy of the GNU General Public License is available on the World * 21 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also * 22 * obtain it by writing to the Free Software Foundation, * 23 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. * 24 * * 25 *************************************************************************** 26} 27{ This unit builds the TSourceNotebook that the editors are held on. 28 It also has a class that controls the editors (TSourceEditor) 29} 30unit SourceEditor; 31 32{$mode objfpc} 33{$H+} 34 35interface 36 37{$I ide.inc} 38 39{ $DEFINE VerboseIDECompletionBox} 40 41uses 42 {$IFDEF IDE_MEM_CHECK} 43 MemCheck, 44 {$ENDIF} 45 SynEditMouseCmds, 46 // RTL + FCL 47 Classes, SysUtils, StrUtils, Types, Contnrs, Math, RegExpr, Laz_AVL_Tree, 48 // LCL 49 Controls, Forms, ComCtrls, StdCtrls, Graphics, Dialogs, Extctrls, Menus, 50 LCLProc, LCLType, LCLIntf, ClipBrd, HelpIntfs, Messages, LMessages, 51 // LazControls 52 ExtendedNotebook, 53 // LazUtils 54 LConvEncoding, FileUtil, LazFileUtils, LazFileCache, LazUTF8, 55 LazMethodList, LazLoggerBase, LazLogger, Translations, LazUtilities, LazTracer, 56 LazStringUtils, 57 // codetools 58 BasicCodeTools, CodeBeautifier, CodeToolManager, CodeCache, SourceLog, 59 LinkScanner, CodeTree, SourceChanger, IdentCompletionTool, 60 // synedit 61 SynEditLines, SynEditStrConst, SynEditTypes, SynEdit, 62 SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion, 63 SynEditMiscClasses, SynEditMarkupHighAll, SynEditMarks, 64 SynBeautifier, SynPluginMultiCaret, 65 SynPluginSyncronizedEditBase, SourceSynEditor, 66 SynExportHTML, SynHighlighterPas, SynEditMarkup, SynEditMarkupIfDef, SynBeautifierPascal, 67 // IdeIntf 68 SrcEditorIntf, MenuIntf, LazIDEIntf, PackageIntf, IDEHelpIntf, IDEImagesIntf, 69 IDEWindowIntf, ProjectIntf, MacroDefIntf, ToolBarIntf, IDEDialogs, IDECommands, 70 EditorSyntaxHighlighterDef, 71 // DebuggerIntf 72 DbgIntfDebuggerBase, 73 // IDE units 74 IDECmdLine, LazarusIDEStrConsts, EditorOptions, 75 EnvironmentOpts, WordCompletion, FindReplaceDialog, IDEProcs, IDEOptionDefs, 76 IDEHelpManager, MacroPromptDlg, TransferMacros, CodeContextForm, 77 SrcEditHintFrm, etMessagesWnd, etSrcEditMarks, CodeMacroPrompt, 78 CodeTemplatesDlg, CodeToolsOptions, editor_general_options, SortSelectionDlg, 79 EncloseSelectionDlg, EncloseIfDef, InvertAssignTool, SourceEditProcs, 80 SourceMarks, CharacterMapDlg, SearchFrm, MultiPasteDlg, EditorMacroListViewer, 81 EditorToolbarStatic, editortoolbar_options, InputhistoryWithSearchOpt, 82 FPDocHints, MainIntf, GotoFrm, BaseDebugManager, Debugger; 83 84type 85 TSourceNotebook = class; 86 TSourceEditorManager = class; 87 TSourceEditor = class; 88 89 TNotifyFileEvent = procedure(Sender: TObject; Filename : AnsiString) of object; 90 91 TOnProcessUserCommand = procedure(Sender: TObject; 92 Command: word; var Handled: boolean) of object; 93 TOnUserCommandProcessed = procedure(Sender: TObject; 94 Command: word; var Handled: boolean) of object; 95 96 TPackageForSourceEditorEvent = function(out APackage: TIDEPackage; 97 ASrcEdit: TObject): TLazPackageFile of object; 98 99 TPlaceBookMarkEvent = procedure(Sender: TObject; var Mark: TSynEditMark) of object; 100 TPlaceBookMarkIdEvent = procedure(Sender: TObject; ID: Integer) of object; 101 TBookMarkActionEvent = procedure(Sender: TObject; ID: Integer; Toggle: Boolean) of object; 102 103 TUpdateProjectFileEvent = procedure(Sender: TObject; AnUpdates: TSrcEditProjectUpdatesNeeded) of object; 104 105 TCharSet = set of Char; 106 107 // for TSourcEditor.CenterCursorHoriz 108 TSourceEditHCenterMode = 109 ( hcmCenter, // Center X-Caret to exact middle of Screen 110 hcmCenterKeepEOL, // Center X-Caret to middle of Screen, but keep EOL at right border 111 hcmSoft, // Soft Center (distance to screen edge) Caret 112 hcmSoftKeepEOL // Soft Center (distance to screen edge) Caret, but keep EOL at right border 113 ); 114 115 TSourceEditCompletionForm = class(TSynCompletionForm) 116 private 117 FTextHighLightColor: TColor; 118 public 119 property TextHighLightColor: TColor read FTextHighLightColor write FTextHighLightColor; 120 end; 121 122 { TSourceEditCompletion } 123 124 TSourceEditCompletion=class(TSynCompletion) 125 private 126 FIdentCompletionJumpToError: boolean; 127 ccSelection: String; 128 // colors for the completion form (popup form, e.g. word completion) 129 130 FActiveEditBackgroundColor: TColor; 131 FActiveEditBackgroundSelectedColor: TColor; 132 FActiveEditBorderColor: TColor; 133 FActiveEditTextColor: TColor; 134 FActiveEditTextSelectedColor: TColor; 135 FActiveEditTextHighLightColor: TColor; 136 137 procedure ccExecute(Sender: TObject); 138 procedure ccCancel(Sender: TObject); 139 procedure ccComplete(var Value: string; SourceValue: string; 140 var SourceStart, SourceEnd: TPoint; 141 KeyChar: TUTF8Char; Shift: TShiftState); 142 function OnSynCompletionPaintItem(const AKey: string; ACanvas: TCanvas; 143 X, Y: integer; ItemSelected: boolean; Index: integer): boolean; 144 function OnSynCompletionMeasureItem(const AKey: string; ACanvas: TCanvas; 145 ItemSelected: boolean; Index: integer): TPoint; 146 procedure OnSynCompletionSearchPosition(var APosition: integer); 147 procedure OnSynCompletionCompletePrefix(Sender: TObject); 148 procedure OnSynCompletionNextChar(Sender: TObject); 149 procedure OnSynCompletionPrevChar(Sender: TObject); 150 procedure OnSynCompletionKeyPress(Sender: TObject; var Key: Char); 151 procedure OnSynCompletionUTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char); 152 procedure OnSynCompletionPositionChanged(Sender: TObject); 153 154 function InitIdentCompletionValues(S: TStrings): boolean; 155 procedure StartShowCodeHelp; 156 procedure CompletionFormResized(Sender: TObject); 157 protected 158 CurrentCompletionType: TCompletionType; 159 function Manager: TSourceEditorManager; 160 function GetCompletionFormClass: TSynBaseCompletionFormClass; override; 161 public 162 constructor Create(AOwner: TComponent); override; 163 property IdentCompletionJumpToError: Boolean 164 read FIdentCompletionJumpToError write FIdentCompletionJumpToError; 165 end; 166 167 { TSourceEditorSharedValues } 168 169 TSourceEditorSharedValues = class(TSourceEditorSharedValuesBase) 170 private 171 FSharedEditorList: TFPList; // list of TSourceEditor sharing one TSynEdit 172 function GetOtherSharedEditors(Caller: TSourceEditor; Index: Integer): TSourceEditor; 173 function GetSharedEditors(Index: Integer): TSourceEditor; 174 function SynEditor: TIDESynEditor; 175 protected 176 function GetSharedEditorsBase(Index: Integer): TSourceEditorBase; override; 177 public 178 procedure AddSharedEditor(AnEditor: TSourceEditor); 179 procedure RemoveSharedEditor(AnEditor: TSourceEditor); 180 procedure SetActiveSharedEditor(AnEditor: TSourceEditor); 181 function SharedEditorCount: Integer; override; 182 function OtherSharedEditorCount: Integer; 183 property SharedEditors[Index: Integer]: TSourceEditor read GetSharedEditors; 184 property OtherSharedEditors[Caller: TSourceEditor; Index: Integer]: TSourceEditor 185 read GetOtherSharedEditors; 186 private 187 FExecutionMark: TSourceMark; 188 FMarksRequested: Boolean; 189 FMarklingsValid: boolean; 190 FMarksRequestedForFile: String; 191 function GetExecutionLine: Integer; 192 public 193 UpdatingExecutionMark: Integer; 194 procedure CreateExecutionMark; 195 property ExecutionLine: Integer read GetExecutionLine;// write FExecutionLine; 196 property ExecutionMark: TSourceMark read FExecutionMark write FExecutionMark; 197 procedure SetExecutionLine(NewLine: integer); 198 property MarksRequested: Boolean read FMarksRequested write FMarksRequested; 199 property MarksRequestedForFile: String read FMarksRequestedForFile write FMarksRequestedForFile; 200 private 201 FInGlobalUpdate: Integer; 202 FModified: boolean; 203 FIgnoreCodeBufferLock: integer; 204 FEditorStampCommitedToCodetools: int64; 205 FCodeBuffer: TCodeBuffer; 206 FLinkScanners: TFPList; // list of TLinkScanner 207 FMainLinkScanner: TLinkScanner; 208 FLastWarnedMainLinkFilename: string; 209 function GetModified: Boolean; 210 procedure SetCodeBuffer(const AValue: TCodeBuffer); 211 procedure SetModified(const AValue: Boolean); 212 procedure OnCodeBufferChanged(Sender: TSourceLog; SrcLogEntry: TSourceLogEntry); 213 public 214 procedure BeginGlobalUpdate; 215 procedure EndGlobalUpdate; 216 property Modified: Boolean read GetModified write SetModified; 217 property IgnoreCodeBufferLock: Integer read FIgnoreCodeBufferLock; 218 procedure IncreaseIgnoreCodeBufferLock; 219 procedure DecreaseIgnoreCodeBufferLock; 220 function NeedsUpdateCodeBuffer: boolean; 221 procedure UpdateCodeBuffer; 222 property CodeBuffer: TCodeBuffer read FCodeBuffer write SetCodeBuffer; 223 // IfDef nodes 224 procedure ConnectScanner(Scanner: TLinkScanner); 225 procedure DisconnectScanner(Scanner: TLinkScanner); 226 function GetMainLinkScanner(Scan: boolean): TLinkScanner; 227 public 228 constructor Create; 229 destructor Destroy; override; 230 function Filename: string; override; 231 end; 232 233{ TSourceEditor --- 234 TSourceEditor is the class that controls access for a single source editor, 235 which is part of TSourceNotebook. } 236 237 TSourceEditor = class(TSourceEditorBase) 238 private 239 //FAOwner is normally a TSourceNotebook. This is set in the Create constructor. 240 FAOwner: TComponent; 241 FIsLocked: Boolean; 242 FProjectFileUpdatesNeeded: TSrcEditProjectUpdatesNeeded; 243 FSharedValues: TSourceEditorSharedValues; 244 FEditor: TIDESynEditor; 245 FTempCaret: TPoint; 246 FTempTopLine: Integer; 247 FEditPlugin: TETSynPlugin; // used to update the "Messages Window" 248 // when text is inserted/deleted 249 FOnIfdefNodeStateRequest: TSynMarkupIfdefStateRequest; 250 FLastIfDefNodeScannerStep: integer; 251 FCodeCompletionState: record 252 State: (ccsReady, ccsCancelled, ccsDot, ccsOnTyping, ccsOnTypingScheduled); 253 LastTokenStartPos: TPoint; 254 end; 255 256 FSyncroLockCount: Integer; 257 FPageName: string; 258 259 FPopUpMenu: TPopupMenu; 260 FMouseActionPopUpMenu: TPopupMenu; 261 FSyntaxHighlighterType: TLazSyntaxHighlighter; 262 FErrorLine: integer; 263 FErrorColumn: integer; 264 FLineInfoNotification: TIDELineInfoNotification; 265 FInEditorChangedUpdating: Boolean; 266 267 FOnEditorChange: TStatusChangeEvent; 268 FVisible: Boolean; 269 FOnMouseMove: TMouseMoveEvent; 270 FOnMouseDown: TMouseEvent; 271 FOnMouseWheel : TMouseWheelEvent; 272 FOnKeyDown: TKeyEvent; 273 FOnKeyUp: TKeyEvent; 274 275 FSourceNoteBook: TSourceNotebook; 276 procedure EditorMouseMoved(Sender: TObject; Shift: TShiftState; X,Y:Integer); 277 procedure EditorMouseDown(Sender: TObject; Button: TMouseButton; 278 Shift: TShiftState; X,Y: Integer); 279 procedure EditorMouseUp(Sender: TObject; Button: TMouseButton; 280 Shift: TShiftState; X, Y: Integer); 281 procedure EditorMouseWheel(Sender: TObject; Shift: TShiftState; 282 WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); 283 procedure EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); 284 procedure EditorKeyUp({%H-}Sender: TObject; var {%H-}Key: Word; {%H-}Shift: TShiftState); 285 procedure EditorStatusChanged(Sender: TObject; {%H-}Changes: TSynStatusChanges); 286 procedure EditorPaste(Sender: TObject; var AText: String; 287 var AMode: TSynSelectionMode; ALogStartPos: TPoint; 288 var AnAction: TSynCopyPasteAction); 289 procedure EditorPlaceBookmark(Sender: TObject; var Mark: TSynEditMark); 290 procedure EditorClearBookmark(Sender: TObject; var Mark: TSynEditMark); 291 procedure EditorEnter(Sender: TObject); 292 procedure EditorActivateSyncro(Sender: TObject); 293 procedure EditorDeactivateSyncro(Sender: TObject); 294 procedure EditorChangeUpdating({%H-}ASender: TObject; AnUpdating: Boolean); 295 function EditorHandleMouseAction(AnAction: TSynEditMouseAction; 296 var {%H-}AnInfo: TSynEditMouseActionInfo): Boolean; 297 function GetCodeBuffer: TCodeBuffer; 298 function GetExecutionLine: integer; 299 function GetHasExecutionMarks: Boolean; 300 function GetSharedEditors(Index: Integer): TSourceEditor; 301 procedure SetCodeBuffer(NewCodeBuffer: TCodeBuffer); 302 function GetSource: TStrings; 303 procedure SetIsLocked(const AValue: Boolean); 304 procedure UpdateExecutionSourceMark; 305 procedure UpdatePageName; 306 procedure SetSource(Value: TStrings); 307 function GetCurrentCursorXLine: Integer; 308 procedure SetCurrentCursorXLine(num : Integer); 309 function GetCurrentCursorYLine: Integer; 310 procedure SetCurrentCursorYLine(num: Integer); 311 Function GetInsertMode: Boolean; 312 procedure SetPopupMenu(NewPopupMenu: TPopupMenu); 313 314 function GotoLine(Value: Integer): Integer; 315 316 procedure CreateEditor(AOwner: TComponent; AParent: TWinControl); 317 procedure UpdateNoteBook(const ANewNoteBook: TSourceNotebook; ANewPage: TTabSheet); 318 procedure SetVisible(Value: boolean); 319 procedure UnbindEditor; 320 321 procedure UpdateIfDefNodeStates(Force: Boolean = False); 322 protected 323 function GetPageCaption: string; override; 324 function GetPageName: string; override; 325 procedure SetPageName(const AValue: string); 326 protected 327 procedure DoMultiCaretBeforeCommand(Sender: TObject; ACommand: TSynEditorCommand; 328 var AnAction: TSynMultiCaretCommandAction; var {%H-}AFlags: TSynMultiCaretCommandFlags); 329 procedure ProcessCommand(Sender: TObject; 330 var Command: TSynEditorCommand; var AChar: TUTF8Char; {%H-}Data: pointer); 331 procedure ProcessUserCommand(Sender: TObject; 332 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer); 333 procedure UserCommandProcessed(Sender: TObject; 334 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer); 335 function AutoCompleteChar(Char: TUTF8Char; var AddChar: boolean; 336 Category: TAutoCompleteOption): boolean; 337 function AutoBlockCompleteChar({%H-}Char: TUTF8Char; var {%H-}AddChar: boolean; 338 Category: TAutoCompleteOption; aTextPos: TPoint; Line: string): boolean; 339 function AutoBlockCompleteChar({%H-}Char: TUTF8Char): boolean; 340 procedure AutoCompleteBlock; 341 342 procedure FocusEditor;// called by TSourceNotebook when the Notebook page 343 // changes so the editor is focused 344 procedure OnGutterClick(Sender: TObject; {%H-}X, {%H-}Y, Line: integer; 345 {%H-}Mark: TSynEditMark); 346 procedure OnEditorSpecialLineColor(Sender: TObject; Line: integer; 347 var Special: boolean; Markup: TSynSelectedColor); 348 function RefreshEditorSettings: Boolean; 349 function GetModified: Boolean; override; 350 procedure SetModified(const NewValue: Boolean); override; 351 procedure SetSyntaxHighlighterType(AHighlighterType: TLazSyntaxHighlighter); 352 procedure SetErrorLine(NewLine: integer); 353 procedure SetExecutionLine(NewLine: integer); 354 procedure StartIdentCompletionBox(JumpToError, CanAutoComplete: boolean); 355 procedure StartWordCompletionBox; 356 357 function IsFirstShared(Sender: TObject): boolean; 358 359 function GetFilename: string; override; 360 function GetEditorControl: TWinControl; override; 361 function GetCodeToolsBuffer: TObject; override; 362 Function GetReadOnly: Boolean; override; 363 procedure SetReadOnly(const NewValue: boolean); override; 364 365 function Manager: TSourceEditorManager; 366 property Visible: Boolean read FVisible write SetVisible default False; 367 function GetSharedValues: TSourceEditorSharedValuesBase; override; 368 function IsSharedWith(AnOtherEditor: TSourceEditor): Boolean; 369 procedure BeforeCodeBufferReplace; 370 procedure AfterCodeBufferReplace; 371 function Close: Boolean; 372 public 373 constructor Create(AOwner: TComponent; AParent: TWinControl; ASharedEditor: TSourceEditor = nil); 374 destructor Destroy; override; 375 376 // codebuffer 377 procedure BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; override; 378 procedure EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; override; 379 procedure BeginUpdate; override; 380 procedure EndUpdate; override; 381 procedure BeginGlobalUpdate; 382 procedure EndGlobalUpdate; 383 procedure IncreaseIgnoreCodeBufferLock; override; 384 procedure DecreaseIgnoreCodeBufferLock; override; 385 procedure UpdateCodeBuffer; override;// copy the source from EditorComponent 386 function NeedsUpdateCodeBuffer: boolean; override; 387 procedure ConnectScanner(Scanner: TLinkScanner); 388 389 // find 390 procedure StartFindAndReplace(Replace:boolean); 391 procedure AskReplace(Sender: TObject; const ASearch, AReplace: 392 string; Line, Column: integer; out Action: TSrcEditReplaceAction); override; 393 procedure OnReplace(Sender: TObject; const ASearch, AReplace: 394 string; {%H-}Line, {%H-}Column: integer; var Action: TSynReplaceAction); 395 function DoFindAndReplace(aFindText, aReplaceText: String; anOptions: TSynSearchOptions): Integer; 396 procedure FindNextUTF8; 397 procedure FindPrevious; 398 procedure FindNextWordOccurrence(DirectionForward: boolean); 399 procedure ShowGotoLineDialog; 400 401 // dialogs 402 procedure GetDialogPosition(Width, Height: integer; out Left, Top: integer); 403 procedure ActivateHint(const ClientPos: TPoint; const ABaseURL, AHint: string; 404 AAutoShown: Boolean = True); overload; 405 procedure ActivateHint(ClientRect: TRect; const ABaseURL, AHint: string; 406 AAutoShown: Boolean; AMouseOffset: Boolean = True); overload; 407 408 // selections 409 function SelectionAvailable: boolean; override; 410 function GetText(OnlySelection: boolean): string; override; 411 procedure SelectText(const StartPos, EndPos: TPoint); override; 412 procedure InsertLine(StartLine: Integer; const NewText: String; aKeepMarks: Boolean = False); override; 413 procedure ReplaceLines(StartLine, EndLine: integer; const NewText: string; aKeepMarks: Boolean = False); override; 414 procedure EncloseSelection; 415 procedure UpperCaseSelection; 416 procedure LowerCaseSelection; 417 procedure SwapCaseSelection; 418 procedure TabsToSpacesInSelection; 419 procedure CommentSelection; 420 procedure UncommentSelection; 421 procedure ToggleCommentSelection; 422 procedure UpdateCommentSelection(CommentOn, Toggle: Boolean); 423 procedure ConditionalSelection; 424 procedure SortSelection; 425 procedure BreakLinesInSelection; 426 procedure InvertAssignment; 427 procedure SelectToBrace; 428 procedure SelectWord; 429 procedure SelectLine; 430 procedure SelectParagraph; 431 function CommentText(const Txt: string; CommentType: TCommentType): string; 432 procedure InsertCharacterFromMap; 433 procedure InsertLicenseNotice(const Notice: string; CommentType: TCommentType); 434 procedure InsertGPLNotice(CommentType: TCommentType; Translated: boolean); 435 procedure InsertLGPLNotice(CommentType: TCommentType; Translated: boolean); 436 procedure InsertModifiedLGPLNotice(CommentType: TCommentType; Translated: boolean); 437 procedure InsertMITNotice(CommentType: TCommentType; Translated: boolean); 438 procedure InsertUsername; 439 procedure InsertDateTime; 440 procedure InsertChangeLogEntry; 441 procedure InsertCVSKeyword(const AKeyWord: string); 442 procedure InsertGUID; 443 procedure InsertFilename; 444 function GetSelEnd: Integer; override; 445 function GetSelStart: Integer; override; 446 procedure SetSelEnd(const AValue: Integer); override; 447 procedure SetSelStart(const AValue: Integer); override; 448 function GetSelection: string; override; 449 procedure SetSelection(const AValue: string); override; 450 procedure CopyToClipboard; override; 451 procedure CutToClipboard; override; 452 function GetBookMark(BookMark: Integer; out X, Y: Integer): Boolean; override; 453 procedure SetBookMark(BookMark: Integer; X, Y: Integer); override; 454 455 procedure ExportAsHtml(AFileName: String); 456 457 // context help 458 procedure FindHelpForSourceAtCursor; 459 //Smart hint 460 procedure ShowSmartHintForSourceAtCursor; 461 462 // editor commands 463 procedure DoEditorExecuteCommand(EditorCommand: word); override; 464 procedure MoveToWindow(AWindowIndex: Integer); override; 465 procedure CopyToWindow(AWindowIndex: Integer); override; 466 467 function GetCodeAttributeName(LogXY: TPoint): String; 468 469 // used to get the word at the mouse cursor 470 function CurrentWordLogStartOrCaret: TPoint; 471 function GetWordFromCaret(const ACaretPos: TPoint): String; 472 function GetWordAtCurrentCaret: String; 473 function GetOperandFromCaret(const ACaretPos: TPoint): String; 474 function GetOperandAtCurrentCaret: String; 475 function CaretInSelection(const ACaretPos: TPoint): Boolean; 476 477 // cursor 478 procedure CenterCursor(SoftCenter: Boolean = False); // vertical 479 procedure CenterCursorHoriz(HCMode: TSourceEditHCenterMode); // horiz 480 function TextToScreenPosition(const Position: TPoint): TPoint; override; 481 function ScreenToTextPosition(const Position: TPoint): TPoint; override; 482 function ScreenToPixelPosition(const Position: TPoint): TPoint; override; 483 function GetCursorScreenXY: TPoint; override; 484 function GetCursorTextXY: TPoint; override; 485 procedure SetCursorScreenXY(const AValue: TPoint); override; 486 procedure SetCursorTextXY(const AValue: TPoint); override; 487 function GetBlockBegin: TPoint; override; 488 function GetBlockEnd: TPoint; override; 489 procedure SetBlockBegin(const AValue: TPoint); override; 490 procedure SetBlockEnd(const AValue: TPoint); override; 491 function GetLinesInWindow: Integer; override; 492 function GetTopLine: Integer; override; 493 procedure SetTopLine(const AValue: Integer); override; 494 function CursorInPixel: TPoint; override; 495 function IsCaretOnScreen(ACaret: TPoint; UseSoftCenter: Boolean = False): Boolean; 496 497 // text 498 procedure MultiPasteText; 499 function SearchReplace(const ASearch, AReplace: string; 500 SearchOptions: TSrcEditSearchOptions): integer; override; 501 function GetSourceText: string; override; 502 procedure SetSourceText(const AValue: string); override; 503 function LineCount: Integer; override; 504 function WidthInChars: Integer; override; 505 function HeightInLines: Integer; override; 506 function CharWidth: integer; override; 507 function GetLineText: string; override; 508 procedure SetLineText(const AValue: string); override; 509 function GetLines: TStrings; override; 510 procedure SetLines(const AValue: TStrings); override; 511 512 // context 513 function GetProjectFile: TLazProjectFile; override; 514 procedure UpdateProjectFile(AnUpdates: TSrcEditProjectUpdatesNeeded = []); override; 515 function GetDesigner(LoadForm: boolean): TIDesigner; override; 516 517 // notebook 518 procedure Activate; 519 function PageIndex: integer; 520 function IsActiveOnNoteBook: boolean; 521 procedure CheckActiveWindow; 522 523 // debugging 524 procedure DoRequestExecutionMarks({%H-}Data: PtrInt); 525 procedure FillExecutionMarks; 526 procedure ClearExecutionMarks; 527 procedure LineInfoNotificationChange(const {%H-}ASender: TObject; const ASource: String); 528 function SourceToDebugLine(aLinePos: Integer): Integer; 529 function DebugToSourceLine(aLinePos: Integer): Integer; 530 531 procedure InvalidateAllIfdefNodes; 532 procedure SetIfdefNodeState(ALinePos, AstartPos: Integer; AState: TSynMarkupIfdefNodeState); 533 property OnIfdefNodeStateRequest: TSynMarkupIfdefStateRequest read FOnIfdefNodeStateRequest write FOnIfdefNodeStateRequest; 534 public 535 // properties 536 property CodeBuffer: TCodeBuffer read GetCodeBuffer write SetCodeBuffer; 537 property CurrentCursorXLine: Integer 538 read GetCurrentCursorXLine write SetCurrentCursorXLine; 539 property CurrentCursorYLine: Integer 540 read GetCurrentCursorYLine write SetCurrentCursorYLine; 541 property EditorComponent: TIDESynEditor read FEditor; 542 property ErrorLine: integer read FErrorLine write SetErrorLine; 543 property ExecutionLine: integer read GetExecutionLine write SetExecutionLine; 544 property HasExecutionMarks: Boolean read GetHasExecutionMarks; 545 property InsertMode: Boolean read GetInsertmode; 546 property OnEditorChange: TStatusChangeEvent read FOnEditorChange 547 write FOnEditorChange; 548 property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove; 549 property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown; 550 property OnMouseWheel: TMouseWheelEvent read FOnMouseWheel write FOnMouseWheel; 551 property OnKeyDown: TKeyEvent read FOnKeyDown write FOnKeyDown; 552 property OnKeyUp: TKeyEvent read FOnKeyUp write FOnKeyUp; 553 property Owner: TComponent read FAOwner; 554 property PageName: string read GetPageName write SetPageName; 555 property PopupMenu: TPopupMenu read FPopUpMenu write SetPopUpMenu; 556 property ReadOnly: Boolean read GetReadOnly write SetReadOnly; 557 property Source: TStrings read GetSource write SetSource; 558 property SourceNotebook: TSourceNotebook read FSourceNoteBook; 559 property SyntaxHighlighterType: TLazSyntaxHighlighter 560 read fSyntaxHighlighterType write SetSyntaxHighlighterType; 561 property SyncroLockCount: Integer read FSyncroLockCount; 562 function SharedEditorCount: Integer; 563 property SharedEditors[Index: Integer]: TSourceEditor read GetSharedEditors; 564 property SharedValues: TSourceEditorSharedValues read FSharedValues; 565 property IsLocked: Boolean read FIsLocked write SetIsLocked; 566 end; 567 568 //============================================================================ 569 570 { TSourceNotebook } 571 572 TJumpHistoryAction = (jhaBack, jhaForward, jhaViewWindow); 573 TCloseSrcEditorOption = (ceoCloseOthers, ceoCloseOthersOnRightSide); 574 TCloseSrcEditorOptions = set of TCloseSrcEditorOption; 575 576 TOnJumpToHistoryPoint = procedure(out NewCaretXY: TPoint; 577 out NewTopLine: integer; 578 out DestEditor: TSourceEditor; 579 Action: TJumpHistoryAction) of object; 580 TOnAddJumpPoint = procedure(ACaretXY: TPoint; ATopLine: integer; 581 AEditor: TSourceEditor; DeleteForwardHistory: boolean) of object; 582 TOnMovingPage = procedure(Sender: TObject; 583 OldPageIndex, NewPageIndex: integer) of object; 584 TOnCloseSrcEditor = procedure(Sender: TObject; ACloseOptions: TCloseSrcEditorOptions) of object; 585 TOnShowHintForSource = procedure(SrcEdit: TSourceEditor; 586 CaretPos: TPoint; AutoShown: Boolean) of object; 587 TOnInitIdentCompletion = procedure(Sender: TObject; JumpToError: boolean; 588 out Handled, Abort: boolean) of object; 589 TSrcEditPopupMenuEvent = procedure(const AddMenuItemProc: TAddMenuItemProc 590 ) of object; 591 TOnShowCodeContext = procedure(JumpToError: boolean; 592 out Abort: boolean) of object; 593 TOnGetIndentEvent = function(Sender: TObject; Editor: TSourceEditor; 594 LogCaret, OldLogCaret: TPoint; FirstLinePos, LinesCount: Integer; 595 Reason: TSynEditorCommand; SetIndentProc: TSynBeautifierSetIndentProc 596 ): boolean of object; 597 598 TSourceNotebookState = ( 599 snIncrementalFind, 600 snWarnedFont, 601 snUpdateStatusBarNeeded, 602 snNotebookPageChangedNeeded 603 ); 604 TSourceNotebookStates = set of TSourceNotebookState; 605 606 TSourceNotebookUpdateFlag = ( 607 ufPageNames, 608 ufTabsAndPage, 609 ufStatusBar, 610 ufProjectFiles, 611 ufFocusEditor, 612 ufActiveEditorChanged, 613 ufPageIndexChanged 614 ); 615 TSourceNotebookUpdateFlags = set of TSourceNotebookUpdateFlag; 616 617 TBrowseEditorTabHistoryDialog = class; 618 619 { TSourceNotebook } 620 621 TSourceNotebook = class(TSourceEditorWindowInterface) 622 GoToLineMenuItem: TMenuItem; 623 OpenFolderMenuItem: TMenuItem; 624 StatusPopUpMenu: TPopupMenu; 625 StatusBar: TStatusBar; 626 procedure CompleteCodeMenuItemClick(Sender: TObject); 627 procedure DbgPopUpMenuPopup(Sender: TObject); 628 procedure EditorLockClicked(Sender: TObject); 629 procedure EncodingClicked(Sender: TObject); 630 procedure ExtractProcMenuItemClick(Sender: TObject); 631 procedure FindOverloadsMenuItemClick(Sender: TObject); 632 procedure FormMouseUp(Sender: TObject; {%H-}Button: TMouseButton; 633 {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer); 634 procedure GoToLineMenuItemClick(Sender: TObject); 635 procedure HighlighterClicked(Sender: TObject); 636 procedure InsertCharacter(const C: TUTF8Char); 637 procedure InvertAssignmentMenuItemClick(Sender: TObject); 638 procedure LineEndingClicked(Sender: TObject); 639 procedure MakeResourceStringMenuItemClick(Sender: TObject); 640 procedure NotebookPageChanged(Sender: TObject); 641 procedure NotebookShowTabHint(Sender: TObject; HintInfo: PHintInfo); 642 procedure OnPopupMenuOpenFile(Sender: TObject); 643 procedure OnPopupOpenPackageFile(Sender: TObject); 644 procedure OnPopupOpenProjectInsp(Sender: TObject); 645 procedure OpenAtCursorClicked(Sender: TObject); 646 procedure OpenFolderMenuItemClick(Sender: TObject); 647 procedure RenameIdentifierMenuItemClick(Sender: TObject); 648 procedure ShowAbstractMethodsMenuItemClick(Sender: TObject); 649 procedure ShowEmptyMethodsMenuItemClick(Sender: TObject); 650 procedure ShowUnusedUnitsMenuItemClick(Sender: TObject); 651 procedure SourceNotebookDropFiles(Sender: TObject; 652 const FileNames: array of String); 653 procedure SrcEditMenuCopyToExistingWindowClicked(Sender: TObject); 654 procedure SrcEditMenuFindInWindowClicked(Sender: TObject); 655 procedure SrcEditMenuMoveToExistingWindowClicked(Sender: TObject); 656 procedure SrcPopUpMenuPopup(Sender: TObject); 657 procedure StatusBarClick(Sender: TObject); 658 procedure StatusBarDblClick(Sender: TObject); 659 procedure StatusBarContextPopup(Sender: TObject; MousePos: TPoint; 660 var {%H-}Handled: Boolean); 661 procedure StatusBarDrawPanel({%H-}AStatusBar: TStatusBar; APanel: TStatusPanel; 662 const ARect: TRect); 663 procedure TabPopUpMenuPopup(Sender: TObject); 664 private 665 FNotebook: TExtendedNotebook; 666 FBaseCaption: String; 667 FIsClosing: Boolean; 668 FSrcEditsSortedForFilenames: TAvlTree; // TSourceEditorInterface sorted for Filename 669 TabPopUpMenu, SrcPopUpMenu, DbgPopUpMenu: TPopupMenu; 670 procedure ApplyPageIndex; 671 procedure ExecuteEditorItemClick(Sender: TObject); 672 public 673 procedure DeleteBreakpointClicked(Sender: TObject); 674 procedure ToggleBreakpointClicked(Sender: TObject); 675 procedure ToggleBreakpointEnabledClicked(Sender: TObject); 676 private 677 FManager: TSourceEditorManager; 678 FUpdateLock, FFocusLock, fAutoFocusLock: Integer; 679 FUpdateFlags: TSourceNotebookUpdateFlags; 680 FPageIndex: Integer; 681 FIncrementalSearchPos: TPoint; // last set position 682 fIncrementalSearchStartPos: TPoint; // position where to start searching 683 FIncrementalSearchStr, FIncrementalFoundStr: string; 684 FIncrementalSearchBackwards : Boolean; 685 FIncrementalSearchEditor: TSourceEditor; // editor with active search (MWE:shouldnt all FIncrementalSearch vars go to that editor ?) 686 FLastCodeBuffer: TCodeBuffer; 687 FProcessingCommand: boolean; 688 FSourceEditorList: TFPList; // list of TSourceEditor 689 FHistoryList: TFPList; // list of TSourceEditor page order for when a window closes 690 FHistoryDlg: TBrowseEditorTabHistoryDialog; 691 FStopBtnIdx: Integer; 692 FOnEditorPageCaptionUpdate: TMethodList; 693 private 694 FUpdateTabAndPageTimer: TTimer; 695 FWindowID: Integer; 696 // PopupMenu 697 procedure BuildPopupMenu; 698 //forwarders to FNoteBook 699 function GetNoteBookPage(Index: Integer): TTabSheet; 700 function GetNotebookPages: TStrings; 701 function GetPageCount: Integer; 702 function GetPageIndex: Integer; 703 procedure SetPageIndex(AValue: Integer); 704 705 procedure UpdateHighlightMenuItems(SrcEdit: TSourceEditor); 706 procedure UpdateLineEndingMenuItems(SrcEdit: TSourceEditor); 707 procedure UpdateEncodingMenuItems(SrcEdit: TSourceEditor); 708 procedure RemoveUserDefinedMenuItems; 709 function AddUserDefinedPopupMenuItem(const NewCaption: string; 710 const NewEnabled: boolean; 711 const NewOnClick: TNotifyEvent): TIDEMenuItem; 712 procedure RemoveContextMenuItems; 713 function AddContextPopupMenuItem(const NewCaption: string; 714 const NewEnabled: boolean; 715 const NewOnClick: TNotifyEvent): TIDEMenuItem; 716 717 // Incremental Search 718 procedure UpdateActiveEditColors(AEditor: TSynEdit); 719 procedure SetIncrementalSearchStr(const AValue: string); 720 procedure IncrementalSearch(ANext, ABackward: Boolean); 721 procedure UpdatePageNames; 722 procedure UpdateProjectFiles(ACurrentEditor: TSourceEditor = nil); 723 724 property NoteBookPage[Index: Integer]: TTabSheet read GetNoteBookPage; 725 procedure NoteBookInsertPage(Index: Integer; const S: string); 726 procedure NoteBookDeletePage(APageIndex: Integer); 727 procedure UpdateTabsAndPageTitle; 728 procedure UpdateTabsAndPageTimeReached(Sender: TObject); 729 procedure CallOnEditorPageCaptionUpdate(Sender: TObject); 730 protected 731 function NoteBookIndexOfPage(APage: TTabSheet): Integer; 732 procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; 733 var Accept: Boolean); override; 734 procedure DragCanceled; override; 735 procedure DoActiveEditorChanged; 736 protected 737 States: TSourceNotebookStates; 738 procedure Activate; override; 739 procedure CreateNotebook; 740 function NewSE(Pagenum: Integer; NewPagenum: Integer = -1; 741 ASharedEditor: TSourceEditor = nil; 742 ATabCaption: String = ''): TSourceEditor; 743 procedure AcceptEditor(AnEditor: TSourceEditor; SendEvent: Boolean = False); 744 procedure ReleaseEditor(AnEditor: TSourceEditor; SendEvent: Boolean = False); 745 procedure EditorChanged(Sender: TObject; Changes: TSynStatusChanges); 746 procedure DoClose(var CloseAction: TCloseAction); override; 747 procedure DoShow; override; 748 procedure DoHide; override; 749 function GetWindowID: Integer; override; 750 protected 751 function GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; override; 752 function GetBaseCaption: String; override; 753 function GetCompletionPlugins(Index: integer): TSourceEditorCompletionPlugin; override; 754 755 procedure EditorMouseMove(Sender: TObject; {%H-}Shift: TShiftstate; 756 {%H-}X,{%H-}Y: Integer); 757 procedure EditorMouseDown(Sender: TObject; {%H-}Button: TMouseButton; 758 {%H-}Shift: TShiftstate; {%H-}X,{%H-}Y: Integer); 759 function EditorGetIndent(Sender: TObject; Editor: TObject; 760 LogCaret, OldLogCaret: TPoint; FirstLinePos, LastLinePos: Integer; 761 Reason: TSynEditorCommand; 762 SetIndentProc: TSynBeautifierSetIndentProc): Boolean; 763 procedure EditorKeyDown(Sender: TObject; var {%H-}Key: Word; {%H-}Shift: TShiftState); 764 procedure EditorKeyUp(Sender: TObject; var {%H-}Key: Word; {%H-}Shift: TShiftState); 765 procedure EditorMouseWheel(Sender: TObject; {%H-}Shift: TShiftState; 766 {%H-}WheelDelta: Integer; {%H-}MousePos: TPoint; var {%H-}Handled: Boolean); 767 768 procedure NotebookMouseDown(Sender: TObject; Button: TMouseButton; 769 {%H-}Shift: TShiftState; X,Y: Integer); 770 procedure NotebookMouseUp(Sender: TObject; Button: TMouseButton; 771 {%H-}Shift: TShiftState; X,Y: Integer); 772 procedure NotebookDragDropEx(Sender, Source: TObject; 773 OldIndex, NewIndex: Integer; CopyDrag: Boolean; 774 var Done: Boolean); 775 procedure NotebookDragOverEx(Sender, Source: TObject; 776 OldIndex, NewIndex: Integer; CopyDrag: Boolean; 777 var Accept: Boolean); 778 procedure NotebookDragOver(Sender, Source: TObject; 779 {%H-}X,{%H-}Y: Integer; State: TDragState; var Accept: Boolean); 780 procedure NotebookEndDrag(Sender, {%H-}Target: TObject; {%H-}X,{%H-}Y: Integer); 781 782 procedure OnApplicationDeactivate(Sender: TObject); 783 procedure ShowSynEditHint(const MousePos: TPoint); 784 785 procedure NextEditor; 786 procedure PrevEditor; 787 procedure MoveEditorLeft(CurrentPageIndex: integer); 788 procedure MoveEditorRight(CurrentPageIndex: integer); 789 procedure MoveActivePageLeft; 790 procedure MoveActivePageRight; 791 procedure MoveEditorFirst(CurrentPageIndex: integer); 792 procedure MoveEditorLast(CurrentPageIndex: integer); 793 procedure MoveActivePageFirst; 794 procedure MoveActivePageLast; 795 procedure GotoNextWindow(Backward: Boolean = False); 796 procedure GotoNextSharedEditor(Backward: Boolean = False); 797 procedure MoveEditorNextWindow(Backward: Boolean = False; Copy: Boolean = False); 798 procedure CopyEditor(OldPageIndex, NewWindowIndex, NewPageIndex: integer; Focus: Boolean = False); 799 800 function GetActiveEditor: TSourceEditorInterface; override; 801 procedure SetActiveEditor(const AValue: TSourceEditorInterface); override; 802 procedure SetBaseCaption(AValue: String); override; 803 function GetItems(Index: integer): TSourceEditorInterface; override; 804 function GetEditors(Index:integer): TSourceEditor; 805 806 property Manager: TSourceEditorManager read FManager; 807 808 procedure BeginAutoFocusLock; 809 procedure EndAutoFocusLock; 810 protected 811 procedure CloseTabClicked(Sender: TObject); 812 procedure CloseClicked(Sender: TObject; CloseOptions: TCloseSrcEditorOptions = []); 813 procedure ToggleFormUnitClicked(Sender: TObject); 814 procedure ToggleObjectInspClicked(Sender: TObject); 815 816 procedure IncUpdateLockInternal; 817 procedure DecUpdateLockInternal; 818 819 // editor page history 820 procedure HistorySetMostRecent(APage: TTabSheet); 821 procedure HistoryRemove(APage: TTabSheet); 822 function HistoryGetTopPageIndex: Integer; 823 824 // incremental find 825 procedure BeginIncrementalFind; 826 procedure EndIncrementalFind; 827 property IncrementalSearchStr: string 828 read FIncrementalSearchStr write SetIncrementalSearchStr; 829 830 procedure StartShowCodeContext(JumpToError: boolean); 831 832 // paste and copy 833 procedure CutClicked(Sender: TObject); 834 procedure CopyClicked(Sender: TObject); 835 procedure PasteClicked(Sender: TObject); 836 837 procedure ReloadEditorOptions; 838 procedure CheckFont; 839 840 public 841 procedure AddUpdateEditorPageCaptionHandler(AEvent: TNotifyEvent; const AsLast: Boolean = True); override; 842 procedure RemoveUpdateEditorPageCaptionHandler(AEvent: TNotifyEvent); override; 843 844 procedure ProcessParentCommand(Sender: TObject; 845 var Command: TSynEditorCommand; var {%H-}AChar: TUTF8Char; {%H-}Data: pointer; 846 var Handled: boolean); 847 procedure ParentCommandProcessed(Sender: TObject; 848 var Command: TSynEditorCommand; var {%H-}AChar: TUTF8Char; {%H-}Data: pointer; 849 var Handled: boolean); 850 public 851 constructor Create(AOwner: TComponent); override; overload; 852 constructor Create(AOwner: TComponent; AWindowID: Integer); overload; 853 destructor Destroy; override; 854 855 function EditorCount: integer; 856 function IndexOfEditor(aEditor: TSourceEditorInterface): integer; 857 function Count: integer; override; 858 859 function SourceEditorIntfWithFilename(const Filename: string 860 ): TSourceEditorInterface; override; 861 function FindSourceEditorWithPageIndex(APageIndex:integer):TSourceEditor; 862 function FindPageWithEditor(ASourceEditor: TSourceEditor):integer; 863 function FindSourceEditorWithEditorComponent(EditorComp: TComponent): TSourceEditor; 864 function GetActiveSE: TSourceEditor; { $note deprecate and use SetActiveEditor} 865 procedure CheckCurrentCodeBufferChanged; 866 function IndexOfEditorInShareWith(AnOtherEditor: TSourceEditorInterface): Integer; override; 867 procedure MoveEditor(OldPageIndex, NewPageIndex: integer); 868 procedure MoveEditor(OldPageIndex, NewWindowIndex, NewPageIndex: integer); 869 870 procedure UpdateStatusBar; 871 procedure ClearExecutionLines; 872 procedure ClearExecutionMarks; 873 874 // new, close, focus 875 function NewFile(const NewShortName: String; ASource: TCodeBuffer; 876 FocusIt: boolean; AShareEditor: TSourceEditor = nil): TSourceEditor; 877 procedure CloseFile(APageIndex:integer); 878 procedure FocusEditor; 879 function GetCapabilities: TCTabControlCapabilities; 880 procedure IncUpdateLock; override; 881 procedure DecUpdateLock; override; 882 public 883 property Editors[Index:integer]:TSourceEditor read GetEditors; // !!! not ordered for PageIndex 884 // forwarders to the FNotebook 885 property PageIndex: Integer read GetPageIndex write SetPageIndex; 886 property PageCount: Integer read GetPageCount; 887 property NotebookPages: TStrings read GetNotebookPages; 888 end; 889 890 { TBrowseEditorTabHistoryDialog } 891 892 TBrowseEditorTabHistoryDialog = class(TForm) 893 private 894 FNotebook: TSourceNotebook; 895 FEditorList: TListBox; 896 897 procedure MoveInList(aForward: Boolean); 898 protected 899 procedure KeyDown(var Key: Word; Shift: TShiftState); override; 900 procedure KeyUp(var Key: Word; Shift: TShiftState); override; 901 procedure DoCreate; override; 902 public 903 procedure Show(aForward: Boolean); reintroduce; 904 end; 905 906 TSrcEditMangerHandlerType = ( 907 semhtCopyPaste 908 ); 909 TSrcEditManagerUpdateFlag = ( 910 ufMgrActiveEditorChanged, 911 ufShowWindowOnTop, 912 ufShowWindowOnTopFocus); 913 TSrcEditManagerUpdateFlags = set of TSrcEditManagerUpdateFlag; 914 915 { TSourceEditorManagerBase } 916 (* Implement all Methods with the Interface types *) 917 918 TSourceEditorManagerBase = class(TSourceEditorManagerInterface) 919 private 920 FActiveWindow: TSourceNotebook; 921 FSourceWindowList: TFPList; 922 FSourceWindowByFocusList: TFPList; 923 FUpdateLock: Integer; 924 FActiveEditorLock: Integer; 925 FAutoFocusLock: Integer; 926 FUpdateFlags: TSrcEditManagerUpdateFlags; 927 FShowTabs: Boolean; 928 procedure FreeSourceWindows; 929 function GetActiveSourceWindowIndex: integer; 930 function GetSourceWindowByLastFocused(Index: Integer): TSourceEditorWindowInterface; 931 procedure SetActiveSourceWindowIndex(const AValue: integer); 932 protected 933 fProducers: TFPList; // list of TSourceMarklingProducer 934 FChangeNotifyLists: Array [TsemChangeReason] of TMethodList; 935 FHandlers: array[TSrcEditMangerHandlerType] of TMethodList; 936 FChangesQueuedForMsgWnd: TETMultiSrcChanges;// source editor changes waiting to be applied to the Messages window 937 function GetActiveSourceWindow: TSourceEditorWindowInterface; override; 938 procedure SetActiveSourceWindow(const AValue: TSourceEditorWindowInterface); override; 939 function GetSourceWindows(Index: integer): TSourceEditorWindowInterface; override; 940 procedure DoWindowFocused({%H-}AWindow: TSourceNotebook); // Includes Focus to ChildControl (aka Activated) 941 function GetActiveEditor: TSourceEditorInterface; override; 942 procedure SetActiveEditor(const AValue: TSourceEditorInterface); override; 943 procedure DoActiveEditorChanged; 944 procedure DoEditorStatusChanged(AEditor: TSourceEditor); 945 function GetSourceEditors(Index: integer): TSourceEditorInterface; override; 946 function GetUniqueSourceEditors(Index: integer): TSourceEditorInterface; override; 947 function GetMarklingProducers(Index: integer): TSourceMarklingProducer; override; 948 procedure SyncMessageWnd(Sender: TObject); 949 procedure DoWindowShow(AWindow: TSourceNotebook); 950 procedure DoWindowHide(AWindow: TSourceNotebook); 951 function GetShowTabs: Boolean; override; 952 procedure SetShowTabs(const AShowTabs: Boolean); override; 953 public 954 procedure BeginAutoFocusLock; 955 procedure EndAutoFocusLock; 956 function HasAutoFocusLock: Boolean; 957 // Windows 958 function SourceWindowWithEditor(const AEditor: TSourceEditorInterface): TSourceEditorWindowInterface; 959 override; 960 function SourceWindowCount: integer; override; 961 function IndexOfSourceWindow(AWindow: TSourceEditorWindowInterface): integer; 962 property ActiveSourceWindowIndex: integer 963 read GetActiveSourceWindowIndex write SetActiveSourceWindowIndex; 964 function IndexOfSourceWindowByLastFocused(AWindow: TSourceEditorWindowInterface): integer; 965 property SourceWindowByLastFocused[Index: Integer]: TSourceEditorWindowInterface 966 read GetSourceWindowByLastFocused; 967 // Editors 968 function SourceEditorIntfWithFilename(const Filename: string): TSourceEditorInterface; 969 override; 970 function SourceEditorCount: integer; override; 971 function UniqueSourceEditorCount: integer; override; 972 // Settings 973 function GetEditorControlSettings(EditControl: TControl): boolean; override; 974 function GetHighlighterSettings(Highlighter: TObject): boolean; override; 975 private 976 // Completion Plugins 977 FCompletionPlugins: TFPList; 978 FDefaultCompletionForm: TSourceEditCompletion; 979 FActiveCompletionPlugin: TSourceEditorCompletionPlugin; 980 function GetDefaultCompletionForm: TSourceEditCompletion; 981 procedure FreeCompletionPlugins; 982 function GetScreenRectForToken(AnEditor: TCustomSynEdit; PhysColumn, PhysRow, EndColumn: Integer): TRect; 983 protected 984 CodeToolsToSrcEditTimer: TTimer; 985 function GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; override; 986 function GetCompletionBoxPosition: integer; override; 987 function GetCompletionPlugins(Index: integer): TSourceEditorCompletionPlugin; override; 988 function GetDefaultSynCompletionForm: TCustomForm; override; 989 function GetSynCompletionLinesInWindow: integer; override; 990 procedure SetSynCompletionLinesInWindow(LineCnt: integer); override; 991 function FindIdentCompletionPlugin(SrcEdit: TSourceEditor; JumpToError: boolean; 992 var s: string; var BoxX, BoxY: integer; 993 var UseWordCompletion: boolean): boolean; 994 property DefaultCompletionForm: TSourceEditCompletion 995 read GetDefaultCompletionForm; 996 public 997 // Completion Plugins 998 function CompletionPluginCount: integer; override; 999 procedure DeactivateCompletionForm; override; 1000 procedure RegisterCompletionPlugin(Plugin: TSourceEditorCompletionPlugin); override; 1001 procedure UnregisterCompletionPlugin(Plugin: TSourceEditorCompletionPlugin); override; 1002 protected 1003 procedure Notification(AComponent: TComponent; Operation: TOperation); override; 1004 procedure IncUpdateLockInternal; 1005 procedure DecUpdateLockInternal; 1006 public 1007 constructor Create(AOwner: TComponent); override; 1008 destructor Destroy; override; 1009 procedure RegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); override; 1010 procedure UnRegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); override; 1011 procedure RegisterCopyPasteEvent(AHandler: TSemCopyPasteEvent); override; 1012 procedure UnRegisterCopyPasteEvent(AHandler: TSemCopyPasteEvent); override; 1013 // producers 1014 function MarklingProducerCount: integer; override; 1015 procedure RegisterMarklingProducer(aProducer: TSourceMarklingProducer); override; 1016 procedure UnregisterMarklingProducer(aProducer: TSourceMarklingProducer); override; 1017 procedure InvalidateMarklingsOfAllFiles(aProducer: TSourceMarklingProducer); override; 1018 procedure InvalidateMarklings(aProducer: TSourceMarklingProducer; aFilename: string); override; 1019 public 1020 procedure IncUpdateLock; 1021 procedure DecUpdateLock; 1022 procedure ShowActiveWindowOnTop(Focus: Boolean = False); override; 1023 private 1024 FMacroRecorder: TIdeEditorMacro; 1025 FOnCurrentCodeBufferChanged: TNotifyEvent; 1026 procedure DoMacroRecorderState(Sender: TObject); 1027 public 1028 // codetools 1029 property OnCurrentCodeBufferChanged: TNotifyEvent 1030 read FOnCurrentCodeBufferChanged write FOnCurrentCodeBufferChanged; 1031 end; 1032 1033 TJumpToSectionType = ( 1034 jmpInterface, jmpInterfaceUses, 1035 jmpImplementation, jmpImplementationUses, 1036 jmpInitialization); 1037 TJumpToProcedureType = (jmpHeader, jmpBegin); 1038 1039 TSourceEditorHintWindowManager = class(TIDEHintWindowManager) 1040 private 1041 FManager: TSourceEditorManager; 1042 FAutoShown: Boolean; 1043 FAutoHintMousePos: TPoint; 1044 FAutoHintTimer: TIdleTimer; 1045 FAutoHideHintTimer: TTimer; 1046 FLastHint: string; 1047 FScreenRect: TRect; 1048 1049 procedure HintTimer(Sender: TObject); 1050 procedure HideHintTimer(Sender: TObject); 1051 public 1052 procedure ActivateHint(const ScreenRect: TRect; const ABaseURL, AHint: string; 1053 AAutoShown: Boolean = True; AMouseOffset: Boolean = True); overload; 1054 procedure ActivateHint(const ScreenPos: TPoint; const ABaseURL, AHint: string; 1055 AAutoShown: Boolean = True; AMouseOffset: Boolean = True); overload; 1056 procedure HideAutoHintAfterMouseMoved; 1057 procedure HideAutoHint; 1058 procedure UpdateHintTimer; 1059 public 1060 constructor Create(AManager: TSourceEditorManager); 1061 destructor Destroy; override; 1062 public 1063 property AutoHintTimer: TIdleTimer read FAutoHintTimer; 1064 end; 1065 1066 { TSourceEditorManager } 1067 (* Reintroduce all Methods with the final types *) 1068 1069 TSourceEditorManager = class(TSourceEditorManagerBase) 1070 private 1071 procedure DoConfigureEditorToolbar(Sender: TObject); 1072 function GetActiveSourceNotebook: TSourceNotebook; 1073 function GetActiveSrcEditor: TSourceEditor; 1074 function GetSourceEditorsByPage(WindowIndex, PageIndex: integer): TSourceEditor; 1075 function GetSourceNbByLastFocused(Index: Integer): TSourceNotebook; 1076 function GetSrcEditors(Index: integer): TSourceEditor; 1077 procedure SetActiveSourceNotebook(const AValue: TSourceNotebook); 1078 function GetSourceNotebook(Index: integer): TSourceNotebook; 1079 procedure SetActiveSrcEditor(const AValue: TSourceEditor); 1080 procedure SrcEditMenuProcedureJumpGetCaption(Sender: TObject; var ACaption, 1081 {%H-}AHint: string); 1082 public 1083 // Windows 1084 function SourceWindowWithEditor(const AEditor: TSourceEditorInterface): TSourceNotebook; 1085 reintroduce; 1086 property SourceWindows[Index: integer]: TSourceNotebook read GetSourceNotebook; // reintroduce 1087 property ActiveSourceWindow: TSourceNotebook 1088 read GetActiveSourceNotebook write SetActiveSourceNotebook; // reintroduce 1089 function ActiveOrNewSourceWindow: TSourceNotebook; 1090 function NewSourceWindow: TSourceNotebook; 1091 procedure CreateSourceWindow(Sender: TObject; aFormName: string; 1092 var AForm: TCustomForm; DoDisableAutoSizing: boolean); 1093 procedure GetDefaultLayout(Sender: TObject; aFormName: string; 1094 out aBounds: TRect; out DockSibling: string; out DockAlign: TAlign); 1095 function SourceWindowWithPage(const APage: TTabSheet): TSourceNotebook; 1096 property SourceWindowByLastFocused[Index: Integer]: TSourceNotebook 1097 read GetSourceNbByLastFocused; 1098 function IndexOfSourceWindowWithID(const AnID: Integer): Integer; override; 1099 function SourceWindowWithID(const AnID: Integer): TSourceNotebook; 1100 // Editors 1101 function SourceEditorCount: integer; override; 1102 function GetActiveSE: TSourceEditor; { $note deprecate and use ActiveEditor} 1103 property ActiveEditor: TSourceEditor read GetActiveSrcEditor write SetActiveSrcEditor; // reintroduced 1104 property SourceEditors[Index: integer]: TSourceEditor read GetSrcEditors; // reintroduced 1105 property SourceEditorsByPage[WindowIndex, PageIndex: integer]: TSourceEditor 1106 read GetSourceEditorsByPage; 1107 procedure SetWindowByIDAndPage(AWindowID, APageIndex: integer); 1108 function SourceEditorIntfWithFilename(const Filename: string): TSourceEditor; reintroduce; 1109 function FindSourceEditorWithEditorComponent(EditorComp: TComponent): TSourceEditor; // With SynEdit 1110 protected 1111 procedure NewEditorCreated(AEditor: TSourceEditor); 1112 procedure EditorRemoved(AEditor: TSourceEditor); 1113 procedure SendEditorCreated(AEditor: TSourceEditor); 1114 procedure SendEditorDestroyed(AEditor: TSourceEditor); 1115 procedure Notification(AComponent: TComponent; Operation: TOperation); override; 1116 procedure RemoveWindow(AWindow: TSourceNotebook); 1117 public 1118 // Forward to all windows 1119 procedure ClearErrorLines; override; 1120 procedure ClearExecutionLines; 1121 procedure ClearExecutionMarks; 1122 procedure FillExecutionMarks; 1123 procedure ReloadEditorOptions; 1124 function Beautify(const Src: string; const Flags: TSemBeautyFlags = []): string; override; 1125 // find / replace text 1126 procedure FindClicked(Sender: TObject); 1127 procedure FindNextClicked(Sender: TObject); 1128 procedure FindPreviousClicked(Sender: TObject); 1129 procedure ReplaceClicked(Sender: TObject); 1130 procedure IncrementalFindClicked(Sender: TObject); 1131 procedure GotoLineClicked(Sender: TObject); 1132 procedure JumpBackClicked(Sender: TObject); 1133 procedure JumpForwardClicked(Sender: TObject); 1134 procedure JumpToNextErrorClicked(Sender: TObject); 1135 procedure JumpToPrevErrorClicked(Sender: TObject); 1136 procedure AddJumpPointClicked(Sender: TObject); 1137 procedure AddCustomJumpPoint(ACaretXY: TPoint; ATopLine: integer; 1138 AEditor: TSourceEditor; DeleteForwardHistory: boolean); 1139 procedure DeleteLastJumpPointClicked(Sender: TObject); 1140 procedure ViewJumpHistoryClicked(Sender: TObject); 1141 protected 1142 // Bookmarks 1143 procedure BookMarkToggleClicked(Sender: TObject); 1144 procedure BookMarkGotoClicked(Sender: TObject); 1145 public 1146 procedure BookMarkNextClicked(Sender: TObject); 1147 procedure BookMarkPrevClicked(Sender: TObject); 1148 procedure JumpToPos(FileName: string; Pos: TCodeXYPosition; TopLine: Integer); 1149 procedure JumpToPos(FileName: string; Pos: TCodeXYPosition; TopLine, BlockTopLine, BlockBottomLine: Integer); 1150 procedure JumpToSection(JumpType: TJumpToSectionType); 1151 procedure JumpToInterfaceClicked(Sender: TObject); 1152 procedure JumpToInterfaceUsesClicked(Sender: TObject); 1153 procedure JumpToImplementationClicked(Sender: TObject); 1154 procedure JumpToImplementationUsesClicked(Sender: TObject); 1155 procedure JumpToInitializationClicked(Sender: TObject); 1156 procedure JumpToProcedure(const JumpType: TJumpToProcedureType); 1157 procedure JumpToProcedureHeaderClicked(Sender: TObject); 1158 procedure JumpToProcedureBeginClicked(Sender: TObject); 1159 protected 1160 // macros 1161 function MacroFuncCol(const {%H-}s:string; const {%H-}Data: PtrInt; 1162 var {%H-}Abort: boolean): string; 1163 function MacroFuncRow(const {%H-}s:string; const {%H-}Data: PtrInt; 1164 var {%H-}Abort: boolean): string; 1165 function MacroFuncEdFile(const {%H-}s:string; const {%H-}Data: PtrInt; 1166 var {%H-}Abort: boolean): string; 1167 function MacroFuncCurToken(const {%H-}s:string; const {%H-}Data: PtrInt; 1168 var {%H-}Abort: boolean): string; 1169 function MacroFuncConfirm(const s:string; const {%H-}Data: PtrInt; 1170 var Abort: boolean): string; 1171 function MacroFuncPrompt(const s:string; const {%H-}Data: PtrInt; 1172 var Abort: boolean): string; 1173 function MacroFuncSave(const {%H-}s:string; const {%H-}Data: PtrInt; 1174 var Abort: boolean): string; 1175 function MacroFuncSaveAll(const {%H-}s:string; const {%H-}Data: PtrInt; 1176 var Abort: boolean): string; 1177 public 1178 procedure InitMacros(AMacroList: TTransferMacroList); 1179 procedure SetupShortCuts; 1180 1181 function FindUniquePageName(FileName:string; IgnoreEditor: TSourceEditor):string; 1182 function SomethingModified(Verbose: boolean = false): boolean; 1183 procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean); 1184 procedure OnUserInput(Sender: TObject; Msg: Cardinal); 1185 procedure LockAllEditorsInSourceChangeCache; 1186 procedure UnlockAllEditorsInSourceChangeCache; 1187 procedure BeginGlobalUpdate; 1188 procedure EndGlobalUpdate; 1189 procedure CloseFile(AEditor: TSourceEditorInterface); 1190 procedure HideHint; 1191 // history jumping 1192 procedure HistoryJump(Sender: TObject; JumpAction: TJumpHistoryAction); 1193 private 1194 // Hints 1195 FHints: TSourceEditorHintWindowManager; 1196 procedure ActivateHint(const ScreenRect: TRect; const BaseURL, TheHint: string; 1197 AutoShown: Boolean = True; AMouseOffset: Boolean = True); overload; 1198 procedure ActivateHint(const ScreenPos: TPoint; const BaseURL, TheHint: string; 1199 AutoShown: Boolean = True; AMouseOffset: Boolean = True); overload; 1200 private 1201 FCodeTemplateModul: TSynEditAutoComplete; 1202 FGotoDialog: TfrmGoto; 1203 procedure OnCodeTemplateTokenNotFound(Sender: TObject; AToken: string; 1204 AnEditor: TCustomSynEdit; var Index:integer); 1205 procedure OnCodeTemplateExecuteCompletion( 1206 ASynAutoComplete: TCustomSynAutoComplete; 1207 Index: integer); 1208 protected 1209 procedure CodeToolsToSrcEditTimerTimer(Sender: TObject); 1210 procedure OnSourceCompletionTimer(Sender: TObject); 1211 // marks 1212 procedure OnSourceMarksAction(AMark: TSourceMark; {%H-}AAction: TMarksAction); 1213 procedure OnSourceMarksGetSynEdit(Sender: TObject; aFilename: string; 1214 var aSynEdit: TSynEdit); 1215 // goto dialog 1216 function GotoDialog: TfrmGoto; 1217 public 1218 constructor Create(AOwner: TComponent); override; 1219 destructor Destroy; override; 1220 function CreateNewWindow(Activate: Boolean= False; 1221 DoDisableAutoSizing: boolean = False; 1222 AnID: Integer = -1 1223 ): TSourceNotebook; 1224 function SenderToEditor(Sender: TObject): TSourceEditor; 1225 property CodeTemplateModul: TSynEditAutoComplete 1226 read FCodeTemplateModul write FCodeTemplateModul; 1227 private 1228 // Context-Menu 1229 procedure CloseOtherPagesClicked(Sender: TObject); 1230 procedure CloseOtherPagesClickedAsync(Sender: PtrInt); 1231 procedure CloseRightPagesClicked(Sender: TObject); 1232 procedure CloseRightPagesClickedAsync(Sender: PtrInt); 1233 procedure ReadOnlyClicked(Sender: TObject); 1234 procedure ToggleLineNumbersClicked(Sender: TObject); 1235 procedure ToggleI18NForLFMClicked(Sender: TObject); 1236 procedure ShowUnitInfo(Sender: TObject); 1237 procedure CopyFilenameClicked(Sender: TObject); 1238 procedure EditorPropertiesClicked(Sender: TObject); 1239 private 1240 FOnAddJumpPoint: TOnAddJumpPoint; 1241 FOnClearBookmark: TPlaceBookMarkEvent; 1242 FOnClearBookmarkId: TPlaceBookMarkIdEvent; 1243 FOnClickLink: TMouseEvent; 1244 FOnCloseClicked: TOnCloseSrcEditor; 1245 FOnDeleteLastJumpPoint: TNotifyEvent; 1246 FOnUpdateProjectFile: TUpdateProjectFileEvent; 1247 FOnFindDeclarationClicked: TNotifyEvent; 1248 FOnGetIndent: TOnGetIndentEvent; 1249 FOnGotoBookmark: TBookMarkActionEvent; 1250 FOnInitIdentCompletion: TOnInitIdentCompletion; 1251 FOnJumpToHistoryPoint: TOnJumpToHistoryPoint; 1252 FOnMouseLink: TSynMouseLinkEvent; 1253 FOnNoteBookCloseQuery: TCloseEvent; 1254 FOnOpenFileAtCursorClicked: TNotifyEvent; 1255 FOnPackageForSourceEditor: TPackageForSourceEditorEvent; 1256 FOnPlaceMark: TPlaceBookMarkEvent; 1257 FOnPopupMenu: TSrcEditPopupMenuEvent; 1258 FOnProcessUserCommand: TOnProcessUserCommand; 1259 fOnReadOnlyChanged: TNotifyEvent; 1260 FOnSetBookmark: TBookMarkActionEvent; 1261 FOnShowCodeContext: TOnShowCodeContext; 1262 FOnShowHintForSource: TOnShowHintForSource; 1263 FOnShowUnitInfo: TNotifyEvent; 1264 FOnToggleFormUnitClicked: TNotifyEvent; 1265 FOnToggleObjectInspClicked: TNotifyEvent; 1266 FOnUserCommandProcessed: TOnUserCommandProcessed; 1267 FOnViewJumpHistory: TNotifyEvent; 1268 public 1269 property OnAddJumpPoint: TOnAddJumpPoint 1270 read FOnAddJumpPoint write FOnAddJumpPoint; 1271 property OnCloseClicked: TOnCloseSrcEditor 1272 read FOnCloseClicked write FOnCloseClicked; 1273 property OnClickLink: TMouseEvent read FOnClickLink write FOnClickLink; 1274 property OnMouseLink: TSynMouseLinkEvent read FOnMouseLink write FOnMouseLink; 1275 property OnGetIndent: TOnGetIndentEvent 1276 read FOnGetIndent write FOnGetIndent; 1277 property OnDeleteLastJumpPoint: TNotifyEvent 1278 read FOnDeleteLastJumpPoint write FOnDeleteLastJumpPoint; 1279 property OnUpdateProjectFile: TUpdateProjectFileEvent 1280 read FOnUpdateProjectFile write FOnUpdateProjectFile; 1281 property OnFindDeclarationClicked: TNotifyEvent 1282 read FOnFindDeclarationClicked write FOnFindDeclarationClicked; 1283 property OnInitIdentCompletion: TOnInitIdentCompletion 1284 read FOnInitIdentCompletion write FOnInitIdentCompletion; 1285 property OnShowCodeContext: TOnShowCodeContext 1286 read FOnShowCodeContext write FOnShowCodeContext; 1287 property OnJumpToHistoryPoint: TOnJumpToHistoryPoint 1288 read FOnJumpToHistoryPoint write FOnJumpToHistoryPoint; 1289 property OnPlaceBookmark: TPlaceBookMarkEvent // Bookmark was placed by SynEdit 1290 read FOnPlaceMark write FOnPlaceMark; 1291 property OnClearBookmark: TPlaceBookMarkEvent // Bookmark was cleared by SynEdit 1292 read FOnClearBookmark write FOnClearBookmark; 1293 property OnClearBookmarkId: TPlaceBookMarkIdEvent 1294 read FOnClearBookmarkId write FOnClearBookmarkId; 1295 property OnSetBookmark: TBookMarkActionEvent // request to set a Bookmark 1296 read FOnSetBookmark write FOnSetBookmark; 1297 property OnGotoBookmark: TBookMarkActionEvent // request to go to a Bookmark 1298 read FOnGotoBookmark write FOnGotoBookmark; 1299 property OnOpenFileAtCursorClicked: TNotifyEvent 1300 read FOnOpenFileAtCursorClicked write FOnOpenFileAtCursorClicked; 1301 property OnProcessUserCommand: TOnProcessUserCommand 1302 read FOnProcessUserCommand write FOnProcessUserCommand; 1303 property OnUserCommandProcessed: TOnUserCommandProcessed 1304 read FOnUserCommandProcessed write FOnUserCommandProcessed; 1305 property OnReadOnlyChanged: TNotifyEvent 1306 read fOnReadOnlyChanged write fOnReadOnlyChanged; 1307 property OnShowHintForSource: TOnShowHintForSource 1308 read FOnShowHintForSource write FOnShowHintForSource; 1309 property OnShowUnitInfo: TNotifyEvent 1310 read FOnShowUnitInfo write FOnShowUnitInfo; 1311 property OnToggleFormUnitClicked: TNotifyEvent 1312 read FOnToggleFormUnitClicked write FOnToggleFormUnitClicked; 1313 property OnToggleObjectInspClicked: TNotifyEvent 1314 read FOnToggleObjectInspClicked write FOnToggleObjectInspClicked; 1315 property OnViewJumpHistory: TNotifyEvent 1316 read FOnViewJumpHistory write FOnViewJumpHistory; 1317 property OnPopupMenu: TSrcEditPopupMenuEvent read FOnPopupMenu write FOnPopupMenu; 1318 property OnNoteBookCloseQuery: TCloseEvent 1319 read FOnNoteBookCloseQuery write FOnNoteBookCloseQuery; 1320 property OnPackageForSourceEditor: TPackageForSourceEditorEvent 1321 read FOnPackageForSourceEditor write FOnPackageForSourceEditor; 1322 end; 1323 1324 TSourceEditorWordCompletion = class(TWordCompletion) 1325 private type 1326 TSourceListItem = class 1327 Source: TStrings; 1328 IgnoreWordPos: TPoint; 1329 end; 1330 private 1331 FIncludeWords: TIdentComplIncludeWords; 1332 FSourceList: TObjectList; 1333 procedure ReloadSourceList; 1334 protected 1335 procedure DoGetSource(var Source: TStrings; var {%H-}TopLine, 1336 {%H-}BottomLine: Integer; var IgnoreWordPos: TPoint; SourceIndex: integer); override; 1337 public 1338 constructor Create; 1339 destructor Destroy; override; 1340 public 1341 property IncludeWords: TIdentComplIncludeWords read FIncludeWords write FIncludeWords; 1342 end; 1343 1344function SourceEditorManager: TSourceEditorManager; inline; 1345 1346 1347 //============================================================================= 1348 1349const 1350 SourceTabMenuRootName = 'SourceTab'; 1351 SourceEditorMenuRootName = 'SourceEditor'; 1352 1353var 1354 // Clipboard 1355 SrcEditMenuCut: TIDEMenuCommand; 1356 SrcEditMenuCopy: TIDEMenuCommand; 1357 SrcEditMenuPaste: TIDEMenuCommand; 1358 SrcEditMenuMultiPaste: TIDEMenuCommand; 1359 SrcEditMenuCopyFilename: TIDEMenuCommand; 1360 SrcEditMenuFindDeclaration: TIDEMenuCommand; 1361 SrcEditMenuSelectAll: TIDEMenuCommand; 1362 // finding / jumping 1363 SrcEditMenuProcedureJump: TIDEMenuCommand; 1364 SrcEditMenuFindNextWordOccurrence: TIDEMenuCommand; 1365 SrcEditMenuFindPrevWordOccurrence: TIDEMenuCommand; 1366 SrcEditMenuFindinFiles: TIDEMenuCommand; 1367 SrcEditMenuFindIdentifierReferences: TIDEMenuCommand; 1368 SrcEditMenuFindUsedUnitReferences: TIDEMenuCommand; 1369 // open file 1370 SrcEditMenuOpenFileAtCursor: TIDEMenuCommand; 1371 SrcEditMenuClosePage: TIDEMenuCommand; 1372 SrcEditMenuCloseOtherPages: TIDEMenuCommand; 1373 SrcEditMenuCloseOtherPagesToRight: TIDEMenuCommand; 1374 // bookmarks 1375 SrcEditMenuNextBookmark: TIDEMenuCommand; 1376 SrcEditMenuPrevBookmark: TIDEMenuCommand; 1377 SrcEditMenuSetFreeBookmark: TIDEMenuCommand; 1378 SrcEditMenuClearFileBookmark: TIDEMenuCommand; 1379 SrcEditMenuClearAllBookmark: TIDEMenuCommand; 1380 SrcEditMenuGotoBookmark: array [TBookmarkNumRange] of TIDEMenuCommand; 1381 SrcEditMenuToggleBookmark: array [TBookmarkNumRange] of TIDEMenuCommand; 1382 // debugging 1383 SrcEditMenuToggleBreakpoint: TIDEMenuCommand; 1384 SrcEditMenuStepToCursor: TIDEMenuCommand; 1385 SrcEditMenuRunToCursor: TIDEMenuCommand; 1386 SrcEditMenuEvaluateModify: TIDEMenuCommand; 1387 SrcEditMenuAddWatchAtCursor: TIDEMenuCommand; 1388 SrcEditMenuAddWatchPointAtCursor: TIDEMenuCommand; 1389 SrcEditMenuInspect: TIDEMenuCommand; 1390 SrcEditMenuViewCallStack: TIDEMenuCommand; 1391 // source 1392 SrcEditMenuEncloseSelection: TIDEMenuCommand; 1393 SrcEditMenuEncloseInIFDEF: TIDEMenuCommand; 1394 SrcEditMenuCompleteCode: TIDEMenuCommand; 1395 SrcEditMenuUseUnit: TIDEMenuCommand; 1396 SrcEditMenuShowUnitInfo: TIDEMenuCommand; 1397 // refactoring 1398 SrcEditMenuRenameIdentifier: TIDEMenuCommand; 1399 SrcEditMenuExtractProc: TIDEMenuCommand; 1400 SrcEditMenuInvertAssignment: TIDEMenuCommand; 1401 SrcEditMenuShowAbstractMethods: TIDEMenuCommand; 1402 SrcEditMenuShowEmptyMethods: TIDEMenuCommand; 1403 SrcEditMenuShowUnusedUnits: TIDEMenuCommand; 1404 SrcEditMenuFindOverloads: TIDEMenuCommand; 1405 SrcEditMenuMakeResourceString: TIDEMenuCommand; 1406 SrcEditMenuMoveEditorLeft: TIDEMenuCommand; 1407 SrcEditMenuMoveEditorRight: TIDEMenuCommand; 1408 SrcEditMenuMoveEditorFirst: TIDEMenuCommand; 1409 SrcEditMenuMoveEditorLast: TIDEMenuCommand; 1410 SrcEditMenuReadOnly: TIDEMenuCommand; 1411 SrcEditMenuShowLineNumbers: TIDEMenuCommand; 1412 SrcEditMenuDisableI18NForLFM: TIDEMenuCommand; 1413 SrcEditMenuEditorProperties: TIDEMenuCommand; 1414 {$IFnDEF SingleSrcWindow} 1415 // Multi Window 1416 SrcEditMenuMoveToNewWindow: TIDEMenuCommand; 1417 SrcEditMenuMoveToOtherWindow: TIDEMenuSection; 1418 SrcEditMenuMoveToOtherWindowNew: TIDEMenuCommand; 1419 SrcEditMenuMoveToOtherWindowList: TIDEMenuSection; 1420 SrcEditMenuCopyToNewWindow: TIDEMenuCommand; 1421 SrcEditMenuCopyToOtherWindow: TIDEMenuSection; 1422 SrcEditMenuCopyToOtherWindowNew: TIDEMenuCommand; 1423 SrcEditMenuCopyToOtherWindowList: TIDEMenuSection; 1424 SrcEditMenuFindInOtherWindow: TIDEMenuSection; 1425 SrcEditMenuFindInOtherWindowList: TIDEMenuSection; 1426 // EditorLocks 1427 SrcEditMenuEditorLock: TIDEMenuCommand; 1428 {$ENDIF} 1429 1430 1431function GetIdeCmdAndToolBtn(ACommand: word; out ToolButton: TIDEButtonCommand): TIDECommand; 1432function GetIdeCmdRegToolBtn(ACommand: word): TIDECommand; 1433procedure RegisterStandardSourceTabMenuItems; 1434procedure RegisterStandardSourceEditorMenuItems; 1435function dbgSourceNoteBook(snb: TSourceNotebook): string; 1436function CompareSrcEditIntfWithFilename(SrcEdit1, SrcEdit2: Pointer): integer; 1437function CompareFilenameWithSrcEditIntf(FilenameStr, SrcEdit: Pointer): integer; 1438 1439var 1440 Highlighters: array[TLazSyntaxHighlighter] of TSynCustomHighlighter; 1441 EnglishGPLNotice: string; 1442 EnglishLGPLNotice: string; 1443 EnglishModifiedLGPLNotice: string; 1444 EnglishMITNotice: string; 1445 1446 1447implementation 1448 1449{$R *.lfm} 1450{$R ../images/bookmark.res} 1451 1452var 1453 AWordCompletion: TWordCompletion = nil; 1454 1455var 1456 SRCED_LOCK, SRCED_OPEN, SRCED_CLOSE, SRCED_PAGES: PLazLoggerLogGroup; 1457 1458const 1459 (* SoftCenter are the visible Lines in the Editor where the caret can be located, 1460 without CenterCursor adjusting the topline. 1461 SoftCenter is defined by the amount of lines on the top/bottom of the editor, 1462 which are *not* part of it. 1463 *) 1464 SoftCenterFactor = 5; // One fifth of the "LinesInWindow"on each side (top/bottom) 1465 SoftCenterMinimum = 1; 1466 SoftCenterMaximum = 8; 1467 1468var 1469 AutoStartCompletionBoxTimer: TIdleTimer = nil; 1470 SourceCompletionCaretXY: TPoint; 1471 PasBeautifier: TSynBeautifierPascal; 1472 1473function dbgs(AFlag: TSourceNotebookUpdateFlag): string; overload; 1474begin 1475 WriteStr(Result, AFlag); 1476end; 1477 1478function dbgs(AFlags: TSourceNotebookUpdateFlags): string; overload; 1479var 1480 i: TSourceNotebookUpdateFlag; 1481begin 1482 Result := ''; 1483 for i := low(TSourceNotebookUpdateFlags) to high(TSourceNotebookUpdateFlags) do 1484 if i in AFlags then begin 1485 if Result <> '' then Result := Result + ','; 1486 Result := Result + dbgs(i); 1487 end; 1488 Result := '['+ Result + ']'; 1489end; 1490 1491function GetIdeCmdAndToolBtn(ACommand: word; out ToolButton: TIDEButtonCommand): TIDECommand; 1492// Find and return IDECommand. 1493// Register IDEButtonCommand for it, also returned in out param. 1494begin 1495 Result:=IDECommandList.FindIDECommand(ACommand); 1496 if Result<>nil then 1497 ToolButton := RegisterIDEButtonCommand(Result) 1498 else 1499 ToolButton := nil; 1500end; 1501 1502function GetIdeCmdRegToolBtn(ACommand: word): TIDECommand; 1503// Find and return IDECommand. Register IDEButtonCommand for it. 1504begin 1505 Result:=IDECommandList.FindIDECommand(ACommand); 1506 if Result<>nil then 1507 RegisterIDEButtonCommand(Result); 1508end; 1509 1510function SourceEditorManager: TSourceEditorManager; 1511begin 1512 Result := TSourceEditorManager(SourceEditorManagerIntf); 1513end; 1514 1515procedure ExecuteIdeMenuClick(Sender: TObject); 1516var 1517 ActEdit: TSourceEditor; 1518 r: Boolean; 1519begin 1520 if SourceEditorManager = nil then exit; 1521 if not (Sender is TIDESpecialCommand) then exit; 1522 if TIDESpecialCommand(Sender).Command = nil then exit; 1523 ActEdit := SourceEditorManager.ActiveEditor; 1524 if ActEdit = nil then 1525 begin 1526 TIDESpecialCommand(Sender).Command.Execute(Sender); 1527 exit; 1528 end; 1529 r := TIDESpecialCommand(Sender).Command.OnExecuteProc = @ExecuteIdeMenuClick; 1530 if r then 1531 TIDESpecialCommand(Sender).Command.OnExecuteProc := nil; 1532 // Commands may not work without focusing when anchordocking is installed 1533 ActEdit.FocusEditor; 1534 ActEdit.DoEditorExecuteCommand(TIDESpecialCommand(Sender).Command.Command); 1535 if r then 1536 TIDESpecialCommand(Sender).Command.OnExecuteProc := @ExecuteIdeMenuClick; 1537end; 1538 1539procedure RegisterStandardSourceTabMenuItems; 1540var 1541 AParent: TIDEMenuSection; 1542begin 1543 SourceTabMenuRoot:=RegisterIDEMenuRoot(SourceTabMenuRootName); 1544 1545 {%region *** Pages section ***} 1546 SrcEditMenuSectionPages:=RegisterIDEMenuSection(SourceTabMenuRoot, 'Pages'); 1547 AParent:=SrcEditMenuSectionPages; 1548 1549 SrcEditMenuClosePage := RegisterIDEMenuCommand(AParent, 1550 'Close Page', uemClosePage, nil, @ExecuteIdeMenuClick, nil, 'menu_close'); 1551 SrcEditMenuCloseOtherPages := RegisterIDEMenuCommand(AParent, 1552 'Close All Other Pages',uemCloseOtherPages, nil, @ExecuteIdeMenuClick); 1553 SrcEditMenuCloseOtherPagesToRight := RegisterIDEMenuCommand(AParent, 1554 'Close Pages To the Right',uemCloseOtherPagesRight, nil, @ExecuteIdeMenuClick); 1555 1556 {$IFnDEF SingleSrcWindow} 1557 // Lock Editor 1558 SrcEditMenuEditorLock := RegisterIDEMenuCommand(AParent, 1559 'LockEditor', uemLockPage, nil, @ExecuteIdeMenuClick); 1560 SrcEditMenuEditorLock.ShowAlwaysCheckable := True; 1561 // Move to other Window 1562 SrcEditMenuMoveToNewWindow := RegisterIDEMenuCommand(AParent, 1563 'MoveToNewWindow', uemMoveToNewWindow, nil, @ExecuteIdeMenuClick); 1564 1565 {%region * Move To Other *} 1566 SrcEditMenuMoveToOtherWindow := RegisterIDESubMenu(AParent, 1567 'MoveToOtherWindow', uemMoveToOtherWindow); 1568 SrcEditMenuMoveToOtherWindowNew := RegisterIDEMenuCommand(SrcEditMenuMoveToOtherWindow, 1569 'MoveToOtherWindowNew', uemMoveToOtherWindowNew, nil, @ExecuteIdeMenuClick); 1570 // Section for dynamically created targets 1571 SrcEditMenuMoveToOtherWindowList := RegisterIDEMenuSection(SrcEditMenuMoveToOtherWindow, 1572 'MoveToOtherWindowList Section'); 1573 {%endregion} 1574 1575 SrcEditMenuCopyToNewWindow := RegisterIDEMenuCommand(AParent, 1576 'CopyToNewWindow', uemCopyToNewWindow, nil, @ExecuteIdeMenuClick); 1577 1578 {%region * Copy To Other *} 1579 SrcEditMenuCopyToOtherWindow := RegisterIDESubMenu(AParent, 1580 'CopyToOtherWindow', uemCopyToOtherWindow); 1581 SrcEditMenuCopyToOtherWindowNew := RegisterIDEMenuCommand(SrcEditMenuCopyToOtherWindow, 1582 'CopyToOtherWindowNew', uemCopyToOtherWindowNew, nil, @ExecuteIdeMenuClick); 1583 // Section for dynamically created targets 1584 SrcEditMenuCopyToOtherWindowList := RegisterIDEMenuSection(SrcEditMenuCopyToOtherWindow, 1585 'CopyToOtherWindowList Section'); 1586 {%endregion} 1587 1588 SrcEditMenuFindInOtherWindow := RegisterIDESubMenu(AParent, 1589 'FindInOtherWindow', uemFindInOtherWindow); 1590 // Section for dynamically created targets 1591 SrcEditMenuFindInOtherWindowList := RegisterIDEMenuSection(SrcEditMenuFindInOtherWindow, 1592 'FindInOtherWindowList Section'); 1593 {$ENDIF} 1594 1595 {%region * Move Page (left/right) *} 1596 SrcEditSubMenuMovePage:=RegisterIDESubMenu(AParent, 'Move Page', lisMovePage); 1597 AParent:=SrcEditSubMenuMovePage; 1598 1599 SrcEditMenuMoveEditorLeft := RegisterIDEMenuCommand(AParent, 1600 'MoveEditorLeft', uemMovePageLeft, nil, @ExecuteIdeMenuClick); 1601 SrcEditMenuMoveEditorRight := RegisterIDEMenuCommand(AParent, 1602 'MoveEditorRight', uemMovePageRight, nil, @ExecuteIdeMenuClick); 1603 SrcEditMenuMoveEditorFirst := RegisterIDEMenuCommand(AParent, 1604 'MoveEditorLeftmost', uemMovePageLeftmost, nil, @ExecuteIdeMenuClick); 1605 SrcEditMenuMoveEditorLast := RegisterIDEMenuCommand(AParent, 1606 'MoveEditorRightmost', uemMovePageRightmost, nil, @ExecuteIdeMenuClick); 1607 {%endregion} 1608 {%endregion} 1609 1610 {%region *** Editors section ***} 1611 SrcEditMenuSectionEditors:=RegisterIDEMenuSection(SourceTabMenuRoot, 'Editors'); 1612 {%endregion} 1613end; 1614 1615procedure RegisterStandardSourceEditorMenuItems; 1616var 1617 AParent: TIDEMenuSection; 1618 I: Integer; 1619begin 1620 SourceEditorMenuRoot:=RegisterIDEMenuRoot(SourceEditorMenuRootName); 1621 AParent:=SourceEditorMenuRoot; 1622 1623 // register the first dynamic section for often used context sensitive stuff 1624 SrcEditMenuSectionFirstDynamic:=RegisterIDEMenuSection(SourceEditorMenuRoot, 'First dynamic section'); 1625 1626 // Felipe: Please keep "Find Declaration" as the first item 1627 {%region *** first static section *** } 1628 SrcEditMenuSectionFirstStatic:=RegisterIDEMenuSection(SourceEditorMenuRoot, 'First static section'); 1629 AParent:=SrcEditMenuSectionFirstStatic; 1630 1631 SrcEditMenuFindDeclaration := RegisterIDEMenuCommand 1632 (AParent, 'Find Declaration', uemFindDeclaration, nil, @ExecuteIdeMenuClick); 1633 1634 {%region *** Submenu: Find Section *** } 1635 SrcEditSubMenuFind := RegisterIDESubMenu(AParent, 1636 'Find section', lisMenuFind, nil, nil, 'menu_search_find'); 1637 AParent:=SrcEditSubMenuFind; 1638 1639 SrcEditMenuProcedureJump := RegisterIDEMenuCommand(AParent, 1640 'Procedure Jump', uemProcedureJump, nil, 1641 @ExecuteIdeMenuClick); 1642 SrcEditMenuFindNextWordOccurrence := RegisterIDEMenuCommand(AParent, 1643 'Find next word occurrence', srkmecFindNextWordOccurrence, nil, 1644 @ExecuteIdeMenuClick, nil, 'next_word'); 1645 SrcEditMenuFindPrevWordOccurrence := RegisterIDEMenuCommand(AParent, 1646 'Find previous word occurrence', srkmecFindPrevWordOccurrence, nil, 1647 @ExecuteIdeMenuClick, nil, 'previous_word'); 1648 SrcEditMenuFindInFiles := RegisterIDEMenuCommand(AParent, 1649 'Find in files', srkmecFindInFiles + ' ...', nil, 1650 @ExecuteIdeMenuClick, nil, 'menu_search_files'); 1651 SrcEditMenuFindIdentifierReferences := RegisterIDEMenuCommand(AParent, 1652 'FindIdentifierReferences',lisMenuFindIdentifierRefs, nil, 1653 @ExecuteIdeMenuClick); 1654 SrcEditMenuFindUsedUnitReferences := RegisterIDEMenuCommand(AParent, 1655 'FindUsedUnitReferences', lisMenuFindReferencesOfUsedUnit, nil, 1656 @ExecuteIdeMenuClick); 1657 {%endregion} 1658 {%endregion} 1659 1660 {%region *** Clipboard section ***} 1661 SrcEditMenuSectionClipboard:=RegisterIDEMenuSection(SourceEditorMenuRoot, 'Clipboard'); 1662 AParent:=SrcEditMenuSectionClipboard; 1663 1664 SrcEditMenuCut:=RegisterIDEMenuCommand(AParent,'Cut',lisCut, nil, nil, nil, 'laz_cut'); 1665 SrcEditMenuCopy:=RegisterIDEMenuCommand(AParent,'Copy',lisCopy, nil, nil, nil, 'laz_copy'); 1666 SrcEditMenuPaste:=RegisterIDEMenuCommand(AParent,'Paste',lisPaste, nil, nil, nil, 'laz_paste'); 1667 SrcEditMenuMultiPaste:=RegisterIDEMenuCommand(AParent,'MultiPaste',lisMenuMultiPaste); 1668 SrcEditMenuSelectAll:=RegisterIDEMenuCommand(AParent,'SelectAll',lisMenuSelectAll); 1669 SrcEditMenuCopyFilename:=RegisterIDEMenuCommand(AParent,'Copy filename', uemCopyFilename); 1670 {%endregion} 1671 1672 {%region *** Files section ***} 1673 SrcEditMenuSectionFiles:=RegisterIDEMenuSection(SourceEditorMenuRoot, 'Files'); 1674 1675 {%region * sub menu Open File *} 1676 SrcEditSubMenuOpenFile:=RegisterIDESubMenu(SrcEditMenuSectionFiles, 1677 'Open File',lisOpenFile, nil, nil, 'laz_open'); 1678 AParent:=SrcEditSubMenuOpenFile; 1679 1680 SrcEditMenuOpenFileAtCursor:=RegisterIDEMenuCommand(AParent, 'Open File At Cursor', 1681 uemOpenFileAtCursor, nil, @ExecuteIdeMenuClick, nil, 'menu_search_openfile_atcursor'); 1682 // register the File Specific dynamic section 1683 SrcEditMenuSectionFileDynamic:=RegisterIDEMenuSection(AParent, 'File dynamic section'); 1684 {%endregion} 1685 1686 {%region * sub menu Flags section *} 1687 SrcEditSubMenuFlags:=RegisterIDESubMenu(SrcEditMenuSectionFiles,'Flags section',lisFileSettings); 1688 AParent:=SrcEditSubMenuFlags; 1689 1690 SrcEditMenuReadOnly := RegisterIDEMenuCommand(AParent,'ReadOnly',uemReadOnly); 1691 SrcEditMenuReadOnly.ShowAlwaysCheckable:=true; 1692 SrcEditMenuShowLineNumbers := RegisterIDEMenuCommand(AParent, 'ShowLineNumbers',uemShowLineNumbers); 1693 SrcEditMenuShowLineNumbers.ShowAlwaysCheckable:=true; 1694 SrcEditMenuDisableI18NForLFM := RegisterIDEMenuCommand(AParent, 'DisableI18NForLFM',lisDisableI18NForLFM); 1695 SrcEditSubMenuHighlighter := RegisterIDESubMenu(AParent,'Highlighter', uemHighlighter); 1696 SrcEditSubMenuEncoding := RegisterIDESubMenu(AParent,'Encoding', uemEncoding); 1697 SrcEditSubMenuLineEnding := RegisterIDESubMenu(AParent,'LineEnding', uemLineEnding); 1698 {%endregion} 1699 {%endregion} 1700 1701 {%region *** Goto Marks section ***} 1702 SrcEditMenuSectionMarks:=RegisterIDEMenuSection(SourceEditorMenuRoot, 'Marks section'); 1703 // register the Goto Bookmarks Submenu 1704 SrcEditSubMenuGotoBookmarks:=RegisterIDESubMenu(SrcEditMenuSectionMarks, 1705 'Goto bookmarks submenu', uemGotoBookmark, nil, nil, 'menu_goto_bookmarks'); 1706 AParent:=SrcEditSubMenuGotoBookmarks; 1707 for I in TBookmarkNumRange do 1708 SrcEditMenuGotoBookmark[I]:=RegisterIDEMenuCommand(AParent, 1709 'GotoBookmark'+IntToStr(I), Format(uemBookmarkNUnSet, [IntToStr(I)]), 1710 nil, @ExecuteIdeMenuClick, nil, 1711 'menu_goto_bookmark'+IntToStr(I)); 1712 1713 AParent:=RegisterIDEMenuSection(AParent, 'Next/Prev Bookmark section'); 1714 SrcEditMenuNextBookmark:=RegisterIDEMenuCommand(AParent, 1715 'Goto next Bookmark',uemNextBookmark, nil, 1716 @ExecuteIdeMenuClick, nil, 'menu_search_next_bookmark'); 1717 SrcEditMenuPrevBookmark:=RegisterIDEMenuCommand(AParent, 1718 'Goto previous Bookmark',uemPrevBookmark, nil, 1719 @ExecuteIdeMenuClick, nil, 'menu_search_previous_bookmark'); 1720 {%endregion} 1721 1722 {%region *** Toggle Bookmarks Submenu ***} 1723 SrcEditSubMenuToggleBookmarks:=RegisterIDESubMenu(SrcEditMenuSectionMarks, 1724 'Toggle bookmarks submenu', uemToggleBookmark, nil, nil, 'menu_toggle_bookmarks'); 1725 AParent:=SrcEditSubMenuToggleBookmarks; 1726 for I in TBookmarkNumRange do 1727 SrcEditMenuToggleBookmark[I]:=RegisterIDEMenuCommand(AParent, 1728 'ToggleBookmark'+IntToStr(I), Format(uemToggleBookmarkNUnset, [IntToStr(I)]), 1729 nil, @ExecuteIdeMenuClick, nil, 1730 'menu_toggle_bookmark'+IntToStr(I)); 1731 1732 AParent:=RegisterIDEMenuSection(AParent, 'Set Free Bookmark section'); 1733 SrcEditMenuSetFreeBookmark:=RegisterIDEMenuCommand(AParent, 1734 'Set a free Bookmark',uemSetFreeBookmark, nil, @ExecuteIdeMenuClick, nil, 'menu_set_free_bookmark'); 1735 1736 AParent:=RegisterIDEMenuSection(AParent, 'Clear Bookmarks section'); 1737 SrcEditMenuClearFileBookmark:=RegisterIDEMenuCommand(AParent, 1738 'Clear Bookmark for current file',srkmecClearBookmarkForFile, nil, @ExecuteIdeMenuClick, nil, 'menu_clear_file_bookmarks'); 1739 SrcEditMenuClearAllBookmark:=RegisterIDEMenuCommand(AParent, 1740 'Clear all Bookmark',srkmecClearAllBookmark, nil, @ExecuteIdeMenuClick, nil, 'menu_clear_all_bookmarks'); 1741 {%endregion} 1742 1743 {%region *** Debug Section ***} 1744 // Commands will be assigned by DebugManager 1745 SrcEditMenuSectionDebug:=RegisterIDEMenuSection(SourceEditorMenuRoot, 'Debug section'); 1746 // register the Debug submenu 1747 SrcEditSubMenuDebug:=RegisterIDESubMenu(SrcEditMenuSectionDebug, 1748 'Debug', uemDebugWord, nil, nil, 'debugger'); 1749 AParent:=SrcEditSubMenuDebug; 1750 1751 // register the Debug submenu items 1752 SrcEditMenuToggleBreakpoint:=RegisterIDEMenuCommand(AParent, 1753 'Toggle Breakpoint', uemToggleBreakpoint, nil, @ExecuteIdeMenuClick); 1754 SrcEditMenuEvaluateModify:=RegisterIDEMenuCommand(AParent, 1755 'Evaluate/Modify...', uemEvaluateModify, nil, nil, nil, 'debugger_modify'); 1756 SrcEditMenuEvaluateModify.Enabled:=False; 1757 SrcEditMenuAddWatchAtCursor:=RegisterIDEMenuCommand(AParent, 1758 'Add Watch at Cursor', uemAddWatchAtCursor); 1759 SrcEditMenuAddWatchPointAtCursor:=RegisterIDEMenuCommand(AParent, 1760 'Add Watch at Cursor', uemAddWatchPointAtCursor); 1761 SrcEditMenuInspect:=RegisterIDEMenuCommand(AParent, 1762 'Inspect...', uemInspect, nil, nil, nil, 'debugger_inspect'); 1763 SrcEditMenuInspect.Enabled:=False; 1764 SrcEditMenuStepToCursor:=RegisterIDEMenuCommand(AParent, 1765 'Run to cursor', lisMenuStepToCursor, nil, nil, nil, 'menu_step_cursor'); 1766 SrcEditMenuRunToCursor:=RegisterIDEMenuCommand(AParent, 1767 'Run to cursor', lisMenuRunToCursor, nil, nil, nil, 'menu_run_cursor'); 1768 SrcEditMenuViewCallStack:=RegisterIDEMenuCommand(AParent, 1769 'View Call Stack', uemViewCallStack, nil, @ExecuteIdeMenuClick, nil, 'debugger_call_stack'); 1770 {%endregion} 1771 1772 {%region *** Source Section ***} 1773 SrcEditSubMenuSource := RegisterIDESubMenu(SourceEditorMenuRoot, 1774 'Source', uemSource, nil, nil, 'item_unit'); 1775 AParent:=SrcEditSubMenuSource; 1776 SrcEditMenuEncloseSelection := RegisterIDEMenuCommand(AParent, 1777 'EncloseSelection', lisMenuEncloseSelection); 1778 SrcEditMenuEncloseInIFDEF := RegisterIDEMenuCommand(AParent, 1779 'itmSourceEncloseInIFDEF', lisMenuEncloseInIFDEF); 1780 SrcEditMenuCompleteCode := RegisterIDEMenuCommand(AParent, 1781 'CompleteCode', lisMenuCompleteCode, nil, @ExecuteIdeMenuClick); 1782 SrcEditMenuInvertAssignment := RegisterIDEMenuCommand(AParent, 1783 'InvertAssignment', uemInvertAssignment, nil, @ExecuteIdeMenuClick); 1784 SrcEditMenuUseUnit := RegisterIDEMenuCommand(AParent, 1785 'UseUnit', lisMenuUseUnit, nil, @ExecuteIdeMenuClick); 1786 SrcEditMenuShowUnitInfo := RegisterIDEMenuCommand(AParent, 1787 'ShowUnitInfo', lisMenuViewUnitInfo , nil, nil, nil, 'menu_view_unit_info'); 1788 {%endregion} 1789 1790 {%region *** Refactoring Section ***} 1791 SrcEditSubMenuRefactor:=RegisterIDESubMenu(SourceEditorMenuRoot, 1792 'Refactoring',uemRefactor); 1793 AParent:=SrcEditSubMenuRefactor; 1794 SrcEditMenuRenameIdentifier := RegisterIDEMenuCommand(AParent, 1795 'RenameIdentifier', lisMenuRenameIdentifier, nil, @ExecuteIdeMenuClick); 1796 SrcEditMenuExtractProc := RegisterIDEMenuCommand(AParent, 1797 'ExtractProc', lisMenuExtractProc, nil, @ExecuteIdeMenuClick); 1798 SrcEditMenuShowAbstractMethods := RegisterIDEMenuCommand(AParent, 1799 'ShowAbstractMethods', srkmecAbstractMethods, nil, @ExecuteIdeMenuClick); 1800 SrcEditMenuShowEmptyMethods := RegisterIDEMenuCommand(AParent, 1801 'ShowEmptyMethods', srkmecEmptyMethods, nil, @ExecuteIdeMenuClick); 1802 SrcEditMenuShowUnusedUnits := RegisterIDEMenuCommand(AParent, 1803 'ShowUnusedUnits', srkmecUnusedUnits, nil, @ExecuteIdeMenuClick); 1804 SrcEditMenuFindOverloads := RegisterIDEMenuCommand(AParent, 1805 'FindOverloads', srkmecFindOverloadsCapt, nil, @ExecuteIdeMenuClick); 1806 {$IFnDEF EnableFindOverloads} 1807 SrcEditMenuFindOverloads.Visible := false; 1808 {$ENDIF} 1809 SrcEditMenuMakeResourceString := RegisterIDEMenuCommand(AParent, 1810 'MakeResourceString', lisMenuMakeResourceString, nil, @ExecuteIdeMenuClick); 1811 {%endregion} 1812 1813 SrcEditMenuEditorProperties:=RegisterIDEMenuCommand(SourceEditorMenuRoot, 1814 'EditorProperties', lisMenuGeneralOptions, nil, nil, nil, 'menu_environment_options'); 1815end; 1816 1817function dbgSourceNoteBook(snb: TSourceNotebook): string; 1818var 1819 i: Integer; 1820begin 1821 Result:=''; 1822 if snb=nil then begin 1823 Result:='nil'; 1824 end else if snb.Count=0 then begin 1825 Result:='empty'; 1826 end else begin 1827 for i:=0 to 4 do begin 1828 if i>=snb.Count then break; 1829 Result+='"'+ExtractFilename(snb.Items[i].FileName)+'",'; 1830 end; 1831 end; 1832 if RightStr(Result,1)=',' then Result:=LeftStr(Result,length(Result)-1); 1833 Result:='['+Result+']'; 1834end; 1835 1836function CompareSrcEditIntfWithFilename(SrcEdit1, SrcEdit2: Pointer): integer; 1837var 1838 SE1: TSourceEditorInterface absolute SrcEdit1; 1839 SE2: TSourceEditorInterface absolute SrcEdit2; 1840begin 1841 Result:=CompareFilenames(SE1.FileName,SE2.FileName); 1842end; 1843 1844function CompareFilenameWithSrcEditIntf(FilenameStr, SrcEdit: Pointer): integer; 1845var 1846 SE1: TSourceEditorInterface absolute SrcEdit; 1847begin 1848 Result:=CompareFilenames(AnsiString(FileNameStr),SE1.FileName); 1849end; 1850 1851{ TSourceEditorWordCompletion } 1852 1853constructor TSourceEditorWordCompletion.Create; 1854begin 1855 inherited Create; 1856 1857 FSourceList := TObjectList.Create; 1858 FIncludeWords := icwIncludeFromAllUnits; 1859end; 1860 1861destructor TSourceEditorWordCompletion.Destroy; 1862begin 1863 FSourceList.Free; 1864 1865 inherited Destroy; 1866end; 1867 1868procedure TSourceEditorWordCompletion.DoGetSource(var Source: TStrings; 1869 var TopLine, BottomLine: Integer; var IgnoreWordPos: TPoint; 1870 SourceIndex: integer); 1871var 1872 SourceItem: TSourceListItem; 1873begin 1874 if SourceIndex=0 then 1875 ReloadSourceList; 1876 1877 if SourceIndex>=FSourceList.Count then 1878 Exit; 1879 1880 SourceItem := FSourceList[SourceIndex] as TSourceListItem; 1881 Source := SourceItem.Source; 1882 IgnoreWordPos := SourceItem.IgnoreWordPos; 1883end; 1884 1885procedure TSourceEditorWordCompletion.ReloadSourceList; 1886var 1887 CurEditor, TempEditor: TSourceEditor; 1888 I: integer; 1889 Mng: TSourceEditorManager; 1890 New: TSourceListItem; 1891 AddedFileNames: TStringListUTF8Fast; 1892begin 1893 FSourceList.Clear; 1894 if FIncludeWords=icwDontInclude then 1895 Exit; 1896 1897 Mng := SourceEditorManager; 1898 CurEditor:=Mng.GetActiveSE; 1899 if (CurEditor<>nil) then 1900 begin 1901 New := TSourceListItem.Create; 1902 New.Source:=CurEditor.EditorComponent.Lines; 1903 New.IgnoreWordPos:=CurEditor.EditorComponent.LogicalCaretXY; 1904 Dec(New.IgnoreWordPos.Y); // LogicalCaretXY starts with 1 as top line 1905 FSourceList.Add(New); 1906 end; 1907 1908 if FIncludeWords=icwIncludeFromAllUnits then 1909 begin 1910 AddedFileNames := TStringListUTF8Fast.Create; 1911 try 1912 AddedFileNames.Sorted := True; 1913 AddedFileNames.Duplicates := dupIgnore; 1914 for I := 0 to Mng.SourceEditorCount-1 do 1915 begin 1916 TempEditor := Mng.SourceEditors[I]; 1917 if ( TempEditor<>CurEditor) 1918 and (TempEditor.FileName<>CurEditor.FileName) 1919 and (AddedFileNames.IndexOf(TempEditor.FileName)=-1) then 1920 begin 1921 New := TSourceListItem.Create; 1922 New.Source:=TempEditor.EditorComponent.Lines; 1923 New.IgnoreWordPos:=Point(-1,-1); 1924 FSourceList.Add(New); 1925 AddedFileNames.Add(TempEditor.FileName); 1926 end; 1927 end; 1928 finally 1929 AddedFileNames.Free; 1930 end; 1931 end; 1932end; 1933 1934{ TBrowseEditorTabHistoryDialog } 1935 1936procedure TBrowseEditorTabHistoryDialog.DoCreate; 1937begin 1938 inherited DoCreate; 1939 1940 Assert(Owner is TSourceNotebook); 1941 FNotebook := TSourceNotebook(Owner); 1942 1943 Caption := lisCoolbarSourceTab; 1944 BorderIcons:=[]; 1945 BorderStyle:=bsSizeable; 1946 KeyPreview := True; 1947 1948 FEditorList := TListBox.Create(Self); 1949 FEditorList.Parent := Self; 1950 FEditorList.Align := alClient; 1951 {$IFDEF MSWINDOWS}//bsNone seems to work on Windows only 1952 FEditorList.BorderStyle := bsNone; 1953 {$ENDIF} 1954end; 1955 1956procedure TBrowseEditorTabHistoryDialog.KeyDown(var Key: Word; 1957 Shift: TShiftState); 1958 function CommandUsed(Command: TIDECommand): Boolean; 1959 begin 1960 Result := 1961 ((Command.ShortcutA.Key1 = Key) and (Command.ShortcutA.Shift1 = Shift)) or 1962 ((Command.ShortcutA.Key2 = Key) and (Command.ShortcutA.Shift2 = Shift)); 1963 end; 1964var 1965 xPrev, xNext: TIDECommand; 1966begin 1967 xPrev := IDECommandList.FindIDECommand(ecPrevEditorInHistory); 1968 if CommandUsed(xPrev) then 1969 begin 1970 MoveInList(True); 1971 Key := 0; 1972 end else 1973 begin 1974 xNext := IDECommandList.FindIDECommand(ecNextEditorInHistory); 1975 if CommandUsed(xNext) then 1976 begin 1977 MoveInList(False); 1978 Key := 0; 1979 end; 1980 end; 1981 inherited KeyDown(Key, Shift); 1982end; 1983 1984procedure TBrowseEditorTabHistoryDialog.MoveInList(aForward: Boolean); 1985begin 1986 if aForward then 1987 begin 1988 if FEditorList.ItemIndex < FEditorList.Items.Count-1 then 1989 FEditorList.ItemIndex := FEditorList.ItemIndex + 1 1990 else 1991 FEditorList.ItemIndex := 0; 1992 end else 1993 begin 1994 if FEditorList.ItemIndex > 0 then 1995 FEditorList.ItemIndex := FEditorList.ItemIndex - 1 1996 else 1997 FEditorList.ItemIndex := FEditorList.Items.Count - 1; 1998 end; 1999end; 2000 2001procedure TBrowseEditorTabHistoryDialog.KeyUp(var Key: Word; Shift: TShiftState); 2002begin 2003 if Key = VK_CONTROL then 2004 begin 2005 Close; 2006 if FEditorList.ItemIndex >= 0 then 2007 FNotebook.PageIndex := TCustomPage(FEditorList.Items.Objects[FEditorList.ItemIndex]).PageIndex; 2008 if (FNotebook.ActiveEditor<>nil) and 2009 FNotebook.ActiveEditor.EditorControl.CanSetFocus 2010 then 2011 FNotebook.ActiveEditor.EditorControl.SetFocus; 2012 Key := 0; 2013 end; 2014 2015 inherited KeyUp(Key, Shift); 2016end; 2017 2018procedure TBrowseEditorTabHistoryDialog.Show(aForward: Boolean); 2019 procedure PlaceMe; 2020 var 2021 xWidth, xHeight: Integer; 2022 xTopLeft, xRightBottom: TPoint; 2023 begin 2024 xWidth := Canvas.TextWidth('m')*20; 2025 if FEditorList.ItemHeight>0 then//ItemHeight can be 0 the first time 2026 xHeight := Min(10, FEditorList.Items.Count)*FEditorList.ItemHeight 2027 else 2028 xHeight := 200; 2029 {$IFNDEF MSWINDOWS} 2030 xHeight := xHeight + GetSystemMetrics(SM_CYBORDER)*2; 2031 {$ENDIF} 2032 2033 xTopLeft := FNotebook.ClientToScreen(Point(0, 0)); 2034 xRightBottom := FNotebook.ClientToScreen(FNotebook.ClientRect.BottomRight); 2035 SetBounds( 2036 (xTopLeft.x+xRightBottom.x-xWidth) div 2, 2037 (xTopLeft.y+xRightBottom.y-xHeight) div 2, 2038 xWidth, 2039 xHeight); 2040 end; 2041 2042var 2043 I: Integer; 2044 xPage: TCustomPage; 2045 xIndex: TAvlTree; 2046begin 2047 if FNotebook.PageCount <= 1 then 2048 Exit; 2049 2050 FEditorList.Items.BeginUpdate; 2051 xIndex := TAvlTree.Create; 2052 try 2053 FEditorList.Items.Clear; 2054 for I := 0 to FNotebook.FHistoryList.Count-1 do 2055 begin 2056 xPage := TCustomPage(FNotebook.FHistoryList[I]); 2057 FEditorList.Items.AddObject(xPage.Caption, xPage); 2058 xIndex.Add(xPage); 2059 end; 2060 2061 //add pages not in history to the right of the active page 2062 for I := FNotebook.PageIndex+1 to FNotebook.PageCount-1 do 2063 begin 2064 xPage := FNotebook.NoteBookPage[I]; 2065 if xIndex.Find(xPage)=nil then 2066 FEditorList.Items.AddObject(xPage.Caption, xPage); 2067 end; 2068 //add pages not in history to the left of the active page 2069 for I := 0 to FNotebook.PageIndex-1 do 2070 begin 2071 xPage := FNotebook.NoteBookPage[I]; 2072 if xIndex.Find(xPage)=nil then 2073 FEditorList.Items.AddObject(xPage.Caption, xPage); 2074 end; 2075 finally 2076 xIndex.Free; 2077 FEditorList.Items.EndUpdate; 2078 end; 2079 2080 if aForward then 2081 FEditorList.ItemIndex := 1 2082 else 2083 FEditorList.ItemIndex := FEditorList.Count-1; 2084 2085 PlaceMe; 2086 Visible := True; 2087 PlaceMe; 2088 BringToFront; 2089end; 2090 2091{ TSourceEditorHintWindowManager } 2092 2093procedure TSourceEditorHintWindowManager.ActivateHint(const ScreenPos: TPoint; 2094 const ABaseURL, AHint: string; AAutoShown: Boolean; AMouseOffset: Boolean); 2095begin 2096 ActivateHint(Rect(ScreenPos.x, ScreenPos.y, ScreenPos.x, ScreenPos.y), ABaseURL, AHint, AAutoShown, AMouseOffset); 2097end; 2098 2099procedure TSourceEditorHintWindowManager.ActivateHint(const ScreenRect: TRect; 2100 const ABaseURL, AHint: string; AAutoShown: Boolean; AMouseOffset: Boolean); 2101begin 2102 FAutoShown := AAutoShown; 2103 BaseURL := ABaseURL; 2104 FLastHint := AHint; 2105 FScreenRect := ScreenRect; 2106 if AAutoShown then 2107 begin 2108 FAutoHintMousePos := Mouse.CursorPos; 2109 if not(HintIsVisible and (FLastHint = AHint)) then 2110 ShowHint(Point(ScreenRect.Left, ScreenRect.Bottom),AHint,AMouseOffset); 2111 end else 2112 begin 2113 if HintIsVisible and (FLastHint = AHint) then 2114 HideIfVisible 2115 else 2116 ShowHint(Point(ScreenRect.Left, ScreenRect.Bottom),AHint,AMouseOffset); 2117 end; 2118 FAutoHideHintTimer.Enabled := AAutoShown; 2119end; 2120 2121constructor TSourceEditorHintWindowManager.Create(AManager: TSourceEditorManager); 2122begin 2123 inherited Create; 2124 2125 FManager := AManager; 2126 // HintTimer 2127 FAutoHintTimer := TIdleTimer.Create(nil); 2128 with FAutoHintTimer do begin 2129 Interval := EditorOpts.AutoHintDelayInMSec; 2130 Enabled := False; 2131 AutoEnabled := False; 2132 OnTimer := @HintTimer; 2133 end; 2134 // Track mouse movements outside the IDE, if hint is visible 2135 FAutoHideHintTimer := TTimer.Create(nil); 2136 with FAutoHideHintTimer do begin 2137 Interval := 500; 2138 Enabled := False; 2139 OnTimer := @HideHintTimer; 2140 end; 2141end; 2142 2143destructor TSourceEditorHintWindowManager.Destroy; 2144begin 2145 FAutoHintTimer.Free; 2146 FAutoHideHintTimer.Free; 2147 2148 inherited Destroy; 2149end; 2150 2151procedure TSourceEditorHintWindowManager.HideAutoHint; 2152begin 2153 if FAutoHintTimer<>nil then 2154 begin 2155 FAutoHintTimer.AutoEnabled := false; 2156 FAutoHintTimer.Enabled:=false; 2157 end; 2158 if FAutoHideHintTimer <> nil then 2159 FAutoHideHintTimer.Enabled := False; 2160 if AutoStartCompletionBoxTimer<>nil then 2161 AutoStartCompletionBoxTimer.Enabled:=false; 2162 if (FManager.ActiveEditor <> nil) and 2163 (FManager.ActiveEditor.FCodeCompletionState.State in [ccsDot, ccsOnTyping]) 2164 then 2165 FManager.ActiveEditor.FCodeCompletionState.State := ccsReady; 2166 if FAutoShown then 2167 HideHint; 2168end; 2169 2170procedure TSourceEditorHintWindowManager.HideHintTimer(Sender: TObject); 2171begin 2172 if HintIsVisible and FAutoShown then begin 2173 if ComparePoints(FAutoHintMousePos, Mouse.CursorPos) <> 0 then begin 2174 // TODO: introduce property, to indicate if hint is interactive 2175 if HintIsComplex or not IsRectEmpty(FScreenRect) then 2176 HideAutoHintAfterMouseMoved 2177 else 2178 HideAutoHint; 2179 end; 2180 end 2181 else 2182 FAutoHideHintTimer.Enabled := false; 2183end; 2184 2185procedure TSourceEditorHintWindowManager.HintTimer(Sender: TObject); 2186var 2187 MousePos: TPoint; 2188 AControl: TControl; 2189begin 2190 FAutoHintTimer.Enabled := False; 2191 FAutoHintTimer.AutoEnabled := False; 2192 if not FManager.ActiveSourceWindow.IsVisible then exit; 2193 MousePos := Mouse.CursorPos; 2194 AControl:=FindLCLControl(MousePos); 2195 if (AControl=nil) or (not FManager.ActiveSourceWindow.ContainsControl(AControl)) then exit; 2196 if AControl is TSynEdit then 2197 FManager.ActiveSourceWindow.ShowSynEditHint(MousePos); 2198end; 2199 2200procedure TSourceEditorHintWindowManager.HideAutoHintAfterMouseMoved; 2201const 2202 MaxJitter = 3; 2203var 2204 Cur: TPoint; 2205 OkX, OkY: Boolean; 2206 hw: THintWindow; 2207begin 2208 if HintIsVisible and not FAutoShown then Exit; 2209 FAutoHideHintTimer.Enabled := False; 2210 if HintIsVisible then begin 2211 Cur := Mouse.CursorPos; // Desktop coordinates 2212 if (not IsRectEmpty(FScreenRect)) then 2213 begin 2214 // Do not close, if mouse still over the same word, that triggered the hint 2215 if PtInRect(FScreenRect, Cur) then 2216 Exit; 2217 end else 2218 begin 2219 // Fallback if FScreenRect is empty (for legacy calls) 2220 hw := CurHintWindow; 2221 OkX := ( (FAutoHintMousePos.x <= hw.Left) and 2222 (Cur.x > FAutoHintMousePos.x) and (Cur.x <= hw.Left + hw.Width) 2223 ) or 2224 ( (FAutoHintMousePos.x >= hw.Left + hw.Width) and 2225 (Cur.x < FAutoHintMousePos.x) and (Cur.x >= hw.Left) 2226 ) or 2227 ( (Cur.x >= hw.Left) and (Cur.x <= hw.Left + hw.Width) ); 2228 OkY := ( (FAutoHintMousePos.y <= hw.Top) and 2229 (Cur.y > FAutoHintMousePos.y) and (Cur.y <= hw.Top + hw.Height) 2230 ) or 2231 ( (FAutoHintMousePos.y >= hw.Top + hw.Height) and 2232 (Cur.y < FAutoHintMousePos.y) and (Cur.y >= hw.Top) 2233 ) or 2234 ( (Cur.y >= hw.Top) and (Cur.y <= hw.Top + hw.Height) ); 2235 2236 if OkX then FAutoHintMousePos.x := Cur.x; 2237 if OkY then FAutoHintMousePos.y := Cur.y; 2238 2239 OkX := OkX or 2240 ( (FAutoHintMousePos.x <= hw.Left + MaxJitter) and 2241 (Cur.x > FAutoHintMousePos.x - MaxJitter) and (Cur.x <= hw.Left + hw.Width + MaxJitter) 2242 ) or 2243 ( (FAutoHintMousePos.x >= hw.Left + hw.Width - MaxJitter) and 2244 (Cur.x < FAutoHintMousePos.x + MaxJitter) and (Cur.x >= hw.Left - MaxJitter) 2245 ); 2246 OkY := OkY or 2247 ( (FAutoHintMousePos.y <= hw.Top + MaxJitter) and 2248 (Cur.y > FAutoHintMousePos.y - MaxJitter) and (Cur.y <= hw.Top + hw.Height + MaxJitter) 2249 ) or 2250 ( (FAutoHintMousePos.y >= hw.Top + hw.Height - MaxJitter) and 2251 (Cur.y < FAutoHintMousePos.y + MaxJitter) and (Cur.y >= hw.Top - MaxJitter) 2252 ); 2253 2254 if (OkX and OkY) then begin 2255 FAutoHideHintTimer.Enabled := True; 2256 exit; 2257 end; 2258 end; 2259 end; 2260 HideHint; 2261end; 2262 2263procedure TSourceEditorHintWindowManager.UpdateHintTimer; 2264begin 2265 with EditorOpts do 2266 if (MainIDEInterface.ToolStatus=itDebugger) then 2267 FAutoHintTimer.AutoEnabled := AutoToolTipExprEval or AutoToolTipSymbTools 2268 else 2269 FAutoHintTimer.AutoEnabled := AutoToolTipSymbTools; 2270end; 2271 2272 2273{ TSourceEditCompletion } 2274 2275procedure TSourceEditCompletion.CompletionFormResized(Sender: TObject); 2276begin 2277 EnvironmentOptions.Desktop.CompletionWindowWidth := TheForm.Width; 2278 EnvironmentOptions.Desktop.CompletionWindowHeight := TheForm.NbLinesInWindow; 2279end; 2280 2281function TSourceEditCompletion.GetCompletionFormClass: TSynBaseCompletionFormClass; 2282begin 2283 Result := TSourceEditCompletionForm; 2284end; 2285 2286procedure TSourceEditCompletion.ccExecute(Sender: TObject); 2287// init completion form 2288// called by OnExecute just before showing 2289var 2290 SL: TStrings; 2291 Prefix: String; 2292 I: Integer; 2293 NewStr: String; 2294 SynEditor: TIDESynEditor; 2295Begin 2296 {$IFDEF VerboseIDECompletionBox} 2297 debugln(['TSourceEditCompletion.ccExecute START']); 2298 {$ENDIF} 2299 TheForm.Font := Editor.Font; 2300 2301 FActiveEditTextColor := Editor.Font.Color; 2302 FActiveEditBorderColor := RGBToColor(200, 200, 200); 2303 FActiveEditBackgroundColor := Editor.Color; 2304 FActiveEditTextSelectedColor := TSynEdit(Editor).SelectedColor.Foreground; 2305 FActiveEditBackgroundSelectedColor := TSynEdit(Editor).SelectedColor.Background; 2306 FActiveEditTextHighLightColor := clNone; 2307 2308 if Editor.Highlighter<>nil 2309 then begin 2310 with Editor.Highlighter do begin 2311 if IdentifierAttribute<>nil 2312 then begin 2313 if IdentifierAttribute.ForeGround<>clNone then 2314 FActiveEditTextColor:=IdentifierAttribute.ForeGround; 2315 if IdentifierAttribute.BackGround<>clNone then 2316 FActiveEditBackgroundColor:=IdentifierAttribute.BackGround; 2317 end; 2318 end; 2319 end; 2320 2321 if Editor is TIDESynEditor then 2322 begin 2323 SynEditor := TIDESynEditor(Editor); 2324 if SynEditor.MarkupIdentComplWindow.TextColor<>clNone then 2325 FActiveEditTextColor := SynEditor.MarkupIdentComplWindow.TextColor; 2326 if SynEditor.MarkupIdentComplWindow.BorderColor<>clNone then 2327 FActiveEditBorderColor := SynEditor.MarkupIdentComplWindow.BorderColor; 2328 if SynEditor.MarkupIdentComplWindow.WindowColor<>clNone then 2329 FActiveEditBackgroundColor := SynEditor.MarkupIdentComplWindow.WindowColor; 2330 if SynEditor.MarkupIdentComplWindow.TextSelectedColor<>clNone then 2331 FActiveEditTextSelectedColor := SynEditor.MarkupIdentComplWindow.TextSelectedColor; 2332 if SynEditor.MarkupIdentComplWindow.BackgroundSelectedColor<>clNone then 2333 FActiveEditBackgroundSelectedColor := SynEditor.MarkupIdentComplWindow.BackgroundSelectedColor; 2334 if SynEditor.MarkupIdentComplWindow.HighlightColor<>clNone then 2335 FActiveEditTextHighLightColor := SynEditor.MarkupIdentComplWindow.HighlightColor; 2336 end; 2337 2338 SL := TStringList.Create; 2339 try 2340 Prefix := CurrentString; 2341 case CurrentCompletionType of 2342 ctIdentCompletion: 2343 if InitIdentCompletionValues(SL) then begin 2344 ToggleReplaceWhole:=not CodeToolsOpts.IdentComplReplaceIdentifier; 2345 end else begin 2346 ItemList.Clear; 2347 exit; 2348 end; 2349 2350 ctWordCompletion: 2351 begin 2352 ToggleReplaceWhole:=not CodeToolsOpts.IdentComplReplaceIdentifier; 2353 ccSelection := ''; 2354 end; 2355 2356 ctTemplateCompletion: 2357 begin 2358 ccSelection:=''; 2359 for I := 0 to Manager.CodeTemplateModul.Completions.Count-1 do begin 2360 NewStr := Manager.CodeTemplateModul.Completions[I]; 2361 if NewStr<>'' then begin 2362 NewStr:=#3'B'+NewStr+#3'b'; 2363 while length(NewStr)<10+4 do NewStr:=NewStr+' '; 2364 NewStr:=NewStr+' '+Manager.CodeTemplateModul.CompletionComments[I]; 2365 SL.Add(NewStr); 2366 end; 2367 end; 2368 end; 2369 2370 end; 2371 2372 ItemList := SL; 2373 finally 2374 SL.Free; 2375 end; 2376 CurrentString:=Prefix; 2377 // set colors 2378 if (Editor<>nil) and (TheForm<>nil) then begin 2379 with TheForm as TSourceEditCompletionForm do begin 2380 DrawBorderColor := FActiveEditBorderColor; 2381 BackgroundColor := FActiveEditBackgroundColor; 2382 clSelect := FActiveEditBackgroundSelectedColor; 2383 TextColor := FActiveEditTextColor; 2384 TextSelectedColor := FActiveEditTextSelectedColor; 2385 TextHighLightColor:= FActiveEditTextHighLightColor; 2386 //debugln('TSourceEditCompletion.ccExecute A Color=',DbgS(Color), 2387 // ' clSelect=',DbgS(clSelect), 2388 // ' TextColor=',DbgS(TextColor), 2389 // ' TextSelectedColor=',DbgS(TextSelectedColor), 2390 // ''); 2391 end; 2392 debugln(['TSourceEditCompletion.ccExecute ',DbgSName(SourceEditorManager.ActiveCompletionPlugin)]); 2393 if (CurrentCompletionType=ctIdentCompletion) 2394 and (SourceEditorManager.ActiveCompletionPlugin=nil) 2395 then 2396 StartShowCodeHelp 2397 else if SrcEditHintWindow<>nil then 2398 begin 2399 SrcEditHintWindow.HelpEnabled:=false; 2400 TheForm.LongLineHintType := EditorOpts.CompletionLongLineHintType; 2401 end; 2402 end; 2403end; 2404 2405procedure TSourceEditCompletion.ccCancel(Sender: TObject); 2406// user cancels completion form 2407begin 2408 {$IFDEF VerboseIDECompletionBox} 2409 DebugLnEnter(['TSourceNotebook.ccCancel START']); 2410 try 2411 //debugln(GetStackTrace(true)); 2412 {$ENDIF} 2413 Manager.DeactivateCompletionForm; 2414 {$IFDEF VerboseIDECompletionBox} 2415 finally 2416 DebugLnExit(['TSourceNotebook.ccCancel END']); 2417 end; 2418 //debugln(GetStackTrace(true)); 2419 {$ENDIF} 2420 2421 with Manager.ActiveEditor do begin 2422 FCodeCompletionState.LastTokenStartPos := CurrentWordLogStartOrCaret; 2423 FCodeCompletionState.State := ccsCancelled; 2424 end; 2425end; 2426 2427procedure TSourceEditCompletion.ccComplete(var Value: string; 2428 SourceValue: string; var SourceStart, SourceEnd: TPoint; KeyChar: TUTF8Char; 2429 Shift: TShiftState); 2430// completion selected -> deactivate completion form 2431// Called when user has selected a completion item 2432 2433 function CharBehindIdent(const Line: string; StartPos: integer): char; 2434 begin 2435 while (StartPos<=length(Line)) 2436 and (Line[StartPos] in ['_','A'..'Z','a'..'z']) do 2437 inc(StartPos); 2438 while (StartPos<=length(Line)) and (Line[StartPos] in [' ',#9]) do 2439 inc(StartPos); 2440 if StartPos<=length(Line) then 2441 Result:=Line[StartPos] 2442 else 2443 Result:=#0; 2444 end; 2445 2446 function CharInFrontOfIdent(const Line: string; StartPos: integer): char; 2447 begin 2448 while (StartPos>=1) 2449 and (Line[StartPos] in ['_','A'..'Z','a'..'z']) do 2450 dec(StartPos); 2451 while (StartPos>=1) and (Line[StartPos] in [' ',#9]) do 2452 dec(StartPos); 2453 if StartPos>=1 then 2454 Result:=Line[StartPos] 2455 else 2456 Result:=#0; 2457 end; 2458 2459var 2460 p1, p2: integer; 2461 ValueType: TIdentComplValue; 2462 NewCaretXY: TPoint; 2463 CursorToLeft: integer; 2464 NewValue: String; 2465 OldCompletionType: TCompletionType; 2466 prototypeAdded: boolean; 2467 SourceNoteBook: TSourceNotebook; 2468 IdentItem: TIdentifierListItem; 2469Begin 2470 {$IFDEF VerboseIDECompletionBox} 2471 DebugLnEnter(['TSourceNotebook.ccComplete START']); 2472 try 2473 {$ENDIF} 2474 prototypeAdded := false; 2475 OldCompletionType:=CurrentCompletionType; 2476 case CurrentCompletionType of 2477 2478 ctIdentCompletion: 2479 begin 2480 if Manager.ActiveCompletionPlugin<>nil then 2481 begin 2482 Manager.ActiveCompletionPlugin.Complete(Value,SourceValue, 2483 SourceStart,SourceEnd,KeyChar,Shift); 2484 Manager.FActiveCompletionPlugin:=nil; 2485 end else begin 2486 IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[Position]; 2487 // add to history 2488 CodeToolBoss.IdentifierHistory.Add(IdentItem); 2489 if IdentItem is TCodeTemplateIdentifierListItem then 2490 begin 2491 if IdentItem.Identifier<>'' then 2492 Manager.CodeTemplateModul.ExecuteCompletion(IdentItem.Identifier, Editor); 2493 end else 2494 begin 2495 // get value 2496 NewValue:=GetIdentCompletionValue(Self, KeyChar, ValueType, CursorToLeft); 2497 if ValueType=icvIdentifier then ; 2498 // insert value plus special chars like brackets, semicolons, ... 2499 if ValueType <> icvNone then 2500 Editor.TextBetweenPointsEx[SourceStart, SourceEnd, scamEnd] := NewValue; 2501 if ValueType in [icvProcWithParams,icvIndexedProp] then 2502 prototypeAdded := true; 2503 if CursorToLeft>0 then 2504 begin 2505 NewCaretXY:=Editor.CaretXY; 2506 dec(NewCaretXY.X,CursorToLeft); 2507 Editor.CaretXY:=NewCaretXY; 2508 end; 2509 end; 2510 ccSelection := ''; 2511 Value:=''; 2512 SourceEnd := SourceStart; 2513 end; 2514 end; 2515 2516 ctTemplateCompletion: 2517 begin 2518 // the completion is the bold text between #3'B' and #3'b' 2519 p1:=Pos(#3,Value); 2520 if p1>=0 then begin 2521 p2:=p1+2; 2522 while (p2<=length(Value)) and (Value[p2]<>#3) do inc(p2); 2523 Value:=copy(Value,p1+2,p2-p1-2); 2524 // keep parent identifier (in front of '.') 2525 p1:=length(ccSelection); 2526 while (p1>=1) and (ccSelection[p1]<>'.') do dec(p1); 2527 if p1>=1 then 2528 Value:=copy(ccSelection,1,p1)+Value; 2529 end; 2530 ccSelection := ''; 2531 if Value<>'' then 2532 Manager.CodeTemplateModul.ExecuteCompletion(Value, Editor); 2533 SourceEnd := SourceStart; 2534 Value:=''; 2535 end; 2536 2537 ctWordCompletion: 2538 // the completion is already in Value 2539 begin 2540 ccSelection := ''; 2541 if Value<>'' then AWordCompletion.AddWord(Value); 2542 end; 2543 2544 else begin 2545 Value:=''; 2546 end; 2547 end; 2548 2549 Manager.DeactivateCompletionForm; 2550 2551 //DebugLn(['TSourceNotebook.ccComplete ',KeyChar,' ',OldCompletionType=ctIdentCompletion]); 2552 Manager.ActiveEditor.FCodeCompletionState.State := ccsReady; 2553 if (KeyChar='.') and (OldCompletionType=ctIdentCompletion) then 2554 begin 2555 SourceCompletionCaretXY:=Editor.LogicalCaretXY; 2556 AutoStartCompletionBoxTimer.AutoEnabled:=true; 2557 Manager.ActiveEditor.FCodeCompletionState.State := ccsDot; 2558 end 2559 else if prototypeAdded and EditorOpts.AutoDisplayFunctionPrototypes then 2560 begin 2561 if Editor.Owner is TSourceNoteBook then 2562 begin 2563 SourceNoteBook := Editor.Owner as TSourceNoteBook; 2564 SourceNotebook.StartShowCodeContext(CodeToolsOpts.IdentComplJumpToError); 2565 end; 2566 end; 2567 2568 {$IFDEF VerboseIDECompletionBox} 2569 finally 2570 DebugLnExit(['TSourceNotebook.ccComplete END']); 2571 end; 2572 {$ENDIF} 2573end; 2574 2575function TSourceEditCompletion.OnSynCompletionPaintItem(const AKey: string; 2576 ACanvas: TCanvas; X, Y: integer; ItemSelected: boolean; Index: integer): boolean; 2577var 2578 MaxX: Integer; 2579 t: TCompletionType; 2580 hl: TSynCustomHighlighter; 2581 Colors: TPaintCompletionItemColors; 2582begin 2583 try 2584 with ACanvas do begin 2585 if (Editor<>nil) then 2586 Font := Editor.Font 2587 else begin 2588 Font.Size:=EditorOpts.EditorFontSize; // set Size before name for XLFD ! 2589 Font.Name:=EditorOpts.EditorFont; 2590 end; 2591 Font.Style:=[]; 2592 end; 2593 Colors.BackgroundColor := FActiveEditBackgroundColor; 2594 Colors.BackgroundSelectedColor := FActiveEditBackgroundSelectedColor; 2595 Colors.TextColor := FActiveEditTextColor; 2596 Colors.TextSelectedColor := FActiveEditTextSelectedColor; 2597 Colors.TextHilightColor := FActiveEditTextHighLightColor; 2598 MaxX:=TheForm.ClientWidth; 2599 t:=CurrentCompletionType; 2600 if Manager.ActiveCompletionPlugin<>nil then 2601 begin 2602 if Manager.ActiveCompletionPlugin.HasCustomPaint then 2603 begin 2604 Manager.ActiveCompletionPlugin.PaintItem(AKey,ACanvas,X,Y,ItemSelected,Index); 2605 end else begin 2606 t:=ctWordCompletion; 2607 end; 2608 end; 2609 hl := nil; 2610 if Editor <> nil then 2611 hl := Editor.Highlighter; 2612 PaintCompletionItem(AKey, ACanvas, X, Y, MaxX, ItemSelected, Index, self, t, hl, @Colors); 2613 Result:=true; 2614 except 2615 DebugLn('OnSynCompletionPaintItem failed'); 2616 DumpStack; 2617 Result := false; 2618 end; 2619end; 2620 2621function TSourceEditCompletion.OnSynCompletionMeasureItem(const AKey: string; 2622 ACanvas: TCanvas; ItemSelected: boolean; Index: integer): TPoint; 2623var 2624 MaxX: Integer; 2625 t: TCompletionType; 2626begin 2627 try 2628 with ACanvas do begin 2629 if (Editor<>nil) then 2630 Font:=Editor.Font 2631 else begin 2632 Font.Size:=EditorOpts.EditorFontSize; // set Size before name of XLFD ! 2633 Font.Name:=EditorOpts.EditorFont; 2634 end; 2635 Font.Style:=[]; 2636 end; 2637 MaxX := Screen.Width-20; 2638 t:=CurrentCompletionType; 2639 if Manager.ActiveCompletionPlugin<>nil then 2640 begin 2641 if Manager.ActiveCompletionPlugin.HasCustomPaint then 2642 begin 2643 Manager.ActiveCompletionPlugin.MeasureItem(AKey,ACanvas,ItemSelected,Index); 2644 end else begin 2645 t:=ctWordCompletion; 2646 end; 2647 end; 2648 Result := PaintCompletionItem(AKey,ACanvas,0,0,MaxX,ItemSelected,Index, 2649 self,t,nil,nil,True); 2650 Result.Y:=FontHeight; 2651 except 2652 DebugLn('OnSynCompletionMeasureItem failed'); 2653 DumpStack; 2654 Result := Point(FontHeight * length(AKey), FontHeight); 2655 end; 2656end; 2657 2658procedure TSourceEditCompletion.OnSynCompletionSearchPosition( 2659 var APosition: integer); 2660// prefix changed -> filter list 2661var 2662 i,x:integer; 2663 CurStr,s:Ansistring; 2664 SL: TStrings; 2665 ItemCnt: Integer; 2666begin 2667 case CurrentCompletionType of 2668 2669 ctIdentCompletion: 2670 if Manager.ActiveCompletionPlugin<>nil then 2671 begin 2672 // let plugin rebuild completion list 2673 SL:=TStringList.Create; 2674 try 2675 Manager.ActiveCompletionPlugin.PrefixChanged(CurrentString,APosition,sl); 2676 ItemList:=SL; 2677 finally 2678 SL.Free; 2679 end; 2680 end else begin 2681 // rebuild completion list 2682 APosition:=0; 2683 CurStr:=CurrentString; 2684 CodeToolBoss.IdentifierList.ContainsFilter := CodeToolsOpts.IdentComplUseContainsFilter; 2685 CodeToolBoss.IdentifierList.Prefix:=CurStr; 2686 ItemCnt:=CodeToolBoss.IdentifierList.GetFilteredCount; 2687 SL:=TStringList.Create; 2688 try 2689 sl.Capacity:=ItemCnt; 2690 for i:=0 to ItemCnt-1 do 2691 SL.Add('Dummy'); // these entries are not shown 2692 ItemList:=SL; 2693 finally 2694 SL.Free; 2695 end; 2696 end; 2697 2698 ctTemplateCompletion: 2699 begin 2700 // search CurrentString in bold words (words after #3'B') 2701 CurStr:=CurrentString; 2702 i:=0; 2703 while i<ItemList.Count do begin 2704 s:=ItemList[i]; 2705 x:=1; 2706 while (x<=length(s)) and (s[x]<>#3) do inc(x); 2707 if x<length(s) then begin 2708 inc(x,2); 2709 if UTF8CompareLatinTextFast(CurStr,copy(s,x,length(CurStr)))=0 then begin 2710 APosition:=i; 2711 break; 2712 end; 2713 end; 2714 inc(i); 2715 end; 2716 end; 2717 2718 ctWordCompletion: 2719 begin 2720 // rebuild completion list 2721 APosition:=0; 2722 CurStr:=CurrentString; 2723 SL:=TStringList.Create; 2724 try 2725 aWordCompletion.GetWordList(SL, CurStr, CodeToolBoss.IdentifierList.ContainsFilter, false, 100); 2726 ItemList:=SL; 2727 finally 2728 SL.Free; 2729 end; 2730 end; 2731 2732 end; 2733 if SrcEditHintWindow<>nil then 2734 SrcEditHintWindow.UpdateHints; 2735end; 2736 2737procedure TSourceEditCompletion.OnSynCompletionCompletePrefix(Sender: TObject); 2738var 2739 OldPrefix: String; 2740 NewPrefix: String; 2741 SL: TStringList; 2742 AddPrefix: String; 2743begin 2744 OldPrefix:=CurrentString; 2745 NewPrefix:=OldPrefix; 2746 2747 case CurrentCompletionType of 2748 2749 ctIdentCompletion: 2750 if Manager.ActiveCompletionPlugin<>nil then 2751 begin 2752 Manager.ActiveCompletionPlugin.CompletePrefix(NewPrefix); 2753 end else begin 2754 NewPrefix:=CodeToolBoss.IdentifierList.CompletePrefix(OldPrefix); 2755 end; 2756 2757 ctWordCompletion: 2758 begin 2759 aWordCompletion.CompletePrefix(OldPrefix,NewPrefix,false); 2760 end; 2761 2762 end; 2763 2764 if NewPrefix<>OldPrefix then begin 2765 AddPrefix:=copy(NewPrefix,length(OldPrefix)+1,length(NewPrefix)); 2766 Editor.InsertTextAtCaret(AddPrefix); 2767 if CurrentCompletionType=ctWordCompletion then begin 2768 SL:=TStringList.Create; 2769 try 2770 aWordCompletion.GetWordList(SL, NewPrefix, CodeToolBoss.IdentifierList.ContainsFilter, false, 100); 2771 ItemList:=SL; 2772 finally 2773 SL.Free; 2774 end; 2775 end; 2776 CurrentString:=NewPrefix; 2777 end; 2778end; 2779 2780procedure TSourceEditCompletion.OnSynCompletionNextChar(Sender: TObject); 2781var 2782 NewPrefix: String; 2783 Line: String; 2784 LogCaret: TPoint; 2785 CharLen: LongInt; 2786 AddPrefix: String; 2787begin 2788 if Editor=nil then exit; 2789 LogCaret:=Editor.LogicalCaretXY; 2790 if LogCaret.Y>=Editor.Lines.Count then exit; 2791 Line:=Editor.Lines[LogCaret.Y-1]; 2792 if LogCaret.X>length(Line) then exit; 2793 CharLen:=UTF8CodepointSize(@Line[LogCaret.X]); 2794 AddPrefix:=copy(Line,LogCaret.X,CharLen); 2795 if not Editor.IsIdentChar(AddPrefix) then exit; 2796 NewPrefix:=CurrentString+AddPrefix; 2797 //debugln('TSourceNotebook.OnSynCompletionNextChar NewPrefix="',NewPrefix,'" LogCaret.X=',dbgs(LogCaret.X)); 2798 inc(LogCaret.X); 2799 Editor.LogicalCaretXY:=LogCaret; 2800 CurrentString:=NewPrefix; 2801end; 2802 2803procedure TSourceEditCompletion.OnSynCompletionPrevChar(Sender: TObject); 2804var 2805 NewPrefix: String; 2806 NewLen: LongInt; 2807begin 2808 NewPrefix:=CurrentString; 2809 if NewPrefix='' then exit; 2810 if Editor=nil then exit; 2811 Editor.CaretX:=Editor.CaretX-1; 2812 NewLen:=UTF8FindNearestCharStart(PChar(NewPrefix),length(NewPrefix), 2813 length(NewPrefix)-1); 2814 NewPrefix:=copy(NewPrefix,1,NewLen); 2815 CurrentString:=NewPrefix; 2816end; 2817 2818procedure TSourceEditCompletion.OnSynCompletionKeyPress(Sender: TObject; 2819 var Key: Char); 2820begin 2821 if (System.Pos(Key,EndOfTokenChr)>0) then begin 2822 // identifier completed 2823 //debugln('TSourceNotebook.OnSynCompletionKeyPress A'); 2824 TheForm.OnValidate(Sender,Key,[]); 2825 //debugln('TSourceNotebook.OnSynCompletionKeyPress B'); 2826 Key:=#0; 2827 end; 2828end; 2829 2830procedure TSourceEditCompletion.OnSynCompletionUTF8KeyPress(Sender: TObject; 2831 var UTF8Key: TUTF8Char); 2832begin 2833 if (length(UTF8Key)=1) 2834 and (System.Pos(UTF8Key[1],EndOfTokenChr)>0) then begin 2835 // identifier completed 2836 //debugln('TSourceNotebook.OnSynCompletionUTF8KeyPress A'); 2837 TheForm.OnValidate(Sender,UTF8Key,[]); 2838 //debugln('TSourceNotebook.OnSynCompletionKeyPress B'); 2839 UTF8Key:=''; 2840 end; 2841 //debugln('TSourceNotebook.OnSynCompletionKeyPress B UTF8Key=',dbgstr(UTF8Key)); 2842end; 2843 2844procedure TSourceEditCompletion.OnSynCompletionPositionChanged(Sender: TObject); 2845begin 2846 if Manager.ActiveCompletionPlugin<>nil then 2847 Manager.ActiveCompletionPlugin.IndexChanged(Position); 2848 if SrcEditHintWindow<>nil then 2849 SrcEditHintWindow.UpdateHints; 2850end; 2851 2852function TSourceEditCompletion.InitIdentCompletionValues(S: TStrings): boolean; 2853var 2854 i: integer; 2855 Handled: boolean; 2856 Abort: boolean; 2857 Prefix: string; 2858 ItemCnt: Integer; 2859begin 2860 Result:=false; 2861 Prefix := CurrentString; 2862 if Manager.ActiveCompletionPlugin<>nil then 2863 begin 2864 Result := Manager.ActiveCompletionPlugin.Collect(S); 2865 end 2866 else if Assigned(Manager.OnInitIdentCompletion) then 2867 begin 2868 Manager.OnInitIdentCompletion(Self, FIdentCompletionJumpToError, Handled, Abort); 2869 if Handled then begin 2870 if Abort then exit; 2871 // add one entry per item 2872 CodeToolBoss.IdentifierList.Prefix:=Prefix; 2873 ItemCnt:=CodeToolBoss.IdentifierList.GetFilteredCount; 2874 //DebugLn('InitIdentCompletion B Prefix=',Prefix,' ItemCnt=',IntToStr(ItemCnt)); 2875 Position:=0; 2876 for i:=0 to ItemCnt-1 do 2877 s.Add('Dummy'); 2878 Result:=true; 2879 exit; 2880 end; 2881 end; 2882end; 2883 2884procedure TSourceEditCompletion.StartShowCodeHelp; 2885begin 2886 if SrcEditHintWindow = nil then begin 2887 SrcEditHintWindow := TSrcEditHintWindow.Create(Manager); 2888 SrcEditHintWindow.Name:='TSourceNotebook_SrcEditHintWindow'; 2889 SrcEditHintWindow.Provider:=TFPDocHintProvider.Create(SrcEditHintWindow); 2890 end; 2891 SrcEditHintWindow.AnchorForm := TheForm; 2892 //debugln(['TSourceEditCompletion.StartShowCodeHelp ',CodeToolsOpts.IdentComplShowHelp]); 2893 if CodeToolsOpts.IdentComplShowHelp then begin 2894 TheForm.LongLineHintType:=sclpNone; 2895 SrcEditHintWindow.HelpEnabled:=true; 2896 end else begin 2897 TheForm.LongLineHintType:=EditorOpts.CompletionLongLineHintType; 2898 SrcEditHintWindow.HelpEnabled:=false; 2899 end; 2900end; 2901 2902function TSourceEditCompletion.Manager: TSourceEditorManager; 2903begin 2904 Result := SourceEditorManager; 2905end; 2906 2907constructor TSourceEditCompletion.Create(AOwner: TComponent); 2908begin 2909 inherited; 2910 EndOfTokenChr:='()[].,;:-+=^*<>/'; 2911 Width:=400; 2912 OnExecute := @ccExecute; 2913 OnCancel := @ccCancel; 2914 OnCodeCompletion := @ccComplete; 2915 OnPaintItem:=@OnSynCompletionPaintItem; 2916 OnMeasureItem := @OnSynCompletionMeasureItem; 2917 OnSearchPosition:=@OnSynCompletionSearchPosition; 2918 OnKeyCompletePrefix:=@OnSynCompletionCompletePrefix; 2919 OnKeyNextChar:=@OnSynCompletionNextChar; 2920 OnKeyPrevChar:=@OnSynCompletionPrevChar; 2921 OnKeyPress:=@OnSynCompletionKeyPress; 2922 OnUTF8KeyPress:=@OnSynCompletionUTF8KeyPress; 2923 OnPositionChanged:=@OnSynCompletionPositionChanged; 2924 ShortCut:=Menus.ShortCut(VK_UNKNOWN,[]); 2925 TheForm.ShowSizeDrag := True; 2926 TheForm.Width := Max(50, EnvironmentOptions.Desktop.CompletionWindowWidth); 2927 TheForm.NbLinesInWindow := Max(3, EnvironmentOptions.Desktop.CompletionWindowHeight); 2928 TheForm.OnDragResized := @CompletionFormResized; 2929end; 2930 2931{ TSourceEditorSharedValues } 2932 2933function TSourceEditorSharedValues.GetSharedEditors(Index: Integer): TSourceEditor; 2934begin 2935 Result := TSourceEditor(FSharedEditorList[Index]); 2936end; 2937 2938function TSourceEditorSharedValues.GetOtherSharedEditors(Caller: TSourceEditor; 2939 Index: Integer): TSourceEditor; 2940begin 2941 if Index >= FSharedEditorList.IndexOf(Caller) then 2942 inc(Index); 2943 Result := TSourceEditor(FSharedEditorList[Index]); 2944end; 2945 2946function TSourceEditorSharedValues.SynEditor: TIDESynEditor; 2947begin 2948 Result := SharedEditors[0].FEditor; 2949end; 2950 2951function TSourceEditorSharedValues.GetSharedEditorsBase(Index: Integer): TSourceEditorBase; 2952begin 2953 Result := TSourceEditorBase(FSharedEditorList[Index]); 2954end; 2955 2956procedure TSourceEditorSharedValues.SetCodeBuffer(const AValue: TCodeBuffer); 2957var 2958 i: Integer; 2959 SrcEdit: TSourceEditor; 2960 SharedEdit: TSourceEditor; 2961 ETChanges: TETSingleSrcChanges; 2962begin 2963 if FCodeBuffer = AValue then exit; 2964 if FCodeBuffer<>nil then begin 2965 for i := 0 to FSharedEditorList.Count - 1 do begin 2966 SharedEdit := SharedEditors[i]; 2967 if SharedEdit.FEditPlugin<>nil then 2968 SharedEdit.FEditPlugin.Changes:=nil; 2969 end; 2970 FCodeBuffer.RemoveChangeHook(@OnCodeBufferChanged); 2971 if FCodeBuffer.Scanner<>nil then 2972 DisconnectScanner(FCodeBuffer.Scanner); 2973 if FMainLinkScanner<>nil then begin 2974 DisconnectScanner(FMainLinkScanner); 2975 FMainLinkScanner:=nil; 2976 end; 2977 end; 2978 2979 for i := 0 to FSharedEditorList.Count - 1 do begin 2980 SrcEdit:=SharedEditors[i]; 2981 SrcEdit.SourceNotebook.FSrcEditsSortedForFilenames.RemovePointer(SrcEdit); 2982 end; 2983 2984 FCodeBuffer := AValue; 2985 2986 for i := 0 to FSharedEditorList.Count - 1 do begin 2987 SrcEdit:=SharedEditors[i]; 2988 SrcEdit.SourceNotebook.FSrcEditsSortedForFilenames.Add(SrcEdit); 2989 end; 2990 2991 if FCodeBuffer <> nil then 2992 begin 2993 DebugBoss.LockCommandProcessing; 2994 try 2995 for i := 0 to FSharedEditorList.Count - 1 do begin 2996 // HasExecutionMarks is shared through synedit => this is only needed once 2997 // but HasExecutionMarks must be called on each synedit, so each synedit is notified 2998 SharedEditors[i].ClearExecutionMarks; 2999 end; 3000 FCodeBuffer.AddChangeHook(@OnCodeBufferChanged); 3001 if FCodeBuffer.Scanner<>nil then 3002 ConnectScanner(FCodeBuffer.Scanner); 3003 ETChanges := SourceEditorManager.FChangesQueuedForMsgWnd.GetChanges( 3004 FCodeBuffer.Filename,true); 3005 for i := 0 to FSharedEditorList.Count - 1 do begin 3006 SharedEdit:=SharedEditors[i]; 3007 if assigned(SharedEdit.FEditPlugin) then 3008 SharedEdit.FEditPlugin.Changes := ETChanges; 3009 end; 3010 if MessagesView<>nil then 3011 MessagesView.MessagesFrame1.CreateMarksForFile(SynEditor,FCodeBuffer.Filename,true); 3012 if (FIgnoreCodeBufferLock <= 0) and (not FCodeBuffer.IsEqual(SynEditor.Lines)) 3013 then begin 3014 {$IFDEF IDE_DEBUG} 3015 debugln(' *** WARNING *** : TSourceEditor.SetCodeBuffer - loosing marks: ',FCodeBuffer.Filename); 3016 {$ENDIF} 3017 for i := 0 to FSharedEditorList.Count - 1 do begin 3018 SharedEdit:=SharedEditors[i]; 3019 if assigned(SharedEdit.FEditPlugin) then 3020 SharedEdit.FEditPlugin.Enabled := False; 3021 end; 3022 SynEditor.BeginUpdate; 3023 SynEditor.InvalidateAllIfdefNodes; 3024 FCodeBuffer.AssignTo(SynEditor.Lines, false); 3025 FEditorStampCommitedToCodetools:=(SynEditor.Lines as TSynEditLines).TextChangeStamp; 3026 SynEditor.EndUpdate; 3027 for i := 0 to FSharedEditorList.Count - 1 do begin 3028 SharedEdit:=SharedEditors[i]; 3029 if assigned(SharedEdit.FEditPlugin) then 3030 SharedEdit.FEditPlugin.Enabled := True; 3031 if SharedEdit.Visible then 3032 SharedEdit.UpdateIfDefNodeStates(True); 3033 end; 3034 end; 3035 for i := 0 to FSharedEditorList.Count - 1 do begin 3036 SharedEdit:=SharedEditors[i]; 3037 if SharedEdit.IsActiveOnNoteBook then 3038 SharedEdit.SourceNotebook.UpdateStatusBar; 3039 // HasExecutionMarks is shared through synedit => this is only needed once 3040 // but HasExecutionMarks must be called on each synedit, so each synedit is notified 3041 if (DebugBoss.State in [dsPause, dsRun]) and 3042 not SharedEdit.HasExecutionMarks and (FCodeBuffer.FileName <> '') 3043 then 3044 SharedEdit.FillExecutionMarks; 3045 end; 3046 finally 3047 DebugBoss.UnLockCommandProcessing; 3048 end; 3049 end; 3050end; 3051 3052function TSourceEditorSharedValues.GetModified: Boolean; 3053begin 3054 Result := FModified or SynEditor.Modified; 3055end; 3056 3057procedure TSourceEditorSharedValues.SetModified(const AValue: Boolean); 3058var 3059 OldModified: Boolean; 3060 i: Integer; 3061begin 3062 OldModified := Modified; // Include SynEdit 3063 FModified := AValue; 3064 if not FModified then 3065 begin 3066 SynEditor.Modified := False; // All shared SynEdits share this value 3067 FEditorStampCommitedToCodetools := TSynEditLines(SynEditor.Lines).TextChangeStamp; 3068 for i := 0 to FSharedEditorList.Count - 1 do 3069 SharedEditors[i].FEditor.MarkTextAsSaved; // Todo: centralize in SynEdit 3070 end; 3071 if OldModified <> Modified then 3072 for i := 0 to FSharedEditorList.Count - 1 do begin 3073 SharedEditors[i].UpdatePageName; 3074 SharedEditors[i].SourceNotebook.UpdateStatusBar; 3075 end; 3076end; 3077 3078procedure TSourceEditorSharedValues.OnCodeBufferChanged(Sender: TSourceLog; 3079 SrcLogEntry: TSourceLogEntry); 3080 3081 procedure MoveTxt(const StartPos, EndPos, MoveToPos: TPoint; 3082 DirectionForward: boolean); 3083 var Txt: string; 3084 begin 3085 if DirectionForward then begin 3086 SynEditor.TextBetweenPointsEx[MoveToPos, MoveToPos, scamAdjust] := 3087 SynEditor.TextBetweenPoints[StartPos, EndPos]; 3088 SynEditor.TextBetweenPointsEx[StartPos, EndPos, scamAdjust] := ''; 3089 end else begin 3090 Txt := SynEditor.TextBetweenPoints[StartPos, EndPos]; 3091 SynEditor.TextBetweenPointsEx[StartPos, EndPos, scamAdjust] := ''; 3092 SynEditor.TextBetweenPointsEx[MoveToPos, MoveToPos, scamAdjust] := Txt;; 3093 end; 3094 end; 3095 3096var 3097 StartPos, EndPos, MoveToPos: TPoint; 3098 CodeToolsInSync: Boolean; 3099 i: Integer; 3100begin 3101 {$IFDEF IDE_DEBUG} 3102 debugln(['[TSourceEditor.OnCodeBufferChanged] A ',FIgnoreCodeBufferLock,' ',SrcLogEntry<>nil]); 3103 {$ENDIF} 3104 if FIgnoreCodeBufferLock>0 then exit; 3105 DebugBoss.LockCommandProcessing; 3106 SynEditor.BeginUpdate; 3107 try 3108 CodeToolsInSync:=not NeedsUpdateCodeBuffer; 3109 if SrcLogEntry<>nil then begin 3110 SynEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorSharedValues.OnCodeBufferChanged'){$ENDIF}; 3111 SynEditor.BeginUpdate; 3112 SynEditor.TemplateEdit.IncExternalEditLock; 3113 SynEditor.SyncroEdit.IncExternalEditLock; 3114 try 3115 case SrcLogEntry.Operation of 3116 sleoInsert: 3117 begin 3118 Sender.AbsoluteToLineCol(SrcLogEntry.Position,StartPos.Y,StartPos.X); 3119 if StartPos.Y>=1 then 3120 SynEditor.TextBetweenPointsEx[StartPos, StartPos, scamAdjust] := SrcLogEntry.Txt; 3121 end; 3122 sleoDelete: 3123 begin 3124 Sender.AbsoluteToLineCol(SrcLogEntry.Position,StartPos.Y,StartPos.X); 3125 Sender.AbsoluteToLineCol(SrcLogEntry.Position+SrcLogEntry.Len, 3126 EndPos.Y,EndPos.X); 3127 if (StartPos.Y>=1) and (EndPos.Y>=1) then 3128 SynEditor.TextBetweenPointsEx[StartPos, EndPos, scamAdjust] := ''; 3129 end; 3130 sleoMove: 3131 begin 3132 Sender.AbsoluteToLineCol(SrcLogEntry.Position,StartPos.Y,StartPos.X); 3133 Sender.AbsoluteToLineCol(SrcLogEntry.Position+SrcLogEntry.Len, 3134 EndPos.Y,EndPos.X); 3135 Sender.AbsoluteToLineCol(SrcLogEntry.MoveTo,MoveToPos.Y,MoveToPos.X); 3136 if (StartPos.Y>=1) and (EndPos.Y>=1) and (MoveToPos.Y>=1) then 3137 MoveTxt(StartPos, EndPos, MoveToPos, 3138 SrcLogEntry.Position<SrcLogEntry.MoveTo); 3139 end; 3140 end; 3141 finally 3142 SynEditor.SyncroEdit.DecExternalEditLock; 3143 SynEditor.TemplateEdit.DecExternalEditLock; 3144 SynEditor.EndUpdate; 3145 SynEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorSharedValues.OnCodeBufferChanged'){$ENDIF}; 3146 end; 3147 end else begin 3148 {$IFDEF VerboseSrcEditBufClean} 3149 debugln(['TSourceEditor.OnCodeBufferChanged clean up ',TCodeBuffer(Sender).FileName,' ',Sender=CodeBuffer,' ',Filename]); 3150 DumpStack; 3151 {$ENDIF} 3152 // HasExecutionMarks is shared through synedit => this is only needed once // but HasExecutionMarks must be called on each synedit, so each synedit is notified 3153 for i := 0 to FSharedEditorList.Count - 1 do 3154 SharedEditors[i].ClearExecutionMarks; 3155 for i := 0 to SharedEditorCount-1 do 3156 SharedEditors[i].BeforeCodeBufferReplace; 3157 3158 SynEditor.InvalidateAllIfdefNodes; 3159 Sender.AssignTo(SynEditor.Lines,false); 3160 3161 for i := 0 to SharedEditorCount-1 do 3162 SharedEditors[i].AfterCodeBufferReplace; 3163 // HasExecutionMarks is shared through synedit => this is only needed once // but HasExecutionMarks must be called on each synedit, so each synedit is notified 3164 for i := 0 to FSharedEditorList.Count - 1 do begin 3165 SharedEditors[i].FillExecutionMarks; 3166 if SharedEditors[i].Visible then 3167 SharedEditors[i].UpdateIfDefNodeStates(True); 3168 end; 3169 end; 3170 if CodeToolsInSync then begin 3171 // synedit and codetools were in sync -> mark as still in sync 3172 FEditorStampCommitedToCodetools:=TSynEditLines(SynEditor.Lines).TextChangeStamp; 3173 end; 3174 finally 3175 SynEditor.EndUpdate; 3176 DebugBoss.UnLockCommandProcessing; 3177 end; 3178end; 3179 3180procedure TSourceEditorSharedValues.BeginGlobalUpdate; 3181begin 3182 inc(FInGlobalUpdate); 3183 if FInGlobalUpdate > 1 then exit; 3184 SynEditor.BeginUpdate; // locks all shared SynEdits too 3185 SynEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorSharedValues.BeginGlobalUpdate'){$ENDIF}; 3186end; 3187 3188procedure TSourceEditorSharedValues.EndGlobalUpdate; 3189begin 3190 dec(FInGlobalUpdate); 3191 if FInGlobalUpdate > 0 then exit; 3192 SynEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorSharedValues.EndGlobalUpdate'){$ENDIF}; 3193 SynEditor.EndUpdate; 3194end; 3195 3196procedure TSourceEditorSharedValues.AddSharedEditor(AnEditor: TSourceEditor); 3197begin 3198 if FSharedEditorList.IndexOf(AnEditor) < 0 then 3199 FSharedEditorList.Add(AnEditor); 3200end; 3201 3202procedure TSourceEditorSharedValues.RemoveSharedEditor(AnEditor: TSourceEditor); 3203begin 3204 FSharedEditorList.Remove(AnEditor); 3205end; 3206 3207procedure TSourceEditorSharedValues.SetActiveSharedEditor(AnEditor: TSourceEditor); 3208begin 3209 if FInGlobalUpdate > 0 then exit; 3210 // Move to the front, for UpdateCodetools (get undo-caret from correct synedit) 3211 FSharedEditorList.Remove(AnEditor); 3212 FSharedEditorList.Insert(0, AnEditor); 3213end; 3214 3215function TSourceEditorSharedValues.SharedEditorCount: Integer; 3216begin 3217 Result := FSharedEditorList.Count; 3218end; 3219 3220function TSourceEditorSharedValues.OtherSharedEditorCount: Integer; 3221begin 3222 Result := FSharedEditorList.Count - 1; 3223end; 3224 3225function TSourceEditorSharedValues.GetExecutionLine: Integer; 3226begin 3227 if (FExecutionMark = nil) or (not FExecutionMark.Visible) then 3228 Result := -1 3229 else 3230 Result := FExecutionMark.Line; 3231end; 3232 3233procedure TSourceEditorSharedValues.CreateExecutionMark; 3234begin 3235 FExecutionMark := TSourceMark.Create(SharedEditors[0], nil); 3236 SourceEditorMarks.Add(FExecutionMark); 3237 FExecutionMark.LineColorAttrib := ahaExecutionPoint; 3238 FExecutionMark.Priority := 1; 3239end; 3240 3241procedure TSourceEditorSharedValues.SetExecutionLine(NewLine: integer); 3242var 3243 BrkMark: TSourceMark; 3244 CurELine: Integer; 3245begin 3246 CurELine := ExecutionLine; 3247 if CurELine = NewLine then 3248 exit; 3249 3250 inc(UpdatingExecutionMark); 3251 try 3252 if CurELine >= 0 then begin 3253 BrkMark := SourceEditorMarks.FindBreakPointMark(SharedEditors[0], CurELine); 3254 if BrkMark <> nil then 3255 BrkMark.Visible := True; 3256 end; 3257 3258 if (FExecutionMark = nil) then 3259 CreateExecutionMark; 3260 3261 FExecutionMark.Visible := NewLine <> -1; 3262 3263 if NewLine >= 0 then begin 3264 BrkMark := SourceEditorMarks.FindBreakPointMark(SharedEditors[0], NewLine); 3265 if BrkMark <> nil then 3266 BrkMark.Visible := False; 3267 end; 3268 3269 FExecutionMark.Line := NewLine; 3270 finally 3271 dec(UpdatingExecutionMark); 3272 end; 3273end; 3274 3275procedure TSourceEditorSharedValues.IncreaseIgnoreCodeBufferLock; 3276begin 3277 inc(FIgnoreCodeBufferLock); 3278end; 3279 3280procedure TSourceEditorSharedValues.DecreaseIgnoreCodeBufferLock; 3281begin 3282 if FIgnoreCodeBufferLock<=0 then raise Exception.Create('unbalanced calls'); 3283 dec(FIgnoreCodeBufferLock); 3284end; 3285 3286function TSourceEditorSharedValues.NeedsUpdateCodeBuffer: boolean; 3287begin 3288 Result := TSynEditLines(SharedEditors[0].FEditor.Lines).TextChangeStamp 3289 <> FEditorStampCommitedToCodetools; 3290end; 3291 3292procedure TSourceEditorSharedValues.UpdateCodeBuffer; 3293begin 3294 if not NeedsUpdateCodeBuffer then exit; 3295 {$IFDEF IDE_DEBUG} 3296 if FCodeBuffer=nil then begin 3297 debugln('*********** Oh, no: UpdateCodeBuffer ************ '); 3298 end; 3299 {$ENDIF} 3300 if FCodeBuffer=nil then exit; 3301 //DebugLn(['TSourceEditor.UpdateCodeBuffer ',FCodeBuffer.FileName]); 3302 IncreaseIgnoreCodeBufferLock; 3303 SynEditor.BeginUpdate(False); 3304 try 3305 FCodeBuffer.Assign(SynEditor.Lines); 3306 FEditorStampCommitedToCodetools:=(SynEditor.Lines as TSynEditLines).TextChangeStamp; 3307 finally 3308 SynEditor.EndUpdate; 3309 DecreaseIgnoreCodeBufferLock; 3310 end; 3311end; 3312 3313function TSourceEditorSharedValues.Filename: string; 3314begin 3315 Result:=FCodeBuffer.Filename; 3316end; 3317 3318procedure TSourceEditorSharedValues.ConnectScanner(Scanner: TLinkScanner); 3319// If this is an include file, several scanners might use this file 3320// all of them should store directives 3321begin 3322 if Scanner=nil then exit; 3323 if FLinkScanners.IndexOf(Scanner)>=0 then exit; 3324 //debugln(['TSourceEditorSharedValues.ConnectScanner ',Filename,' ',Scanner.MainFilename]); 3325 FLinkScanners.Add(Scanner); 3326 Scanner.DemandStoreDirectives; 3327end; 3328 3329procedure TSourceEditorSharedValues.DisconnectScanner(Scanner: TLinkScanner); 3330var 3331 i: Integer; 3332begin 3333 if Scanner=nil then exit; 3334 i:=FLinkScanners.IndexOf(Scanner); 3335 if i<0 then exit; 3336 FLinkScanners.Delete(i); 3337 Scanner.ReleaseStoreDirectives; 3338 if Scanner=FMainLinkScanner then 3339 FMainLinkScanner:=nil; 3340end; 3341 3342function TSourceEditorSharedValues.GetMainLinkScanner(Scan: boolean): TLinkScanner; 3343// Note: if this is an include file, the main scanner may change 3344var 3345 SrcEdit: TIDESynEditor; 3346begin 3347 Result:=FMainLinkScanner; 3348 if Result=nil then 3349 begin 3350 // create main scanner 3351 //debugln(['TSourceEditorSharedValues.GetMainLinkScanner fetching unit codebuffer ...']); 3352 if CodeBuffer=nil then begin 3353 // file is currently creating 3354 //debugln(['TSourceEditorSharedValues.GetMainLinkScanner CodeBuffer=nil']); 3355 exit; 3356 end; 3357 if SharedEditorCount=0 then exit; 3358 SrcEdit:=SharedEditors[0].EditorComponent; 3359 if SrcEdit=nil then exit; 3360 if not (SrcEdit.Highlighter is TSynPasSyn) then 3361 begin 3362 if Filename<>FLastWarnedMainLinkFilename then 3363 begin 3364 if FilenameIsPascalSource(Filename) then 3365 if ConsoleVerbosity>1 then 3366 debugln(['TSourceEditorSharedValues.GetMainLinkScanner not Pascal highlighted: ',Filename,' Highligther=',DbgSName(SrcEdit.Highlighter)]); 3367 end; 3368 FLastWarnedMainLinkFilename:=Filename; 3369 exit; 3370 end; 3371 if not CodeToolBoss.InitCurCodeTool(CodeBuffer) then 3372 begin 3373 if Filename<>FLastWarnedMainLinkFilename then 3374 debugln(['TSourceEditorSharedValues.GetMainLinkScanner failed to find the unit of ',Filename]); 3375 FLastWarnedMainLinkFilename:=Filename; 3376 exit; 3377 end; 3378 Result:=CodeToolBoss.CurCodeTool.Scanner; 3379 ConnectScanner(Result); 3380 FMainLinkScanner:=Result; 3381 end; 3382 if Scan and (FMainLinkScanner<>nil) then 3383 begin 3384 try 3385 FMainLinkScanner.Scan(lsrEnd,false); 3386 except 3387 on E: Exception do begin 3388 //CodeToolBoss.HandleException(e); 3389 end; 3390 end; 3391 end; 3392end; 3393 3394constructor TSourceEditorSharedValues.Create; 3395begin 3396 FSharedEditorList := TFPList.Create; 3397 FExecutionMark := nil; 3398 FMarksRequested := False; 3399 FInGlobalUpdate := 0; 3400 FLinkScanners := TFPList.Create; 3401end; 3402 3403destructor TSourceEditorSharedValues.Destroy; 3404var 3405 i: integer; 3406begin 3407 SourceEditorMarks.DeleteAllForEditorID(Self); 3408 CodeBuffer := nil; 3409 FreeAndNil(FSharedEditorList); 3410 if FLinkScanners<>nil then begin 3411 for i:=0 to FLinkScanners.Count-1 do 3412 TLinkScanner(FLinkScanners[i]).ReleaseStoreDirectives; 3413 FreeAndNil(FLinkScanners); 3414 end; 3415 // no need to care about ExecutionMark, it is removed with all other marks, 3416 // if the last SynEdit is destroyed (TSynEditMark.Destroy will free the SourceMark) 3417 inherited Destroy; 3418end; 3419 3420{ TSourceEditor } 3421 3422{ The constructor for @link(TSourceEditor). 3423 AOwner is the @link(TSourceNotebook) 3424 and the AParent is usually a page of a @link(TPageControl) } 3425constructor TSourceEditor.Create(AOwner: TComponent; AParent: TWinControl; 3426 ASharedEditor: TSourceEditor = nil); 3427Begin 3428 FInEditorChangedUpdating := False; 3429 3430 if ASharedEditor = nil then 3431 FSharedValues := TSourceEditorSharedValues.Create 3432 else 3433 FSharedValues := ASharedEditor.FSharedValues; 3434 FSharedValues.AddSharedEditor(Self); 3435 3436 inherited Create; 3437 FAOwner := AOwner; 3438 if FAOwner is TSourceNotebook then 3439 FSourceNoteBook:=TSourceNotebook(FAOwner) 3440 else 3441 FSourceNoteBook:=nil; 3442 3443 FSyntaxHighlighterType:=lshNone; 3444 FErrorLine:=-1; 3445 FErrorColumn:=-1; 3446 FSyncroLockCount := 0; 3447 FLineInfoNotification := TIDELineInfoNotification.Create; 3448 FLineInfoNotification.AddReference; 3449 FLineInfoNotification.OnChange := @LineInfoNotificationChange; 3450 3451 CreateEditor(AOwner,AParent); 3452 FProjectFileUpdatesNeeded := []; 3453 if ASharedEditor <> nil then begin 3454 PageName := ASharedEditor.PageName; 3455 FEditor.ShareTextBufferFrom(ASharedEditor.EditorComponent); 3456 FEditor.Highlighter := ASharedEditor.EditorComponent.Highlighter; 3457 if ASharedEditor.EditorComponent.Beautifier is TSynBeautifierPascal then 3458 FEditor.Beautifier := ASharedEditor.EditorComponent.Beautifier; 3459 end; 3460 3461 FEditPlugin := TETSynPlugin.Create(FEditor); 3462 FEditPlugin.OnIsEnabled:=@IsFirstShared; 3463end; 3464 3465destructor TSourceEditor.Destroy; 3466begin 3467 DebugLnEnter(SRCED_CLOSE, ['TSourceEditor.Destroy ']); 3468 Application.RemoveAsyncCalls(Self); 3469 if FInEditorChangedUpdating then begin 3470 debugln(['***** TSourceEditor.Destroy: FInEditorChangedUpdating was true']); 3471 DebugBoss.UnLockCommandProcessing; 3472 FInEditorChangedUpdating := False; 3473 end; 3474 PopupMenu := nil; 3475 if (FAOwner<>nil) and (FEditor<>nil) then begin 3476 UnbindEditor; 3477 FEditor.Visible:=false; 3478 FEditor.Parent:=nil; 3479 TSourceNotebook(FAOwner).ReleaseEditor(self, True); 3480 // free the synedit control after processing the events 3481 EditorComponent.Owner.RemoveComponent(EditorComponent); 3482 Application.ReleaseComponent(FEditor); 3483 end; 3484 FEditor:=nil; 3485 if (DebugBoss <> nil) and (DebugBoss.LineInfo <> nil) then 3486 DebugBoss.LineInfo.RemoveNotification(FLineInfoNotification); 3487 FLineInfoNotification.ReleaseReference; 3488 inherited Destroy; 3489 FSharedValues.RemoveSharedEditor(Self); 3490 if FSharedValues.SharedEditorCount = 0 then begin 3491 if FSharedValues.MarksRequested and (FSharedValues.MarksRequestedForFile <> '') then 3492 DebugBoss.LineInfo.Cancel(FSharedValues.MarksRequestedForFile); 3493 FreeAndNil(FSharedValues); 3494 end; 3495 DebugLnExit(SRCED_CLOSE, ['TSourceEditor.Destroy ']); 3496end; 3497 3498{------------------------------G O T O L I N E -----------------------------} 3499function TSourceEditor.GotoLine(Value: Integer): Integer; 3500Var 3501 P: TPoint; 3502 NewTopLine: integer; 3503Begin 3504 Manager.AddJumpPointClicked(Self); 3505 P.X := 1; 3506 P.Y := Value; 3507 NewTopLine := P.Y - (FEditor.LinesInWindow div 2); 3508 if NewTopLine < 1 then NewTopLine:=1; 3509 FEditor.CaretXY := P; 3510 FEditor.TopLine := NewTopLine; 3511 Result:=FEditor.CaretY; 3512end; 3513 3514procedure TSourceEditor.ShowGotoLineDialog; 3515var 3516 NewLeft: integer; 3517 NewTop: integer; 3518 dlg: TfrmGoto; 3519begin 3520 dlg := Manager.GotoDialog; 3521 dlg.Edit1.Text:=''; 3522 GetDialogPosition(dlg.Width, dlg.Height, NewLeft, NewTop); 3523 dlg.SetBounds(NewLeft, NewTop, dlg.Width, dlg.Height); 3524 if (dlg.ShowModal = mrOK) then 3525 GotoLine(StrToIntDef(dlg.Edit1.Text,1)); 3526 Self.FocusEditor; 3527end; 3528 3529procedure TSourceEditor.ShowSmartHintForSourceAtCursor; 3530begin 3531 if Assigned(Manager) and Assigned(Manager.OnShowHintForSource) then 3532 Manager.OnShowHintForSource(Self,FEditor.LogicalCaretXY, False); 3533end; 3534 3535procedure TSourceEditor.GetDialogPosition(Width, Height: integer; 3536 out Left, Top: integer); 3537var 3538 P: TPoint; 3539 ABounds: TRect; 3540begin 3541 with EditorComponent do 3542 P := ClientToScreen(Point(CaretXPix, CaretYPix)); 3543 ABounds := Screen.MonitorFromPoint(P).WorkareaRect; 3544 Left := EditorComponent.ClientOrigin.X + (EditorComponent.Width - Width) div 2; 3545 Top := P.Y - Height - 3 * EditorComponent.LineHeight; 3546 if Top < ABounds.Top + 10 then 3547 Top := P.Y + 2 * EditorComponent.LineHeight; 3548 if Top + Height > ABounds.Bottom then 3549 Top := (ABounds.Bottom + ABounds.Top - Height) div 2; 3550 if Top < ABounds.Top then Top := ABounds.Top; 3551end; 3552 3553procedure TSourceEditor.ActivateHint(ClientRect: TRect; const ABaseURL, 3554 AHint: string; AAutoShown: Boolean; AMouseOffset: Boolean); 3555var 3556 ScreenRect: TRect; 3557begin 3558 if SourceNotebook=nil then exit; 3559 ScreenRect.TopLeft:=EditorComponent.ClientToScreen(ClientRect.TopLeft); 3560 ScreenRect.BottomRight:=EditorComponent.ClientToScreen(ClientRect.BottomRight); 3561 Manager.ActivateHint(ScreenRect,ABaseURL,AHint,AAutoShown,AMouseOffset); 3562end; 3563 3564{------------------------------S T A R T F I N D-----------------------------} 3565procedure TSourceEditor.StartFindAndReplace(Replace:boolean); 3566var 3567 NewOptions: TSynSearchOptions; 3568 ALeft,ATop:integer; 3569 DlgResult: TModalResult; 3570 AState: TLazFindReplaceState; 3571begin 3572 LazFindReplaceDialog.SaveState(AState); 3573 LazFindReplaceDialog.ResetUserHistory; 3574 //debugln('TSourceEditor.StartFindAndReplace A LazFindReplaceDialog.FindText="',dbgstr(LazFindReplaceDialog.FindText),'"'); 3575 if ReadOnly then Replace := False; 3576 NewOptions:=LazFindReplaceDialog.Options; 3577 if Replace then 3578 NewOptions := NewOptions + [ssoReplace, ssoReplaceAll] 3579 else 3580 NewOptions := NewOptions - [ssoReplace, ssoReplaceAll]; 3581 NewOptions:=NewOptions-InputHistoriesSO.SaveOptions 3582 +InputHistoriesSO.FindOptions[EditorComponent.SelAvail]; 3583 3584 // Fill in history items 3585 LazFindReplaceDialog.TextToFindComboBox.Items.Assign(InputHistoriesSO.FindHistory); 3586 LazFindReplaceDialog.ReplaceTextComboBox.Items.Assign(InputHistoriesSO.ReplaceHistory); 3587 3588 with EditorComponent do begin 3589 if EditorOpts.FindTextAtCursor then begin 3590 if SelAvail and (BlockBegin.Y = BlockEnd.Y) and 3591 ( ((ComparePoints(BlockBegin, LogicalCaretXY) <= 0) and 3592 (ComparePoints(BlockEnd, LogicalCaretXY) >= 0)) or 3593 ((ComparePoints(BlockBegin, LogicalCaretXY) >= 0) and 3594 (ComparePoints(BlockEnd, LogicalCaretXY) <= 0)) 3595 ) 3596 then begin 3597 //debugln('TSourceEditor.StartFindAndReplace B FindTextAtCursor SelAvail'); 3598 LazFindReplaceDialog.FindText := SelText; 3599 end else begin 3600 //debugln('TSourceEditor.StartFindAndReplace B FindTextAtCursor not SelAvail'); 3601 LazFindReplaceDialog.FindText := GetWordAtRowCol(LogicalCaretXY); 3602 end; 3603 end else begin 3604 //debugln('TSourceEditor.StartFindAndReplace B not FindTextAtCursor'); 3605 LazFindReplaceDialog.FindText:=''; 3606 end; 3607 end; 3608 LazFindReplaceDialog.EnableAutoComplete:=InputHistoriesSO.FindAutoComplete; 3609 // if there is no FindText, use the most recently used FindText 3610 if (LazFindReplaceDialog.FindText='') and (InputHistoriesSO.FindHistory.Count > 0) then 3611 LazFindReplaceDialog.FindText:=InputHistoriesSO.FindHistory[0]; 3612 3613 GetDialogPosition(LazFindReplaceDialog.Width,LazFindReplaceDialog.Height,ALeft,ATop); 3614 LazFindReplaceDialog.Left:=ALeft; 3615 LazFindReplaceDialog.Top:=ATop; 3616 3617 LazFindReplaceDialog.Options := NewOptions; 3618 DlgResult:=LazFindReplaceDialog.ShowModal; 3619 InputHistoriesSO.FindOptions[EditorComponent.SelAvail]:=LazFindReplaceDialog.Options; 3620 InputHistoriesSO.FindAutoComplete:=LazFindReplaceDialog.EnableAutoComplete; 3621 if DlgResult = mrCancel then 3622 begin 3623 LazFindReplaceDialog.RestoreState(AState); 3624 exit; 3625 end; 3626 //debugln('TSourceEditor.StartFindAndReplace B LazFindReplaceDialog.FindText="',dbgstr(LazFindReplaceDialog.FindText),'"'); 3627 3628 Replace:=ssoReplace in LazFindReplaceDialog.Options; 3629 if Replace then 3630 InputHistoriesSO.AddToReplaceHistory(LazFindReplaceDialog.ReplaceText); 3631 InputHistoriesSO.AddToFindHistory(LazFindReplaceDialog.FindText); 3632 InputHistoriesSO.Save; 3633 DoFindAndReplace(LazFindReplaceDialog.FindText, LazFindReplaceDialog.ReplaceText, 3634 LazFindReplaceDialog.Options); 3635end; 3636 3637procedure TSourceEditor.AskReplace(Sender: TObject; const ASearch, 3638 AReplace: string; Line, Column: integer; out Action: TSrcEditReplaceAction); 3639var 3640 SynAction: TSynReplaceAction; 3641begin 3642 SynAction:=raCancel; 3643 SourceNotebook.BringToFront; 3644 OnReplace(Sender, ASearch, AReplace, Line, Column, SynAction); 3645 case SynAction of 3646 raSkip: Action:=seraSkip; 3647 raReplaceAll: Action:=seraReplaceAll; 3648 raReplace: Action:=seraReplace; 3649 raCancel: Action:=seraCancel; 3650 else 3651 RaiseGDBException('TSourceEditor.AskReplace: inconsistency'); 3652 end; 3653end; 3654 3655{------------------------------F I N D A G A I N ----------------------------} 3656procedure TSourceEditor.FindNextUTF8; 3657begin 3658 if snIncrementalFind in FSourceNoteBook.States then begin 3659 FSourceNoteBook.IncrementalSearch(True, False); 3660 end 3661 else if LazFindReplaceDialog.FindText = '' then begin 3662 StartFindAndReplace(False) 3663 end 3664 else begin 3665 DoFindAndReplace(LazFindReplaceDialog.FindText, LazFindReplaceDialog.ReplaceText, 3666 LazFindReplaceDialog.Options - [ssoEntireScope, ssoSelectedOnly] 3667 + [ssoFindContinue]); 3668 end; 3669End; 3670 3671{---------------------------F I N D P R E V I O U S ------------------------} 3672procedure TSourceEditor.FindPrevious; 3673var 3674 SrchOptions: TSynSearchOptions; 3675begin 3676 if snIncrementalFind in FSourceNoteBook.States then begin 3677 FSourceNoteBook.IncrementalSearch(True, True); 3678 end 3679 else if LazFindReplaceDialog.FindText = '' then begin 3680 // TODO: maybe start with default set to backwards direction? But StartFindAndReplace replaces it with input-history 3681 StartFindAndReplace(False); 3682 end else begin 3683 SrchOptions:=LazFindReplaceDialog.Options - [ssoEntireScope, ssoSelectedOnly] 3684 + [ssoFindContinue]; 3685 if ssoBackwards in SrchOptions then 3686 SrchOptions := SrchOptions - [ssoBackwards] 3687 else 3688 SrchOptions := SrchOptions + [ssoBackwards]; 3689 DoFindAndReplace(LazFindReplaceDialog.FindText, LazFindReplaceDialog.ReplaceText, 3690 SrchOptions); 3691 end; 3692end; 3693 3694procedure TSourceEditor.FindNextWordOccurrence(DirectionForward: boolean); 3695var 3696 StartX, EndX: Integer; 3697 Flags: TSynSearchOptions; 3698 LogCaret: TPoint; 3699begin 3700 LogCaret:=EditorComponent.LogicalCaretXY; 3701 EditorComponent.GetWordBoundsAtRowCol(LogCaret,StartX,EndX); 3702 if EndX<=StartX then exit; 3703 Flags:=[ssoWholeWord]; 3704 if DirectionForward then begin 3705 LogCaret.X:=EndX; 3706 end else begin 3707 LogCaret.X:=StartX; 3708 Include(Flags,ssoBackwards); 3709 end; 3710 EditorComponent.BeginUpdate(False); 3711 try 3712 EditorComponent.LogicalCaretXY:=LogCaret; 3713 EditorComponent.SearchReplace(EditorComponent.GetWordAtRowCol(LogCaret), 3714 '',Flags); 3715 CenterCursor(True); 3716 finally 3717 EditorComponent.EndUpdate; 3718 end; 3719end; 3720 3721function TSourceEditor.DoFindAndReplace(aFindText, aReplaceText: String; 3722 anOptions: TSynSearchOptions): Integer; 3723var 3724 AText, ACaption: String; 3725 OldEntireScope, Again: Boolean; 3726begin 3727 Result:=0; 3728 if (ssoReplace in anOptions) and ReadOnly then begin 3729 DebugLn(['TSourceEditor.DoFindAndReplace Read only']); 3730 exit; 3731 end; 3732 if SourceNotebook<>nil then 3733 Manager.AddJumpPointClicked(Self); 3734 3735 OldEntireScope := ssoEntireScope in anOptions; 3736 //do not show lisUESearchStringContinueBeg/lisUESearchStringContinueEnd if the caret is in the beginning/end 3737 if ssoBackwards in anOptions then 3738 Again := ((FEditor.CaretY >= FEditor.Lines.Count) and (FEditor.CaretX > Length(FEditor.LineText)))//caret in the last line and last character 3739 else 3740 Again := ((FEditor.CaretY = 1) and (FEditor.CaretX = 1));//caret at the top/left 3741 repeat 3742 try 3743 Result:=EditorComponent.SearchReplace(aFindText, aReplaceText, anOptions); 3744 except 3745 on E: ERegExpr do begin 3746 IDEMessageDialog(lisUEErrorInRegularExpression, E.Message,mtError,[mbCancel]); 3747 exit; 3748 end; 3749 end; 3750 if (Result = 0) and not (ssoReplaceAll in anOptions) then begin 3751 ACaption:=lisUENotFound; 3752 AText:=Format(lisUESearchStringNotFound, [Utf8EscapeControlChars(aFindText, emPascal)]); 3753 if not (Again or OldEntireScope) then begin 3754 if ssoBackwards in anOptions then 3755 AText:=AText+' '+lisUESearchStringContinueEnd 3756 else 3757 AText:=AText+' '+lisUESearchStringContinueBeg; 3758 Again:=MessageDlg(ACaption, AText, mtConfirmation, [mbYes,mbNo], 0) = mrYes; 3759 anOptions:=anOptions + [ssoEntireScope]; 3760 end 3761 else begin 3762 Again := False; 3763 IDEMessageDialog(ACaption, AText, mtInformation, [mbOK]); 3764 end; 3765 if not Again then 3766 Manager.DeleteLastJumpPointClicked(Self); 3767 end 3768 else begin 3769 Again := False; 3770 CenterCursor(True); 3771 end; 3772 until not Again; 3773end; 3774 3775procedure TSourceEditor.OnReplace(Sender: TObject; const ASearch, AReplace: 3776 string; Line, Column: integer; var Action: TSynReplaceAction); 3777 3778 function Shorten(const s: string): string; 3779 const 3780 MAX_LEN=300; 3781 begin 3782 Result:=s; 3783 if Length(Result)>MAX_LEN then 3784 Result:=LeftStr(Result, MAX_LEN)+'...'; 3785 end; 3786 3787var a,x,y:integer; 3788 AText:AnsiString; 3789begin 3790 if FAOwner<>nil then 3791 TSourceNotebook(FAOwner).UpdateStatusBar; 3792 3793 CenterCursor(True); 3794 CenterCursorHoriz(hcmSoftKeepEOL); 3795 3796 AText:=Format(lisUEReplaceThisOccurrenceOfWith,[Shorten(ASearch),LineEnding,Shorten(AReplace)]); 3797 3798 GetDialogPosition(FEditor.Scale96ToFont(300), FEditor.Scale96ToFont(150), X, Y); 3799 a:=MessageDlgPos(AText,mtconfirmation, 3800 [mbYes,mbYesToAll,mbNo,mbCancel],0,X,Y); 3801 3802 case a of 3803 mrYes:Action:=raReplace; 3804 mrNo :Action:=raSkip; 3805 mrAll,mrYesToAll:Action:=raReplaceAll; 3806 else 3807 Action:=raCancel; 3808 end; 3809end; 3810 3811//----------------------------------------------------------------------------- 3812 3813procedure TSourceEditor.FocusEditor; 3814Begin 3815 DebugLnEnter(SRCED_PAGES, ['>> TSourceEditor.FocusEditor A ',PageName,' ',FEditor.Name]); 3816 IDEWindowCreators.ShowForm(SourceNotebook, true, vmOnlyMoveOffScreenToVisible); 3817 if FEditor.IsVisible then begin 3818 FEditor.SetFocus; // TODO: will cal EditorEnter, which does self.Activate => maybe lock, and do here? 3819 FSharedValues.SetActiveSharedEditor(Self); 3820 end else begin 3821 debugln(SRCED_PAGES, ['TSourceEditor.FocusEditor not IsVisible: ',PageName,' ',FEditor.Name]); 3822 end; 3823 //DebugLn('TSourceEditor.FocusEditor ',dbgsName(FindOwnerControl(GetFocus)),' ',dbgs(GetFocus)); 3824 DebugLnExit(SRCED_PAGES, ['<< TSourceEditor.FocusEditor END ',PageName,' ',FEditor.Name]); 3825end; 3826 3827function TSourceEditor.GetReadOnly: Boolean; 3828Begin 3829 Result:=FEditor.ReadOnly; 3830End; 3831 3832procedure TSourceEditor.SetReadOnly(const NewValue: boolean); 3833begin 3834 FEditor.ReadOnly:=NewValue; 3835end; 3836 3837function TSourceEditor.Manager: TSourceEditorManager; 3838begin 3839 if FSourceNoteBook <> nil then 3840 Result := FSourceNoteBook.Manager 3841 else 3842 Result := nil; 3843end; 3844 3845procedure TSourceEditor.MoveToWindow(AWindowIndex: Integer); 3846begin 3847 SourceNotebook.MoveEditor(PageIndex, AWindowIndex, -1) 3848end; 3849 3850function TSourceEditor.GetSharedValues: TSourceEditorSharedValuesBase; 3851begin 3852 Result := FSharedValues; 3853end; 3854 3855function TSourceEditor.IsSharedWith(AnOtherEditor: TSourceEditor): Boolean; 3856begin 3857 Result := (AnOtherEditor <> nil) and 3858 (AnOtherEditor.FSharedValues = FSharedValues); 3859end; 3860 3861procedure TSourceEditor.BeforeCodeBufferReplace; 3862begin 3863 FTempTopLine := FEditor.TopLine; 3864 FTempCaret := FEditor.CaretXY; 3865end; 3866 3867procedure TSourceEditor.AfterCodeBufferReplace; 3868begin 3869 if (FTempTopLine > FEditor.Lines.Count) or(FTempCaret.Y > FEditor.Lines.Count) 3870 then 3871 exit; 3872 FEditor.TopLine := FTempTopLine; 3873 FEditor.CaretXY := FTempCaret; 3874end; 3875 3876procedure TSourceEditor.DoMultiCaretBeforeCommand(Sender: TObject; 3877 ACommand: TSynEditorCommand; var AnAction: TSynMultiCaretCommandAction; 3878 var AFlags: TSynMultiCaretCommandFlags); 3879begin 3880 if (FSourceNoteBook<>nil) and (snIncrementalFind in FSourceNoteBook.States) then begin 3881 AnAction := ccaClearCarets; 3882 end; 3883 3884 case ACommand of 3885 ecToggleComment: 3886 if FEditor.SelAvail then 3887 AnAction := ccaAdjustCarets 3888 else 3889 AnAction := ccaRepeatCommandPerLine; // one per line 3890 ecInsertUserName, 3891 ecInsertDateTime, 3892 ecInsertChangeLogEntry, 3893 ecInsertCVSAuthor, 3894 ecInsertCVSDate, 3895 ecInsertCVSHeader, 3896 ecInsertCVSID, 3897 ecInsertCVSLog, 3898 ecInsertCVSName, 3899 ecInsertCVSRevision, 3900 ecInsertCVSSource, 3901 ecInsertGUID, 3902 ecInsertFilename: 3903 AnAction := ccaRepeatCommand; 3904 end; 3905end; 3906 3907procedure TSourceEditor.ProcessCommand(Sender: TObject; 3908 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer); 3909// these are normal commands for synedit (lower than ecUserFirst), 3910// define extra actions here 3911// for non synedit keys (bigger than ecUserFirst) use ProcessUserCommand 3912var 3913 AddChar, IsIdent, ok: Boolean; 3914 s, AttrName: String; 3915 i, WordStart, WordEnd: Integer; 3916 p: TPoint; 3917begin 3918 //DebugLn('TSourceEditor.ProcessCommand Command=',dbgs(Command)); 3919 FSharedValues.SetActiveSharedEditor(Self); 3920 AutoStartCompletionBoxTimer.AutoEnabled:=false; 3921 if FCodeCompletionState.State in [ccsDot, ccsOnTyping] then 3922 FCodeCompletionState.State := ccsReady; 3923 3924 if (Command=ecChar) and (AChar=#27) then begin 3925 // close hint windows 3926 if (CodeContextFrm<>nil) then 3927 CodeContextFrm.Hide; 3928 if (SrcEditHintWindow<>nil) then 3929 SrcEditHintWindow.Hide; 3930 end; 3931 Manager.HideHint; 3932 3933 if (FSourceNoteBook<>nil) 3934 and (snIncrementalFind in FSourceNoteBook.States) then begin 3935 case Command of 3936 ecChar: 3937 begin 3938 if AChar=#27 then begin 3939 if (CodeContextFrm<>nil) then 3940 CodeContextFrm.Hide; 3941 3942 FSourceNoteBook.IncrementalSearchStr:=''; 3943 end else 3944 FSourceNoteBook.IncrementalSearchStr:= 3945 FSourceNoteBook.IncrementalSearchStr+AChar; 3946 Command:=ecNone; 3947 end; 3948 3949 ecDeleteLastChar: 3950 begin 3951 i := length(FSourceNoteBook.IncrementalSearchStr); 3952 i := UTF8FindNearestCharStart(PChar(FSourceNoteBook.IncrementalSearchStr), i, i-1); 3953 FSourceNoteBook.IncrementalSearchStr:= LeftStr(FSourceNoteBook.IncrementalSearchStr, i); 3954 Command:=ecNone; 3955 end; 3956 3957 ecLineBreak: 3958 begin 3959 FSourceNoteBook.EndIncrementalFind; 3960 Command:=ecNone; 3961 end; 3962 3963 ecPaste: 3964 begin 3965 s:=Clipboard.AsText; 3966 s:=copy(s,1,EditorOpts.RightMargin); 3967 FSourceNoteBook.IncrementalSearchStr:= 3968 FSourceNoteBook.IncrementalSearchStr+s; 3969 Command:=ecNone; 3970 end; 3971 3972 ecScrollUp, ecScrollDown, ecScrollLeft, ecScrollRight: ; // ignore 3973 3974 else 3975 FSourceNoteBook.EndIncrementalFind; 3976 end; 3977 end; 3978 3979 case Command of 3980 3981 ecSelEditorTop, ecSelEditorBottom, ecEditorTop, ecEditorBottom: 3982 begin 3983 if (FaOwner<>nil) and (not FEditor.IsInMultiCaretRepeatExecution) then 3984 Manager.AddJumpPointClicked(Self); 3985 end; 3986 3987 ecCopy,ecCut,ecCopyAdd,ecCutAdd: 3988 begin 3989 if (not FEditor.SelAvail) then begin 3990 // nothing selected 3991 if EditorOpts.CopyWordAtCursorOnCopyNone then begin 3992 FEditor.SelectWord; 3993 end; 3994 end; 3995 end; 3996 3997 ecTab: 3998 begin 3999 AddChar:=true; 4000 if AutoCompleteChar(aChar,AddChar,acoTab) then begin 4001 // completed 4002 end; 4003 if not AddChar then Command:=ecNone; 4004 end; 4005 4006 ecChar: 4007 begin 4008 AddChar:=true; 4009 IsIdent:=FEditor.IsIdentChar(aChar); 4010 //debugln(['TSourceEditor.ProcessCommand AChar="',AChar,'" AutoIdentifierCompletion=',dbgs(EditorOpts.AutoIdentifierCompletion),' Interval=',AutoStartCompletionBoxTimer.Interval,' ',Dbgs(FEditor.CaretXY),' ',FEditor.IsIdentChar(aChar)]); 4011 if (aChar=' ') and AutoCompleteChar(aChar,AddChar,acoSpace) then begin 4012 // completed 4013 end 4014 else 4015 if (not IsIdent) 4016 and AutoCompleteChar(aChar,AddChar,acoWordEnd) then begin 4017 // completed 4018 end 4019 else 4020 if CodeToolsOpts.IdentComplAutoInvokeOnType and 4021 ( IsIdent or (AChar='.') ) and 4022 (ActiveEditorMacro = nil) 4023 then begin 4024 // store caret position to detect caret changes // add the char 4025 p := FEditor.LogicalCaretXY; 4026 SourceCompletionCaretXY:=p; 4027 inc(SourceCompletionCaretXY.x,length(AChar)); 4028 4029 AttrName := GetCodeAttributeName(p); 4030 ok := (FCodeCompletionState.State <> ccsCancelled) and 4031 (FEditor.MultiCaret.CaretsCount = 0) and 4032 (AttrName <> SYNS_XML_AttrComment) and 4033 (AttrName <> SYNS_XML_AttrDirective) and 4034 (AttrName <> SYNS_XML_AttrString); 4035 if ok then begin 4036 if AChar = '.' then begin 4037 ok := CodeToolsOpts.IdentComplAutoStartAfterPoint; 4038 end 4039 else 4040 if (CodeToolsOpts.IdentComplOnTypeMinLength > 1) or CodeToolsOpts.IdentComplOnTypeOnlyWordEnd 4041 then begin 4042 FEditor.GetWordBoundsAtRowCol(p, WordStart, WordEnd); 4043 ok := (p.x <= WordEnd) and // inside word 4044 ((not CodeToolsOpts.IdentComplOnTypeOnlyWordEnd) or (p.x = WordEnd)) and // at word end? 4045 ((WordEnd-WordStart+1) >= CodeToolsOpts.IdentComplOnTypeMinLength); 4046 end; 4047 end; 4048 4049 if ok then begin 4050 if CodeToolsOpts.IdentComplOnTypeUseTimer then begin 4051 AutoStartCompletionBoxTimer.AutoEnabled:=true; 4052 FCodeCompletionState.State := ccsOnTyping; 4053 end 4054 else begin 4055 FCodeCompletionState.State := ccsOnTypingScheduled; 4056 end; 4057 end; 4058 end 4059 else 4060 if CodeToolsOpts.IdentComplAutoStartAfterPoint and 4061 (AChar='.') and (ActiveEditorMacro = nil) 4062 then begin 4063 // store caret position to detect caret changes // add the char 4064 SourceCompletionCaretXY:=FEditor.LogicalCaretXY; 4065 inc(SourceCompletionCaretXY.x,length(AChar)); 4066 AutoStartCompletionBoxTimer.AutoEnabled:=true; 4067 FCodeCompletionState.State := ccsDot; 4068 end; 4069 //DebugLn(['TSourceEditor.ProcessCommand ecChar AddChar=',AddChar]); 4070 if not AddChar then Command:=ecNone; 4071 end; 4072 4073 ecLineBreak: 4074 begin 4075 AddChar:=true; 4076 if AutoCompleteChar(aChar,AddChar,acoLineBreak) then ; 4077 //DebugLn(['TSourceEditor.ProcessCommand ecLineBreak AddChar=',AddChar,' EditorOpts.AutoBlockCompletion=',EditorOpts.AutoBlockCompletion]); 4078 if not AddChar then Command:=ecNone; 4079 if EditorOpts.AutoBlockCompletion then 4080 AutoCompleteBlock; 4081 end; 4082 4083 ecPrevBookmark: // Note: book mark commands lower than ecUserFirst must be handled here 4084 if Assigned(Manager.OnGotoBookmark) then 4085 Manager.OnGotoBookmark(Self, -1, True); 4086 4087 ecNextBookmark: 4088 if Assigned(Manager.OnGotoBookmark) then 4089 Manager.OnGotoBookmark(Self, -1, False); 4090 4091 ecGotoMarker0..ecGotoMarker9: 4092 if Assigned(Manager.OnGotoBookmark) then 4093 Manager.OnGotoBookmark(Self, Command - ecGotoMarker0, False); 4094 4095 ecSetMarker0..ecSetMarker9: 4096 if Assigned(Manager.OnSetBookmark) then 4097 Manager.OnSetBookmark(Self, Command - ecSetMarker0, False); 4098 4099 ecToggleMarker0..ecToggleMarker9: 4100 if Assigned(Manager.OnSetBookmark) then 4101 Manager.OnSetBookmark(Self, Command - ecToggleMarker0, True); 4102 4103 ecSelectAll: 4104 Manager.AddJumpPointClicked(Self); 4105 4106 end; 4107 //debugln('TSourceEditor.ProcessCommand B IdentCompletionTimer.AutoEnabled=',dbgs(AutoStartCompletionBoxTimer.AutoEnabled)); 4108end; 4109 4110procedure TSourceEditor.ProcessUserCommand(Sender: TObject; 4111 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer); 4112// these are the keys above ecUserFirst 4113// define all extra keys here, that should not be handled by synedit 4114var 4115 Handled: boolean; 4116 i,x,y: Integer; 4117Begin 4118 //debugln('TSourceEditor.ProcessUserCommand A ',dbgs(Command)); 4119 FSharedValues.SetActiveSharedEditor(Self); 4120 Handled:=true; 4121 CheckActiveWindow; 4122 4123 case Command of 4124 ecMultiPaste: MultiPasteText; 4125 ecContextHelp: FindHelpForSourceAtCursor; 4126 ecSmartHint: ShowSmartHintForSourceAtCursor; 4127 ecIdentCompletion: StartIdentCompletionBox(CodeToolsOpts.IdentComplJumpToError,true); 4128 ecShowCodeContext: SourceNotebook.StartShowCodeContext(CodeToolsOpts.IdentComplJumpToError); 4129 ecWordCompletion: StartWordCompletionBox; 4130 ecFind: StartFindAndReplace(false); 4131 ecFindNext: FindNextUTF8; 4132 ecFindPrevious: FindPrevious; 4133 ecIncrementalFind: if FSourceNoteBook<>nil then FSourceNoteBook.BeginIncrementalFind; 4134 ecReplace: StartFindAndReplace(true); 4135 ecGotoLineNumber: ShowGotoLineDialog; 4136 ecFindNextWordOccurrence: FindNextWordOccurrence(true); 4137 ecFindPrevWordOccurrence: FindNextWordOccurrence(false); 4138 ecSelectionEnclose: EncloseSelection; 4139 ecSelectionUpperCase: UpperCaseSelection; 4140 ecSelectionLowerCase: LowerCaseSelection; 4141 ecSelectionSwapCase: SwapCaseSelection; 4142 ecSelectionTabs2Spaces: TabsToSpacesInSelection; 4143 ecSelectionComment: CommentSelection; 4144 ecSelectionUnComment: UncommentSelection; 4145 ecToggleComment: ToggleCommentSelection; 4146 ecSelectionEncloseIFDEF: ConditionalSelection; 4147 ecSelectionSort: SortSelection; 4148 ecSelectionBreakLines: BreakLinesInSelection; 4149 ecInvertAssignment: InvertAssignment; 4150 ecSelectToBrace: SelectToBrace; 4151 ecSelectLine: SelectLine; 4152 ecSelectWord: SelectWord; 4153 ecSelectParagraph: SelectParagraph; 4154 ecInsertCharacter: InsertCharacterFromMap; 4155 ecInsertGPLNotice: InsertGPLNotice(comtDefault,false); 4156 ecInsertGPLNoticeTranslated: InsertGPLNotice(comtDefault,true); 4157 ecInsertLGPLNotice: InsertLGPLNotice(comtDefault,false); 4158 ecInsertLGPLNoticeTranslated:InsertLGPLNotice(comtDefault,true); 4159 ecInsertModifiedLGPLNotice: InsertModifiedLGPLNotice(comtDefault,false); 4160 ecInsertModifiedLGPLNoticeTranslated: InsertModifiedLGPLNotice(comtDefault,true); 4161 ecInsertMITNotice: InsertMITNotice(comtDefault,false); 4162 ecInsertMITNoticeTranslated: InsertMITNotice(comtDefault,true); 4163 ecInsertUserName: InsertUsername; 4164 ecInsertDateTime: InsertDateTime; 4165 ecInsertChangeLogEntry: InsertChangeLogEntry; 4166 ecInsertCVSAuthor: InsertCVSKeyword('Author'); 4167 ecInsertCVSDate: InsertCVSKeyword('Date'); 4168 ecInsertCVSHeader: InsertCVSKeyword('Header'); 4169 ecInsertCVSID: InsertCVSKeyword('ID'); 4170 ecInsertCVSLog: InsertCVSKeyword('Log'); 4171 ecInsertCVSName: InsertCVSKeyword('Name'); 4172 ecInsertCVSRevision: InsertCVSKeyword('Revision'); 4173 ecInsertCVSSource: InsertCVSKeyword('Source'); 4174 ecInsertGUID: InsertGUID; 4175 ecInsertFilename: InsertFilename; 4176 ecLockEditor: IsLocked := not IsLocked; 4177 ecSynMacroPlay: begin 4178 If ActiveEditorMacro = EditorMacroForRecording then begin 4179 if EditorMacroForRecording.State = emRecording 4180 then EditorMacroForRecording.Pause 4181 else EditorMacroForRecording.Resume; 4182 end 4183 else 4184 if (SelectedEditorMacro <> nil) and 4185 (SelectedEditorMacro.State = emStopped) 4186 then 4187 SelectedEditorMacro.PlaybackMacro(FEditor); 4188 end; 4189 ecSynMacroRecord: begin 4190 If ActiveEditorMacro = nil then 4191 EditorMacroForRecording.RecordMacro(FEditor) 4192 else 4193 If ActiveEditorMacro = EditorMacroForRecording then 4194 EditorMacroForRecording.Stop; 4195 end; 4196 ecClearBookmarkForFile: begin 4197 if Assigned(Manager) and Assigned(Manager.OnClearBookmarkId) then 4198 for i in TBookmarkNumRange do 4199 if EditorComponent.GetBookMark(i,x{%H-},y{%H-}) then 4200 Manager.OnClearBookmarkId(Self, i); 4201 end; 4202 4203 ecCloseOtherTabs: Application.QueueAsyncCall(@Manager.CloseOtherPagesClickedAsync, PtrInt(SourceNotebook.GetNoteBookPage(SourceNotebook.FindPageWithEditor(Self)))); 4204 ecCloseRightTabs: Application.QueueAsyncCall(@Manager.CloseRightPagesClickedAsync, PtrInt(SourceNotebook.GetNoteBookPage(SourceNotebook.FindPageWithEditor(Self)))); 4205 4206 else 4207 begin 4208 Handled:=false; 4209 if FaOwner<>nil then 4210 TSourceNotebook(FaOwner).ProcessParentCommand(self,Command,aChar,Data, 4211 Handled); 4212 end; 4213 end; //case 4214 if Handled then Command:=ecNone; 4215end; 4216 4217procedure TSourceEditor.UserCommandProcessed(Sender: TObject; 4218 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer); 4219// called after the source editor processed a key 4220var Handled: boolean; 4221begin 4222 Handled:=true; 4223 4224 if (Command <> ecCompleteCode) and (Command <> ecCompleteCodeInteractive) and 4225 (FCodeCompletionState.State = ccsCancelled) 4226 then begin 4227 if CompareCaret(FCodeCompletionState.LastTokenStartPos, CurrentWordLogStartOrCaret) <> 0 then 4228 FCodeCompletionState.State := ccsReady; 4229 end; 4230 4231 case Command of 4232 ecNone: ; 4233 4234 ecChar: 4235 begin 4236 if AutoBlockCompleteChar(AChar) then 4237 Handled:=true; 4238 if EditorOpts.AutoDisplayFunctionPrototypes then 4239 if (aChar = '(') or (aChar = ',') then 4240 SourceNotebook.StartShowCodeContext(False); 4241 4242 if FCodeCompletionState.State = ccsOnTypingScheduled then begin 4243 FCodeCompletionState.State := ccsOnTyping; 4244 StartIdentCompletionBox(false,false); 4245 end; 4246 end; 4247 4248 else 4249 begin 4250 Handled:=false; 4251 if FaOwner<>nil then 4252 TSourceNotebook(FaOwner).ParentCommandProcessed(Self,Command,aChar,Data, 4253 Handled); 4254 end; 4255 end; 4256 if Handled then Command:=ecNone; 4257end; 4258 4259procedure TSourceEditor.EditorStatusChanged(Sender: TObject; 4260 Changes: TSynStatusChanges); 4261Begin 4262 If Assigned(OnEditorChange) then 4263 OnEditorChange(Sender, Changes); 4264 UpdatePageName; 4265 if Changes * [scCaretX, scCaretY, scSelection] <> [] then 4266 IDECommandList.PostponeUpdateEvents; 4267end; 4268 4269function TSourceEditor.SelectionAvailable: boolean; 4270begin 4271 Result := EditorComponent.SelAvail; 4272end; 4273 4274function TSourceEditor.GetText(OnlySelection: boolean): string; 4275begin 4276 if OnlySelection then 4277 Result:=EditorComponent.SelText 4278 else 4279 Result:=EditorComponent.Lines.Text; 4280end; 4281 4282procedure TSourceEditor.UpperCaseSelection; 4283// Turns current text selection uppercase. 4284begin 4285 if ReadOnly then exit; 4286 if not EditorComponent.SelAvail then exit; 4287 FEditor.SetTextBetweenPoints(FEditor.BlockBegin, FEditor.BlockEnd, 4288 UTF8UpperCase(EditorComponent.SelText), 4289 [setSelect], scamIgnore, smaKeep, smCurrent 4290 ); 4291end; 4292 4293procedure TSourceEditor.LowerCaseSelection; 4294// Turns current text selection lowercase. 4295begin 4296 if ReadOnly then exit; 4297 if not EditorComponent.SelAvail then exit; 4298 FEditor.SetTextBetweenPoints(FEditor.BlockBegin, FEditor.BlockEnd, 4299 UTF8LowerCase(EditorComponent.SelText), 4300 [setSelect], scamIgnore, smaKeep, smCurrent 4301 ); 4302end; 4303 4304procedure TSourceEditor.SwapCaseSelection; 4305begin 4306 if ReadOnly then exit; 4307 if not EditorComponent.SelAvail then exit; 4308 FEditor.SetTextBetweenPoints(FEditor.BlockBegin, FEditor.BlockEnd, 4309 UTF8SwapCase(EditorComponent.SelText), 4310 [setSelect], scamIgnore, smaKeep, smCurrent 4311 ); 4312end; 4313 4314{------------------------------------------------------------------------------- 4315 method TSourceEditor.TabsToSpacesInSelection 4316 4317 Convert all tabs into spaces in current text selection. 4318-------------------------------------------------------------------------------} 4319procedure TSourceEditor.TabsToSpacesInSelection; 4320begin 4321 if ReadOnly then exit; 4322 if not EditorComponent.SelAvail then exit; 4323 FEditor.SetTextBetweenPoints(FEditor.BlockBegin, FEditor.BlockEnd, 4324 TabsToSpaces(EditorComponent.SelText, EditorComponent.TabWidth, FEditor.UseUTF8), 4325 [setSelect], scamAdjust, smaKeep, smCurrent 4326 ); 4327end; 4328 4329procedure TSourceEditor.CommentSelection; 4330begin 4331 UpdateCommentSelection(True, False); 4332end; 4333 4334procedure TSourceEditor.UncommentSelection; 4335begin 4336 UpdateCommentSelection(False, False); 4337end; 4338 4339procedure TSourceEditor.ToggleCommentSelection; 4340begin 4341 UpdateCommentSelection(False, True); 4342end; 4343 4344procedure TSourceEditor.UpdateCommentSelection(CommentOn, Toggle: Boolean); 4345var 4346 OldCaretPos, OldBlockStart, OldBlockEnd: TPoint; 4347 WasSelAvail: Boolean; 4348 WasSelMode: TSynSelectionMode; 4349 BlockBeginLine: Integer; 4350 BlockEndLine: Integer; 4351 CommonIndent: Integer; 4352 4353 function FirstNonBlankPos(const Text: String; Start: Integer = 1): Integer; 4354 var 4355 i: Integer; 4356 begin 4357 for i := Start to Length(Text) do 4358 if (Text[i] <> #32) and (Text[i] <> #9) then 4359 exit(i); 4360 Result := -1; 4361 end; 4362 4363 function MinCommonIndent: Integer; 4364 var 4365 i, j: Integer; 4366 begin 4367 If CommonIndent = 0 then begin 4368 CommonIndent := Max(FirstNonBlankPos(FEditor.Lines[BlockBeginLine - 1]), 1); 4369 for i := BlockBeginLine + 1 to BlockEndLine do begin 4370 j := FirstNonBlankPos(FEditor.Lines[i - 1]); 4371 if (j < CommonIndent) and (j > 0) then 4372 CommonIndent := j; 4373 end; 4374 end; 4375 Result := CommonIndent; 4376 end; 4377 4378 function InsertPos(ALine: Integer): Integer; 4379 begin 4380 if not WasSelAvail then 4381 Result := MinCommonIndent 4382 else case WasSelMode of 4383 smColumn: // CommonIndent is not used otherwise 4384 begin 4385 if CommonIndent = 0 then 4386 CommonIndent := Min(FEditor.LogicalToPhysicalPos(OldBlockStart).X, 4387 FEditor.LogicalToPhysicalPos(OldBlockEnd).X); 4388 Result := FEditor.PhysicalToLogicalPos(Point(CommonIndent, ALine)).X; 4389 end; 4390 smNormal: 4391 begin 4392 Result := MinCommonIndent; 4393 end; 4394 else 4395 Result := 1; 4396 end; 4397 end; 4398 4399 function DeletePos(ALine: Integer): Integer; 4400 var 4401 line: String; 4402 begin 4403 line := FEditor.Lines[ALine - 1]; 4404 Result := FirstNonBlankPos(line, InsertPos(ALine)); 4405 if (WasSelMode = smColumn) and((Result < 1) or (Result > length(line) - 1)) 4406 then 4407 Result := length(line) - 1; 4408 Result := Max(1, Result); 4409 if (Length(line) < Result +1) or 4410 (line[Result] <> '/') or (line[Result+1] <> '/') then 4411 Result := -1; 4412 end; 4413 4414var 4415 i: Integer; 4416 NonBlankStart: Integer; 4417begin 4418 if ReadOnly then exit; 4419 OldCaretPos := FEditor.CaretXY; 4420 OldBlockStart := FEditor.BlockBegin; 4421 OldBlockEnd := FEditor.BlockEnd; 4422 WasSelAvail := FEditor.SelAvail; 4423 WasSelMode := FEditor.SelectionMode; 4424 CommonIndent := 0; 4425 4426 BlockBeginLine := OldBlockStart.Y; 4427 BlockEndLine := OldBlockEnd.Y; 4428 if (OldBlockEnd.X = 1) and (BlockEndLine > BlockBeginLine) and (FEditor.SelectionMode <> smLine) then 4429 Dec(BlockEndLine); 4430 4431 if Toggle then begin 4432 CommentOn := False; 4433 for i := BlockBeginLine to BlockEndLine do 4434 if DeletePos(i) < 0 then begin 4435 CommentOn := True; 4436 break; 4437 end; 4438 end; 4439 4440 BeginUpdate; 4441 BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.UpdateCommentSelection'){$ENDIF}; 4442 FEditor.SelectionMode := smNormal; 4443 4444 if CommentOn then begin 4445 for i := BlockEndLine downto BlockBeginLine do 4446 FEditor.TextBetweenPoints[Point(InsertPos(i), i), Point(InsertPos(i), i)] := '//'; 4447 if OldCaretPos.X > InsertPos(OldCaretPos.Y) then 4448 OldCaretPos.x := OldCaretPos.X + 2; 4449 if OldBlockStart.X > InsertPos(OldBlockStart.Y) then 4450 OldBlockStart.X := OldBlockStart.X + 2; 4451 if OldBlockEnd.X > InsertPos(OldBlockEnd.Y) then 4452 OldBlockEnd.X := OldBlockEnd.X + 2; 4453 end 4454 else begin 4455 for i := BlockEndLine downto BlockBeginLine do 4456 begin 4457 NonBlankStart := DeletePos(i); 4458 if NonBlankStart < 1 then continue; 4459 FEditor.TextBetweenPoints[Point(NonBlankStart, i), Point(NonBlankStart + 2, i)] := ''; 4460 if (OldCaretPos.Y = i) and (OldCaretPos.X > NonBlankStart) then 4461 OldCaretPos.x := Max(OldCaretPos.X - 2, NonBlankStart); 4462 if (OldBlockStart.Y = i) and (OldBlockStart.X > NonBlankStart) then 4463 OldBlockStart.X := Max(OldBlockStart.X - 2, NonBlankStart); 4464 if (OldBlockEnd.Y = i) and (OldBlockEnd.X > NonBlankStart) then 4465 OldBlockEnd.X := Max(OldBlockEnd.X - 2, NonBlankStart); 4466 end; 4467 end; 4468 4469 EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.UpdateCommentSelection'){$ENDIF}; 4470 EndUpdate; 4471 4472 FEditor.CaretXY := OldCaretPos; 4473 FEditor.BlockBegin := OldBlockStart; 4474 FEditor.BlockEnd := OldBlockEnd; 4475 FEditor.SelectionMode := WasSelMode; 4476end; 4477 4478procedure TSourceEditor.ConditionalSelection; 4479var 4480 IsPascal: Boolean; 4481 i: Integer; 4482 P: TPoint; 4483begin 4484 if ReadOnly then exit; 4485 FEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.ConditionalSelection'){$ENDIF}; 4486 try 4487 if not EditorComponent.SelAvail then begin 4488 P.Y := FEditor.CaretY; 4489 P.X := 1; 4490 FEditor.BlockBegin := P; 4491 Inc(P.Y); 4492 FEditor.BlockEnd := P; 4493 end; 4494 // ToDo: replace step by step to keep bookmarks and breakpoints 4495 IsPascal := True; 4496 i:=EditorOpts.HighlighterList.FindByHighlighter(FEditor.Highlighter); 4497 if i>=0 then 4498 IsPascal := EditorOpts.HighlighterList[i].DefaultCommentType <> comtCPP; 4499 // will show modal dialog - must not be in Editor.BeginUpdate block, or painting will not work 4500 FEditor.SelText:=EncloseInsideIFDEF(EditorComponent.SelText,IsPascal); 4501 finally 4502 FEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.ConditionalSelection'){$ENDIF}; 4503 end; 4504end; 4505 4506procedure TSourceEditor.SortSelection; 4507var 4508 OldSelText, NewSortedText: string; 4509begin 4510 if ReadOnly then exit; 4511 OldSelText:=EditorComponent.SelText; 4512 if OldSelText='' then exit; 4513 if ShowSortSelectionDialog(OldSelText,EditorComponent.Highlighter, 4514 NewSortedText)=mrOk 4515 then 4516 EditorComponent.SelText:=NewSortedText; 4517end; 4518 4519procedure TSourceEditor.BreakLinesInSelection; 4520var 4521 OldSelection: String; 4522begin 4523 if ReadOnly then exit; 4524 if not EditorComponent.SelAvail then exit; 4525 FEditor.BeginUpdate; 4526 FEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.BreakLinesInSelection'){$ENDIF}; 4527 // ToDo: replace step by step to keep bookmarks and breakpoints 4528 try 4529 OldSelection:=EditorComponent.SelText; 4530 FEditor.SelText:=BreakLinesInText(OldSelection,FEditor.RightEdge); 4531 finally 4532 FEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.BreakLinesInSelection'){$ENDIF}; 4533 FEditor.EndUpdate; 4534 end; 4535end; 4536 4537procedure TSourceEditor.InvertAssignment; 4538begin 4539 if ReadOnly then exit; 4540 if not EditorComponent.SelAvail then exit; 4541 FEditor.BeginUpdate; 4542 FEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.InvertAssignment'){$ENDIF}; 4543 try 4544 // ToDo: replace step by step to keep bookmarks and breakpoints 4545 FEditor.SelText := InvertAssignTool.InvertAssignment(FEditor.SelText); 4546 finally 4547 FEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.InvertAssignment'){$ENDIF}; 4548 FEditor.EndUpdate; 4549 end; 4550end; 4551 4552procedure TSourceEditor.SelectToBrace; 4553begin 4554 EditorComponent.SelectToBrace; 4555end; 4556 4557procedure TSourceEditor.SelectWord; 4558begin 4559 EditorComponent.SelectWord; 4560end; 4561 4562procedure TSourceEditor.SelectLine; 4563begin 4564 EditorComponent.SelectLine; 4565end; 4566 4567procedure TSourceEditor.SelectParagraph; 4568begin 4569 EditorComponent.SelectParagraph; 4570end; 4571 4572function TSourceEditor.CommentText(const Txt: string; CommentType: TCommentType 4573 ): string; 4574var 4575 i: integer; 4576begin 4577 Result:=Txt; 4578 case CommentType of 4579 comtNone: exit; 4580 comtDefault: 4581 begin 4582 i:=EditorOpts.HighlighterList.FindByHighlighter(FEditor.Highlighter); 4583 if i>=0 then 4584 CommentType:=EditorOpts.HighlighterList[i].DefaultCommentType; 4585 end; 4586 end; 4587 Result:=LazStringUtils.CommentText(Txt,CommentType); 4588end; 4589 4590procedure TSourceEditor.InsertCharacterFromMap; 4591begin 4592 ShowCharacterMap(@SourceNotebook.InsertCharacter); 4593end; 4594 4595procedure TSourceEditor.InsertLicenseNotice(const Notice: string; 4596 CommentType: TCommentType); 4597var 4598 Txt: string; 4599begin 4600 if ReadOnly then Exit; 4601 Txt:=CommentText(BreakString(Notice, FEditor.RightEdge-2,0),CommentType); 4602 FEditor.InsertTextAtCaret(Txt); 4603end; 4604 4605procedure TSourceEditor.InsertGPLNotice(CommentType: TCommentType; 4606 Translated: boolean); 4607var 4608 s: String; 4609begin 4610 if Translated then 4611 s:=lisGPLNotice 4612 else 4613 s:=EnglishGPLNotice; 4614 InsertLicenseNotice(s, CommentType); 4615end; 4616 4617procedure TSourceEditor.InsertLGPLNotice(CommentType: TCommentType; 4618 Translated: boolean); 4619var 4620 s: String; 4621begin 4622 if Translated then 4623 s:=lisLGPLNotice 4624 else 4625 s:=EnglishLGPLNotice; 4626 InsertLicenseNotice(s, CommentType); 4627end; 4628 4629procedure TSourceEditor.InsertModifiedLGPLNotice(CommentType: TCommentType; 4630 Translated: boolean); 4631var 4632 s: String; 4633begin 4634 if Translated then 4635 s:=lisModifiedLGPLNotice 4636 else 4637 s:=EnglishModifiedLGPLNotice; 4638 InsertLicenseNotice(s, CommentType); 4639end; 4640 4641procedure TSourceEditor.InsertMITNotice(CommentType: TCommentType; 4642 Translated: boolean); 4643var 4644 s: String; 4645begin 4646 if Translated then 4647 s:=lisMITNotice 4648 else 4649 s:=EnglishMITNotice; 4650 InsertLicenseNotice(s, CommentType); 4651end; 4652 4653procedure TSourceEditor.InsertUsername; 4654begin 4655 if ReadOnly then Exit; 4656 FEditor.InsertTextAtCaret(GetCurrentUserName); 4657end; 4658 4659procedure TSourceEditor.InsertDateTime; 4660begin 4661 if ReadOnly then Exit; 4662 FEditor.InsertTextAtCaret(DateTimeToStr(now)); 4663end; 4664 4665procedure TSourceEditor.InsertChangeLogEntry; 4666var s: string; 4667begin 4668 if ReadOnly then Exit; 4669 s:=DateToStr(now)+' '+GetCurrentUserName+' '+GetCurrentChangeLog; 4670 FEditor.InsertTextAtCaret(s); 4671end; 4672 4673procedure TSourceEditor.InsertCVSKeyword(const AKeyWord: string); 4674begin 4675 if ReadOnly then Exit; 4676 FEditor.InsertTextAtCaret('$'+AKeyWord+'$'+LineEnding); 4677end; 4678 4679procedure TSourceEditor.InsertGUID; 4680const 4681 cGUID = '[''%s'']'; // The format of the GUID used for Interfaces 4682var 4683 lGUID: TGUID; 4684begin 4685 if ReadOnly then Exit; 4686 CreateGUID(lGUID); 4687 FEditor.InsertTextAtCaret(Format(cGUID, [GUIDToString(lGUID)])); 4688end; 4689 4690procedure TSourceEditor.InsertFilename; 4691var 4692 Dlg: TIDEOpenDialog; 4693begin 4694 if ReadOnly then Exit; 4695 Dlg:=IDEOpenDialogClass.Create(nil); 4696 try 4697 InitIDEFileDialog(Dlg); 4698 Dlg.Title:=lisSelectFile; 4699 if not Dlg.Execute then exit; 4700 FEditor.InsertTextAtCaret(Dlg.FileName); 4701 finally 4702 Dlg.Free; 4703 end; 4704end; 4705 4706function TSourceEditor.GetSelEnd: Integer; 4707begin 4708 Result:=FEditor.SelEnd; 4709end; 4710 4711function TSourceEditor.GetSelStart: Integer; 4712begin 4713 Result:=FEditor.SelStart; 4714end; 4715 4716procedure TSourceEditor.SetSelEnd(const AValue: Integer); 4717begin 4718 FEditor.SelEnd:=AValue; 4719end; 4720 4721procedure TSourceEditor.SetSelStart(const AValue: Integer); 4722begin 4723 FEditor.SelStart:=AValue; 4724end; 4725 4726function TSourceEditor.GetSelection: string; 4727begin 4728 Result:=FEditor.SelText; 4729end; 4730 4731procedure TSourceEditor.SetSelection(const AValue: string); 4732begin 4733 FEditor.SelText:=AValue; 4734end; 4735 4736procedure TSourceEditor.CopyToClipboard; 4737begin 4738 FEditor.CopyToClipboard; 4739end; 4740 4741procedure TSourceEditor.CutToClipboard; 4742begin 4743 FEditor.CutToClipboard; 4744end; 4745 4746function TSourceEditor.GetBookMark(BookMark: Integer; out X, Y: Integer): Boolean; 4747begin 4748 X := 0; Y := 0; 4749 Result := FEditor.GetBookMark(BookMark, X, Y); 4750end; 4751 4752procedure TSourceEditor.SetBookMark(BookMark: Integer; X, Y: Integer); 4753begin 4754 FEditor.SetBookMark(BookMark, X, Y); 4755end; 4756 4757procedure TSourceEditor.ExportAsHtml(AFileName: String); 4758var 4759 Html: TSynExporterHTML; 4760begin 4761 Html := TSynExporterHTML.Create(nil); 4762 try 4763 Html.Clear; 4764 Html.ExportAsText := True; 4765 Html.Highlighter := FEditor.Highlighter; 4766 Html.Title := PageName; 4767 Html.ExportAll(FEditor.Lines); 4768 Html.SaveToFile(AFileName); 4769 finally 4770 Html.Free; 4771 end; 4772end; 4773 4774procedure TSourceEditor.FindHelpForSourceAtCursor; 4775begin 4776 //DebugLn('TSourceEditor.FindHelpForSourceAtCursor A'); 4777 ShowHelpOrErrorForSourcePosition(Filename,FEditor.LogicalCaretXY); 4778end; 4779 4780procedure TSourceEditor.OnGutterClick(Sender: TObject; X, Y, Line: integer; 4781 Mark: TSynEditMark); 4782var 4783 Marks: PSourceMark; 4784 i, MarkCount: Integer; 4785 BreakFound: Boolean; 4786 Ctrl: Boolean; 4787 ABrkPoint: TIDEBreakPoint; 4788 Mrk: TSourceMark; 4789begin 4790 // create or delete breakpoint 4791 // find breakpoint Mark at line 4792 Marks := nil; 4793 Ctrl := SYNEDIT_LINK_MODIFIER in GetKeyShiftState; 4794 try 4795 SourceEditorMarks.GetMarksForLine(Self, Line, Marks, MarkCount); 4796 BreakFound := False; 4797 for i := 0 to MarkCount - 1 do 4798 begin 4799 Mrk := Marks[i]; 4800 if Mrk.IsBreakPoint and 4801 (Mrk.Data <> nil) and (Mrk.Data is TIDEBreakPoint) 4802 then begin 4803 BreakFound := True; 4804 if Ctrl then 4805 TIDEBreakPoint(Mrk.Data).Enabled := not TIDEBreakPoint(Mrk.Data).Enabled 4806 else 4807 DebugBoss.DoDeleteBreakPointAtMark(Mrk) 4808 end; 4809 end; 4810 finally 4811 FreeMem(Marks); 4812 end; 4813 4814 if not BreakFound then begin 4815 DebugBoss.LockCommandProcessing; 4816 try 4817 DebugBoss.DoCreateBreakPoint(Filename, Line, True, ABrkPoint, True); 4818 if Ctrl and (ABrkPoint <> nil) 4819 then ABrkPoint.Enabled := False; 4820 finally 4821 if ABrkPoint <> nil then 4822 ABrkPoint.EndUpdate; 4823 DebugBoss.UnLockCommandProcessing; 4824 end; 4825 end; 4826end; 4827 4828procedure TSourceEditor.OnEditorSpecialLineColor(Sender: TObject; Line: integer; 4829 var Special: boolean; Markup: TSynSelectedColor); 4830var 4831 i:integer; 4832 aha: TAdditionalHilightAttribute; 4833 CurMarks: PSourceMark; 4834 CurMarkCount: integer; 4835 CurFG: TColor; 4836 CurBG: TColor; 4837begin 4838 aha := ahaNone; 4839 Special := False; 4840 4841 if ErrorLine = Line 4842 then begin 4843 aha := ahaErrorLine 4844 end 4845 else begin 4846 SourceEditorMarks.GetMarksForLine(Self, Line, CurMarks, CurMarkCount); 4847 if CurMarkCount > 0 then 4848 begin 4849 for i := 0 to CurMarkCount - 1 do 4850 begin 4851 if not CurMarks[i].Visible then 4852 Continue; 4853 // check highlight attribute 4854 aha := CurMarks[i].LineColorAttrib; 4855 if aha <> ahaNone then Break; 4856 4857 // check custom colors 4858 CurFG := CurMarks[i].LineColorForeGround; 4859 CurBG := CurMarks[i].LineColorBackGround; 4860 if (CurFG <> clNone) or (CurBG <> clNone) then 4861 begin 4862 Markup.Foreground := CurFG; 4863 Markup.Background := CurBG; 4864 Special := True; 4865 break; 4866 end; 4867 end; 4868 // clean up 4869 FreeMem(CurMarks); 4870 end; 4871 end; 4872 4873 if aha <> ahaNone 4874 then begin 4875 Special := True; 4876 EditorOpts.SetMarkupColor(TCustomSynEdit(Sender).Highlighter, aha, Markup); 4877 end; 4878end; 4879 4880procedure TSourceEditor.SetSyntaxHighlighterType(AHighlighterType: TLazSyntaxHighlighter); 4881var 4882 HlIsPas, OldHlIsPas: Boolean; 4883begin 4884 if (AHighlighterType=fSyntaxHighlighterType) 4885 and ((FEditor.Highlighter<>nil) = EditorOpts.UseSyntaxHighlight) then exit; 4886 4887 OldHlIsPas := FEditor.Highlighter is TSynPasSyn; 4888 HlIsPas := False; 4889 if EditorOpts.UseSyntaxHighlight then begin 4890 if Highlighters[AHighlighterType]=nil then 4891 Highlighters[AHighlighterType]:=EditorOpts.CreateSyn(AHighlighterType); 4892 FEditor.Highlighter:=Highlighters[AHighlighterType]; 4893 HlIsPas := FEditor.Highlighter is TSynPasSyn; 4894 end 4895 else 4896 FEditor.Highlighter:=nil; 4897 4898 if (OldHlIsPas <> HlIsPas) then begin 4899 if HlIsPas then 4900 FEditor.Beautifier := PasBeautifier 4901 else 4902 FEditor.Beautifier := nil; // use default 4903 EditorOpts.GetSynEditSettings(FEditor, nil); 4904 end; 4905 4906 FSyntaxHighlighterType:=AHighlighterType; 4907 SourceNotebook.UpdateActiveEditColors(FEditor); 4908end; 4909 4910procedure TSourceEditor.SetErrorLine(NewLine: integer); 4911begin 4912 if fErrorLine=NewLine then exit; 4913 fErrorLine:=NewLine; 4914 fErrorColumn:=EditorComponent.CaretX; 4915 EditorComponent.Invalidate; 4916end; 4917 4918procedure TSourceEditor.UpdateExecutionSourceMark; 4919var 4920 BreakPoint: TIDEBreakPoint; 4921 ExecutionMark: TSourceMark; 4922 BrkMark: TSourceMark; 4923begin 4924 if FSharedValues.UpdatingExecutionMark > 0 then exit; 4925 ExecutionMark := FSharedValues.ExecutionMark; 4926 if ExecutionMark = nil then exit; 4927 4928 inc(FSharedValues.UpdatingExecutionMark); 4929 try 4930 if ExecutionMark.Visible then 4931 begin 4932 BrkMark := SourceEditorMarks.FindBreakPointMark(Self, ExecutionLine); 4933 if BrkMark <> nil then begin 4934 BrkMark.Visible := False; 4935 BreakPoint := DebugBoss.BreakPoints.Find(Self.FileName, ExecutionLine); 4936 if (BreakPoint <> nil) and (not BreakPoint.Enabled) then 4937 ExecutionMark.ImageIndex := SourceEditorMarks.CurrentLineDisabledBreakPointImg 4938 else 4939 ExecutionMark.ImageIndex := SourceEditorMarks.CurrentLineBreakPointImg; 4940 end 4941 else 4942 ExecutionMark.ImageIndex := SourceEditorMarks.CurrentLineImg; 4943 end; 4944 finally 4945 dec(FSharedValues.UpdatingExecutionMark); 4946 end; 4947end; 4948 4949procedure TSourceEditor.SetExecutionLine(NewLine: integer); 4950begin 4951 if ExecutionLine=NewLine then exit; 4952 FSharedValues.SetExecutionLine(NewLine); 4953 UpdateExecutionSourceMark; 4954end; 4955 4956function TSourceEditor.RefreshEditorSettings: Boolean; 4957var 4958 SimilarEditor: TSynEdit; 4959Begin 4960 Result:=true; 4961 SetSyntaxHighlighterType(fSyntaxHighlighterType); 4962 4963 // try to copy settings from an editor to the left 4964 SimilarEditor:=nil; 4965 if (SourceNotebook.EditorCount>0) and (SourceNotebook.Editors[0]<>Self) then 4966 SimilarEditor:=SourceNotebook.Editors[0].EditorComponent; 4967 EditorOpts.GetSynEditSettings(FEditor,SimilarEditor); 4968 4969 SourceNotebook.UpdateActiveEditColors(FEditor); 4970 if Visible then 4971 UpdateIfDefNodeStates(True); 4972end; 4973 4974function TSourceEditor.AutoCompleteChar(Char: TUTF8Char; var AddChar: boolean; 4975 Category: TAutoCompleteOption): boolean; 4976// returns true if handled 4977var 4978 AToken: String; 4979 i, x1, x2: Integer; 4980 p: TPoint; 4981 Line: String; 4982 CatName: String; 4983 SrcToken: String; 4984 IdChars: TSynIdentChars; 4985 WordToken: String; 4986begin 4987 Result:=false; 4988 Line:=GetLineText; 4989 p:=GetCursorTextXY; 4990 if (p.x>length(Line)+1) or (Line='') then exit; 4991 CatName:=AutoCompleteOptionNames[Category]; 4992 4993 FEditor.GetWordBoundsAtRowCol(p, x1, x2); 4994 // use the token left of the caret 4995 x2 := Min(x2, p.x); 4996 WordToken := copy(Line, x1, x2-x1); 4997 IdChars := FEditor.IdentChars; 4998 for i:=0 to Manager.CodeTemplateModul.Completions.Count-1 do begin 4999 AToken:=Manager.CodeTemplateModul.Completions[i]; 5000 if AToken='' then continue; 5001 if AToken[1] in IdChars then 5002 SrcToken:=WordToken 5003 else 5004 SrcToken:=copy(Line,length(Line)-length(AToken)+1,length(AToken)); 5005 //DebugLn(['TSourceEditor.AutoCompleteChar ',AToken,' SrcToken=',SrcToken,' CatName=',CatName,' Index=',Manager.CodeTemplateModul.CompletionAttributes[i].IndexOfName(CatName)]); 5006 if (UTF8CompareLatinTextFast(AToken,SrcToken)=0) 5007 and (Manager.CodeTemplateModul.CompletionAttributes[i].IndexOfName(CatName)>=0) 5008 and ( (not FEditor.SelAvail) or 5009 (Manager.CodeTemplateModul.CompletionAttributes[i].IndexOfName( 5010 AutoCompleteOptionNames[acoIgnoreForSelection]) < 0) ) 5011 then begin 5012 Result:=true; 5013 //DebugLn(['TSourceEditor.AutoCompleteChar ',AToken,' SrcToken=',SrcToken,' CatName=',CatName,' Index=',Manager.CodeTemplateModul.CompletionAttributes[i].IndexOfName(CatName)]); 5014 Manager.CodeTemplateModul.ExecuteCompletion(AToken,FEditor); 5015 AddChar:=not Manager.CodeTemplateModul.CompletionAttributes[i].IndexOfName( 5016 AutoCompleteOptionNames[acoRemoveChar])>=0; 5017 exit; 5018 end; 5019 end; 5020 5021 if EditorOpts.AutoBlockCompletion 5022 and (SyntaxHighlighterType in [lshFreePascal,lshDelphi]) then 5023 Result:=AutoBlockCompleteChar(Char,AddChar,Category,p,Line); 5024end; 5025 5026function TSourceEditor.AutoBlockCompleteChar(Char: TUTF8Char; 5027 var AddChar: boolean; Category: TAutoCompleteOption; aTextPos: TPoint; 5028 Line: string): boolean; 5029// returns true if handled 5030var 5031 x1: integer; 5032 x2: integer; 5033 WordToken: String; 5034 p: LongInt; 5035 StartPos: integer; 5036 s: String; 5037begin 5038 Result:=false; 5039 if (not EditorOpts.AutoBlockCompletion) 5040 or (not (SyntaxHighlighterType in [lshFreePascal,lshDelphi])) then 5041 exit; 5042 FEditor.GetWordBoundsAtRowCol(aTextPos, x1, x2); 5043 // use the token left of the caret 5044 x2 := Min(x2, aTextPos.x); 5045 WordToken := copy(Line, x1, x2-x1); 5046 if (Category in [acoSpace]) 5047 and ((SysUtils.CompareText(WordToken,'if')=0) 5048 or (SysUtils.CompareText(WordToken,'while')=0) 5049 or (SysUtils.CompareText(WordToken,'for')=0) 5050 ) 5051 then begin 5052 p:=x2; 5053 ReadRawNextPascalAtom(Line,p,StartPos); 5054 if SysUtils.CompareText(copy(Line,StartPos,p-StartPos),'begin')=0 then begin 5055 // 'if begin' => insert 'then' 5056 // 'while begin' => insert 'do' 5057 // 'for begin' => insert 'do' 5058 Result:=true; 5059 if (SysUtils.CompareText(WordToken,'if')=0) then 5060 s:='then' 5061 else 5062 s:='do'; 5063 s:=' '+CodeToolBoss.SourceChangeCache.BeautifyCodeOptions.BeautifyKeyWord(s); 5064 if not (Line[x2] in [' ',#9]) then 5065 s:=s+' '; 5066 FEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.AutoBlockCompleteChar'){$ENDIF}; 5067 try 5068 FEditor.InsertTextAtCaret(s); 5069 FEditor.LogicalCaretXY:=aTextPos; 5070 finally 5071 FEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.AutoBlockCompleteChar'){$ENDIF}; 5072 end; 5073 end; 5074 end; 5075end; 5076 5077function TSourceEditor.AutoBlockCompleteChar(Char: TUTF8Char): boolean; 5078var 5079 p: TPoint; 5080 x1: integer; 5081 x2: integer; 5082 Line: String; 5083 WordToken: String; 5084begin 5085 Result:=false; 5086 if (not EditorOpts.AutoBlockCompletion) 5087 or (not (SyntaxHighlighterType in [lshFreePascal,lshDelphi])) then 5088 exit; 5089 p:=GetCursorTextXY; 5090 FEditor.GetWordBoundsAtRowCol(p, x1, x2); 5091 Line:=GetLineText; 5092 WordToken := copy(Line, x1, x2-x1); 5093 if (SysUtils.CompareText(WordToken,'begin')=0) 5094 then begin 5095 debugln(['TSourceEditor.AutoBlockCompleteChar ']); 5096 // user typed 'begin' 5097 LazarusIDE.SaveSourceEditorChangesToCodeCache(self); 5098 FEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.AutoBlockCompleteChar (2)'){$ENDIF}; 5099 FEditor.BeginUpdate; 5100 try 5101 if not CodeToolBoss.CompleteBlock(CodeBuffer,p.X,p.Y,true) then exit; 5102 finally 5103 FEditor.EndUpdate; 5104 FEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.AutoBlockCompleteChar (2)'){$ENDIF}; 5105 end; 5106 end; 5107end; 5108 5109procedure TSourceEditor.AutoCompleteBlock; 5110var 5111 XY: TPoint; 5112 NewCode: TCodeBuffer; 5113 NewX, NewY, NewTopLine: integer; 5114begin 5115 LazarusIDE.SaveSourceEditorChangesToCodeCache(Self); 5116 XY:=FEditor.LogicalCaretXY; 5117 FEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.AutoCompleteBlock'){$ENDIF}; 5118 FEditor.BeginUpdate; 5119 try 5120 if not CodeToolBoss.CompleteBlock(CodeBuffer,XY.X,XY.Y,false, 5121 NewCode,NewX,NewY,NewTopLine) then exit; 5122 XY:=FEditor.LogicalCaretXY; 5123 //DebugLn(['TSourceEditor.AutoCompleteBlock XY=',dbgs(XY),' NewX=',NewX,' NewY=',NewY]); 5124 if (NewCode<>CodeBuffer) or (NewX<>XY.X) or (NewY<>XY.Y) or (NewTopLine>0) 5125 then begin 5126 XY.X:=NewX; 5127 XY.Y:=NewY; 5128 FEditor.LogicalCaretXY:=XY; 5129 end; 5130 finally 5131 FEditor.EndUpdate; 5132 FEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.AutoCompleteBlock'){$ENDIF}; 5133 end; 5134end; 5135 5136procedure TSourceEditor.UpdateNoteBook(const ANewNoteBook: TSourceNotebook; ANewPage: TTabSheet); 5137begin 5138 if FSourceNoteBook = ANewNoteBook then exit; 5139 5140 FSourceNoteBook := ANewNoteBook; 5141 FAOwner := ANewNoteBook; 5142 FPageName := ANewNoteBook.NoteBookPages[ANewNoteBook.NoteBookIndexOfPage(ANewPage)]; 5143 5144 EditorComponent.Parent := nil; 5145 // Change the Owner of the SynEdit 5146 EditorComponent.Owner.RemoveComponent(EditorComponent); 5147 FSourceNoteBook.InsertComponent(EditorComponent); 5148 // And the Parent 5149 EditorComponent.Parent := ANewPage; 5150end; 5151 5152{ AOwner is the TSourceNotebook 5153 AParent is a page of the TPageControl } 5154procedure TSourceEditor.CreateEditor(AOwner: TComponent; AParent: TWinControl); 5155var 5156 NewName: string; 5157 i: integer; 5158 bmp: TCustomBitmap; 5159Begin 5160 {$IFDEF IDE_DEBUG} 5161 debugln('TSourceEditor.CreateEditor A '); 5162 {$ENDIF} 5163 if not assigned(FEditor) then Begin 5164 FVisible := False; 5165 i:=0; 5166 repeat 5167 inc(i); 5168 NewName:='SynEdit'+IntToStr(i); 5169 until (AOwner.FindComponent(NewName)=nil); 5170 FEditor := TIDESynEditor.Create(AOwner); 5171 FEditor.BeginUpdate; 5172 with FEditor do begin 5173 Name:=NewName; 5174 Text:=''; 5175 Align := alClient; 5176 Visible := False; 5177 BookMarkOptions.EnableKeys := false; 5178 BookMarkOptions.LeftMargin:=1; 5179 BookMarkOptions.BookmarkImages := SourceEditorMarks.ImgList; 5180 Gutter.MarksPart.DebugMarksImageIndex := SourceEditorMarks.SourceLineImg; 5181 WantTabs := true; 5182 ScrollBars := ssAutoBoth; 5183 5184 // IMPORTANT: when you change below, don't forget updating UnbindEditor 5185 OnStatusChange := @EditorStatusChanged; 5186 OnProcessCommand := @ProcessCommand; 5187 OnProcessUserCommand := @ProcessUserCommand; 5188 OnCommandProcessed := @UserCommandProcessed; 5189 OnReplaceText := @OnReplace; 5190 OnGutterClick := @Self.OnGutterClick; 5191 OnSpecialLineMarkup := @OnEditorSpecialLineColor; 5192 OnMouseMove := @EditorMouseMoved; 5193 OnMouseWheel := @EditorMouseWheel; 5194 OnMouseDown := @EditorMouseDown; 5195 OnMouseUp := @EditorMouseUp; 5196 OnClickLink := Manager.OnClickLink; 5197 OnMouseLink := Manager.OnMouseLink; 5198 OnKeyDown := @EditorKeyDown; 5199 OnKeyUp := @EditorKeyUp; 5200 OnPaste:=@EditorPaste; 5201 OnEnter:=@EditorEnter; 5202 OnPlaceBookmark := @EditorPlaceBookmark; 5203 OnClearBookmark := @EditorClearBookmark; 5204 OnChangeUpdating := @EditorChangeUpdating; 5205 OnMultiCaretBeforeCommand := @DoMultiCaretBeforeCommand; 5206 RegisterMouseActionExecHandler(@EditorHandleMouseAction); 5207 // IMPORTANT: when you change above, don't forget updating UnbindEditor 5208 Parent := AParent; 5209 if AParent.Font.PixelsPerInch<>96 then 5210 AutoAdjustLayout(lapAutoAdjustForDPI, 96, AParent.Font.PixelsPerInch, 0, 0); 5211 end; 5212 Manager.CodeTemplateModul.AddEditor(FEditor); 5213 Manager.FMacroRecorder.AddEditor(FEditor); 5214 Manager.NewEditorCreated(self); 5215 FEditor.TemplateEdit.OnActivate := @EditorActivateSyncro; 5216 FEditor.TemplateEdit.OnDeactivate := @EditorDeactivateSyncro; 5217 bmp := CreateBitmapFromResourceName(HInstance, 'tsynsyncroedit'); 5218 FEditor.SyncroEdit.GutterGlyph.Assign(bmp); 5219 bmp.Free; 5220 FEditor.SyncroEdit.OnBeginEdit := @EditorActivateSyncro; 5221 FEditor.SyncroEdit.OnEndEdit := @EditorDeactivateSyncro; 5222 5223 RefreshEditorSettings; 5224 FEditor.EndUpdate; 5225 end else begin 5226 FEditor.Parent:=AParent; 5227 end; 5228end; 5229 5230procedure TSourceEditor.SetCodeBuffer(NewCodeBuffer: TCodeBuffer); 5231begin 5232 FSharedValues.CodeBuffer := NewCodeBuffer; 5233end; 5234 5235procedure TSourceEditor.StartIdentCompletionBox(JumpToError, 5236 CanAutoComplete: boolean); 5237var 5238 I: Integer; 5239 TextS, TextS2: String; 5240 LogCaret: TPoint; 5241 UseWordCompletion: Boolean; 5242 Completion: TSourceEditCompletion; 5243 CompletionRect: TRect; 5244begin 5245 {$IFDEF VerboseIDECompletionBox} 5246 debugln(['TSourceEditor.StartIdentCompletionBox JumpToError: ',JumpToError]); 5247 {$ENDIF} 5248 if (FEditor.ReadOnly) then exit; 5249 Completion := Manager.DefaultCompletionForm; 5250 if (Completion.CurrentCompletionType<>ctNone) then exit; 5251 Completion.IdentCompletionJumpToError := JumpToError; 5252 Completion.CurrentCompletionType:=ctIdentCompletion; 5253 TextS := FEditor.LineText; 5254 LogCaret:=FEditor.LogicalCaretXY; 5255 Completion.Editor:=FEditor; 5256 i := LogCaret.X - 1; 5257 if i > length(TextS) then 5258 TextS2 := '' 5259 else begin 5260 while (i > 0) and (TextS[i] in ['a'..'z','A'..'Z','0'..'9','_']) do 5261 dec(i); 5262 TextS2 := Trim(copy(TextS, i + 1, LogCaret.X - i - 1)); 5263 end; 5264 UseWordCompletion:=false; 5265 CompletionRect := Manager.GetScreenRectForToken(FEditor, FEditor.CaretX-length(TextS2), FEditor.CaretY, FEditor.CaretX-1); 5266 5267 if not Manager.FindIdentCompletionPlugin 5268 (Self, JumpToError, TextS2, CompletionRect.Top, CompletionRect.Left, UseWordCompletion) 5269 then 5270 exit; 5271 if UseWordCompletion then 5272 Completion.CurrentCompletionType:=ctWordCompletion; 5273 5274 Completion.AutoUseSingleIdent := CanAutoComplete and 5275 (FCodeCompletionState.State = ccsDot) and 5276 CodeToolsOpts.IdentComplAutoUseSingleIdent; 5277 Completion.Execute(TextS2, CompletionRect); 5278 {$IFDEF VerboseIDECompletionBox} 5279 debugln(['TSourceEditor.StartIdentCompletionBox END Completion.TheForm.Visible=',Completion.TheForm.Visible]); 5280 {$ENDIF} 5281end; 5282 5283procedure TSourceEditor.StartWordCompletionBox; 5284var 5285 TextS: String; 5286 LogCaret: TPoint; 5287 i: Integer; 5288 TextS2: String; 5289 Completion: TSourceEditCompletion; 5290begin 5291 if (FEditor.ReadOnly) then exit; 5292 Completion := Manager.DefaultCompletionForm; 5293 if (Completion.CurrentCompletionType<>ctNone) then exit; 5294 Completion.CurrentCompletionType:=ctWordCompletion; 5295 TextS := FEditor.LineText; 5296 LogCaret:=FEditor.LogicalCaretXY; 5297 Completion.Editor:=FEditor; 5298 i := LogCaret.X - 1; 5299 if i > length(TextS) then 5300 TextS2 := '' 5301 else begin 5302 while (i > 0) and (TextS[i] in ['a'..'z','A'..'Z','0'..'9','_']) do 5303 dec(i); 5304 TextS2 := Trim(copy(TextS, i + 1, LogCaret.X - i - 1)); 5305 end; 5306 Completion.Execute 5307 (TextS2, Manager.GetScreenRectForToken(FEditor, FEditor.CaretX-length(TextS2), FEditor.CaretY, FEditor.CaretX-1)); 5308end; 5309 5310procedure TSourceEditor.IncreaseIgnoreCodeBufferLock; 5311begin 5312 FSharedValues.IncreaseIgnoreCodeBufferLock; 5313end; 5314 5315procedure TSourceEditor.DecreaseIgnoreCodeBufferLock; 5316begin 5317 FSharedValues.DecreaseIgnoreCodeBufferLock; 5318end; 5319 5320procedure TSourceEditor.UpdateCodeBuffer; 5321// copy the source from EditorComponent to codetools 5322begin 5323 FSharedValues.UpdateCodeBuffer; 5324end; 5325 5326function TSourceEditor.NeedsUpdateCodeBuffer: boolean; 5327begin 5328 Result := FSharedValues.NeedsUpdateCodeBuffer; 5329end; 5330 5331procedure TSourceEditor.ConnectScanner(Scanner: TLinkScanner); 5332begin 5333 FSharedValues.ConnectScanner(Scanner); 5334end; 5335 5336function TSourceEditor.GetSource: TStrings; 5337Begin 5338 //return synedit's source. 5339 Result := FEditor.Lines; 5340end; 5341 5342procedure TSourceEditor.SetIsLocked(const AValue: Boolean); 5343begin 5344 if FIsLocked = AValue then exit; 5345 FIsLocked := AValue; 5346 UpdatePageName; 5347 SourceNotebook.UpdateStatusBar; 5348 UpdateProjectFile; 5349end; 5350 5351procedure TSourceEditor.SetPageName(const AValue: string); 5352begin 5353 if FPageName=AValue then exit; 5354 FPageName:=AValue; 5355 UpdatePageName; 5356end; 5357 5358procedure TSourceEditor.UpdatePageName; 5359var 5360 p: Integer; 5361 NewPageCaption: String; 5362begin 5363 if SourceNotebook.FUpdateLock > 0 then begin 5364 include(SourceNotebook.FUpdateFlags, ufPageNames); 5365 exit; 5366 end; 5367 p:=SourceNotebook.FindPageWithEditor(Self); 5368 if EditorOpts.ShowTabNumbers and (p < 10) then 5369 // Number pages 1, ..., 9, 0 -- according to Alt+N hotkeys. 5370 NewPageCaption:=Format('%s:%d', [FPageName, (p+1) mod 10]) 5371 else 5372 NewPageCaption:=FPageName; 5373 if IsLocked then NewPageCaption:='#'+NewPageCaption; 5374 if Modified then NewPageCaption:='*'+NewPageCaption; 5375 if SourceNotebook.NoteBookPages[p] <> NewPageCaption then begin 5376 SourceNotebook.NoteBookPages[p] := NewPageCaption; 5377 SourceNotebook.UpdateTabsAndPageTitle; 5378 SourceNotebook.CallOnEditorPageCaptionUpdate(Self); 5379 end; 5380end; 5381 5382procedure TSourceEditor.SetSource(Value: TStrings); 5383Begin 5384 FEditor.Lines.Assign(Value); 5385end; 5386 5387function TSourceEditor.GetCurrentCursorXLine: Integer; 5388Begin 5389 Result := FEditor.CaretX 5390end; 5391 5392procedure TSourceEditor.SetCurrentCursorXLine(num: Integer); 5393Begin 5394 FEditor.CaretX := Num; 5395end; 5396 5397function TSourceEditor.GetCurrentCursorYLine: Integer; 5398Begin 5399 Result := FEditor.CaretY; 5400end; 5401 5402procedure TSourceEditor.SetCurrentCursorYLine(num: Integer); 5403Begin 5404 FEditor.CaretY := Num; 5405end; 5406 5407procedure TSourceEditor.SelectText(const StartPos, EndPos: TPoint); 5408Begin 5409 FEditor.BlockBegin := StartPos; 5410 FEditor.BlockEnd := EndPos; 5411end; 5412 5413procedure TSourceEditor.InsertLine(StartLine: Integer; const NewText: String; 5414 aKeepMarks: Boolean); 5415const 5416 MarksMode: array[Boolean] of TSynMarksAdjustMode = (smaMoveUp, smaKeep); 5417var 5418 Pt: TPoint; 5419begin 5420 if not ReadOnly then 5421 begin 5422 if StartLine > 1 then 5423 Pt := Point(Length(FEditor.Lines[StartLine - 2]) + 1, StartLine - 1) 5424 else 5425 Pt := Point(1, 1); 5426 FEditor.SetTextBetweenPoints(Pt, Pt, 5427 LineEnding + NewText, [], scamEnd, MarksMode[aKeepMarks]); 5428 end; 5429end; 5430 5431procedure TSourceEditor.ReplaceLines(StartLine, EndLine: integer; 5432 const NewText: string; aKeepMarks: Boolean = False); 5433const 5434 MarksMode: array[Boolean] of TSynMarksAdjustMode = (smaMoveUp, smaKeep); 5435begin 5436 if not ReadOnly then 5437 FEditor.SetTextBetweenPoints( 5438 Point(1, StartLine), 5439 Point(Length(FEditor.Lines[Endline - 1]) + 1, EndLine), 5440 NewText, [], scamEnd, MarksMode[aKeepMarks]); 5441end; 5442 5443procedure TSourceEditor.EncloseSelection; 5444var 5445 EncloseType: TEncloseSelectionType; 5446 EncloseTemplate: string; 5447 NewSelection: string; 5448 NewCaretXY: TPoint; 5449begin 5450 if ReadOnly then exit; 5451 if not FEditor.SelAvail then 5452 exit; 5453 if ShowEncloseSelectionDialog(EncloseType)<>mrOk then exit; 5454 GetEncloseSelectionParams(EncloseType,EncloseTemplate); 5455 EncloseTextSelection(EncloseTemplate,FEditor.Lines, 5456 FEditor.BlockBegin,FEditor.BlockEnd, 5457 NewSelection,NewCaretXY); 5458 //debugln(['TSourceEditor.EncloseSelection A NewCaretXY=',NewCaretXY.X,',',NewCaretXY.Y,' "',NewSelection,'"']); 5459 FEditor.SelText:=NewSelection; 5460 FEditor.LogicalCaretXY:=NewCaretXY; 5461end; 5462 5463function TSourceEditor.GetModified: Boolean; 5464Begin 5465 Result := FSharedValues.Modified; 5466end; 5467 5468procedure TSourceEditor.SetModified(const NewValue: Boolean); 5469begin 5470 FSharedValues.SetModified(NewValue); 5471end; 5472 5473function TSourceEditor.GetInsertMode: Boolean; 5474Begin 5475 Result := FEditor.Insertmode; 5476end; 5477 5478function TSourceEditor.Close: Boolean; 5479Begin 5480 DebugLnEnter(SRCED_CLOSE, ['TSourceEditor.Close ShareCount=', FSharedValues.SharedEditorCount]); 5481 Result := True; 5482 Visible := False; 5483 Manager.EditorRemoved(Self); 5484 UnbindEditor; 5485 FEditor.Parent:=nil; 5486 if FSharedValues.SharedEditorCount = 1 then 5487 CodeBuffer := nil; 5488 DebugLnExit(SRCED_CLOSE, ['TSourceEditor.Close ']); 5489end; 5490 5491procedure TSourceEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; 5492begin 5493 FEditor.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.BeginUndoBlock ' + ACaller){$ENDIF}; 5494end; 5495 5496procedure TSourceEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; 5497begin 5498 FEditor.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditor.EndUndoBlock ' + ACaller){$ENDIF}; 5499end; 5500 5501procedure TSourceEditor.BeginUpdate; 5502begin 5503 FEditor.BeginUpdate; 5504end; 5505 5506procedure TSourceEditor.EndUpdate; 5507begin 5508 FEditor.EndUpdate; 5509end; 5510 5511procedure TSourceEditor.BeginGlobalUpdate; 5512begin 5513 FSharedValues.BeginGlobalUpdate; 5514end; 5515 5516procedure TSourceEditor.EndGlobalUpdate; 5517begin 5518 FSharedValues.EndGlobalUpdate; 5519end; 5520 5521procedure TSourceEditor.SetPopupMenu(NewPopupMenu: TPopupMenu); 5522begin 5523 if NewPopupMenu<>FPopupMenu then begin 5524 FPopupMenu:=NewPopupMenu; 5525 if FEditor<>nil then begin 5526 if FEditor.PopupMenu <> nil then // Todo: why? 5527 FEditor.PopupMenu.RemoveFreeNotification(FEditor); 5528 FEditor.PopupMenu:=NewPopupMenu; 5529 end; 5530 end; 5531end; 5532 5533function TSourceEditor.GetFilename: string; 5534begin 5535 if CodeBuffer <> nil then 5536 Result := CodeBuffer.Filename 5537 else 5538 Result := ''; 5539end; 5540 5541function TSourceEditor.GetEditorControl: TWinControl; 5542begin 5543 Result:=FEditor; 5544end; 5545 5546function TSourceEditor.GetCodeToolsBuffer: TObject; 5547begin 5548 Result:=CodeBuffer; 5549end; 5550 5551procedure TSourceEditor.EditorPaste(Sender: TObject; var AText: String; 5552 var AMode: TSynSelectionMode; ALogStartPos: TPoint; 5553 var AnAction: TSynCopyPasteAction); 5554var 5555 p: integer; 5556 NestedComments: Boolean; 5557 NewIndent: TFABIndentationPolicy; 5558 Indent: LongInt; 5559 NewSrc: string; 5560 i: Integer; 5561 SemMode: TSemSelectionMode; 5562 SemAction: TSemCopyPasteAction; 5563begin 5564 if Assigned(Manager) then begin 5565 // call handlers 5566 i:=Manager.FHandlers[semhtCopyPaste].Count; 5567 while Manager.FHandlers[semhtCopyPaste].NextDownIndex(i) do begin 5568 SemMode:=TSemSelectionMode(AMode); 5569 SemAction:=TSemCopyPasteAction(AnAction); 5570 TSemCopyPasteEvent(Manager.FHandlers[semhtCopyPaste][i])(Self,AText, 5571 SemMode,ALogStartPos,SemAction); 5572 AMode:=TSynSelectionMode(SemMode); 5573 AnAction:=TSynCopyPasteAction(SemAction); 5574 if AnAction=scaAbort then exit; 5575 end; 5576 end; 5577 5578 if AMode<>smNormal then exit; 5579 if SyncroLockCount > 0 then exit; 5580 if not CodeToolsOpts.IndentOnPaste then exit; 5581 if not (SyntaxHighlighterType in [lshFreePascal, lshDelphi]) then 5582 exit; 5583 {$IFDEF VerboseIndenter} 5584 debugln(['TSourceEditor.EditorPaste LogCaret=',dbgs(ALogStartPos)]); 5585 {$ENDIF} 5586 if ALogStartPos.X>1 then exit; 5587 UpdateCodeBuffer; 5588 CodeBuffer.LineColToPosition(ALogStartPos.Y,ALogStartPos.X,p); 5589 if p<1 then exit; 5590 {$IFDEF VerboseIndenter} 5591 if ALogStartPos.Y>1 then 5592 DebugLn(['TSourceEditor.EditorPaste Y-1=',Lines[ALogStartPos.Y-2]]); 5593 DebugLn(['TSourceEditor.EditorPaste Y+0=',Lines[ALogStartPos.Y-1]]); 5594 if ALogStartPos.Y<LineCount then 5595 DebugLn(['TSourceEditor.EditorPaste Y+1=',Lines[ALogStartPos.Y+0]]); 5596 {$ENDIF} 5597 NestedComments:=CodeToolBoss.GetNestedCommentsFlagForFile(CodeBuffer.Filename); 5598 if not CodeToolBoss.Indenter.GetIndent(CodeBuffer.Source,p,NestedComments, 5599 true,NewIndent,CodeToolsOpts.IndentContextSensitive,AText) 5600 then exit; 5601 if not NewIndent.IndentValid then exit; 5602 Indent:=NewIndent.Indent-GetLineIndentWithTabs(AText,1,EditorComponent.TabWidth); 5603 {$IFDEF VerboseIndenter} 5604 debugln(AText); 5605 DebugLn(['TSourceEditor.EditorPaste Indent=',Indent]); 5606 {$ENDIF} 5607 IndentText(AText,Indent,EditorComponent.TabWidth,NewSrc); 5608 AText:=NewSrc; 5609 {$IFDEF VerboseIndenter} 5610 debugln(AText); 5611 DebugLn(['TSourceEditor.EditorPaste END']); 5612 {$ENDIF} 5613end; 5614 5615procedure TSourceEditor.EditorPlaceBookmark(Sender: TObject; 5616 var Mark: TSynEditMark); 5617begin 5618 if Assigned(Manager) and Assigned(Manager.OnPlaceBookmark) then 5619 Manager.OnPlaceBookmark(Self, Mark); 5620end; 5621 5622procedure TSourceEditor.EditorClearBookmark(Sender: TObject; 5623 var Mark: TSynEditMark); 5624begin 5625 if Assigned(Manager) and Assigned(Manager.OnClearBookmark) then 5626 Manager.OnClearBookmark(Self, Mark); 5627end; 5628 5629procedure TSourceEditor.EditorEnter(Sender: TObject); 5630var 5631 SrcEdit: TSourceEditor; 5632begin 5633 debugln(SRCED_PAGES, ['TSourceEditor.EditorEnter ']); 5634 if (FSourceNoteBook.FUpdateLock <> 0) or 5635 (FSourceNoteBook.FFocusLock <> 0) 5636 then exit; 5637 if (FSourceNoteBook.PageIndex = PageIndex) then 5638 Activate 5639 else begin 5640 SrcEdit:=SourceNotebook.GetActiveSE; 5641 if SrcEdit<>nil then 5642 SrcEdit.FocusEditor; 5643 // Navigating with mousebuttons between editors (eg jump history on btn 4/5) 5644 // can trigger the old editor to be refocused (while not visible) 5645 end; 5646end; 5647 5648procedure TSourceEditor.EditorActivateSyncro(Sender: TObject); 5649begin 5650 inc(FSyncroLockCount); 5651end; 5652 5653procedure TSourceEditor.EditorDeactivateSyncro(Sender: TObject); 5654begin 5655 dec(FSyncroLockCount); 5656end; 5657 5658function TSourceEditor.GetCodeBuffer: TCodeBuffer; 5659begin 5660 Result := FSharedValues.CodeBuffer; 5661end; 5662 5663function TSourceEditor.GetExecutionLine: integer; 5664begin 5665 Result := FSharedValues.ExecutionLine; 5666end; 5667 5668function TSourceEditor.GetHasExecutionMarks: Boolean; 5669begin 5670 Result := EditorComponent.IDEGutterMarks.HasDebugMarks; 5671end; 5672 5673function TSourceEditor.GetSharedEditors(Index: Integer): TSourceEditor; 5674begin 5675 Result := FSharedValues.SharedEditors[Index]; 5676end; 5677 5678procedure TSourceEditor.EditorChangeUpdating(ASender: TObject; AnUpdating: Boolean); 5679begin 5680 // Calls may be unbalanced, because the event handler may not be assigned to the event on the first BeginUpdate 5681 If AnUpdating then begin 5682 //if FInEditorChangedUpdating then 5683 // debugln(['***** TSourceEditor.EditorChangeUpdating: Updating=True, but FInEditorChangedUpdating was true already']); 5684 if not FInEditorChangedUpdating then begin 5685 FInEditorChangedUpdating := True; 5686 DebugBoss.LockCommandProcessing; 5687 end; 5688 FMouseActionPopUpMenu := nil; 5689 end else 5690 begin 5691 //if not FInEditorChangedUpdating then 5692 // debugln(['***** TSourceEditor.EditorChangeUpdating: Updating=False, but FInEditorChangedUpdating was false already']); 5693 if FInEditorChangedUpdating then begin 5694 FInEditorChangedUpdating := False; // set before unlocking 5695 DebugBoss.UnLockCommandProcessing; // may lead to recursion 5696 end; 5697 //FMouseActionPopUpMenu := 5698 if (FMouseActionPopUpMenu <> nil) then begin 5699 FMouseActionPopUpMenu.PopupComponent := FEditor; 5700 FMouseActionPopUpMenu.PopUp; 5701 FMouseActionPopUpMenu := nil; 5702 end; 5703 end; 5704end; 5705 5706function TSourceEditor.EditorHandleMouseAction(AnAction: TSynEditMouseAction; 5707 var AnInfo: TSynEditMouseActionInfo): Boolean; 5708begin 5709 Result := AnAction.Command = emcContextMenu; 5710 if not Result then exit; 5711 5712 case AnAction.Option2 of 5713 1: FMouseActionPopUpMenu := SourceNotebook.DbgPopUpMenu; 5714 2: FMouseActionPopUpMenu := SourceNotebook.TabPopUpMenu; 5715 else 5716 FMouseActionPopUpMenu := PopupMenu; 5717 end; 5718 5719 if (not FInEditorChangedUpdating) and (FMouseActionPopUpMenu <> nil) then begin 5720 FMouseActionPopUpMenu.PopupComponent := FEditor; 5721 FMouseActionPopUpMenu.PopUp; 5722 FMouseActionPopUpMenu := nil; 5723 end; 5724end; 5725 5726procedure TSourceEditor.EditorMouseMoved(Sender: TObject; Shift: TShiftState; 5727 X, Y: Integer); 5728begin 5729// debugln('MouseMove in Editor',X,',',Y); 5730 if Assigned(OnMouseMove) then 5731 OnMouseMove(Self,Shift,X,Y); 5732end; 5733 5734procedure TSourceEditor.EditorMouseWheel(Sender: TObject; Shift: TShiftState; 5735 WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); 5736begin 5737// debugln('MouseWheel in Editor'); 5738 if Assigned(OnMouseWheel) then 5739 OnMouseWheel(Self, Shift, WheelDelta, MousePos, Handled) 5740end; 5741 5742procedure TSourceEditor.EditorMouseDown(Sender: TObject; Button: TMouseButton; 5743 Shift: TShiftState; X, Y: Integer); 5744begin 5745 CheckActiveWindow; 5746 if Assigned(OnMouseDown) then 5747 OnMouseDown(Sender, Button, Shift, X,Y); 5748 5749 if (Manager <> nil) then 5750 Manager.FChangeNotifyLists[semEditorMouseDown].CallNotifyEvents(Self); 5751end; 5752 5753procedure TSourceEditor.EditorMouseUp(Sender: TObject; Button: TMouseButton; 5754 Shift: TShiftState; X, Y: Integer); 5755begin 5756 if (Manager <> nil) then 5757 Manager.FChangeNotifyLists[semEditorMouseUp].CallNotifyEvents(Self); 5758end; 5759 5760procedure TSourceEditor.EditorKeyDown(Sender: TObject; var Key: Word; 5761 Shift: TShiftState); 5762begin 5763 //DebugLn(['TSourceEditor.EditorKeyDown A ',dbgsName(Sender),' Key=',IntToStr(Key),' File=',ExtractFileName(Filename),' Wnd=',dbgSourceNoteBook(SourceNotebook)]); 5764 CheckActiveWindow; 5765 if Assigned(OnKeyDown) then 5766 OnKeyDown(Sender, Key, Shift); 5767 5768 IDECommandList.PostponeUpdateEvents; 5769end; 5770 5771procedure TSourceEditor.EditorKeyUp(Sender: TObject; var Key: Word; 5772 Shift: TShiftState); 5773begin 5774 CheckActiveWindow; 5775 if Assigned(OnKeyUp) then 5776 OnKeyUp(Sender, Key, Shift); 5777 5778 IDECommandList.PostponeUpdateEvents; 5779end; 5780 5781{------------------------------------------------------------------------------- 5782 method TSourceEditor.CenterCursor 5783 Params: none 5784 Result: none 5785 5786 Center the current cursor line in editor. 5787-------------------------------------------------------------------------------} 5788procedure TSourceEditor.CenterCursor(SoftCenter: Boolean = False); 5789var 5790 Y, CurTopLine, LinesInWin, MinLines, NewTopLine: Integer; 5791begin 5792 LinesInWin := EditorComponent.LinesInWindow; 5793 CurTopLine := EditorComponent.TopView; 5794 Y := EditorComponent.TextIndexToViewPos(EditorComponent.CaretY); 5795 5796 if SoftCenter then begin 5797 MinLines := Min( 5798 Min( Max(LinesInWin div SoftCenterFactor, SoftCenterMinimum), 5799 SoftCenterMaximum), 5800 Max(LinesInWin div 2 - 1, 0) // make sure there is at least one line in the soft center 5801 ); 5802 5803 if (Y <= CurTopLine) or (Y >= CurTopLine + LinesInWin) then 5804 // Caret not yet visible => hard-center 5805 NewTopLine := Max(1, Y - (LinesInWin div 2)) 5806 else 5807 if Y < CurTopLine + MinLines then 5808 NewTopLine := Max(1, Y - MinLines) 5809 else 5810 if Y > CurTopLine + LinesInWin - MinLines then 5811 NewTopLine := Max(1, Y - LinesInWin + MinLines) 5812 else 5813 NewTopLine := CurTopLine; 5814 end 5815 else 5816 // not using SoftCenter 5817 NewTopLine := Max(1, Y - (LinesInWin div 2)); 5818 5819 if NewTopLine < 1 then NewTopLine := 1; 5820 EditorComponent.TopView := NewTopLine; 5821end; 5822 5823procedure TSourceEditor.CenterCursorHoriz(HCMode: TSourceEditHCenterMode); 5824var 5825 i: Integer; 5826begin 5827 case HCMode of 5828 hcmCenter: 5829 with EditorComponent do begin 5830 LeftChar:=Max(LogicalCaretXY.X - (CharsInWindow div 2), 1); 5831 end; 5832 hcmCenterKeepEOL: 5833 with EditorComponent do begin 5834 i := LogicalToPhysicalPos(Point(Length(Lines[CaretY-1]) + 1, CaretY)).X; 5835 LeftChar:=Max(Min(LogicalCaretXY.X - (CharsInWindow div 2), 5836 i - CharsInWindow 5837 ), 1); 5838 end; 5839 hcmSoft: 5840 // TODO: offset on left side 5841 with EditorComponent do begin 5842 LeftChar:=Max(LogicalCaretXY.X - (CharsInWindow * 4 div 5), 1); 5843 end; 5844 hcmSoftKeepEOL: 5845 // TODO: offset on left side 5846 with EditorComponent do begin 5847 i := LogicalToPhysicalPos(Point(Length(Lines[CaretY-1]) + 1, CaretY)).X; 5848 LeftChar:=Max(Min(LogicalCaretXY.X - (CharsInWindow * 4 div 5), 5849 i - CharsInWindow 5850 ), 1); 5851 end; 5852 end; 5853end; 5854 5855function TSourceEditor.TextToScreenPosition(const Position: TPoint): TPoint; 5856begin 5857 Result:=FEditor.LogicalToPhysicalPos(Position); 5858end; 5859 5860function TSourceEditor.ScreenToTextPosition(const Position: TPoint): TPoint; 5861begin 5862 Result:=FEditor.PhysicalToLogicalPos(Position); 5863end; 5864 5865function TSourceEditor.ScreenToPixelPosition(const Position: TPoint): TPoint; 5866begin 5867 Result:=FEditor.ScreenXYToPixels(FEditor.TextXYToScreenXY(Position)); 5868end; 5869 5870function TSourceEditor.LineCount: Integer; 5871begin 5872 Result:=FEditor.Lines.Count; 5873end; 5874 5875function TSourceEditor.WidthInChars: Integer; 5876begin 5877 Result:=FEditor.CharsInWindow; 5878end; 5879 5880function TSourceEditor.HeightInLines: Integer; 5881begin 5882 Result:=FEditor.LinesInWindow; 5883end; 5884 5885function TSourceEditor.CharWidth: integer; 5886begin 5887 Result:=FEditor.CharWidth; 5888end; 5889 5890function TSourceEditor.GetLineText: string; 5891begin 5892 Result:=FEditor.LineText; 5893end; 5894 5895procedure TSourceEditor.SetLineText(const AValue: string); 5896begin 5897 FEditor.LineText:=AValue; 5898end; 5899 5900function TSourceEditor.GetLines: TStrings; 5901begin 5902 Result:=FEditor.Lines; 5903end; 5904 5905function TSourceEditor.GetLinesInWindow: Integer; 5906begin 5907 Result := FEditor.LinesInWindow; 5908end; 5909 5910procedure TSourceEditor.SetLines(const AValue: TStrings); 5911begin 5912 FEditor.Lines:=AValue; 5913end; 5914 5915function TSourceEditor.CurrentWordLogStartOrCaret: TPoint; 5916var 5917 StartX, EndX: integer; 5918begin 5919 Result := FEditor.LogicalCaretXY; 5920 FEditor.GetWordBoundsAtRowCol(Result, StartX, EndX); 5921 if (Result.x >= StartX) and (Result.x <= EndX) then 5922 Result.x := StartX; 5923end; 5924 5925function TSourceEditor.GetProjectFile: TLazProjectFile; 5926begin 5927 Result:=LazarusIDE.GetProjectFileForProjectEditor(Self); 5928end; 5929 5930procedure TSourceEditor.UpdateProjectFile(AnUpdates: TSrcEditProjectUpdatesNeeded); 5931begin 5932 AnUpdates := AnUpdates + FProjectFileUpdatesNeeded; 5933 FProjectFileUpdatesNeeded := []; 5934 if Assigned(Manager) and Assigned(Manager.OnUpdateProjectFile) 5935 then Manager.OnUpdateProjectFile(self, AnUpdates); 5936end; 5937 5938function TSourceEditor.GetDesigner(LoadForm: boolean): TIDesigner; 5939begin 5940 Result:=LazarusIDE.GetDesignerForProjectEditor(Self, LoadForm) 5941end; 5942 5943function TSourceEditor.GetCursorScreenXY: TPoint; 5944begin 5945 Result:=FEditor.CaretXY; 5946end; 5947 5948function TSourceEditor.GetCursorTextXY: TPoint; 5949begin 5950 Result:=FEditor.LogicalCaretXY; 5951end; 5952 5953procedure TSourceEditor.SetCursorScreenXY(const AValue: TPoint); 5954begin 5955 FEditor.CaretXY:=AValue; 5956end; 5957 5958procedure TSourceEditor.SetCursorTextXY(const AValue: TPoint); 5959begin 5960 FEditor.LogicalCaretXY:=AValue; 5961end; 5962 5963function TSourceEditor.GetBlockBegin: TPoint; 5964begin 5965 Result:=FEditor.BlockBegin; 5966end; 5967 5968function TSourceEditor.GetBlockEnd: TPoint; 5969begin 5970 Result:=FEditor.BlockEnd; 5971end; 5972 5973procedure TSourceEditor.SetBlockBegin(const AValue: TPoint); 5974begin 5975 FEditor.BlockBegin:=AValue; 5976end; 5977 5978procedure TSourceEditor.SetBlockEnd(const AValue: TPoint); 5979begin 5980 FEditor.BlockEnd:=AValue; 5981end; 5982 5983function TSourceEditor.GetTopLine: Integer; 5984begin 5985 Result:=FEditor.TopLine; 5986end; 5987 5988procedure TSourceEditor.SetTopLine(const AValue: Integer); 5989begin 5990 FEditor.TopLine:=AValue; 5991end; 5992 5993function TSourceEditor.CursorInPixel: TPoint; 5994begin 5995 Result:=Point(FEditor.CaretXPix,FEditor.CaretYPix); 5996end; 5997 5998function TSourceEditor.IsCaretOnScreen(ACaret: TPoint; UseSoftCenter: Boolean = False): Boolean; 5999var 6000 LinesInWin, MinLines, CurTopLine, Y: Integer; 6001begin 6002 LinesInWin := EditorComponent.LinesInWindow; 6003 CurTopLine := EditorComponent.TopView; 6004 Y := EditorComponent.TextIndexToViewPos(ACaret.Y); 6005 if UsesoftCenter then begin 6006 MinLines := Min( 6007 Min( Max(LinesInWin div SoftCenterFactor, SoftCenterMinimum), 6008 SoftCenterMaximum), 6009 Max(LinesInWin div 2 - 1, 0) // make sure there is at least one line in the soft center 6010 ); 6011 end 6012 else 6013 MinLines := 0; 6014 6015 Result := (Y >= CurTopLine + MinLines) and 6016 (Y <= CurTopLine + LinesInWin - MinLines) and 6017 (ACaret.X >= FEditor.LeftChar) and 6018 (ACaret.X <= FEditor.LeftChar + FEditor.CharsInWindow); 6019end; 6020 6021procedure TSourceEditor.MultiPasteText; 6022var 6023 I, CaretX: Integer; 6024 Content: TStringList; 6025 Dialog: TMultiPasteDialog; 6026begin 6027 if ReadOnly then Exit; 6028 Dialog := TMultiPasteDialog.Create(nil); 6029 try 6030 if Dialog.ShowModal <> mrOK then Exit; 6031 CaretX := FEditor.CaretX; 6032 if CaretX > 1 then 6033 begin 6034 Content := TStringList.Create; 6035 try 6036 Content.Text := Dialog.Content.Text; 6037 for I := 0 to Pred(Content.Count) do 6038 if I > 0 then 6039 Content[I] := Concat(DupeString(' ', Pred(CaretX)), Content[I]); 6040 FEditor.InsertTextAtCaret(Content.Text); 6041 finally 6042 Content.Free; 6043 end; 6044 end 6045 else 6046 FEditor.InsertTextAtCaret(Dialog.Content.Text); 6047 finally 6048 Dialog.Free; 6049 end; 6050end; 6051 6052function TSourceEditor.SearchReplace(const ASearch, AReplace: string; 6053 SearchOptions: TSrcEditSearchOptions): integer; 6054const 6055 SrcEdit2SynEditSearchOption: array[TSrcEditSearchOption] of TSynSearchOption =( 6056 ssoMatchCase, 6057 ssoWholeWord, 6058 ssoBackwards, 6059 ssoEntireScope, 6060 ssoSelectedOnly, 6061 ssoReplace, 6062 ssoReplaceAll, 6063 ssoPrompt, 6064 ssoRegExpr, 6065 ssoRegExprMultiLine 6066 ); 6067var 6068 NewOptions: TSynSearchOptions; 6069 o: TSrcEditSearchOption; 6070begin 6071 NewOptions:=[]; 6072 for o:=Low(TSrcEditSearchOption) to High(TSrcEditSearchOption) do 6073 if o in SearchOptions then 6074 Include(NewOptions,SrcEdit2SynEditSearchOption[o]); 6075 Result:=DoFindAndReplace(ASearch, AReplace, NewOptions); 6076end; 6077 6078function TSourceEditor.GetSourceText: string; 6079begin 6080 Result:=FEditor.Text; 6081end; 6082 6083procedure TSourceEditor.SetSourceText(const AValue: string); 6084begin 6085 FEditor.Text:=AValue; 6086end; 6087 6088procedure TSourceEditor.Activate; 6089begin 6090 { $note: avoid this if FSourceNoteBook.FUpdateLock > 0 / e.g. debugger calls ProcessMessages, and the internall Index is lost/undone} 6091 if (FSourceNoteBook=nil) then exit; 6092 if (FSourceNoteBook.FUpdateLock = 0) then 6093 FSourceNoteBook.ActiveEditor := Self; 6094end; 6095 6096procedure TSourceEditor.ActivateHint(const ClientPos: TPoint; const ABaseURL, 6097 AHint: string; AAutoShown: Boolean); 6098var 6099 ScreenPos: TPoint; 6100begin 6101 if SourceNotebook=nil then exit; 6102 ScreenPos:=EditorComponent.ClientToScreen(ClientPos); 6103 Manager.ActivateHint(ScreenPos,ABaseURL,AHint,AAutoShown); 6104end; 6105 6106function TSourceEditor.PageIndex: integer; 6107begin 6108 if FSourceNoteBook<>nil then 6109 Result:=FSourceNoteBook.FindPageWithEditor(Self) 6110 else 6111 Result:=-1; 6112end; 6113 6114function TSourceEditor.CaretInSelection(const ACaretPos: TPoint): Boolean; 6115begin 6116 Result := (CompareCaret(EditorComponent.BlockBegin, ACaretpos) >= 0) 6117 and (CompareCaret(ACaretPos, EditorComponent.BlockEnd) >= 0); 6118end; 6119 6120function TSourceEditor.IsActiveOnNoteBook: boolean; 6121begin 6122 if FSourceNoteBook<>nil then 6123 Result:=(FSourceNoteBook.GetActiveSE=Self) 6124 else 6125 Result:=false; 6126end; 6127 6128procedure TSourceEditor.CheckActiveWindow; 6129begin 6130 if Manager.ActiveSourceWindow = SourceNotebook then exit; 6131 debugln('Warning: ActiveSourceWindow is set incorrectly Active=',dbgSourceNoteBook(Manager.ActiveSourceWindow),' Me=',dbgSourceNoteBook(SourceNotebook)); 6132 Manager.ActiveSourceWindow := SourceNotebook; 6133end; 6134 6135procedure TSourceEditor.DoRequestExecutionMarks(Data: PtrInt); 6136begin 6137 DebugBoss.LineInfo.Request(FSharedValues.MarksRequestedForFile); 6138end; 6139 6140procedure TSourceEditor.FillExecutionMarks; 6141var 6142 ASource: String; 6143 i, idx: integer; 6144 HasAddr: Boolean; 6145 j: Integer; 6146begin 6147 if EditorComponent.IDEGutterMarks.HasDebugMarks then Exit; 6148 6149 ASource := FileName; 6150 idx := DebugBoss.LineInfo.IndexOf(ASource); 6151 if (idx = -1) then 6152 begin 6153 if not FSharedValues.MarksRequested then 6154 begin 6155 FSharedValues.MarksRequested := True; 6156 FSharedValues.MarksRequestedForFile := ASource; 6157 DebugBoss.LineInfo.AddNotification(FLineInfoNotification); 6158 Application.QueueAsyncCall(@DoRequestExecutionMarks, 0); 6159 end; 6160 Exit; 6161 end; 6162 6163 FSharedValues.MarksRequestedForFile := ''; 6164 j := -1; 6165 EditorComponent.IDEGutterMarks.BeginSetDebugMarks; 6166 try 6167 for i := 1 to EditorComponent.Lines.Count do 6168 begin 6169 HasAddr := DebugBoss.LineInfo.HasAddress(idx, i); 6170 if (HasAddr) and (j < 0) then 6171 j := i; 6172 if (not HasAddr) and (j >= 0) then begin 6173 EditorComponent.IDEGutterMarks.SetDebugMarks(j, i-1); 6174 j := -1; 6175 end; 6176 end; 6177 if (HasAddr) and (j >= 0) then 6178 EditorComponent.IDEGutterMarks.SetDebugMarks(j, EditorComponent.Lines.Count); 6179 finally 6180 EditorComponent.IDEGutterMarks.EndSetDebugMarks; 6181 end; 6182 6183 // TODO: move to SourceSyneditor 6184 for i := 0 to SharedEditorCount - 1 do 6185 SharedEditors[i].EditorComponent.IDEGutterMarks.HasDebugMarks; // update all shared editors 6186end; 6187 6188procedure TSourceEditor.ClearExecutionMarks; 6189var 6190 i: Integer; 6191begin 6192 if FSharedValues.MarksRequested and (FSharedValues.MarksRequestedForFile <> '') then 6193 DebugBoss.LineInfo.Cancel(FSharedValues.MarksRequestedForFile); 6194 FSharedValues.MarksRequestedForFile := ''; 6195 6196 EditorComponent.IDEGutterMarks.ClearDebugMarks; 6197 FSharedValues.MarksRequested := False; 6198 for i := 0 to SharedEditorCount - 1 do 6199 SharedEditors[i].EditorComponent.IDEGutterMarks.ClearDebugMarks; // update all shared editors 6200 if (FLineInfoNotification <> nil) and (DebugBoss <> nil) and (DebugBoss.LineInfo <> nil) then 6201 DebugBoss.LineInfo.RemoveNotification(FLineInfoNotification); 6202end; 6203 6204procedure TSourceEditor.CopyToWindow(AWindowIndex: Integer); 6205begin 6206 SourceNotebook.CopyEditor(PageIndex, AWindowIndex, -1) 6207end; 6208 6209function TSourceEditor.GetCodeAttributeName(LogXY: TPoint): String; 6210var 6211 Token: string; 6212 Attri: TSynHighlighterAttributes; 6213begin 6214 Result := ''; 6215 if EditorComponent.GetHighlighterAttriAtRowCol(LogXY,Token,Attri) 6216 and (Attri<>nil) then 6217 begin 6218 Result := Attri.StoredName; 6219 end; 6220end; 6221 6222procedure TSourceEditor.LineInfoNotificationChange(const ASender: TObject; const ASource: String); 6223begin 6224 if ASource = FileName then begin 6225 Application.RemoveAsyncCalls(Self); 6226 FillExecutionMarks; 6227 end; 6228end; 6229 6230function TSourceEditor.SourceToDebugLine(aLinePos: Integer): Integer; 6231begin 6232 Result := FEditor.IDEGutterMarks.SourceLineToDebugLine(aLinePos, True); 6233end; 6234 6235function TSourceEditor.DebugToSourceLine(aLinePos: Integer): Integer; 6236begin 6237 Result := FEditor.IDEGutterMarks.DebugLineToSourceLine(aLinePos); 6238end; 6239 6240procedure TSourceEditor.InvalidateAllIfdefNodes; 6241begin 6242 FEditor.InvalidateAllIfdefNodes; 6243end; 6244 6245procedure TSourceEditor.SetIfdefNodeState(ALinePos, AstartPos: Integer; 6246 AState: TSynMarkupIfdefNodeState); 6247begin 6248 FEditor.SetIfdefNodeState(ALinePos, AstartPos, AState); 6249end; 6250 6251procedure TSourceEditor.UpdateIfDefNodeStates(Force: Boolean = False); 6252{off $DEFINE VerboseUpdateIfDefNodeStates} 6253{$IFDEF VerboseUpdateIfDefNodeStates} 6254const 6255 VFilePattern='blaunit'; 6256 VMinY=1; 6257 VMaxY=70; 6258{$ENDIF} 6259var 6260 Scanner: TLinkScanner; 6261 i: Integer; 6262 aDirective: PLSDirective; 6263 Code: TCodeBuffer; 6264 Y: integer; 6265 X: integer; 6266 SynState: TSynMarkupIfdefNodeStateEx; 6267 SrcPos: Integer; 6268 ActiveCnt: Integer; 6269 InactiveCnt: Integer; 6270 SkippedCnt: Integer; 6271begin 6272 //debugln(['TSourceEditor.UpdateIfDefNodeStates START ',Filename]); 6273 if not EditorComponent.IsIfdefMarkupActive then 6274 exit; 6275 //debugln(['TSourceEditor.UpdateIfDefNodeStates CHECK ',Filename]); 6276 UpdateCodeBuffer; 6277 Scanner:=SharedValues.GetMainLinkScanner(true); 6278 if Scanner=nil then exit; 6279 if (Scanner.ChangeStep=FLastIfDefNodeScannerStep) and (not Force) then exit; 6280 //debugln(['TSourceEditor.UpdateIfDefNodeStates UPDATING ',Filename]); 6281 FLastIfDefNodeScannerStep:=Scanner.ChangeStep; 6282 EditorComponent.BeginUpdate; 6283 try 6284 //EditorComponent.InvalidateAllIfdefNodes; 6285 Code:=CodeBuffer; 6286 i:=0; 6287 while i<Scanner.DirectiveCount do 6288 begin 6289 aDirective:=Scanner.DirectivesSorted[i]; 6290 //if (Pos(VFilePattern,Code.Filename)>0) then 6291 // debugln(['TSourceEditor.UpdateIfDefNodeStates ',i+1,'/',Scanner.DirectiveCount,' ',dbgs(aDirective^.Kind)]); 6292 inc(i); 6293 if TCodeBuffer(aDirective^.Code)<>Code then continue; 6294 if not (aDirective^.Kind in (lsdkAllIf+lsdkAllElse)) then continue; 6295 Code.AbsoluteToLineCol(aDirective^.SrcPos,Y,X); 6296 if Y<1 then continue; 6297 SynState:=idnInvalid; 6298 // a directive can be scanned multiple times (multi included include files) 6299 // => show it enabled if it was active at least once 6300 {$IFDEF VerboseUpdateIfDefNodeStates} 6301 if (Pos(VFilePattern,Code.Filename)>0) and (Y>=VMinY) and (Y<=VMaxY) then 6302 debugln(['TSourceEditor.UpdateIfDefNodeStates ',i,'/',Scanner.DirectiveCount,' ',dbgs(Pointer(Code)),' ',Code.Filename,' X=',X,' Y=',Y,' SrcPos=',aDirective^.SrcPos,' State=',dbgs(aDirective^.State)]); 6303 {$ENDIF} 6304 SrcPos:=aDirective^.SrcPos; 6305 ActiveCnt:=0; 6306 InactiveCnt:=0; 6307 SkippedCnt:=0; 6308 repeat 6309 case aDirective^.State of 6310 lsdsActive: inc(ActiveCnt); 6311 lsdsInactive: inc(InactiveCnt); 6312 lsdsSkipped: inc(SkippedCnt); 6313 end; 6314 if i < Scanner.DirectiveCount then begin 6315 ADirective:=Scanner.DirectivesSorted[i]; 6316 {$IFDEF VerboseUpdateIfDefNodeStates} 6317 if (Pos(VFilePattern,Code.Filename)>0) and (Y>=VMinY) and (Y<=VMaxY) and (ADirective^.SrcPos=SrcPos) then 6318 debugln(['TSourceEditor.UpdateIfDefNodeStates ',i,'/',Scanner.DirectiveCount,' MERGING ',dbgs(ADirective^.Code),' ',Code.Filename,' X=',X,' Y=',Y,' SrcPos=',aDirective^.SrcPos,' State=',dbgs(aDirective^.State)]); 6319 {$ENDIF} 6320 end; 6321 inc(i); 6322 until (ADirective^.SrcPos<>SrcPos) or (TCodeBuffer(ADirective^.Code)<>Code) 6323 or (i > Scanner.DirectiveCount); 6324 dec(i); 6325 if (ActiveCnt>0) and (InactiveCnt=0) and (SkippedCnt=0) then 6326 SynState:=idnEnabled 6327 else if (ActiveCnt=0) and (InactiveCnt+SkippedCnt>0) then 6328 SynState:=idnDisabled 6329 else if (ActiveCnt>0) then 6330 SynState:=idnTempEnabled 6331 else 6332 SynState:=idnInvalid; 6333 {$IFDEF VerboseUpdateIfDefNodeStates} 6334 if (Pos(VFilePattern,Code.Filename)>0) and (Y>=VMinY) and (Y<=VMaxY) then 6335 debugln(['TSourceEditor.UpdateIfDefNodeStates y=',y,' x=',x,' Counts:Inactive=',InactiveCnt,' Active=',ActiveCnt,' Skipped=',SkippedCnt,' SET SynState=',dbgs(SynState)]); 6336 {$ENDIF} 6337 EditorComponent.SetIfdefNodeState(Y,X,SynState); 6338 end; 6339 finally 6340 EditorComponent.EndUpdate; 6341 end; 6342end; 6343 6344function TSourceEditor.SharedEditorCount: Integer; 6345begin 6346 Result := FSharedValues.SharedEditorCount; 6347 if Result = 1 then 6348 Result := 0; // not a sharing editor 6349end; 6350 6351function TSourceEditor.GetWordAtCurrentCaret: String; 6352var 6353 CaretPos: TPoint; 6354begin 6355 CaretPos.Y := CurrentCursorYLine; 6356 CaretPos.X := CurrentCursorXLine; 6357 Result := GetWordFromCaret(ScreenToTextPosition(CaretPos)); 6358end; 6359 6360function TSourceEditor.GetOperandFromCaret(const ACaretPos: TPoint): String; 6361begin 6362 UpdateCodeBuffer; 6363 if not CodeToolBoss.GetExpandedOperand(CodeBuffer, ACaretPos.X, ACaretPos.Y, 6364 Result, False) 6365 then 6366 if not CodeToolBoss.ExtractOperand(CodeBuffer, ACaretPos.X, ACaretPos.Y, 6367 Result, False, False, true) 6368 then 6369 Result := GetWordFromCaret(ACaretPos); 6370end; 6371 6372function TSourceEditor.GetPageCaption: string; 6373var 6374 I: Integer; 6375begin 6376 I := SourceNotebook.FindPageWithEditor(Self); 6377 if I >= 0 then 6378 Result := SourceNotebook.NoteBookPages[I] 6379 else 6380 Result := FPageName; 6381end; 6382 6383function TSourceEditor.GetPageName: string; 6384begin 6385 Result := FPageName; 6386end; 6387 6388function TSourceEditor.GetOperandAtCurrentCaret: String; 6389var 6390 CaretPos: TPoint; 6391begin 6392 CaretPos.Y := CurrentCursorYLine; 6393 CaretPos.X := CurrentCursorXLine; 6394 Result := GetOperandFromCaret(ScreenToTextPosition(CaretPos)); 6395end; 6396 6397function TSourceEditor.GetWordFromCaret(const ACaretPos: TPoint): String; 6398begin 6399 Result := FEditor.GetWordAtRowCol(ACaretPos); 6400end; 6401 6402function TSourceEditor.IsFirstShared(Sender: TObject): boolean; 6403begin 6404 Result:=SharedEditors[0]=Self; 6405end; 6406 6407procedure TSourceEditor.SetVisible(Value: boolean); 6408begin 6409 if FVisible=Value then exit; 6410 if FEditor<>nil then FEditor.Visible:=Value; 6411 FVisible:=Value; 6412end; 6413 6414procedure TSourceEditor.UnbindEditor; 6415// disconnect all events 6416var 6417 i: Integer; 6418begin 6419 with EditorComponent do begin 6420 OnStatusChange := nil; 6421 OnProcessCommand := nil; 6422 OnProcessUserCommand := nil; 6423 OnCommandProcessed := nil; 6424 OnReplaceText := nil; 6425 OnGutterClick := nil; 6426 OnSpecialLineMarkup := nil; 6427 OnMouseMove := nil; 6428 OnMouseWheel := nil; 6429 OnMouseDown := nil; 6430 OnClickLink := nil; 6431 OnMouseLink := nil; 6432 OnKeyDown := nil; 6433 OnKeyUp := nil; 6434 OnEnter := nil; 6435 OnPlaceBookmark := nil; 6436 OnClearBookmark := nil; 6437 OnChangeUpdating := nil; 6438 OnIfdefNodeStateRequest := nil; 6439 UnregisterMouseActionExecHandler(@EditorHandleMouseAction); 6440 end; 6441 for i := 0 to EditorComponent.PluginCount - 1 do 6442 if EditorComponent.Plugin[i] is TSynPluginSyncronizedEditBase then begin 6443 TSynPluginSyncronizedEditBase(EditorComponent.Plugin[i]).OnActivate := nil; 6444 TSynPluginSyncronizedEditBase(EditorComponent.Plugin[i]).OnDeactivate := nil; 6445 end; 6446 if FEditPlugin<>nil then begin 6447 FEditPlugin.Enabled:=false; 6448 end; 6449end; 6450 6451procedure TSourceEditor.DoEditorExecuteCommand(EditorCommand: word); 6452begin 6453 EditorComponent.CommandProcessor(TSynEditorCommand(EditorCommand),' ',nil); 6454end; 6455 6456{------------------------------------------------------------------------} 6457 { TSourceNotebook } 6458 6459constructor TSourceNotebook.Create(AOwner: TComponent); 6460var 6461 i: Integer; 6462 n: TComponent; 6463begin 6464 FPageIndex := -1; 6465 i := 1; 6466 n := AOwner.FindComponent(NonModalIDEWindowNames[nmiwSourceNoteBook]); 6467 while (n <> nil) do begin 6468 inc(i); 6469 n := AOwner.FindComponent(NonModalIDEWindowNames[nmiwSourceNoteBook]+IntToStr(i)); 6470 end; 6471 6472 Create(AOwner, i-1); 6473end; 6474 6475constructor TSourceNotebook.Create(AOwner: TComponent; AWindowID: Integer); 6476begin 6477 inherited Create(AOwner); 6478 FManager := TSourceEditorManager(AOwner); 6479 FUpdateLock := 0; 6480 FFocusLock := 0; 6481 Visible := false; 6482 FIsClosing := False; 6483 FWindowID := AWindowID; 6484 if AWindowID > 0 then 6485 Name := NonModalIDEWindowNames[nmiwSourceNoteBook] + IntToStr(AWindowID+1) 6486 else 6487 Name := NonModalIDEWindowNames[nmiwSourceNoteBook]; 6488 6489 if AWindowID > 0 then 6490 BaseCaption := locWndSrcEditor + ' (' + IntToStr(AWindowID+1) + ')' 6491 else 6492 BaseCaption := locWndSrcEditor; 6493 Caption := BaseCaption; 6494 KeyPreview := true; 6495 FProcessingCommand := false; 6496 6497 FSourceEditorList := TFPList.Create; 6498 FHistoryList := TFPList.Create; 6499 FSrcEditsSortedForFilenames := TAvlTree.Create(@CompareSrcEditIntfWithFilename); 6500 6501 FHistoryDlg := TBrowseEditorTabHistoryDialog.CreateNew(Self); 6502 FOnEditorPageCaptionUpdate := TMethodList.Create; 6503 6504 OnDropFiles := @SourceNotebookDropFiles; 6505 AllowDropFiles:=true; 6506 6507 // popup menu 6508 BuildPopupMenu; 6509 6510 FUpdateTabAndPageTimer := TTimer.Create(Self); 6511 FUpdateTabAndPageTimer.Interval := 500; 6512 FUpdateTabAndPageTimer.OnTimer := @UpdateTabsAndPageTimeReached; 6513 6514 CreateNotebook; 6515 6516 Application.AddOnDeactivateHandler(@OnApplicationDeactivate); 6517 Application.AddOnMinimizeHandler(@OnApplicationDeactivate); 6518 6519 FStopBtnIdx := IDEImages.LoadImage('menu_stop'); 6520 6521 {$IFNDEF LCLGtk2} 6522 try 6523 Icon.LoadFromResourceName(HInstance, 'WIN_SOURCEEDITOR'); 6524 except 6525 end; 6526 {$ENDIF} 6527end; 6528 6529destructor TSourceNotebook.Destroy; 6530var 6531 i: integer; 6532begin 6533 DebugLnEnter(SRCED_CLOSE, ['TSourceNotebook.Destroy ']); 6534 if assigned(Manager) then 6535 Manager.RemoveWindow(Self); 6536 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceNotebook.Destroy'){$ENDIF}; 6537 FProcessingCommand:=false; 6538 6539 for i:=FSourceEditorList.Count-1 downto 0 do 6540 Editors[i].Free; 6541 FreeAndNil(FSourceEditorList); 6542 FreeAndNil(FHistoryList); 6543 FreeAndNil(FOnEditorPageCaptionUpdate); 6544 FreeAndNil(FSrcEditsSortedForFilenames); 6545 6546 Application.RemoveOnDeactivateHandler(@OnApplicationDeactivate); 6547 Application.RemoveOnMinimizeHandler(@OnApplicationDeactivate); 6548 FreeAndNil(FNotebook); 6549 6550 inherited Destroy; 6551 DebugLnExit(SRCED_CLOSE, ['TSourceNotebook.Destroy ']); 6552end; 6553 6554procedure TSourceNotebook.CreateNotebook; 6555var 6556 APage: TTabSheet; 6557Begin 6558 {$IFDEF IDE_DEBUG} 6559 debugln('[TSourceNotebook.CreateNotebook] START'); 6560 {$ENDIF} 6561 {$IFDEF IDE_MEM_CHECK} 6562 CheckHeapWrtMemCnt('[TSourceNotebook.CreateNotebook] A '); 6563 {$ENDIF} 6564 FNotebook := TExtendedNotebook.Create(self); 6565 {$IFDEF IDE_DEBUG} 6566 debugln('[TSourceNotebook.CreateNotebook] B'); 6567 {$ENDIF} 6568 {$IFDEF IDE_MEM_CHECK} 6569 CheckHeapWrtMemCnt('[TSourceNotebook.CreateNotebook] B '); 6570 {$ENDIF} 6571 FPageIndex := -1; 6572 with FNotebook do Begin 6573 Name:='SrcEditNotebook'; 6574 Parent := Self; 6575 {$IFDEF IDE_DEBUG} 6576 debugln('[TSourceNotebook.CreateNotebook] C'); 6577 {$ENDIF} 6578 Align := alClient; 6579 APage:=TTabSheet.Create(FNotebook); 6580 APage.Caption:='unit1'; 6581 APage.Parent:=FNotebook; 6582 PageIndex := 0; // Set it to the first page 6583 Options:=Options+[nboHidePageListPopup]; // hide default popup menu, we show custom in mouse up 6584 if EditorOpts.ShowTabCloseButtons then 6585 Options:=Options+[nboShowCloseButtons] 6586 else 6587 Options:=Options-[nboShowCloseButtons]; 6588 MultiLine := EditorOpts.MultiLineTab; 6589 if Manager<>nil then 6590 ShowTabs := Manager.ShowTabs 6591 else 6592 ShowTabs := True; 6593 if ShowTabs then 6594 TabPosition := EditorOpts.TabPosition; 6595 OnChange := @NotebookPageChanged; 6596 OnCloseTabClicked := @CloseTabClicked; 6597 OnMouseDown:=@NotebookMouseDown; 6598 OnMouseUp:=@NotebookMouseUp; 6599 TabDragMode := dmAutomatic; 6600 OnTabDragOverEx := @NotebookDragOverEx; 6601 OnTabDragDropEx := @NotebookDragDropEx; 6602 OnTabDragOver := @NotebookDragOver; 6603 OnTabEndDrag := @NotebookEndDrag; 6604 ShowHint:=true; 6605 OnShowHint:=@NotebookShowTabHint; 6606 {$IFDEF IDE_DEBUG} 6607 debugln('[TSourceNotebook.CreateNotebook] D'); 6608 {$ENDIF} 6609 Visible := False; 6610 end; //with 6611 {$IFDEF IDE_DEBUG} 6612 debugln('[TSourceNotebook.CreateNotebook] END'); 6613 {$ENDIF} 6614 {$IFDEF IDE_MEM_CHECK} 6615 CheckHeapWrtMemCnt('[TSourceNotebook.CreateNotebook] END '); 6616 {$ENDIF} 6617End; 6618 6619type 6620 TLineEnding = (leLF, leCR, leCRLF); 6621const 6622 LE_Strs : array [TLineEnding] of String = (#10, #13, #13#10); 6623 6624procedure TSourceNotebook.LineEndingClicked(Sender: TObject); 6625var 6626 IDEMenuItem: TIDEMenuItem; 6627 SrcEdit: TSourceEditor; 6628 NewLineEnding: String; 6629 OldLineEnding: String; 6630begin 6631 SrcEdit:=GetActiveSE; 6632 if SrcEdit=nil then exit; 6633 if not (Sender is TIDEMenuItem) then exit; 6634 if SrcEdit.CodeBuffer=nil then exit; 6635 6636 IDEMenuItem:=TIDEMenuItem(Sender); 6637 NewLineEnding:=LE_Strs[TLineEnding(IDEMenuItem.Tag)]; 6638 DebugLn(['TSourceNotebook.LineEndingClicked NewLineEnding=',NewLineEnding]); 6639 OldLineEnding:=SrcEdit.CodeBuffer.DiskLineEnding; 6640 if OldLineEnding='' then 6641 OldLineEnding:=LineEnding; 6642 if NewLineEnding<>SrcEdit.CodeBuffer.DiskLineEnding then begin 6643 DebugLn(['TSourceNotebook.LineEndingClicked Old=',dbgstr(OldLineEnding),' New=',dbgstr(NewLineEnding)]); 6644 // change file 6645 SrcEdit.CodeBuffer.DiskLineEnding:=NewLineEnding; 6646 SrcEdit.CodeBuffer.Source:= 6647 ChangeLineEndings(SrcEdit.CodeBuffer.Source,NewLineEnding); 6648 SrcEdit.CodeBuffer.Modified:=true; 6649 SrcEdit.Modified:=true; 6650 end; 6651end; 6652 6653procedure TSourceNotebook.EncodingClicked(Sender: TObject); 6654var 6655 IDEMenuItem: TIDEMenuItem; 6656 SrcEdit: TSourceEditor; 6657 NewEncoding: String; 6658 OldEncoding: String; 6659 CurResult: TModalResult; 6660begin 6661 SrcEdit:=GetActiveSE; 6662 if SrcEdit=nil then exit; 6663 if Sender is TIDEMenuItem then begin 6664 IDEMenuItem:=TIDEMenuItem(Sender); 6665 NewEncoding:=IDEMenuItem.Caption; 6666 if SysUtils.CompareText(copy(NewEncoding,1,length(EncodingAnsi)+2),EncodingAnsi+' (')=0 6667 then begin 6668 // the ansi encoding is shown as 'ansi (system encoding)' -> cut 6669 NewEncoding:=EncodingAnsi; 6670 end else if NewEncoding=lisUtf8WithBOM then begin 6671 NewEncoding:=EncodingUTF8BOM; 6672 end; 6673 DebugLn(['Hint: (lazarus) TSourceNotebook.EncodingClicked NewEncoding=',NewEncoding]); 6674 if SrcEdit.CodeBuffer<>nil then begin 6675 OldEncoding:=NormalizeEncoding(SrcEdit.CodeBuffer.DiskEncoding); 6676 if OldEncoding='' then 6677 OldEncoding:=GetDefaultTextEncoding; 6678 if NewEncoding<>SrcEdit.CodeBuffer.DiskEncoding then begin 6679 DebugLn(['Hint: (lazarus) TSourceNotebook.EncodingClicked Old=',OldEncoding,' New=',NewEncoding]); 6680 if SrcEdit.ReadOnly then begin 6681 if SrcEdit.CodeBuffer.IsVirtual then 6682 CurResult:=mrCancel 6683 else 6684 CurResult:=IDEQuestionDialog(lisChangeEncoding, 6685 Format(lisEncodingOfFileOnDiskIsNewEncodingIs, 6686 [SrcEdit.CodeBuffer.Filename, LineEnding, OldEncoding, NewEncoding]), 6687 mtConfirmation, [mrOk, lisReopenWithAnotherEncoding, mrCancel]); 6688 end else begin 6689 if SrcEdit.CodeBuffer.IsVirtual then 6690 CurResult:=IDEQuestionDialog(lisChangeEncoding, 6691 Format(lisEncodingOfFileOnDiskIsNewEncodingIs, 6692 [SrcEdit.CodeBuffer.Filename, LineEnding, OldEncoding, NewEncoding]), 6693 mtConfirmation, [mrYes, lisChangeFile, mrCancel]) 6694 else 6695 CurResult:=IDEQuestionDialog(lisChangeEncoding, 6696 Format(lisEncodingOfFileOnDiskIsNewEncodingIs, 6697 [SrcEdit.CodeBuffer.Filename, LineEnding, OldEncoding, NewEncoding]), 6698 mtConfirmation, [mrYes,lisChangeFile,mrOk,lisReopenWithAnotherEncoding,mrCancel]); 6699 end; 6700 if CurResult=mrYes then begin 6701 // change file 6702 SrcEdit.CodeBuffer.DiskEncoding:=NewEncoding; 6703 SrcEdit.CodeBuffer.Modified:=true; 6704 // set override 6705 InputHistoriesSO.FileEncodings[SrcEdit.CodeBuffer.Filename]:=NewEncoding; 6706 DebugLn(['Hint: (lazarus) TSourceNotebook.EncodingClicked Change file to ',SrcEdit.CodeBuffer.DiskEncoding]); 6707 if (not SrcEdit.CodeBuffer.IsVirtual) 6708 and (LazarusIDE.DoSaveEditorFile(SrcEdit, []) <> mrOk) 6709 then begin 6710 DebugLn(['Hint: (lazarus) TSourceNotebook.EncodingClicked LazarusIDE.DoSaveEditorFile failed']); 6711 end; 6712 end else if CurResult=mrOK then begin 6713 // reopen with another encoding 6714 if SrcEdit.Modified then begin 6715 if IDEQuestionDialog(lisAbandonChanges, 6716 Format(lisAllYourModificationsToWillBeLostAndTheFileReopened, 6717 [SrcEdit.CodeBuffer.Filename, LineEnding]), 6718 mtConfirmation,[mbOk,mbAbort],'')<>mrOk 6719 then begin 6720 exit; 6721 end; 6722 end; 6723 // set override 6724 InputHistoriesSO.FileEncodings[SrcEdit.CodeBuffer.Filename]:=NewEncoding; 6725 if not SrcEdit.CodeBuffer.Revert then begin 6726 IDEMessageDialog(lisCodeToolsDefsReadError, 6727 Format(lisUnableToRead, [SrcEdit.CodeBuffer.Filename]), 6728 mtError,[mbCancel],''); 6729 exit; 6730 end; 6731 SrcEdit.EditorComponent.BeginUpdate; 6732 SrcEdit.CodeBuffer.AssignTo(SrcEdit.EditorComponent.Lines,False); 6733 SrcEdit.EditorComponent.EndUpdate; 6734 end; 6735 end; 6736 end; 6737 end; 6738end; 6739 6740procedure TSourceNotebook.HighlighterClicked(Sender: TObject); 6741var 6742 IDEMenuItem: TIDEMenuItem; 6743 i: LongInt; 6744 SrcEdit: TSourceEditor; 6745 h: TLazSyntaxHighlighter; 6746begin 6747 SrcEdit:=GetActiveSE; 6748 if SrcEdit=nil then exit; 6749 if Sender is TIDEMenuItem then begin 6750 IDEMenuItem:=TIDEMenuItem(Sender); 6751 i:=IDEMenuItem.SectionIndex; 6752 if (i>=ord(Low(TLazSyntaxHighlighter))) 6753 and (i<=ord(High(TLazSyntaxHighlighter))) then begin 6754 h:=TLazSyntaxHighlighter(i); 6755 SrcEdit.SyntaxHighlighterType:=h; 6756 SrcEdit.UpdateProjectFile([sepuChangedHighlighter]); 6757 end; 6758 end; 6759end; 6760 6761procedure TSourceNotebook.TabPopUpMenuPopup(Sender: TObject); 6762var 6763 ASrcEdit: TSourceEditor; 6764 6765 {$IFnDEF SingleSrcWindow} 6766 function ToWindow(ASection: TIDEMenuSection; const OpName: string; 6767 const OnClickMethod: TNotifyEvent; WinForFind: Boolean = False): Boolean; 6768 var 6769 i, ThisWin, SharedEditor: Integer; 6770 nb: TSourceNotebook; 6771 begin 6772 Result := False; 6773 ASection.Clear; 6774 ThisWin := Manager.IndexOfSourceWindow(self); 6775 for i := 0 to Manager.SourceWindowCount - 1 do begin 6776 nb:=Manager.SourceWindows[i]; 6777 SharedEditor:=nb.IndexOfEditorInShareWith(ASrcEdit); 6778 if (i <> ThisWin) and ((SharedEditor < 0) <> WinForFind) then begin 6779 Result := True; 6780 with RegisterIDEMenuCommand(ASection,OpName+IntToStr(i),nb.Caption,OnClickMethod) do 6781 Tag := i; 6782 end; 6783 end; 6784 end; 6785 {$ENDIF} 6786 procedure AddEditorToMenuSection(AEditor: TSourceEditor; AMenu: TIDEMenuSection; AIndex: Integer); 6787 var 6788 S: String; 6789 begin 6790 S := AEditor.PageName; 6791 if AEditor.Modified then 6792 S := '*'+S; 6793 6794 RegisterIDEMenuCommand(AMenu, 'File'+IntToStr(AIndex), 6795 S, @ExecuteEditorItemClick, nil, nil, '', PtrUInt(AEditor)); 6796 end; 6797 6798var 6799 PageCtrl: TPageControl; 6800 PopM: TPopupMenu; 6801 PageI: integer; 6802 i: Integer; 6803 S: String; 6804 EditorCur: TSourceEditor; 6805 P: TIDEPackage; 6806 RecMenu, ProjMenu, M: TIDEMenuSection; 6807 EdList: TStringListUTF8Fast; 6808begin 6809 PopM:=TPopupMenu(Sender); 6810 SourceTabMenuRoot.MenuItem:=PopM.Items; 6811 // Get the tab that was clicked 6812 if PopM.PopupComponent is TPageControl then begin 6813 PageCtrl:=TPageControl(PopM.PopupComponent); 6814 PageI:=PageCtrl.IndexOfPageAt(PageCtrl.ScreenToClient(PopM.PopupPoint)); 6815 if (PageI>=0) and (PageI<PageCtrl.PageCount) then 6816 PageIndex := PageI // Todo: This should be in MouseDown / or both, whichever is first 6817 else 6818 DebugLn(['TSourceNotebook.TabPopUpMenuPopup: Popup PageIndex=', PageI]); 6819 end; 6820 ASrcEdit:=ActiveEditor as TSourceEditor; 6821 6822 {$IFnDEF SingleSrcWindow} 6823 // Multi win 6824 ToWindow(SrcEditMenuMoveToOtherWindowList, 'MoveToWindow', 6825 @SrcEditMenuMoveToExistingWindowClicked); 6826 ToWindow(SrcEditMenuCopyToOtherWindowList, 'CopyToWindow', 6827 @SrcEditMenuCopyToExistingWindowClicked); 6828 ToWindow(SrcEditMenuFindInOtherWindowList, 'FindInWindow', 6829 @SrcEditMenuFindInWindowClicked, True); 6830 {$ENDIF} 6831 6832 SrcEditMenuSectionEditors.Clear; 6833 if Manager <> nil then begin 6834 EdList := TStringListUTF8Fast.Create; 6835 EdList.OwnsObjects := False; 6836 for i := 0 to EditorCount - 1 do 6837 EdList.AddObject(Editors[i].PageName+' '+Editors[i].FileName, Editors[i]); 6838 EdList.Sorted := True; 6839 6840 RecMenu := RegisterIDESubMenu(SrcEditMenuSectionEditors, lisRecentTabs, lisRecentTabs); 6841 RecMenu.Visible := False; 6842 ProjMenu := RegisterIDESubMenu(SrcEditMenuSectionEditors, dlgEnvProject, dlgEnvProject); 6843 ProjMenu.Visible := False; 6844 RegisterIDESubMenu(SrcEditMenuSectionEditors, lisMEOther, lisMEOther).Visible := False; 6845 6846 //first add all pages in the correct order since the editor order can be different from the tab order 6847 for i := 0 to EdList.Count - 1 do 6848 begin 6849 EditorCur := TSourceEditor(EdList.Objects[i]); 6850 s := lisMEOther; 6851 P := nil; 6852 if (EditorCur.GetProjectFile <> nil) and (EditorCur.GetProjectFile.IsPartOfProject) then 6853 s := dlgEnvProject 6854 else begin 6855 Manager.OnPackageForSourceEditor(P, EditorCur); 6856 if P <> nil then 6857 s := Format(lisTabsFor, [p.Name]); 6858 end; 6859 6860 if SrcEditMenuSectionEditors.FindByName(S) is TIDEMenuSection then begin 6861 M := TIDEMenuSection(SrcEditMenuSectionEditors.FindByName(S)) 6862 end else begin 6863 M := RegisterIDESubMenu(SrcEditMenuSectionEditors, S, S); 6864 M.UserTag := PtrUInt(P); 6865 end; 6866 M.Visible := True; 6867 6868 AddEditorToMenuSection(EditorCur, M, i); 6869 // use tag to count modified 6870 if EditorCur.Modified then M.Tag := m.Tag + 1; 6871 end; 6872 6873 EdList.Free; 6874 6875 // add recent tabs. skip 0 since that is the active tab 6876 for i := 1 to Min(10, FHistoryList.Count-1) do 6877 begin 6878 EditorCur := FindSourceEditorWithPageIndex(FNotebook.IndexOf(TCustomPage(FHistoryList[i]))); 6879 if (EditorCur = nil) or (not EditorCur.FEditor.HandleAllocated) then continue; // show only if it was visited 6880 AddEditorToMenuSection(EditorCur, RecMenu, i); 6881 RecMenu.Visible := True; 6882 end; 6883 6884 for i := 0 to SrcEditMenuSectionEditors.Count - 1 do begin 6885 if SrcEditMenuSectionEditors.Items[i] is TIDEMenuSection then begin 6886 M := SrcEditMenuSectionEditors.Items[i] as TIDEMenuSection; 6887 6888 if M.Tag = 0 then 6889 M.Caption := M.Caption + Format(' (%d)', [M.Count]) 6890 else 6891 M.Caption := M.Caption + Format(' (*%d/%d)', [M.Tag, M.Count]); 6892 6893 if M.UserTag <> 0 then 6894 RegisterIDEMenuCommand( 6895 RegisterIDEMenuSection(M as TIDEMenuSection, 'Open lpk sect '+TIDEPackage(M.UserTag).Filename), 6896 'Open lpk '+TIDEPackage(M.UserTag).Filename, 6897 lisCompPalOpenPackage, @OnPopupOpenPackageFile, nil, nil, '', M.UserTag); 6898 end; 6899 end; 6900 6901 if ProjMenu.Visible then begin 6902 RegisterIDEMenuCommand( 6903 RegisterIDEMenuSection(ProjMenu, 'Open proj sect '), 6904 'Open proj', lisOpenProject2, @OnPopupOpenProjectInsp); 6905 end; 6906 6907 end; 6908end; 6909 6910procedure TSourceNotebook.SrcPopUpMenuPopup(Sender: TObject); 6911var 6912 ASrcEdit: TSourceEditor; 6913 CurFilename: String; 6914 6915 function MaybeAddPopup(const ASuffix: String; ANewOnClick: TNotifyEvent = nil; 6916 Filename: string = ''): TIDEMenuItem; 6917 begin 6918 Result:=nil; 6919 if ANewOnClick=nil then 6920 ANewOnClick:=@OnPopupMenuOpenFile; 6921 if Filename='' then 6922 Filename:=CurFilename; 6923 Filename:=ChangeFileExt(Filename,ASuffix); 6924 if FileExistsCached(Filename) then begin 6925 Filename:=CreateRelativePath(Filename,ExtractFilePath(ASrcEdit.FileName)); 6926 Result:=AddContextPopupMenuItem(Format(lisOpenLfm,[Filename]), true, ANewOnClick); 6927 end; 6928 end; 6929 6930var 6931 FPDocSrc, ShortFileName: String; 6932 EditorComp: TSynEdit; 6933 MainCodeBuf: TCodeBuffer; 6934 AnOwner: TObject; 6935 Marks: PSourceMark; 6936 i, MarkCount: integer; 6937 EditorPopupPoint, EditorCaret: TPoint; 6938begin 6939 IDECommandList.ExecuteUpdateEvents; 6940 6941 SourceEditorMenuRoot.MenuItem:=SrcPopupMenu.Items; 6942 RemoveUserDefinedMenuItems; 6943 RemoveContextMenuItems; 6944 6945 ASrcEdit:=FindSourceEditorWithEditorComponent(TPopupMenu(Sender).PopupComponent); 6946 Assert(Assigned(ASrcEdit), 'TSourceNotebook.SrcPopUpMenuPopup: ASrcEdit=nil'); 6947 Assert((ASrcEdit=GetActiveSE), 'TSourceNotebook.SrcPopUpMenuPopup: ASrcEdit<>GetActiveSE'); 6948 EditorComp:=ASrcEdit.EditorComponent; 6949 6950 SrcEditMenuReadOnly.Checked:=ASrcEdit.ReadOnly; 6951 SrcEditMenuShowLineNumbers.Checked := ASrcEdit.EditorComponent.Gutter.LineNumberPart.Visible; 6952 SrcEditMenuDisableI18NForLFM.Visible:=false; 6953 6954 UpdateHighlightMenuItems(ASrcEdit); 6955 UpdateEncodingMenuItems(ASrcEdit); 6956 UpdateLineEndingMenuItems(ASrcEdit); 6957 6958 // ask Codetools 6959 CurFilename:=ASrcEdit.FileName; 6960 ShortFileName:=ExtractFileName(CurFilename); 6961 MainCodeBuf:=nil; 6962 if FilenameHasPascalExt(ShortFileName) or FilenameExtIs(ShortFileName,'inc') then 6963 MainCodeBuf:=CodeToolBoss.GetMainCode(ASrcEdit.CodeBuffer) 6964 else if FilenameIsPascalSource(ShortFileName) then 6965 MainCodeBuf:=ASrcEdit.CodeBuffer; 6966 6967 if (FilenameIsAbsolute(CurFilename)) then begin 6968 if (MainCodeBuf<>nil) and (MainCodeBuf<>ASrcEdit.CodeBuffer) 6969 and (not MainCodeBuf.IsVirtual) then begin 6970 // this is an include file => add link to open unit 6971 CurFilename:=MainCodeBuf.Filename; 6972 ShortFileName:=ExtractFileName(CurFilename); 6973 AddContextPopupMenuItem( 6974 Format(lisOpenLfm, 6975 [CreateRelativePath(CurFilename,ExtractFilePath(ASrcEdit.Filename))]), 6976 true,@OnPopupMenuOpenFile); 6977 end; 6978 if FilenameHasPascalExt(ShortFileName) then begin 6979 MaybeAddPopup('.lfm'); 6980 MaybeAddPopup('.dfm'); 6981 MaybeAddPopup('.lrs'); 6982 MaybeAddPopup('.s'); 6983 end; 6984 // ToDo: unit resources 6985 if FilenameExtIs(ShortFileName,'lfm',true) 6986 or FilenameExtIs(ShortFileName,'dfm') then begin 6987 MaybeAddPopup('.pas'); 6988 MaybeAddPopup('.pp'); 6989 MaybeAddPopup('.p'); 6990 end; 6991 if FilenameExtIn(ShortFileName, ['lpi','lpk'], true) then begin 6992 AddContextPopupMenuItem(Format(lisOpenLfm,[ShortFileName]),true,@OnPopupMenuOpenFile); 6993 end; 6994 FPDocSrc:=LazarusHelp.GetFPDocFilenameForSource(CurFilename,false,AnOwner); 6995 if FPDocSrc<>'' then 6996 AddContextPopupMenuItem( 6997 Format(lisOpenLfm, 6998 [CreateRelativePath(FPDocSrc,ExtractFilePath(CurFilename))]), 6999 true,@OnPopupMenuOpenFile); 7000 end; 7001 7002 EditorPopupPoint:=EditorComp.ScreenToClient(SrcPopUpMenu.PopupPoint); 7003 if EditorPopupPoint.X<=EditorComp.Gutter.Width then begin 7004 EditorCaret := EditorComp.PhysicalToLogicalPos(EditorComp.PixelsToRowColumn(EditorPopupPoint)); 7005 // user clicked on gutter 7006 SourceEditorMarks.GetMarksForLine(ASrcEdit, EditorCaret.y, Marks, MarkCount); 7007 if Marks <> nil then begin 7008 for i := 0 to MarkCount-1 do 7009 Marks[i].CreatePopupMenuItems(@AddUserDefinedPopupMenuItem); 7010 FreeMem(Marks); 7011 end; 7012 if (EditorCaret.Y<=EditorComp.Lines.Count) 7013 and (MessagesView<>nil) then 7014 MessagesView.SourceEditorPopup(EditorComp.Marks.Line[EditorCaret.Y], 7015 EditorComp.LogicalCaretXY); 7016 end; 7017 7018 if Assigned(Manager.OnPopupMenu) then 7019 Manager.OnPopupMenu(@AddContextPopupMenuItem); 7020 SourceEditorMenuRoot.NotifySubSectionOnShow(Self); 7021 //SrcPopupMenu.Items.WriteDebugReport('TSourceNotebook.SrcPopUpMenuPopup() '); 7022end; 7023 7024procedure TSourceNotebook.DbgPopUpMenuPopup(Sender: TObject); 7025begin 7026 SrcEditSubMenuDebug.MenuItem:=DbgPopUpMenu.Items; 7027end; 7028 7029procedure TSourceNotebook.NotebookShowTabHint(Sender: TObject; 7030 HintInfo: PHintInfo); 7031var 7032 Tabindex: integer; 7033 ASrcEdit: TSourceEditor; 7034begin 7035 if (PageCount=0) or (HintInfo=nil) then exit; 7036 TabIndex:=FNoteBook.IndexOfPageAt(FNotebook.ScreenToClient(Mouse.CursorPos)); 7037 if TabIndex<0 then exit; 7038 ASrcEdit:=FindSourceEditorWithPageIndex(TabIndex); 7039 if ASrcEdit=nil then exit; 7040 if ASrcEdit.CodeBuffer<>nil then begin 7041 HintInfo^.HintStr:=ASrcEdit.CodeBuffer.Filename; 7042 end; 7043end; 7044 7045function TSourceNotebook.GetItems(Index: integer): TSourceEditorInterface; 7046begin 7047 Result:=TSourceEditorInterface(FSourceEditorList[Index]); 7048end; 7049 7050procedure TSourceNotebook.BuildPopupMenu; 7051begin 7052 //debugln('TSourceNotebook.BuildPopupMenu'); 7053 7054 TabPopUpMenu := TPopupMenu.Create(Self); 7055 with TabPopupMenu do 7056 begin 7057 AutoPopup := True; 7058 OnPopup :=@TabPopupMenuPopup; 7059 Images := IDEImages.Images_16; 7060 end; 7061 7062 SrcPopupMenu := TPopupMenu.Create(Self); 7063 with SrcPopupMenu do 7064 begin 7065 AutoPopup := True; 7066 OnPopup :=@SrcPopupMenuPopup; 7067 Images := IDEImages.Images_16; 7068 end; 7069 7070 DbgPopUpMenu := TPopupMenu.Create(Self); 7071 with DbgPopupMenu do 7072 begin 7073 AutoPopup := True; 7074 OnPopup :=@DbgPopupMenuPopup; 7075 Images := IDEImages.Images_16; 7076 end; 7077 7078 GoToLineMenuItem.Caption := lisMenuGotoLine; 7079 OpenFolderMenuItem.Caption := lisMenuOpenFolder; 7080 {$IFDEF VerboseMenuIntf} 7081 SrcPopupMenu.Items.WriteDebugReport('TSourceNotebook.BuildPopupMenu '); 7082 SourceTabMenuRoot.ConsistencyCheck; 7083 SourceEditorMenuRoot.ConsistencyCheck; 7084 {$ENDIF} 7085end; 7086 7087procedure TSourceNotebook.CallOnEditorPageCaptionUpdate(Sender: TObject); 7088begin 7089 FOnEditorPageCaptionUpdate.CallNotifyEvents(Sender); 7090end; 7091 7092function TSourceNotebook.GetNoteBookPage(Index: Integer): TTabSheet; 7093begin 7094 if FNotebook.Visible then 7095 Result := FNotebook.Pages[Index] 7096 else 7097 Result := nil; 7098end; 7099 7100function TSourceNotebook.GetNotebookPages: TStrings; 7101begin 7102 if FNotebook.Visible then 7103 Result := TCustomTabControl(FNotebook).Pages 7104 else 7105 Result := nil; 7106end; 7107 7108function TSourceNotebook.GetPageCount: Integer; 7109begin 7110 If FNotebook.Visible then 7111 Result := FNotebook.PageCount 7112 else 7113 Result := 0; 7114end; 7115 7116function TSourceNotebook.GetPageIndex: Integer; 7117begin 7118 if FUpdateLock > 0 then 7119 Result := FPageIndex 7120 else 7121 if FNotebook.Visible then 7122 Result := FNotebook.PageIndex 7123 else 7124 Result := -1 7125end; 7126 7127function TSourceNotebook.GetWindowID: Integer; 7128begin 7129 Result := FWindowID; 7130end; 7131 7132procedure TSourceNotebook.SetPageIndex(AValue: Integer); 7133begin 7134 if (fPageIndex = AValue) and (FNotebook.PageIndex = AValue) then begin 7135 //debugln(['>> TSourceNotebook.SetPageIndex PageIndex=', PageIndex, ' FPageIndex=', FPageIndex, ' Value=', AValue, ' FUpdateLock=', FUpdateLock]); 7136 //DumpStack; 7137 exit; 7138 end; 7139 DebugLnEnter(SRCED_PAGES, ['>> TSourceNotebook.SetPageIndex Cur-PgIdx=', PageIndex, ' FPageIndex=', FPageIndex, ' Value=', AValue, ' FUpdateLock=', FUpdateLock]); 7140 //debugln(['>> TSourceNotebook.SetPageIndex CHANGE PageIndex=', PageIndex, ' FPageIndex=', FPageIndex, ' Value=', AValue, ' FUpdateLock=', FUpdateLock]); 7141 FPageIndex := AValue; 7142 if FUpdateLock = 0 then 7143 ApplyPageIndex 7144 else 7145 Include(FUpdateFlags,ufPageIndexChanged); 7146 DebugLnExit(SRCED_PAGES, ['<< TSourceNotebook.SetPageIndex ']); 7147end; 7148 7149procedure TSourceNotebook.UpdateHighlightMenuItems(SrcEdit: TSourceEditor); 7150var 7151 h: TLazSyntaxHighlighter; 7152 i: Integer; 7153 CurName: String; 7154 CurCaption: String; 7155 IDEMenuItem: TIDEMenuItem; 7156begin 7157 SrcEditSubMenuHighlighter.ChildrenAsSubMenu:=true; 7158 i:=0; 7159 for h:=Low(TLazSyntaxHighlighter) to High(TLazSyntaxHighlighter) do begin 7160 CurName:='Highlighter'+IntToStr(i); 7161 CurCaption:=GetSyntaxHighlighterCaption(h); 7162 if SrcEditSubMenuHighlighter.Count=i then begin 7163 // add new item 7164 IDEMenuItem:=RegisterIDEMenuCommand(SrcEditSubMenuHighlighter, 7165 CurName,CurCaption,@HighlighterClicked); 7166 end else begin 7167 IDEMenuItem:=SrcEditSubMenuHighlighter[i]; 7168 IDEMenuItem.Caption:=CurCaption; 7169 IDEMenuItem.OnClick:=@HighlighterClicked; 7170 end; 7171 if IDEMenuItem is TIDEMenuCommand then 7172 TIDEMenuCommand(IDEMenuItem).Checked:=(SrcEdit<>nil) 7173 and (SrcEdit.SyntaxHighlighterType=h); 7174 inc(i); 7175 end; 7176end; 7177 7178procedure TSourceNotebook.UpdateLineEndingMenuItems(SrcEdit: TSourceEditor); 7179var 7180 le: TLineEnding; 7181 FileEndings: String; 7182 IDEMenuItem: TIDEMenuCommand; 7183const 7184 LE_Names : array [TLineEnding] of String =( 7185 'LF (Unix, Linux)', 7186 'CR (Classic Mac)', 7187 'CRLF (Win, DOS)' 7188 ); 7189begin 7190 SrcEditSubMenuLineEnding.ChildrenAsSubMenu:=true; 7191 if (SrcEdit<>nil) and (SrcEdit.CodeBuffer<>nil) then 7192 FileEndings:=SrcEdit.CodeBuffer.DiskLineEnding 7193 else 7194 FileEndings:=LineEnding; 7195 //DebugLn(['TSourceNotebook.UpdateEncodingMenuItems ',Encoding]); 7196 for le:=low(TLineEnding) to High(TLineEnding) do begin 7197 if SrcEditSubMenuLineEnding.Count=Ord(le) then begin 7198 // add new item 7199 IDEMenuItem:=RegisterIDEMenuCommand(SrcEditSubMenuLineEnding, 7200 'LineEnding'+IntToStr(Ord(le)),LE_Names[le],@LineEndingClicked); 7201 end else begin 7202 IDEMenuItem:=SrcEditSubMenuLineEnding[Ord(le)] as TIDEMenuCommand; 7203 IDEMenuItem.Caption:=LE_Names[le]; 7204 IDEMenuItem.OnClick:=@LineEndingClicked; 7205 end; 7206 IDEMenuItem.Tag:=Ord(le); 7207 IDEMenuItem.Checked:=(FileEndings=LE_Strs[le]); 7208 end; 7209end; 7210 7211procedure TSourceNotebook.UpdatePageNames; 7212var 7213 i: Integer; 7214begin 7215 if FUpdateLock > 0 then begin 7216 include(FUpdateFlags, ufPageNames); 7217 exit; 7218 end; 7219 for i := 0 to EditorCount - 1 do 7220 Editors[i].UpdatePageName; 7221 UpdateTabsAndPageTitle; 7222end; 7223 7224procedure TSourceNotebook.UpdateProjectFiles(ACurrentEditor: TSourceEditor = nil); 7225var 7226 i: Integer; 7227begin 7228 if FUpdateLock > 0 then begin 7229 if ACurrentEditor <> nil then 7230 ACurrentEditor.UpdateProjectFile; 7231 include(FUpdateFlags, ufProjectFiles); 7232 exit; 7233 end; 7234 for i := 0 to EditorCount - 1 do 7235 Editors[i].UpdateProjectFile; 7236end; 7237 7238procedure TSourceNotebook.UpdateEncodingMenuItems(SrcEdit: TSourceEditor); 7239var 7240 List: TStringList; 7241 i: Integer; 7242 Encoding: String; 7243 CurEncoding: string; 7244 CurName: String; 7245 CurCaption: String; 7246 IDEMenuItem: TIDEMenuItem; 7247 SysEncoding: String; 7248begin 7249 SrcEditSubMenuEncoding.ChildrenAsSubMenu:=true; 7250 Encoding:=''; 7251 if SrcEdit<>nil then begin 7252 if SrcEdit.CodeBuffer<>nil then 7253 Encoding:=NormalizeEncoding(SrcEdit.CodeBuffer.DiskEncoding); 7254 end; 7255 if Encoding='' then 7256 Encoding:=GetDefaultTextEncoding; 7257 //DebugLn(['TSourceNotebook.UpdateEncodingMenuItems ',Encoding]); 7258 List:=TStringList.Create; 7259 GetSupportedEncodings(List); 7260 for i:=0 to List.Count-1 do begin 7261 CurName:='Encoding'+IntToStr(i); 7262 CurEncoding:=List[i]; 7263 CurCaption:=CurEncoding; 7264 if SysUtils.CompareText(CurEncoding,EncodingAnsi)=0 then begin 7265 SysEncoding:=GetDefaultTextEncoding; 7266 if (SysEncoding<>'') and (SysUtils.CompareText(SysEncoding,EncodingAnsi)<>0) 7267 then 7268 CurCaption:=CurCaption+' ('+GetDefaultTextEncoding+')'; 7269 end; 7270 if CurEncoding='UTF-8BOM' then begin 7271 CurCaption:=lisUtf8WithBOM; 7272 end; 7273 if SrcEditSubMenuEncoding.Count=i then begin 7274 // add new item 7275 IDEMenuItem:=RegisterIDEMenuCommand(SrcEditSubMenuEncoding, 7276 CurName,CurCaption,@EncodingClicked); 7277 end else begin 7278 IDEMenuItem:=SrcEditSubMenuEncoding[i]; 7279 IDEMenuItem.Caption:=CurCaption; 7280 IDEMenuItem.OnClick:=@EncodingClicked; 7281 end; 7282 if IDEMenuItem is TIDEMenuCommand then 7283 TIDEMenuCommand(IDEMenuItem).Checked:= 7284 Encoding=NormalizeEncoding(CurEncoding); 7285 end; 7286 List.Free; 7287end; 7288 7289procedure TSourceNotebook.RemoveUserDefinedMenuItems; 7290begin 7291 SrcEditMenuSectionFirstDynamic.Clear; 7292end; 7293 7294function TSourceNotebook.AddUserDefinedPopupMenuItem(const NewCaption: string; 7295 const NewEnabled: boolean; const NewOnClick: TNotifyEvent): TIDEMenuItem; 7296begin 7297 Result:=RegisterIDEMenuCommand(SrcEditMenuSectionFirstDynamic.GetPath, 7298 'Dynamic',NewCaption,NewOnClick); 7299 Result.Enabled:=NewEnabled; 7300end; 7301 7302procedure TSourceNotebook.RemoveContextMenuItems; 7303begin 7304 SrcEditMenuSectionFileDynamic.Clear; 7305 {$IFDEF VerboseMenuIntf} 7306 SrcEditMenuSectionFileDynamic.WriteDebugReport('TSourceNotebook.RemoveContextMenuItems ', true); 7307 {$ENDIF} 7308end; 7309 7310procedure TSourceNotebook.RemoveUpdateEditorPageCaptionHandler( 7311 AEvent: TNotifyEvent); 7312begin 7313 FOnEditorPageCaptionUpdate.Remove(TMethod(AEvent)); 7314end; 7315 7316function TSourceNotebook.AddContextPopupMenuItem(const NewCaption: string; 7317 const NewEnabled: boolean; const NewOnClick: TNotifyEvent): TIDEMenuItem; 7318begin 7319 Result:=RegisterIDEMenuCommand(SrcEditMenuSectionFileDynamic.GetPath, 7320 'FileDynamic',NewCaption,NewOnClick); 7321 Result.Enabled:=NewEnabled; 7322end; 7323 7324procedure TSourceNotebook.AddUpdateEditorPageCaptionHandler( 7325 AEvent: TNotifyEvent; const AsLast: Boolean); 7326begin 7327 FOnEditorPageCaptionUpdate.Add(TMethod(AEvent), AsLast); 7328end; 7329 7330{------------------------------------------------------------------------------- 7331 Procedure TSourceNotebook.EditorChanged 7332 Params: Sender: TObject 7333 Result: none 7334 7335 Called whenever an editor status changes. Sender is normally a TSynEdit. 7336-------------------------------------------------------------------------------} 7337procedure TSourceNotebook.EditorChanged(Sender: TObject; 7338 Changes: TSynStatusChanges); 7339var SenderDeleted: boolean; 7340Begin 7341 SenderDeleted:=(Sender as TControl).Parent=nil; 7342 if SenderDeleted then exit; 7343 UpdateStatusBar; 7344 if Assigned(Manager) then begin 7345 if not(Changes=[scFocus]) then // has to be here because of issue #29726 7346 Manager.FHints.HideIfVisible; 7347 Manager.DoEditorStatusChanged(FindSourceEditorWithEditorComponent(TSynEdit(Sender))); 7348 end; 7349End; 7350 7351procedure TSourceNotebook.DoClose(var CloseAction: TCloseAction); 7352var 7353 Layout: TSimpleWindowLayout; 7354begin 7355 DebugLnEnter(SRCED_CLOSE, ['TSourceNotebook.DoClose ', DbgSName(self)]); 7356 inherited DoClose(CloseAction); 7357 CloseAction := caHide; 7358 {$IFnDEF SingleSrcWindow} 7359 if (PageCount = 0) and (Parent=nil) then begin { $NOTE maybe keep the last one} 7360 // Make the name unique, because it may not immediately be released 7361 // => disconnect first 7362 Layout:=IDEWindowCreators.SimpleLayoutStorage.ItemByForm(Self); 7363 if Layout<>nil then 7364 Layout.Form:=nil; 7365 Name := Name + '___' + IntToStr({%H-}PtrUInt(Pointer(Self))); 7366 CloseAction := caFree; 7367 end 7368 else begin 7369 FIsClosing := True; 7370 try 7371 if Assigned(Manager) and Assigned(Manager.OnNoteBookCloseQuery) then 7372 Manager.OnNoteBookCloseQuery(Self, CloseAction); 7373 finally 7374 FIsClosing := False; 7375 end; 7376 end; 7377 {$ENDIF} 7378 DebugLnExit(SRCED_CLOSE, ['TSourceNotebook.DoClose ']); 7379end; 7380 7381procedure TSourceNotebook.DoShow; 7382begin 7383 inherited DoShow; 7384 // statusbar was not updated when visible=false, update now 7385 if snUpdateStatusBarNeeded in States then 7386 UpdateStatusBar; 7387 if Assigned(Manager) and (Parent <> nil) then 7388 Manager.DoWindowShow(Self); 7389end; 7390 7391procedure TSourceNotebook.DoHide; 7392begin 7393 inherited DoHide; 7394 if Assigned(Manager) and (Parent <> nil) then 7395 Manager.DoWindowHide(Self); 7396end; 7397 7398function TSourceNotebook.IndexOfEditorInShareWith( 7399 AnOtherEditor: TSourceEditorInterface): Integer; 7400var 7401 i: Integer; 7402begin 7403 for i := 0 to EditorCount - 1 do 7404 if Editors[i].IsSharedWith(AnOtherEditor as TSourceEditor) then 7405 exit(i); 7406 Result := -1; 7407end; 7408 7409function TSourceNotebook.GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; 7410begin 7411 Result := Manager.ActiveCompletionPlugin; 7412end; 7413 7414function TSourceNotebook.GetBaseCaption: String; 7415begin 7416 Result := FBaseCaption; 7417end; 7418 7419function TSourceNotebook.GetCompletionPlugins(Index: integer 7420 ): TSourceEditorCompletionPlugin; 7421begin 7422 Result := SourceEditorManager.CompletionPlugins[Index]; 7423end; 7424 7425function TSourceNotebook.NewSE(Pagenum: Integer; NewPagenum: Integer; 7426 ASharedEditor: TSourceEditor; ATabCaption: String): TSourceEditor; 7427begin 7428 {$IFDEF IDE_DEBUG} 7429 debugln('TSourceNotebook.NewSE A '); 7430 {$ENDIF} 7431 if Pagenum < 0 then begin 7432 // add a new page right to the current 7433 if NewPageNum >= 0 then 7434 PageNum := NewPageNum 7435 else 7436 Pagenum := PageIndex+1; 7437 Pagenum := Max(0,Min(PageNum, PageCount)); 7438 if ATabCaption = '' then 7439 ATabCaption := Manager.FindUniquePageName('', nil); 7440 NoteBookInsertPage(PageNum, ATabCaption); 7441 NotebookPage[PageNum].ReAlign; 7442 end; 7443 {$IFDEF IDE_DEBUG} 7444 debugln(['TSourceNotebook.NewSE B ', PageIndex,',',PageCount]); 7445 {$ENDIF} 7446 Result := TSourceEditor.Create(Self, NotebookPage[PageNum], ASharedEditor); 7447 Result.FPageName := NoteBookPages[Pagenum]; 7448 AcceptEditor(Result); 7449 PageIndex := Pagenum; 7450 {$IFDEF IDE_DEBUG} 7451 debugln('TSourceNotebook.NewSE end '); 7452 {$ENDIF} 7453end; 7454 7455procedure TSourceNotebook.AcceptEditor(AnEditor: TSourceEditor; SendEvent: Boolean); 7456begin 7457 FSourceEditorList.Add(AnEditor); 7458 FSrcEditsSortedForFilenames.Add(AnEditor); 7459 7460 AnEditor.EditorComponent.BeginUpdate; 7461 AnEditor.PopupMenu := SrcPopupMenu; 7462 AnEditor.OnEditorChange := @EditorChanged; 7463 AnEditor.OnMouseMove := @EditorMouseMove; 7464 AnEditor.OnMouseDown := @EditorMouseDown; 7465 AnEditor.OnMouseWheel := @EditorMouseWheel; 7466 AnEditor.OnKeyDown := @EditorKeyDown; 7467 AnEditor.OnKeyUp := @EditorKeyUp; 7468 AnEditor.EditorComponent.Beautifier.OnGetDesiredIndent := @EditorGetIndent; 7469 AnEditor.EditorComponent.EndUpdate; 7470 7471 if SendEvent then 7472 Manager.SendEditorCreated(AnEditor); 7473end; 7474 7475procedure TSourceNotebook.ReleaseEditor(AnEditor: TSourceEditor; SendEvent: Boolean); 7476begin 7477 FSourceEditorList.Remove(AnEditor); 7478 FSrcEditsSortedForFilenames.RemovePointer(AnEditor); 7479 if SendEvent then 7480 Manager.SendEditorDestroyed(AnEditor); 7481end; 7482 7483function TSourceNotebook.FindSourceEditorWithPageIndex(APageIndex: integer): TSourceEditor; 7484var 7485 I: integer; 7486 TempEditor: TControl; 7487 7488 function FindSynEdit(AControl: TWinControl): TControl; 7489 var 7490 I: Integer; 7491 begin 7492 Result := nil; 7493 7494 with AControl do 7495 for I := 0 to ControlCount - 1 do 7496 begin 7497 if Controls[I] is TIDESynEditor then 7498 Exit(Controls[I]) 7499 else 7500 if Controls[I] is TWinControl then 7501 begin 7502 Result := FindSynEdit(TWinControl(Controls[I])); 7503 if Result <> nil then 7504 Exit; 7505 end; 7506 end; 7507 end; 7508 7509begin 7510 Result := nil; 7511 if (FSourceEditorList=nil) 7512 or (APageIndex < 0) or (APageIndex >= PageCount) then exit; 7513 7514 TempEditor := FindSynEdit(NotebookPage[APageIndex]); 7515 { 7516 TempEditor:=nil; 7517 with NotebookPage[APageIndex] do 7518 for I := 0 to ControlCount-1 do 7519 if Controls[I] is TSynEdit then 7520 Begin 7521 TempEditor := Controls[I]; 7522 Break; 7523 end; 7524 } 7525 if TempEditor=nil then exit; 7526 I := FSourceEditorList.Count-1; 7527 while (I>=0) and (TSourceEditor(FSourceEditorList[I]).EditorComponent <> TempEditor) do 7528 dec(i); 7529 if i<0 then exit; 7530 Result := TSourceEditor(FSourceEditorList[i]); 7531end; 7532 7533function TSourceNotebook.GetActiveSE: TSourceEditor; 7534Begin 7535 Result := nil; 7536 if (FSourceEditorList=nil) or (FSourceEditorList.Count=0) or (PageIndex<0) then 7537 exit; 7538 Result:=FindSourceEditorWithPageIndex(PageIndex); 7539end; 7540 7541function TSourceNotebook.GetActiveEditor: TSourceEditorInterface; 7542begin 7543 Result:=GetActiveSE; 7544end; 7545 7546procedure TSourceNotebook.SetActiveEditor(const AValue: TSourceEditorInterface); 7547var 7548 i: integer; 7549begin 7550 i := FindPageWithEditor(AValue as TSourceEditor); 7551 inc(FFocusLock); 7552 if i>= 0 then 7553 PageIndex := i; 7554 dec(FFocusLock); 7555 SourceEditorManager.ActiveSourceWindow := Self; 7556 if EditorOpts.ShowFileNameInCaption then 7557 begin 7558 if ActiveEditor<>nil then 7559 Caption := BaseCaption+' - '+ActiveEditor.FileName 7560 else 7561 Caption := BaseCaption; 7562 end; 7563end; 7564 7565procedure TSourceNotebook.SetBaseCaption(AValue: String); 7566begin 7567 FBaseCaption := AValue; 7568end; 7569 7570procedure TSourceNotebook.CheckCurrentCodeBufferChanged; 7571var 7572 SrcEdit: TSourceEditor; 7573begin 7574 // Todo: Move to manager, include window changes 7575 SrcEdit:=GetActiveSE; 7576 if SrcEdit <> nil then 7577 begin 7578 if FLastCodeBuffer=SrcEdit.CodeBuffer then exit; 7579 FLastCodeBuffer:=SrcEdit.CodeBuffer; 7580 end else if FLastCodeBuffer=nil then 7581 exit; 7582 if assigned(Manager) and Assigned(Manager.OnCurrentCodeBufferChanged) then 7583 Manager.OnCurrentCodeBufferChanged(Self); 7584end; 7585 7586function TSourceNotebook.GetCapabilities: TCTabControlCapabilities; 7587begin 7588 Result := FNotebook.GetCapabilities 7589end; 7590 7591procedure TSourceNotebook.IncUpdateLockInternal; 7592begin 7593 if FUpdateLock = 0 then begin 7594 FUpdateFlags := []; 7595 DebugLn(SRCED_LOCK, ['TSourceNotebook.IncUpdateLockInternal']); 7596 FPageIndex := PageIndex; 7597 end; 7598 inc(FUpdateLock); 7599end; 7600 7601procedure TSourceNotebook.DecUpdateLockInternal; 7602begin 7603 dec(FUpdateLock); 7604 if FUpdateLock = 0 then begin 7605 DebugLnEnter(SRCED_LOCK, ['>> TSourceNotebook.DecUpdateLockInternal UpdateFlags=', dbgs(FUpdateFlags), ' PageIndex=', FPageIndex]); 7606 if (ufPageIndexChanged in FUpdateFlags) or (PageIndex<>FPageIndex) then ApplyPageIndex; 7607 if (ufPageNames in FUpdateFlags) then UpdatePageNames; 7608 if (ufTabsAndPage in FUpdateFlags) then UpdateTabsAndPageTitle; 7609 if (ufStatusBar in FUpdateFlags) then UpdateStatusBar; 7610 if (ufProjectFiles in FUpdateFlags) then UpdateProjectFiles; 7611 if (ufFocusEditor in FUpdateFlags) then FocusEditor; 7612 if (ufActiveEditorChanged in FUpdateFlags) then DoActiveEditorChanged; 7613 FUpdateFlags := []; 7614 DebugLnExit(SRCED_LOCK, ['<< TSourceNotebook.DecUpdateLockInternal']); 7615 end; 7616end; 7617 7618procedure TSourceNotebook.IncUpdateLock; 7619begin 7620 Manager.IncUpdateLockInternal; // ensure mgr holds ActiveEditorChanged notificationback // TODO: make sure they are hlod in SourceNotebook instead, including SetAciveEditor.... 7621 IncUpdateLockInternal; 7622end; 7623 7624procedure TSourceNotebook.DecUpdateLock; 7625begin 7626 try 7627 DecUpdateLockInternal; 7628 finally 7629 Manager.DecUpdateLockInternal; 7630 end; 7631end; 7632 7633procedure TSourceNotebook.NoteBookInsertPage(Index: Integer; const S: string); 7634begin 7635 if FNotebook.Visible then 7636 NotebookPages.Insert(Index, S) 7637 else begin 7638 if Index<>0 then 7639 RaiseGDBException(''); 7640 IDEWindowCreators.ShowForm(Self,false); 7641 FNotebook.Visible := True; 7642 NotebookPages[Index] := S; 7643 FPageIndex := -1; 7644 end; 7645 UpdateTabsAndPageTitle; 7646end; 7647 7648procedure TSourceNotebook.NoteBookDeletePage(APageIndex: Integer); 7649begin 7650 DebugLnEnter(SRCED_PAGES, ['TSourceNotebook.NoteBookDeletePage ', APageIndex]); 7651 HistoryRemove(FNotebook.Pages[APageIndex]); 7652 //debugln(['TSourceNotebook.NoteBookDeletePage APageIndex=',APageIndex,' PageIndex=',PageIndex,' PageCount=',PageCount]); 7653 if PageCount > 1 then begin 7654 // make sure to select another page in the NoteBook, otherwise the 7655 // widgetset will choose one and will send a message 7656 // if this is the current page, switch to right APageIndex (if possible) 7657 if PageIndex = APageIndex then begin 7658 if EditorOpts.UseTabHistory then 7659 FPageIndex := HistoryGetTopPageIndex 7660 else 7661 FPageIndex := -1; 7662 // default if not in history or not using history 7663 if FPageIndex = -1 then 7664 if APageIndex < PageCount - 1 then 7665 FPageIndex := APageIndex + 1 7666 else 7667 FPageIndex := APageIndex - 1; 7668 if FUpdateLock = 0 then 7669 ApplyPageIndex 7670 else 7671 Include(FUpdateFlags,ufPageIndexChanged); 7672 end; 7673 NotebookPages.Delete(APageIndex); 7674 end else begin 7675 FPageIndex := -1; 7676 FNotebook.Visible := False; 7677 end; 7678 //debugln(['TSourceNotebook.NoteBookDeletePage END PageIndex=',PageIndex,' FPageIndex=',FPageIndex]); 7679 UpdateTabsAndPageTitle; 7680 DebugLnExit(SRCED_PAGES, ['TSourceNotebook.NoteBookDeletePage ']); 7681end; 7682 7683procedure TSourceNotebook.UpdateTabsAndPageTitle; 7684begin 7685 if FUpdateLock > 0 then begin 7686 include(FUpdateFlags, ufTabsAndPage); 7687 exit; 7688 end; 7689 if (PageCount = 1) and (EditorOpts.HideSingleTabInWindow) then begin 7690 if not EditorOpts.ShowFileNameInCaption then 7691 Caption := BaseCaption + ': ' + NotebookPages[0]; 7692 FNotebook.ShowTabs := False; 7693 end else begin 7694 if not EditorOpts.ShowFileNameInCaption then 7695 Caption := BaseCaption; 7696 FNotebook.ShowTabs := (Manager=nil) or Manager.ShowTabs; 7697 end; 7698end; 7699 7700procedure TSourceNotebook.UpdateTabsAndPageTimeReached(Sender: TObject); 7701begin 7702 FUpdateTabAndPageTimer.Enabled := False; 7703 UpdateTabsAndPageTitle; 7704end; 7705 7706function TSourceNotebook.NoteBookIndexOfPage(APage: TTabSheet): Integer; 7707begin 7708 Result := FNoteBook.IndexOf(APage); 7709end; 7710 7711procedure TSourceNotebook.DragOver(Source: TObject; X, Y: Integer; State: TDragState; 7712 var Accept: Boolean); 7713begin 7714 FUpdateTabAndPageTimer.Enabled := False; 7715 inherited DragOver(Source, X, Y, State, Accept); 7716 if State = dsDragLeave then 7717 FUpdateTabAndPageTimer.Enabled := True 7718 else if Source is TExtendedNotebook then 7719 FNotebook.ShowTabs := (Manager=nil) or Manager.ShowTabs; 7720end; 7721 7722procedure TSourceNotebook.DragCanceled; 7723begin 7724 inherited DragCanceled; 7725 FUpdateTabAndPageTimer.Enabled := True; 7726end; 7727 7728procedure TSourceNotebook.DoActiveEditorChanged; 7729begin 7730 if FUpdateLock > 0 then begin 7731 DebugLn(SRCED_PAGES, ['TSourceNotebook.DoActiveEditorChanged LOCKED']); 7732 include(FUpdateFlags, ufActiveEditorChanged); 7733 exit; 7734 end; 7735 exclude(FUpdateFlags, ufActiveEditorChanged); 7736 DebugLnEnter(SRCED_PAGES, ['>> TSourceNotebook.DoActiveEditorChanged ']); 7737 Manager.DoActiveEditorChanged; 7738 DebugLnExit(SRCED_PAGES, ['<< TSourceNotebook.DoActiveEditorChanged ']); 7739end; 7740 7741procedure TSourceNotebook.BeginIncrementalFind; 7742var 7743 TempEditor: TSourceEditor; 7744begin 7745 if (snIncrementalFind in States)AND not(FIncrementalSearchEditor = nil) 7746 then begin 7747 if (IncrementalSearchStr= '') then begin 7748 FIncrementalSearchStr := FIncrementalFoundStr; 7749 IncrementalSearch(False, FIncrementalSearchBackwards); 7750 end 7751 else IncrementalSearch(True, FIncrementalSearchBackwards); 7752 exit; 7753 end; 7754 7755 TempEditor:=GetActiveSE; 7756 if TempEditor = nil then exit; 7757 Include(States, snIncrementalFind); 7758 fIncrementalSearchStartPos:=TempEditor.EditorComponent.LogicalCaretXY; 7759 FIncrementalSearchPos:=fIncrementalSearchStartPos; 7760 FIncrementalSearchEditor := TempEditor; 7761 if assigned(FIncrementalSearchEditor.EditorComponent) then 7762 with FIncrementalSearchEditor.EditorComponent do begin 7763 UseIncrementalColor:= true; 7764 if assigned(MarkupByClass[TSynEditMarkupHighlightAllCaret]) then 7765 MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable; 7766 end; 7767 7768 IncrementalSearchStr:=''; 7769 7770 UpdateStatusBar; 7771end; 7772 7773procedure TSourceNotebook.EndIncrementalFind; 7774begin 7775 if not (snIncrementalFind in States) then exit; 7776 7777 Exclude(States,snIncrementalFind); 7778 7779 if FIncrementalSearchEditor <> nil 7780 then begin 7781 if assigned(FIncrementalSearchEditor.EditorComponent) then 7782 with FIncrementalSearchEditor.EditorComponent do begin 7783 UseIncrementalColor:= False; 7784 if assigned(MarkupByClass[TSynEditMarkupHighlightAllCaret]) then 7785 MarkupByClass[TSynEditMarkupHighlightAllCaret].TempEnable; 7786 end; 7787 FIncrementalSearchEditor.EditorComponent.SetHighlightSearch('', []); 7788 FIncrementalSearchEditor := nil; 7789 end; 7790 7791 LazFindReplaceDialog.FindText:=fIncrementalSearchStr; 7792 LazFindReplaceDialog.Options:=[]; 7793 UpdateStatusBar; 7794end; 7795 7796procedure TSourceNotebook.NextEditor; 7797Begin 7798 if PageIndex < PageCount-1 then 7799 PageIndex := PageIndex+1 7800 else 7801 PageIndex := 0; 7802End; 7803 7804procedure TSourceNotebook.PrevEditor; 7805Begin 7806 if PageIndex > 0 then 7807 PageIndex := PageIndex-1 7808 else 7809 PageIndex := PageCount-1; 7810End; 7811 7812procedure TSourceNotebook.MoveEditor(OldPageIndex, NewPageIndex: integer); 7813begin 7814 if (PageCount<=1) 7815 or (OldPageIndex=NewPageIndex) 7816 or (OldPageIndex<0) or (OldPageIndex>=PageCount) 7817 or (NewPageIndex<0) or (NewPageIndex>=PageCount) 7818 then 7819 exit; 7820 NoteBookPages.Move(OldPageIndex,NewPageIndex); 7821 UpdatePageNames; 7822 UpdateProjectFiles; 7823end; 7824 7825procedure TSourceNotebook.MoveEditorLeft(CurrentPageIndex: integer); 7826begin 7827 if (PageCount<=1) then exit; 7828 if CurrentPageIndex>0 then 7829 MoveEditor(CurrentPageIndex, CurrentPageIndex-1) 7830 else 7831 MoveEditor(CurrentPageIndex, PageCount-1); 7832end; 7833 7834procedure TSourceNotebook.MoveEditorRight(CurrentPageIndex: integer); 7835begin 7836 if (PageCount<=1) then exit; 7837 if CurrentPageIndex < PageCount-1 then 7838 MoveEditor(CurrentPageIndex, CurrentPageIndex+1) 7839 else 7840 MoveEditor(CurrentPageIndex, 0); 7841end; 7842 7843procedure TSourceNotebook.MoveEditorFirst(CurrentPageIndex: integer); 7844begin 7845 if (PageCount<=1) then exit; 7846 MoveEditor(CurrentPageIndex, 0) 7847end; 7848 7849procedure TSourceNotebook.MoveEditorLast(CurrentPageIndex: integer); 7850begin 7851 if (PageCount<=1) then exit; 7852 MoveEditor(CurrentPageIndex, PageCount-1); 7853end; 7854 7855procedure TSourceNotebook.MoveActivePageLeft; 7856begin 7857 MoveEditorLeft(PageIndex); 7858end; 7859 7860procedure TSourceNotebook.MoveActivePageRight; 7861begin 7862 MoveEditorRight(PageIndex); 7863end; 7864 7865procedure TSourceNotebook.MoveActivePageFirst; 7866begin 7867 MoveEditorFirst(PageIndex); 7868end; 7869 7870procedure TSourceNotebook.MoveActivePageLast; 7871begin 7872 MoveEditorLast(PageIndex); 7873end; 7874 7875procedure TSourceNotebook.GotoNextWindow(Backward: Boolean); 7876begin 7877 if Backward then begin 7878 if Manager.IndexOfSourceWindow(Self) > 0 then 7879 Manager.ActiveSourceWindow := Manager.SourceWindows[Manager.IndexOfSourceWindow(Self)-1] 7880 else 7881 Manager.ActiveSourceWindow := Manager.SourceWindows[Manager.SourceWindowCount-1]; 7882 end else begin 7883 if Manager.IndexOfSourceWindow(Self) < Manager.SourceWindowCount - 1 then 7884 Manager.ActiveSourceWindow := Manager.SourceWindows[Manager.IndexOfSourceWindow(Self)+1] 7885 else 7886 Manager.ActiveSourceWindow := Manager.SourceWindows[0]; 7887 end; 7888 Manager.ShowActiveWindowOnTop(True); 7889end; 7890 7891procedure TSourceNotebook.GotoNextSharedEditor(Backward: Boolean = False); 7892var 7893 SrcEd: TSourceEditor; 7894 i, j: Integer; 7895begin 7896 i := Manager.IndexOfSourceWindow(Self); 7897 SrcEd := GetActiveSE; 7898 repeat 7899 if Backward then dec(i) 7900 else inc(i); 7901 if i < 0 then 7902 i := Manager.SourceWindowCount - 1; 7903 if i = Manager.SourceWindowCount then 7904 i := 0; 7905 j := Manager.SourceWindows[i].IndexOfEditorInShareWith(SrcEd); 7906 if j >= 0 then begin 7907 Manager.ActiveEditor := Manager.SourceWindows[i].Editors[j]; 7908 Manager.ShowActiveWindowOnTop(True); 7909 exit; 7910 end; 7911 until Manager.SourceWindows[i] = Self; 7912end; 7913 7914procedure TSourceNotebook.MoveEditorNextWindow(Backward: Boolean; Copy: Boolean); 7915var 7916 SrcEd: TSourceEditor; 7917 i: Integer; 7918begin 7919 i := Manager.IndexOfSourceWindow(Self); 7920 SrcEd := GetActiveSE; 7921 repeat 7922 if Backward then dec(i) 7923 else inc(i); 7924 if i < 0 then 7925 i := Manager.SourceWindowCount - 1; 7926 if i = Manager.SourceWindowCount then 7927 i := 0; 7928 if Manager.SourceWindows[i].IndexOfEditorInShareWith(SrcEd) < 0 then 7929 break; 7930 until Manager.SourceWindows[i] = Self; 7931 if Manager.SourceWindows[i] = Self then exit; 7932 7933 if Copy then 7934 CopyEditor(FindPageWithEditor(GetActiveSE), i, -1) 7935 else 7936 MoveEditor(FindPageWithEditor(GetActiveSE), i, -1); 7937 7938 Manager.ActiveSourceWindowIndex := i; 7939 Manager.ShowActiveWindowOnTop(True); 7940end; 7941 7942procedure TSourceNotebook.MoveEditor(OldPageIndex, NewWindowIndex, 7943 NewPageIndex: integer); 7944var 7945 DestWin: TSourceNotebook; 7946 Edit: TSourceEditor; 7947begin 7948 if (NewWindowIndex < 0) or (NewWindowIndex >= Manager.SourceWindowCount) then 7949 exit; 7950 DestWin := Manager.SourceWindows[NewWindowIndex]; 7951 if DestWin = self then begin 7952 MoveEditor(OldPageIndex, NewPageIndex); 7953 exit 7954 end; 7955 7956 if NewPageIndex < 0 then 7957 NewPageIndex := DestWin.PageCount; 7958 if (OldPageIndex<0) or (OldPageIndex>=PageCount) or 7959 (NewPageIndex<0) or (NewPageIndex>DestWin.PageCount) 7960 then 7961 exit; 7962 7963 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceNotebook.MoveEditor'){$ENDIF}; 7964 IncUpdateLock; 7965 try 7966 DestWin.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceNotebook.MoveEdito DestWinr'){$ENDIF}; 7967 DestWin.IncUpdateLock; 7968 try 7969 Edit := FindSourceEditorWithPageIndex(OldPageIndex); 7970 DestWin.NoteBookInsertPage(NewPageIndex, Edit.PageName); 7971 DestWin.PageIndex := NewPageIndex; 7972 7973 ReleaseEditor(Edit); 7974 Edit.UpdateNoteBook(DestWin, DestWin.NoteBookPage[NewPageIndex]); 7975 DestWin.AcceptEditor(Edit); 7976 DestWin.NotebookPage[NewPageIndex].ReAlign; 7977 7978 NoteBookDeletePage(OldPageIndex); 7979 UpdatePageNames; 7980 UpdateProjectFiles; 7981 DestWin.UpdatePageNames; 7982 DestWin.UpdateProjectFiles(Edit); 7983 DestWin.UpdateActiveEditColors(Edit.EditorComponent); 7984 DestWin.UpdateStatusBar; 7985 DestWin.NotebookPageChanged(nil); // make sure page SynEdit willl be visible 7986 finally 7987 DestWin.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceNotebook.MoveEdito DestWinr'){$ENDIF}; 7988 DestWin.DecUpdateLock; 7989 end; 7990 finally 7991 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceNotebook.MoveEditor'){$ENDIF}; 7992 DecUpdateLock 7993 end; 7994 7995 if (PageCount = 0) and (Parent=nil) and not FIsClosing then 7996 Close; 7997 7998 DoActiveEditorChanged; 7999 Manager.ActiveEditor := Edit; 8000end; 8001 8002procedure TSourceNotebook.CopyEditor(OldPageIndex, NewWindowIndex, 8003 NewPageIndex: integer; Focus: Boolean = False); 8004var 8005 DestWin: TSourceNotebook; 8006 SrcEdit, NewEdit: TSourceEditor; 8007 i: Integer; 8008begin 8009 if (NewWindowIndex < 0) or (NewWindowIndex >= Manager.SourceWindowCount) then 8010 exit; 8011 DestWin := Manager.SourceWindows[NewWindowIndex]; 8012 if DestWin = self then exit; 8013 8014 if (OldPageIndex<0) or (OldPageIndex>=PageCount) or (NewPageIndex>DestWin.PageCount) 8015 then 8016 exit; 8017 8018 SrcEdit := FindSourceEditorWithPageIndex(OldPageIndex); 8019 NewEdit := DestWin.NewSE(-1, NewPageIndex, SrcEdit, SrcEdit.PageName); 8020 Include(NewEdit.FProjectFileUpdatesNeeded, sepuNewShared); 8021 8022 NewEdit.PageName := SrcEdit.PageName; 8023 NewEdit.SyntaxHighlighterType := SrcEdit.SyntaxHighlighterType; 8024 NewEdit.EditorComponent.TopLine := SrcEdit.EditorComponent.TopLine; 8025 NewEdit.EditorComponent.CaretXY := SrcEdit.EditorComponent.CaretXY; 8026 8027 UpdatePageNames; 8028 UpdateProjectFiles; 8029 DestWin.UpdateProjectFiles(NewEdit); 8030 // Creating a shared edit invalidates the tree in SynMarkup. Force setting it for all editors 8031 for i := 0 to SrcEdit.SharedEditorCount - 1 do 8032 SrcEdit.SharedEditors[i].UpdateIfDefNodeStates(True); 8033 // Update IsVisibleTab; needs UnitEditorInfo created in DestWin.UpdateProjectFiles 8034 if Focus then begin 8035 Manager.ActiveEditor := NewEdit; 8036 Manager.ShowActiveWindowOnTop(True); 8037 end; 8038 DestWin.NotebookPageChanged(nil); // make sure page SynEdit willl be visible 8039 DoActiveEditorChanged; 8040end; 8041 8042procedure TSourceNotebook.StartShowCodeContext(JumpToError: boolean); 8043var 8044 Abort: boolean; 8045begin 8046 if assigned(Manager) and (Manager.OnShowCodeContext<>nil) then begin 8047 Manager.OnShowCodeContext(JumpToError,Abort); 8048 if Abort then ; 8049 end; 8050end; 8051 8052procedure TSourceNotebook.OnPopupMenuOpenFile(Sender: TObject); 8053var 8054 ResStr: String; 8055 p: SizeInt; 8056 aFilename: TTranslateString; 8057begin 8058 // open the filename of the caption 8059 // the caption was created by the resourcestring lisOpenLFM, with the 8060 // placeholder %s 8061 // => cut the surrounding caption to the get the filename 8062 aFilename:=(Sender as TIDEMenuItem).Caption; 8063 ResStr:=lisOpenLfm; 8064 p:=System.Pos('%s',ResStr); 8065 aFilename:=copy(aFilename,p,length(aFilename)-(length(ResStr)-2)); 8066 if not FilenameIsAbsolute(aFilename) then 8067 aFilename:=TrimFilename(ExtractFilePath(GetActiveSE.Filename)+aFilename); 8068 if FilenameExtIs(aFilename,'lpi',true) then 8069 MainIDEInterface.DoOpenProjectFile(aFilename,[ofOnlyIfExists,ofAddToRecent,ofUseCache]) 8070 else if FilenameExtIs(aFilename,'lpk',true) then 8071 PackageEditingInterface.DoOpenPackageFile(aFilename,[pofAddToRecent],false) 8072 else 8073 MainIDEInterface.DoOpenEditorFile(aFilename, 8074 PageIndex+1, Manager.IndexOfSourceWindow(self), 8075 [ofOnlyIfExists,ofAddToRecent,ofRegularFile,ofUseCache,ofDoNotLoadResource]); 8076end; 8077 8078procedure TSourceNotebook.OnPopupOpenPackageFile(Sender: TObject); 8079begin 8080 if (Sender as TIDEMenuItem).UserTag <> 0 then begin 8081 PackageEditingInterface.DoOpenPackageFile 8082 (TIDEPackage((Sender as TIDEMenuItem).UserTag).Filename,[pofAddToRecent],false) 8083 end; 8084end; 8085 8086procedure TSourceNotebook.OnPopupOpenProjectInsp(Sender: TObject); 8087begin 8088 MainIDEInterface.DoShowProjectInspector; 8089end; 8090 8091procedure TSourceNotebook.OpenAtCursorClicked(Sender: TObject); 8092begin 8093 if Assigned(Manager) and Assigned(Manager.OnOpenFileAtCursorClicked) then 8094 Manager.OnOpenFileAtCursorClicked(Sender); 8095end; 8096 8097procedure TSourceNotebook.CutClicked(Sender: TObject); 8098var ActSE: TSourceEditor; 8099begin 8100 ActSE := GetActiveSE; 8101 if ActSE <> nil then 8102 ActSE.DoEditorExecuteCommand(ecCut); 8103end; 8104 8105procedure TSourceNotebook.CopyClicked(Sender: TObject); 8106var ActSE: TSourceEditor; 8107begin 8108 ActSE := GetActiveSE; 8109 if ActSE <> nil then 8110 ActSE.DoEditorExecuteCommand(ecCopy); 8111end; 8112 8113procedure TSourceNotebook.PasteClicked(Sender: TObject); 8114var ActSE: TSourceEditor; 8115begin 8116 ActSE := GetActiveSE; 8117 if ActSE <> nil then 8118 ActSE.DoEditorExecuteCommand(ecPaste); 8119end; 8120 8121procedure TSourceNotebook.StatusBarClick(Sender: TObject); 8122var 8123 P: TPoint; 8124begin 8125 P := StatusBar.ScreenToClient(Mouse.CursorPos); 8126 if StatusBar.GetPanelIndexAt(P.X, P.Y) = 1 then 8127 EditorMacroForRecording.Stop; 8128end; 8129 8130procedure TSourceNotebook.StatusBarDblClick(Sender: TObject); 8131var 8132 P: TPoint; 8133begin 8134 P := StatusBar.ScreenToClient(Mouse.CursorPos); 8135 case StatusBar.GetPanelIndexAt(P.X, P.Y) of // Based on panel: 8136 0: GoToLineMenuItemClick(Nil); // Show "Goto Line" dialog. 8137 4: OpenFolderMenuItemClick(Nil); // Show system file manager on file's folder. 8138 end; 8139end; 8140 8141procedure TSourceNotebook.StatusBarContextPopup(Sender: TObject; MousePos: TPoint; 8142 var Handled: Boolean); 8143var 8144 Pnl: Integer; 8145begin 8146 Pnl := StatusBar.GetPanelIndexAt(MousePos.X, MousePos.Y); 8147 GoToLineMenuItem.Visible := Pnl=0; 8148 OpenFolderMenuItem.Visible := Pnl=4; 8149 if Pnl in [0, 4] then 8150 StatusPopUpMenu.PopUp; 8151end; 8152 8153procedure TSourceNotebook.StatusBarDrawPanel(AStatusBar: TStatusBar; APanel: TStatusPanel; 8154 const ARect: TRect); 8155begin 8156 if APanel = StatusBar.Panels[1] then begin 8157 IDEImages.Images_16.ResolutionForControl[16, AStatusBar] 8158 .Draw(StatusBar.Canvas, ARect.Left, ARect.Top, FStopBtnIdx); 8159 end; 8160end; 8161 8162procedure TSourceNotebook.ToggleBreakpointClicked(Sender: TObject); 8163var 8164 ASrcEdit: TSourceEditor; 8165 Line: LongInt; 8166 BreakPtMark: TSourceMark; 8167begin 8168 ASrcEdit:=GetActiveSE; 8169 if ASrcEdit=nil then exit; 8170 // create or delete breakpoint 8171 // find breakpoint mark at line 8172 Line:=ASrcEdit.EditorComponent.CaretY; 8173 BreakPtMark := SourceEditorMarks.FindBreakPointMark(ASrcEdit, Line); 8174 if BreakPtMark = nil then 8175 DebugBoss.DoCreateBreakPoint(ASrcEdit.Filename,Line,true) 8176 else 8177 DebugBoss.DoDeleteBreakPointAtMark(BreakPtMark); 8178end; 8179 8180procedure TSourceNotebook.ToggleBreakpointEnabledClicked(Sender: TObject); 8181var 8182 ASrcEdit: TSourceEditor; 8183 Line: LongInt; 8184 BreakPtMark: TSourceMark; 8185 BreakPoint: TIDEBreakPoint; 8186begin 8187 ASrcEdit:=GetActiveSE; 8188 if ASrcEdit=nil then exit; 8189 // create or delete breakpoint 8190 // find breakpoint mark at line 8191 Line:=ASrcEdit.EditorComponent.CaretY; 8192 BreakPtMark := SourceEditorMarks.FindBreakPointMark(ASrcEdit, Line); 8193 if BreakPtMark = nil then begin 8194 DebugBoss.DoCreateBreakPoint(ASrcEdit.Filename,Line,true, BreakPoint, True); 8195 if BreakPoint <> nil then begin 8196 BreakPoint.Enabled := False; 8197 BreakPoint.EndUpdate; 8198 end; 8199 end 8200 else 8201 begin 8202 BreakPoint := DebugBoss.BreakPoints.Find(ASrcEdit.FileName, Line); 8203 BreakPoint.Enabled := not BreakPoint.Enabled; 8204 end; 8205end; 8206 8207procedure TSourceNotebook.CompleteCodeMenuItemClick(Sender: TObject); 8208begin 8209 MainIDEInterface.DoCommand(ecCompleteCode); 8210end; 8211 8212procedure TSourceNotebook.DeleteBreakpointClicked(Sender: TObject); 8213var 8214 ASrcEdit: TSourceEditor; 8215begin 8216 ASrcEdit:=GetActiveSE; 8217 if ASrcEdit=nil then exit; 8218 DebugBoss.DoDeleteBreakPoint(ASrcEdit.Filename, 8219 ASrcEdit.EditorComponent.CaretY); 8220end; 8221 8222procedure TSourceNotebook.ExtractProcMenuItemClick(Sender: TObject); 8223begin 8224 MainIDEInterface.DoCommand(ecExtractProc); 8225end; 8226 8227procedure TSourceNotebook.InvertAssignmentMenuItemClick(Sender: TObject); 8228var 8229 ASrcEdit: TSourceEditor; 8230begin 8231 ASrcEdit:=GetActiveSE; 8232 if ASrcEdit=nil then exit; 8233 ASrcEdit.InvertAssignment; 8234end; 8235 8236procedure TSourceNotebook.RenameIdentifierMenuItemClick(Sender: TObject); 8237begin 8238 MainIDEInterface.DoCommand(ecRenameIdentifier); 8239end; 8240 8241procedure TSourceNotebook.ShowAbstractMethodsMenuItemClick(Sender: TObject); 8242begin 8243 MainIDEInterface.DoCommand(ecShowAbstractMethods); 8244end; 8245 8246procedure TSourceNotebook.ShowEmptyMethodsMenuItemClick(Sender: TObject); 8247begin 8248 MainIDEInterface.DoCommand(ecRemoveEmptyMethods); 8249end; 8250 8251procedure TSourceNotebook.ShowUnusedUnitsMenuItemClick(Sender: TObject); 8252begin 8253 MainIDEInterface.DoCommand(ecRemoveUnusedUnits); 8254end; 8255 8256procedure TSourceNotebook.SourceNotebookDropFiles(Sender: TObject; 8257 const FileNames: array of String); 8258begin 8259 FManager.ActiveSourceWindow := Self; 8260 LazarusIDE.DoDropFiles(Sender,Filenames,WindowID); 8261end; 8262 8263procedure TSourceNotebook.FindOverloadsMenuItemClick(Sender: TObject); 8264begin 8265 MainIDEInterface.DoCommand(ecFindOverloads); 8266end; 8267 8268procedure TSourceNotebook.MakeResourceStringMenuItemClick(Sender: TObject); 8269begin 8270 MainIDEInterface.DoCommand(ecMakeResourceString); 8271end; 8272 8273function TSourceNotebook.NewFile(const NewShortName: String; 8274 ASource: TCodeBuffer; FocusIt: boolean; AShareEditor: TSourceEditor = nil): TSourceEditor; 8275var 8276 s: String; 8277Begin 8278 //create a new page 8279 debugln(SRCED_OPEN, '[TSourceNotebook.NewFile] A '); 8280 // Debugger cause ProcessMessages, which could lead to entering methods in unexpected order 8281 DebugBoss.LockCommandProcessing; 8282 try 8283 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceNotebook.NewFile'){$ENDIF}; 8284 try 8285 IDEWindowCreators.ShowForm(Self,false); 8286 s := Manager.FindUniquePageName(NewShortName, AShareEditor); 8287 Result := NewSE(-1, -1, AShareEditor, s); 8288 debugln(SRCED_OPEN, '[TSourceNotebook.NewFile] B '); 8289 Result.CodeBuffer:=ASource; 8290 debugln(SRCED_OPEN, '[TSourceNotebook.NewFile] D '); 8291 //debugln(['TSourceNotebook.NewFile ',NewShortName,' ',ASource.Filename]); 8292 Result.PageName:= s; 8293 UpdatePageNames; 8294 UpdateProjectFiles(Result); 8295 UpdateStatusBar; 8296 Manager.SendEditorCreated(Result); 8297 finally 8298 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceNotebook.NewFile'){$ENDIF}; 8299 end; 8300 if FocusIt then FocusEditor; 8301 finally 8302 DebugBoss.UnLockCommandProcessing; 8303 end; 8304 debugln(SRCED_OPEN, '[TSourceNotebook.NewFile] end'); 8305 CheckFont; 8306end; 8307 8308procedure TSourceNotebook.CloseFile(APageIndex:integer); 8309var 8310 TempEditor: TSourceEditor; 8311 WasSelected: Boolean; 8312begin 8313 (* Do not use DisableAutoSizing in here, if a new Editor is focused it needs immediate autosize (during handle creation) *) 8314 // Inc/DecUpdateLockInternal does currently noth work, since a tab will be removed 8315 DebugLnEnter(SRCED_CLOSE, ['>> TSourceNotebook.CloseFile A APageIndex=',APageIndex, ' Cur-Page=', PageIndex]); 8316 DebugBoss.LockCommandProcessing; 8317 try 8318 TempEditor:=FindSourceEditorWithPageIndex(APageIndex); 8319 if TempEditor=nil then exit; 8320 WasSelected:=PageIndex=APageIndex; 8321 debugln(SRCED_CLOSE, ['TSourceNotebook.CloseFile ', DbgSName(TempEditor), ' ', TempEditor.FileName]); 8322 EndIncrementalFind; 8323 TempEditor.Close; 8324 NoteBookDeletePage(APageIndex); // delete page before sending notification senEditorDestroyed 8325 TempEditor.Free; // sends semEditorDestroy 8326 TempEditor:=nil; 8327 // delete the page 8328 UpdateProjectFiles; 8329 UpdatePageNames; 8330 if WasSelected then 8331 UpdateStatusBar; 8332 // set focus to new editor 8333 if (PageCount = 0) and (Parent=nil) then begin 8334 {$IFnDEF SingleSrcWindow} 8335 Manager.RemoveWindow(self); 8336 FManager := nil; 8337 {$ENDIF} 8338 if not FIsClosing then 8339 Close; 8340 end; 8341 // Move focus from Notebook-tabs to editor 8342 TempEditor:=FindSourceEditorWithPageIndex(PageIndex); 8343 if IsVisible and (TempEditor <> nil) and (FUpdateLock = 0) then 8344 // this line raises exception when editor is in other tab (for example - focused is designer) 8345 ;// TempEditor.EditorComponent.SetFocus; 8346 finally 8347 debugln(SRCED_CLOSE, ['TSourceNotebook.CloseFile UnLock']); 8348 DebugBoss.UnLockCommandProcessing; 8349 DebugLnExit(SRCED_CLOSE, ['<< TSourceNotebook.CloseFile']); 8350 end; 8351end; 8352 8353procedure TSourceNotebook.FocusEditor; 8354var 8355 SrcEdit: TSourceEditor; 8356begin 8357 if FUpdateLock > 0 then begin 8358 include(FUpdateFlags, ufFocusEditor); 8359 exit; 8360 end; 8361 if (fAutoFocusLock>0) then exit; 8362 SrcEdit:=GetActiveSE; 8363 if SrcEdit=nil then exit; 8364 SrcEdit.FocusEditor; 8365end; 8366 8367procedure TSourceNotebook.FormMouseUp(Sender: TObject; Button: TMouseButton; 8368 Shift: TShiftState; X, Y: Integer); 8369begin 8370 Cursor:=crDefault; 8371end; 8372 8373// Two Popup menu handlers: 8374procedure TSourceNotebook.GoToLineMenuItemClick(Sender: TObject); 8375begin 8376 if Assigned(Manager) then 8377 Manager.GotoLineClicked(nil); 8378end; 8379 8380procedure TSourceNotebook.OpenFolderMenuItemClick(Sender: TObject); 8381begin 8382 OpenDocument(ExtractFilePath(Statusbar.Panels[4].Text)); 8383end; 8384 8385procedure TSourceNotebook.ExecuteEditorItemClick(Sender: TObject); 8386var 8387 Editor: TSourceEditor; 8388begin 8389 if SourceEditorManager = nil then exit; 8390 8391 Editor := TSourceEditor((sender as TIDEMenuCommand).UserTag); 8392 SourceEditorManager.ActiveEditor :=Editor; 8393 SourceEditorManager.ShowActiveWindowOnTop(True); 8394end; 8395 8396procedure TSourceNotebook.ApplyPageIndex; 8397begin 8398 Exclude(FUpdateFlags,ufPageIndexChanged); 8399 DebugBoss.LockCommandProcessing; 8400 try 8401 //debugln(['TSourceNotebook.ApplyPageIndex FPageIndex=',FPageIndex]); 8402 FPageIndex := Max(0,Min(FPageIndex,FNotebook.PageCount-1)); 8403 if Assigned(Manager) and (FNotebook.PageIndex = FPageIndex) then 8404 DoActiveEditorChanged; 8405 // make sure the statusbar is updated 8406 Include(States, snNotebookPageChangedNeeded); 8407 FNotebook.PageIndex := FPageIndex; 8408 if snNotebookPageChangedNeeded in States then begin 8409 DebugLn(SRCED_PAGES, ['TSourceNotebook.ApplyPageIndex calling NotebookPageChanged']); 8410 NotebookPageChanged(nil); 8411 end; 8412 HistorySetMostRecent(FNotebook.Pages[FPageIndex]); 8413 finally 8414 DebugBoss.UnLockCommandProcessing; 8415 end; 8416end; 8417 8418procedure TSourceNotebook.CloseTabClicked(Sender: TObject); 8419begin 8420 if (GetKeyShiftState * [ssShift, ssCtrl, ssAlt] = EditorOpts.MiddleTabClickClosesOthersModifier) and 8421 (EditorOpts.MiddleTabClickClosesOthersModifier <> []) 8422 then 8423 CloseClicked(Sender, [ceoCloseOthers]) 8424 else 8425 if (GetKeyShiftState * [ssShift, ssCtrl, ssAlt] = EditorOpts.MiddleTabClickClosesToRightModifier) and 8426 (EditorOpts.MiddleTabClickClosesToRightModifier <> []) 8427 then 8428 CloseClicked(Sender, [ceoCloseOthersOnRightSide]) 8429 else 8430 CloseClicked(Sender, []); 8431end; 8432 8433function TSourceNotebook.GetEditors(Index:integer):TSourceEditor; 8434begin 8435 Result:=TSourceEditor(FSourceEditorList[Index]); 8436end; 8437 8438function TSourceNotebook.EditorCount:integer; 8439begin 8440 Result:=FSourceEditorList.Count; 8441end; 8442 8443function TSourceNotebook.IndexOfEditor(aEditor: TSourceEditorInterface): integer; 8444begin 8445 Result := FSourceEditorList.IndexOf(aEditor); 8446end; 8447 8448function TSourceNotebook.Count: integer; 8449begin 8450 Result:=FSourceEditorList.Count; 8451end; 8452 8453function TSourceNotebook.SourceEditorIntfWithFilename(const Filename: string 8454 ): TSourceEditorInterface; 8455var 8456 Node: TAvlTreeNode; 8457begin 8458 Node:=FSrcEditsSortedForFilenames.FindKey(Pointer(Filename),@CompareFilenameWithSrcEditIntf); 8459 if Node<>nil then 8460 Result:=TSourceEditorInterface(Node.Data) 8461 else 8462 Result:=nil; 8463end; 8464 8465procedure TSourceNotebook.CloseClicked(Sender: TObject; 8466 CloseOptions: TCloseSrcEditorOptions); 8467Begin 8468 if assigned(Manager) and Assigned(Manager.OnCloseClicked) then 8469 Manager.OnCloseClicked(Sender, CloseOptions); 8470end; 8471 8472procedure TSourceNotebook.ToggleFormUnitClicked(Sender: TObject); 8473begin 8474 if assigned(Manager) and Assigned(Manager.OnToggleFormUnitClicked) then 8475 Manager.OnToggleFormUnitClicked(Sender); 8476end; 8477 8478procedure TSourceNotebook.ToggleObjectInspClicked(Sender: TObject); 8479begin 8480 if assigned(Manager) and Assigned(Manager.OnToggleObjectInspClicked) then 8481 Manager.OnToggleObjectInspClicked(Sender); 8482end; 8483 8484procedure TSourceNotebook.HistorySetMostRecent(APage: TTabSheet); 8485var 8486 Index: Integer; 8487begin 8488 if APage = nil then 8489 Exit; 8490 Index := FHistoryList.IndexOf(APage); 8491 if Index <> -1 then 8492 FHistoryList.Delete(Index); 8493 FHistoryList.Insert(0, APage); 8494end; 8495 8496procedure TSourceNotebook.HistoryRemove(APage: TTabSheet); 8497var 8498 Index: Integer; 8499begin 8500 Index := FHistoryList.IndexOf(APage); 8501 if Index <> -1 then 8502 FHistoryList.Delete(Index); 8503end; 8504 8505function TSourceNotebook.HistoryGetTopPageIndex: Integer; 8506begin 8507 Result := -1; 8508 if FHistoryList.Count = 0 then 8509 Exit; 8510 Result := FNotebook.IndexOf(TCustomPage(FHistoryList.Items[0])); 8511end; 8512 8513procedure TSourceNotebook.InsertCharacter(const C: TUTF8Char); 8514var 8515 FActiveEdit: TSourceEditor; 8516begin 8517 FActiveEdit := GetActiveSE; 8518 if FActiveEdit <> nil then 8519 begin 8520 if FActiveEdit.ReadOnly then Exit; 8521 FActiveEdit.EditorComponent.InsertTextAtCaret(C); 8522 end; 8523end; 8524 8525procedure TSourceNotebook.SrcEditMenuCopyToExistingWindowClicked(Sender: TObject); 8526begin 8527 inc(FFocusLock); 8528 try 8529 CopyEditor(PageIndex, (Sender as TIDEMenuItem).Tag, -1); 8530 finally 8531 dec(FFocusLock); 8532 end; 8533end; 8534 8535procedure TSourceNotebook.SrcEditMenuMoveToExistingWindowClicked(Sender: TObject); 8536begin 8537 MoveEditor(PageIndex, (Sender as TIDEMenuItem).Tag, -1) 8538end; 8539 8540procedure TSourceNotebook.SrcEditMenuFindInWindowClicked(Sender: TObject); 8541var 8542 TargetIndex: Integer; 8543 DestWin: TSourceNotebook; 8544 Edit: TSourceEditor; 8545 SharedEditorIdx: Integer; 8546begin 8547 TargetIndex := (Sender as TIDEMenuItem).Tag; 8548 if (TargetIndex < 0) or (TargetIndex >= Manager.SourceWindowCount) then 8549 exit; 8550 DestWin := Manager.SourceWindows[TargetIndex]; 8551 Edit := FindSourceEditorWithPageIndex(PageIndex); 8552 SharedEditorIdx := DestWin.IndexOfEditorInShareWith(Edit); 8553 If SharedEditorIdx < 0 then 8554 exit; 8555 Manager.ActiveEditor := DestWin.Editors[SharedEditorIdx]; 8556 Manager.ShowActiveWindowOnTop(True); 8557end; 8558 8559procedure TSourceNotebook.EditorLockClicked(Sender: TObject); 8560begin 8561 GetActiveSE.IsLocked := not GetActiveSE.IsLocked; 8562end; 8563 8564procedure TSourceNotebook.UpdateStatusBar; 8565var 8566 tempEditor: TSourceEditor; 8567 PanelFilename: String; 8568 PanelCharMode: string; 8569 PanelXY: string; 8570 PanelFileMode: string; 8571 CurEditor: TSynEdit; 8572begin 8573 if FUpdateLock > 0 then begin 8574 include(FUpdateFlags, ufStatusBar); 8575 exit; 8576 end; 8577 if (not IsVisible) or (FUpdateLock > 0) then 8578 begin 8579 Include(States,snUpdateStatusBarNeeded); 8580 exit; 8581 end; 8582 Exclude(States,snUpdateStatusBarNeeded); 8583 TempEditor := GetActiveSE; 8584 if TempEditor = nil then Exit; 8585 CurEditor:=TempEditor.EditorComponent; 8586 //debugln(['TSourceNotebook.UpdateStatusBar ',tempEditor.FileName,' ',PageIndex]); 8587 8588 if (snIncrementalFind in States) 8589 and (CompareCaret(CurEditor.LogicalCaretXY,FIncrementalSearchPos)<>0) then 8590 begin 8591 // some action has changed the cursor during incremental search 8592 // -> end incremental search 8593 EndIncrementalFind; 8594 // this called UpdateStatusBar -> exit 8595 exit; 8596 end; 8597 8598 if (CurEditor.CaretY<>TempEditor.ErrorLine) 8599 or (CurEditor.CaretX<>TempEditor.fErrorColumn) then 8600 TempEditor.ErrorLine:=-1; 8601 Statusbar.BeginUpdate; 8602 8603 if snIncrementalFind in States then begin 8604 Statusbar.SimplePanel:=true; 8605 Statusbar.SimpleText:=Format(lisUESearching, [IncrementalSearchStr]); 8606 8607 end else begin 8608 Statusbar.SimplePanel:=false; 8609 PanelFilename:=TempEditor.Filename; 8610 8611 If TempEditor.Modified then 8612 PanelFileMode := ueModified 8613 else 8614 PanelFileMode := ''; 8615 8616 If TempEditor.ReadOnly then begin 8617 if PanelFileMode <> '' then 8618 PanelFileMode := PanelFileMode + lisUEModeSeparator; 8619 PanelFileMode := PanelFileMode + uepReadonly; 8620 end; 8621 8622 if (EditorMacroForRecording.State = emRecording) and 8623 (EditorMacroForRecording.IsRecording(CurEditor)) 8624 then begin 8625 if PanelFileMode <> '' then 8626 PanelFileMode := PanelFileMode + lisUEModeSeparator; 8627 PanelFileMode := PanelFileMode + ueMacroRecording; 8628 end; 8629 if (EditorMacroForRecording.State = emRecPaused) and 8630 (EditorMacroForRecording.IsRecording(CurEditor)) 8631 then begin 8632 if PanelFileMode <> '' then 8633 PanelFileMode := PanelFileMode + lisUEModeSeparator; 8634 PanelFileMode := PanelFileMode + ueMacroRecordingPaused; 8635 end; 8636 8637 If TempEditor.IsLocked then begin 8638 if PanelFileMode <> '' then 8639 PanelFileMode := PanelFileMode + lisUEModeSeparator; 8640 PanelFileMode := PanelFileMode + ueLocked; 8641 end; 8642 8643 PanelXY := Format(' %6d:%4d', 8644 [TempEditor.CurrentCursorYLine,TempEditor.CurrentCursorXLine]); 8645 8646 if GetActiveSE.InsertMode then 8647 PanelCharMode := uepIns 8648 else 8649 PanelCharMode := uepOvr; 8650 8651 Statusbar.Panels[0].Text := PanelXY; 8652 StatusBar.Panels[2].Text := PanelFileMode; 8653 Statusbar.Panels[3].Text := PanelCharMode; 8654 Statusbar.Panels[4].Text := PanelFilename; 8655 if(EditorMacroForRecording.IsRecording(CurEditor)) then 8656 Statusbar.Panels[1].Width := IDEImages.ScaledSize(20) 8657 else 8658 Statusbar.Panels[1].Width := 0; 8659 8660 end; 8661 Statusbar.EndUpdate; 8662 8663 CheckCurrentCodeBufferChanged; 8664End; 8665 8666function TSourceNotebook.FindPageWithEditor(ASourceEditor: TSourceEditor): integer; 8667var 8668 LTabSheet, LParent: TWinControl; 8669begin 8670 Result:=-1; 8671 LParent := ASourceEditor.EditorComponent.Parent; 8672 if LParent is TTabSheet then 8673 begin 8674 repeat 8675 LTabSheet := LParent; 8676 LParent := LParent.Parent; 8677 until (LParent = FNotebook) or (LParent = nil); 8678 if (LParent <> nil) and (LTabSheet is TTabSheet) then 8679 Result:=TTabSheet(LTabSheet).PageIndex; 8680 end; 8681end; 8682 8683function TSourceNotebook.FindSourceEditorWithEditorComponent(EditorComp: TComponent): TSourceEditor; 8684var 8685 i: integer; 8686begin 8687 for i:=0 to EditorCount-1 do begin 8688 Result:=Editors[i]; 8689 if Result.EditorComponent=EditorComp then exit; 8690 end; 8691 Result:=nil; 8692end; 8693 8694procedure TSourceNotebook.NotebookMouseDown(Sender: TObject; Button: TMouseButton; 8695 Shift: TShiftState; X, Y: Integer); 8696var 8697 TabIndex: Integer; 8698begin 8699 if (Button = mbMiddle) then 8700 begin 8701 TabIndex:=FNotebook.IndexOfPageAt(X, Y); 8702 if TabIndex>=0 then begin 8703 if (GetKeyShiftState * [ssShift, ssCtrl, ssAlt] = EditorOpts.MiddleTabClickClosesOthersModifier) and 8704 (EditorOpts.MiddleTabClickClosesOthersModifier <> []) 8705 then 8706 CloseClicked(NoteBookPage[TabIndex], [ceoCloseOthers]) 8707 else 8708 if (GetKeyShiftState * [ssShift, ssCtrl, ssAlt] = EditorOpts.MiddleTabClickClosesToRightModifier) and 8709 (EditorOpts.MiddleTabClickClosesToRightModifier <> []) 8710 then 8711 CloseClicked(NoteBookPage[TabIndex], [ceoCloseOthersOnRightSide]) 8712 else 8713 CloseClicked(NoteBookPage[TabIndex], []); 8714 end; 8715 end else 8716 if (Button = mbRight) then 8717 begin 8718 //select on right click 8719 TabIndex:=FNotebook.IndexOfPageAt(X, Y); 8720 if TabIndex>=0 then 8721 begin 8722 FNotebook.ActivePageIndex := TabIndex; 8723 if Assigned(IDEDockMaster) then 8724 Manager.ActiveEditor:=GetActiveSE; 8725 end; 8726 end; 8727end; 8728 8729procedure TSourceNotebook.NotebookMouseUp(Sender: TObject; 8730 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 8731var 8732 TabIndex: Integer; 8733begin 8734 if (Button = mbRight) then 8735 begin 8736 TabIndex:=FNotebook.IndexOfPageAt(X, Y); 8737 if TabIndex>=0 then 8738 begin 8739 TabPopUpMenu.PopupComponent := FNotebook; 8740 TabPopUpMenu.PopUp; 8741 TabPopUpMenu.PopupComponent := nil; 8742 end; 8743 end; 8744end; 8745 8746procedure TSourceNotebook.NotebookDragDropEx(Sender, Source: TObject; OldIndex, 8747 NewIndex: Integer; CopyDrag: Boolean; var Done: Boolean); 8748 function SourceIndex: Integer; 8749 begin 8750 Result := Manager.SourceWindowCount - 1; 8751 while Result >= 0 do begin 8752 if Manager.SourceWindows[Result].FNotebook = Source then break; 8753 dec(Result); 8754 end; 8755 end; 8756begin 8757 {$IFnDEF SingleSrcWindow} 8758 If CopyDrag then begin 8759 Manager.SourceWindows[SourceIndex].CopyEditor 8760 (OldIndex, Manager.IndexOfSourceWindow(self), NewIndex); 8761 end 8762 else begin 8763 {$ENDIF} 8764 if (Source = FNotebook) then 8765 MoveEditor(OldIndex, NewIndex) 8766 else begin 8767 Manager.SourceWindows[SourceIndex].MoveEditor 8768 (OldIndex, Manager.IndexOfSourceWindow(self), NewIndex); 8769 end; 8770 {$IFnDEF SingleSrcWindow} 8771 end; 8772 {$ENDIF} 8773 Manager.ActiveSourceWindow := self; 8774 Manager.ShowActiveWindowOnTop(True); 8775 Done := True; 8776end; 8777 8778procedure TSourceNotebook.NotebookDragOverEx(Sender, Source: TObject; 8779 OldIndex, NewIndex: Integer; CopyDrag: Boolean; var Accept: Boolean); 8780 8781 function SourceIndex: Integer; 8782 begin 8783 Result := Manager.SourceWindowCount - 1; 8784 while Result >= 0 do begin 8785 if Manager.SourceWindows[Result].FNotebook = Source then break; 8786 dec(Result); 8787 end; 8788 end; 8789var 8790 Src: TSourceNotebook; 8791 NBHasSharedEditor: Boolean; 8792begin 8793 Src := Manager.SourceWindows[SourceIndex]; 8794 NBHasSharedEditor := IndexOfEditorInShareWith 8795 (Src.FindSourceEditorWithPageIndex(OldIndex)) >= 0; 8796 {$IFnDEF SingleSrcWindow} 8797 if CopyDrag then 8798 Accept := (NewIndex >= 0) and (Source <> Sender) and (not NBHasSharedEditor) 8799 else 8800 {$ENDIF} 8801 Accept := (NewIndex >= 0) and 8802 ((Source <> Sender) or (OldIndex <> NewIndex)) and 8803 ((Source = Sender) or (not NBHasSharedEditor)); 8804end; 8805 8806procedure TSourceNotebook.NotebookDragOver(Sender, Source: TObject; X, Y: Integer; 8807 State: TDragState; var Accept: Boolean); 8808begin 8809 if Accept=true then ; // set by NotebookDragOverEx 8810 FUpdateTabAndPageTimer.Enabled := False; 8811 if State = dsDragLeave then 8812 FUpdateTabAndPageTimer.Enabled := True 8813 else if Source is TExtendedNotebook then 8814 FNotebook.ShowTabs := (Manager=nil) or Manager.ShowTabs; 8815end; 8816 8817procedure TSourceNotebook.NotebookEndDrag(Sender, Target: TObject; X, Y: Integer); 8818begin 8819 FUpdateTabAndPageTimer.Enabled := True; 8820end; 8821 8822procedure TSourceNotebook.NotebookPageChanged(Sender: TObject); 8823var 8824 SrcEdit:TSourceEditor; 8825 CaretXY: TPoint; 8826 TopLine: Integer; 8827Begin 8828 if (Manager = nil) or (FUpdateLock > 0) Then begin 8829 Include(States, snNotebookPageChangedNeeded); 8830 exit; 8831 end; 8832 DebugLnEnter(SRCED_PAGES, ['>> TSourceNotebook.NotebookPageChanged PageIndex=', PageIndex, ' AutoFocusLock=', fAutoFocusLock, ' Sender=',DbgSName(Sender)]); 8833 8834 DebugBoss.LockCommandProcessing; 8835 try 8836 Exclude(States, snNotebookPageChangedNeeded); 8837 SrcEdit:=GetActiveSE; 8838 Manager.FHints.HideIfVisible; 8839 if (CodeContextFrm<>nil) then 8840 CodeContextFrm.Hide; 8841 8842 DebugLn(SRCED_PAGES, ['TSourceNotebook.NotebookPageChanged TempEdit=', DbgSName(SrcEdit), ' Vis=', dbgs(IsVisible), ' Hnd=', dbgs(HandleAllocated)]); 8843 if SrcEdit <> nil then 8844 begin 8845 if not SrcEdit.Visible then begin 8846 // As long as SynEdit had no Handle, it had kept all those Values untouched 8847 CaretXY := SrcEdit.EditorComponent.CaretXY; 8848 TopLine := SrcEdit.EditorComponent.TopLine; 8849 TSynEditMarkupManager(SrcEdit.EditorComponent.MarkupMgr).IncPaintLock; 8850 SrcEdit.BeginUpdate; 8851 SrcEdit.FEditor.HandleNeeded; // make sure we have a handle 8852 SrcEdit.Visible := True; 8853 SrcEdit.EndUpdate; 8854 // Restore the intial Positions, must be after lock 8855 SrcEdit.EditorComponent.LeftChar := 1; 8856 SrcEdit.EditorComponent.CaretXY := CaretXY; 8857 SrcEdit.EditorComponent.TopLine := TopLine; 8858 TSynEditMarkupManager(SrcEdit.EditorComponent.MarkupMgr).DecPaintLock; 8859 SrcEdit.UpdateIfDefNodeStates; // after editor is initialized 8860 end; 8861 if (fAutoFocusLock=0) and (Screen.ActiveCustomForm=GetParentForm(Self)) and 8862 not(Manager.HasAutoFocusLock) 8863 then 8864 begin 8865 DebugLnEnter(SRCED_PAGES, ['TSourceNotebook.NotebookPageChanged BEFORE SetFocus ', DbgSName(SrcEdit.EditorComponent),' Page=', FindPageWithEditor(SrcEdit), ' ', SrcEdit.FileName]); 8866 SrcEdit.FocusEditor; // recursively calls NotebookPageChanged, via EditorEnter 8867 DebugLnExit(SRCED_PAGES, ['TSourceNotebook.NotebookPageChanged AFTER SetFocus ', DbgSName(SrcEdit.EditorComponent),' Page=', FindPageWithEditor(SrcEdit)]); 8868 end; 8869 UpdateStatusBar; 8870 UpdateActiveEditColors(SrcEdit.EditorComponent); 8871 if (DebugBoss.State in [dsPause, dsRun]) and 8872 not SrcEdit.HasExecutionMarks and 8873 (SrcEdit.FileName <> '') then 8874 SrcEdit.FillExecutionMarks; 8875 DoActiveEditorChanged; 8876 end; 8877 8878 CheckCurrentCodeBufferChanged; 8879 finally 8880 DebugBoss.UnLockCommandProcessing; 8881 end; 8882 DebugLnExit(SRCED_PAGES, ['<< TSourceNotebook.NotebookPageChanged ']); 8883end; 8884 8885procedure TSourceNotebook.ProcessParentCommand(Sender: TObject; 8886 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer; 8887 var Handled: boolean); 8888var 8889 IDECmd: TIDECommand; 8890 r: Boolean; 8891begin 8892 //DebugLn(['TSourceNotebook.ProcessParentCommand START ',dbgsName(Sender),' Command=',Command,' AChar=',AChar]); 8893 8894 FProcessingCommand:=true; 8895 if Assigned(Manager.OnProcessUserCommand) then begin 8896 Handled:=false; 8897 IDECmd:=IDECommandList.FindIDECommand(Command); 8898 r := (IDECmd <> nil) and (IDECmd.OnExecuteProc = @ExecuteIdeMenuClick); 8899 if r then IDECmd.OnExecuteProc := nil; 8900 8901 Manager.OnProcessUserCommand(Self,Command,Handled); 8902 8903 if r then IDECmd.OnExecuteProc := @ExecuteIdeMenuClick; 8904 8905 if Handled or (Command=ecNone) then begin 8906 FProcessingCommand:=false; 8907 Command:=ecNone; 8908 exit; 8909 end; 8910 end; 8911 //DebugLn(['TSourceNotebook.ProcessParentCommand after mainide: ',dbgsName(Sender),' Command=',Command,' AChar=',AChar]); 8912 8913 Handled:=true; 8914 case Command of 8915 ecNextEditor: NextEditor; 8916 ecPrevEditor: PrevEditor; 8917 ecPrevEditorInHistory: FHistoryDlg.Show(True); 8918 ecNextEditorInHistory: FHistoryDlg.Show(False); 8919 ecMoveEditorLeft: MoveActivePageLeft; 8920 ecMoveEditorRight: MoveActivePageRight; 8921 ecMoveEditorLeftmost: MoveActivePageFirst; 8922 ecMoveEditorRightmost: MoveActivePageLast; 8923 ecNextSharedEditor: GotoNextSharedEditor(False); 8924 ecPrevSharedEditor: GotoNextSharedEditor(True); 8925 ecNextWindow: GotoNextWindow(False); 8926 ecPrevWindow: GotoNextWindow(True); 8927 ecMoveEditorNextWindow: MoveEditorNextWindow(False, False); 8928 ecMoveEditorPrevWindow: MoveEditorNextWindow(True, False); 8929 ecMoveEditorNewWindow: 8930 if EditorCount > 1 then 8931 MoveEditor(FindPageWithEditor(GetActiveSE), 8932 Manager.IndexOfSourceWindow(Manager.CreateNewWindow(True)), -1); 8933 8934 ecCopyEditorNextWindow: MoveEditorNextWindow(False, True); 8935 ecCopyEditorPrevWindow: MoveEditorNextWindow(True, True); 8936 ecCopyEditorNewWindow: 8937 CopyEditor(FindPageWithEditor(GetActiveSE), 8938 Manager.IndexOfSourceWindow(Manager.CreateNewWindow(True)), -1, True); 8939 8940 ecOpenFileAtCursor: OpenAtCursorClicked(self); 8941 ecGotoEditor1..ecGotoEditor9,ecGotoEditor0: 8942 if PageCount>Command-ecGotoEditor1 then 8943 PageIndex := Command-ecGotoEditor1; 8944 8945 ecToggleFormUnit: ToggleFormUnitClicked(Self); 8946 ecToggleObjectInsp: ToggleObjectInspClicked(Self); 8947 ecSetFreeBookmark: 8948 if Assigned(Manager.OnSetBookmark) then 8949 Manager.OnSetBookmark(GetActiveSE, -1, False); 8950 8951 ecClearAllBookmark: 8952 if Assigned(Manager.OnClearBookmarkId) then 8953 Manager.OnClearBookmarkId(Self, -1); 8954 8955 ecJumpBack: Manager.HistoryJump(Self,jhaBack); 8956 ecJumpForward: Manager.HistoryJump(Self,jhaForward); 8957 ecAddJumpPoint: Manager.AddJumpPointClicked(Self); 8958 ecViewJumpHistory: Manager.ViewJumpHistoryClicked(Self); 8959 8960 else 8961 Handled:=ExecuteIDECommand(Self,Command); 8962 DebugLn('TSourceNotebook.ProcessParentCommand Command=',dbgs(Command),' Handled=',dbgs(Handled)); 8963 end; //case 8964 if Handled then Command:=ecNone; 8965 FProcessingCommand:=false; 8966end; 8967 8968procedure TSourceNotebook.ParentCommandProcessed(Sender: TObject; 8969 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer; 8970 var Handled: boolean); 8971begin 8972 Assert(Assigned(Manager), 'TSourceNotebook.ParentCommandProcessed: Manager=Nil.'); 8973 if Assigned(Manager.OnUserCommandProcessed) then begin 8974 Handled:=false; 8975 Manager.OnUserCommandProcessed(Self,Command,Handled); 8976 if Handled then exit; 8977 end; 8978 8979 Handled:=(Command=ecClose); 8980 8981 if Handled then Command:=ecNone; 8982end; 8983 8984procedure TSourceNotebook.ReloadEditorOptions; 8985var 8986 I: integer; 8987Begin 8988 for i := 0 to EditorCount-1 do 8989 Editors[i].RefreshEditorSettings; 8990 8991 if EditorOpts.ShowTabCloseButtons then 8992 FNoteBook.Options:=FNoteBook.Options+[nboShowCloseButtons] 8993 else 8994 FNoteBook.Options:=FNoteBook.Options-[nboShowCloseButtons]; 8995 FNoteBook.MultiLine := EditorOpts.MultiLineTab; 8996 if FNotebook.ShowTabs then 8997 FNotebook.TabPosition := EditorOpts.TabPosition 8998 else 8999 FNotebook.TabPosition := tpTop; 9000 9001 Exclude(States,snWarnedFont); 9002 CheckFont; 9003 UpdatePageNames; 9004end; 9005 9006procedure TSourceNotebook.CheckFont; 9007var 9008 SrcEdit: TSourceEditor; 9009 DummyResult: TModalResult; 9010 CurFont: TFont; 9011begin 9012 if (snWarnedFont in States) then exit; 9013 Include(States,snWarnedFont); 9014 SrcEdit:=GetActiveSE; 9015 if SrcEdit = nil then 9016 Exit; 9017 CurFont:=SrcEdit.EditorComponent.Font; 9018 if SystemCharSetIsUTF8 9019 and ((EditorOpts.DoNotWarnForFont='') 9020 or (EditorOpts.DoNotWarnForFont<>CurFont.Name)) 9021 then begin 9022 {$IFDEF HasMonoSpaceFonts} 9023 DummyResult:=IDEQuestionDialog(lisUEFontWith, 9024 Format(lisUETheCurre, [LineEnding, LineEnding]), 9025 mtWarning, [mrIgnore, mrYesToAll, lisUEDoNotSho]); 9026 {$ELSE} 9027 DummyResult:=mrYesToAll; 9028 {$ENDIF} 9029 if DummyResult=mrYesToAll then begin 9030 if EditorOpts.DoNotWarnForFont<>CurFont.Name then begin 9031 EditorOpts.DoNotWarnForFont:=CurFont.Name; 9032 EditorOpts.Save; 9033 end; 9034 end; 9035 end; 9036end; 9037 9038procedure TSourceNotebook.BeginAutoFocusLock; 9039begin 9040 inc(fAutoFocusLock); 9041end; 9042 9043procedure TSourceNotebook.EndAutoFocusLock; 9044begin 9045 dec(fAutoFocusLock); 9046end; 9047 9048procedure TSourceNotebook.EditorMouseMove(Sender: TObject; Shift: TShiftstate; 9049 X, Y: Integer); 9050begin 9051 Manager.FHints.HideAutoHintAfterMouseMoved; 9052 if Visible then 9053 Manager.FHints.UpdateHintTimer; 9054end; 9055 9056procedure TSourceNotebook.EditorMouseWheel(Sender: TObject; Shift: TShiftState; 9057 WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); 9058begin 9059 //handled:=true; //The scrolling is not done: it's not handled! See TWinControl.DoMouseWheel 9060end; 9061 9062procedure TSourceNotebook.EditorMouseDown(Sender: TObject; 9063 Button: TMouseButton; Shift: TShiftstate; X, Y: Integer); 9064begin 9065 9066end; 9067 9068function TSourceNotebook.EditorGetIndent(Sender: TObject; Editor: TObject; 9069 LogCaret, OldLogCaret: TPoint; FirstLinePos, LastLinePos: Integer; 9070 Reason: TSynEditorCommand; SetIndentProc: TSynBeautifierSetIndentProc 9071 ): Boolean; 9072var 9073 SrcEdit: TSourceEditor; 9074 p: LongInt; 9075 NestedComments: Boolean; 9076 NewIndent: TFABIndentationPolicy; 9077 Indent: LongInt; 9078 CodeBuf: TCodeBuffer; 9079begin 9080 Result:=false; 9081 // SynBeautifier is shared arrcoss SynEdits, and may call the wrong SrcNoteBook 9082 if assigned(Manager) 9083 then SrcEdit := Manager.FindSourceEditorWithEditorComponent(TComponent(Editor)) 9084 else SrcEdit := FindSourceEditorWithEditorComponent(TComponent(Editor)); 9085 if SrcEdit = nil then 9086 exit; 9087 if assigned(Manager) and Assigned(Manager.OnGetIndent) then begin 9088 Result := Manager.OnGetIndent(Sender, SrcEdit, LogCaret, OldLogCaret, FirstLinePos, LastLinePos, 9089 Reason, SetIndentProc); 9090 if Result then exit; 9091 end; 9092 if (SrcEdit.SyncroLockCount > 0) then exit; 9093 if not (SrcEdit.SyntaxHighlighterType in [lshFreePascal, lshDelphi]) then 9094 exit; 9095 if Reason<>ecLineBreak then exit; 9096 if not CodeToolsOpts.IndentOnLineBreak then exit; 9097 {$IFDEF VerboseIndenter} 9098 debugln(['TSourceNotebook.EditorGetIndent LogCaret=',dbgs(LogCaret),' FirstLinePos=',FirstLinePos,' LastLinePos=',LastLinePos]); 9099 {$ENDIF} 9100 Result := True; 9101 SrcEdit.UpdateCodeBuffer; 9102 CodeBuf:=SrcEdit.CodeBuffer; 9103 CodeBuf.LineColToPosition(LogCaret.Y,LogCaret.X,p); 9104 if p<1 then exit; 9105 {$IFDEF VerboseIndenter} 9106 if FirstLinePos>0 then 9107 DebugLn(['TSourceNotebook.EditorGetIndent Firstline-1=',SrcEdit.Lines[FirstLinePos-2]]); 9108 DebugLn(['TSourceNotebook.EditorGetIndent Firstline+0=',SrcEdit.Lines[FirstLinePos-1]]); 9109 if FirstLinePos<SrcEdit.LineCount then 9110 DebugLn(['TSourceNotebook.EditorGetIndent Firstline+1=',SrcEdit.Lines[FirstLinePos+0]]); 9111 DebugLn(['TSourceNotebook.EditorGetIndent CodeBuffer: ',dbgstr(copy(CodeBuf.Source,p-10,10)),'|',dbgstr(copy(CodeBuf.Source,p,10))]); 9112 DebugLn(['TSourceNotebook.EditorGetIndent CodeBuffer: "',copy(CodeBuf.Source,p-10,10),'|',copy(CodeBuf.Source,p,10)]); 9113 {$ENDIF} 9114 NestedComments:=CodeToolBoss.GetNestedCommentsFlagForFile(CodeBuf.Filename); 9115 if not CodeToolBoss.Indenter.GetIndent(CodeBuf.Source,p,NestedComments, 9116 True,NewIndent,CodeToolsOpts.IndentContextSensitive) 9117 then exit; 9118 if not NewIndent.IndentValid then exit; 9119 Indent:=NewIndent.Indent; 9120 {$IFDEF VerboseIndenter} 9121 DebugLn(['TSourceNotebook.EditorGetIndent Indent=',Indent]); 9122 {$ENDIF} 9123 {$IFDEF VerboseIndenter} 9124 DebugLn(['TSourceNotebook.EditorGetIndent Apply to FirstLinePos+1']); 9125 {$ENDIF} 9126 SetIndentProc(LogCaret.Y, Indent, 0,' '); 9127 SrcEdit.CursorScreenXY:=Point(Indent+1,SrcEdit.CursorScreenXY.Y); 9128end; 9129 9130procedure TSourceNotebook.OnApplicationDeactivate(Sender: TObject); 9131begin 9132 if (CodeContextFrm<>nil) then 9133 CodeContextFrm.Hide; 9134 if (Manager<>nil) and (Manager.FHints<>nil) then 9135 Manager.FHints.HideIfVisible; 9136end; 9137 9138procedure TSourceNotebook.EditorKeyDown(Sender: TObject; var Key: Word; 9139 Shift: TShiftState); 9140begin 9141 9142end; 9143 9144procedure TSourceNotebook.EditorKeyUp(Sender: TObject; var Key: Word; 9145 Shift: TShiftState); 9146begin 9147 9148end; 9149 9150procedure TSourceNotebook.ShowSynEditHint(const MousePos: TPoint); 9151var 9152 EditPos: TPoint; 9153 ASrcEdit: TSourceEditor; 9154 ASynEdit: TSynEdit; 9155 EditCaret: TPoint; 9156 AMark: TSourceMark; 9157 i: integer; 9158 HintStr: String; 9159 CurHint: String; 9160 MLine: TSynEditMarkLine; 9161begin 9162 // hide other hints 9163 //debugln('TSourceNotebook.ShowSynEditHint A'); 9164 Application.HideHint; 9165 // 9166 ASrcEdit:=GetActiveSE; 9167 if ASrcEdit=nil then exit; 9168 ASynEdit:=ASrcEdit.EditorComponent; 9169 EditPos:=ASynEdit.ScreenToClient(MousePos); 9170 if not PtInRect(ASynEdit.ClientRect,EditPos) then exit; 9171 EditCaret:=ASynEdit.PhysicalToLogicalPos(ASynEdit.PixelsToRowColumn(EditPos)); 9172 if (EditCaret.Y<1) then exit; 9173 if EditPos.X<ASynEdit.Gutter.Width then begin 9174 // hint for a gutter item 9175 if EditorOpts.ShowGutterHints then begin 9176 HintStr:=''; 9177 MLine := ASynEdit.Marks.Line[EditCaret.Y]; 9178 if MLine <> nil then begin 9179 if ASynEdit.BookMarkOptions.DrawBookmarksFirst then 9180 MLine.Sort(smsoBookmarkFirst, smsoColumn) 9181 else 9182 MLine.Sort(smsoBookMarkLast, smsoColumn); 9183 9184 for i := 0 to MLine.Count - 1 do begin 9185 if not (MLine[i] is TSourceMark) then continue; 9186 AMark := TSourceMark(MLine[i]); 9187 if AMark = nil then continue; 9188 CurHint:=AMark.GetHint; 9189 if CurHint='' then continue; 9190 if HintStr<>'' then HintStr:=HintStr+LineEnding; 9191 HintStr:=HintStr+CurHint; 9192 end; 9193 9194 if (MessagesView<>nil) then 9195 MessagesView.SourceEditorHint(MLine,HintStr); 9196 end; 9197 9198 if HintStr<>'' then 9199 Manager.ActivateHint(MousePos,'',HintStr); 9200 end; 9201 end else begin 9202 // hint for source 9203 if Assigned(Manager) and Assigned(Manager.OnShowHintForSource) then 9204 Manager.OnShowHintForSource(ASrcEdit,EditCaret, True); 9205 end; 9206end; 9207 9208procedure TSourceNotebook.SetIncrementalSearchStr(const AValue: string); 9209begin 9210 if FIncrementalSearchStr=AValue then exit; 9211 FIncrementalSearchStr:=AValue; 9212 IncrementalSearch(False, False); 9213end; 9214 9215procedure TSourceNotebook.IncrementalSearch(ANext, ABackward: Boolean); 9216const 9217 SEARCH_OPTS: array[Boolean] of TSynSearchOptions = ([], [ssoBackwards]); 9218var 9219 CurEdit: TSynEdit; 9220 AStart : TPoint; 9221begin 9222 if not (snIncrementalFind in States) 9223 then begin 9224 UpdateStatusBar; 9225 Exit; 9226 end; 9227 if FIncrementalSearchEditor = nil then Exit; 9228 9229 // search string 9230 CurEdit := FIncrementalSearchEditor.EditorComponent; 9231 CurEdit.BeginUpdate; 9232 if FIncrementalSearchStr<>'' 9233 then begin 9234 // search from search start position when not searching for the next 9235 AStart := CurEdit.LogicalCaretXY; 9236 if not ANext 9237 then AStart := FIncrementalSearchStartPos 9238 else if ABackward 9239 then AStart := CurEdit.BlockBegin; 9240 FIncrementalSearchBackwards:=ABackward; 9241 CurEdit.SearchReplaceEx(FIncrementalSearchStr,'', SEARCH_OPTS[ABackward], AStart); 9242 9243 // searching next resets incremental history 9244 if ANext 9245 then begin 9246 FIncrementalSearchStartPos := CurEdit.BlockBegin; 9247 end; 9248 9249 // cut the not found 9250 FIncrementalSearchStr := CurEdit.SelText; 9251 9252 CurEdit.SetHighlightSearch(FIncrementalSearchStr, []); 9253 if Length(FIncrementalSearchStr) > 0 9254 then FIncrementalFoundStr := FIncrementalSearchStr; 9255 end 9256 else begin 9257 // go to start 9258 CurEdit.LogicalCaretXY:= FIncrementalSearchStartPos; 9259 CurEdit.BlockBegin:=CurEdit.LogicalCaretXY; 9260 CurEdit.BlockEnd:=CurEdit.BlockBegin; 9261 CurEdit.SetHighlightSearch('', []); 9262 end; 9263 FIncrementalSearchPos:=CurEdit.LogicalCaretXY; 9264 CurEdit.EndUpdate; 9265 9266 UpdateStatusBar; 9267end; 9268 9269procedure TSourceNotebook.Activate; 9270begin 9271 inherited Activate; 9272 if assigned(Manager) then begin 9273 Manager.ActiveSourceWindow := self; 9274 Manager.DoWindowFocused(Self); 9275 end; 9276end; 9277 9278procedure TSourceNotebook.UpdateActiveEditColors(AEditor: TSynEdit); 9279begin 9280 if AEditor=nil then exit; 9281 EditorOpts.SetMarkupColors(AEditor); 9282 AEditor.UseIncrementalColor:= snIncrementalFind in States; 9283end; 9284 9285procedure TSourceNotebook.ClearExecutionLines; 9286var 9287 i: integer; 9288begin 9289 for i := 0 to EditorCount - 1 do 9290 Editors[i].ExecutionLine := -1; 9291end; 9292 9293procedure TSourceNotebook.ClearExecutionMarks; 9294var 9295 i: integer; 9296begin 9297 for i := 0 to EditorCount - 1 do 9298 Editors[i].ClearExecutionMarks; 9299end; 9300 9301//----------------------------------------------------------------------------- 9302 9303procedure InternalInit; 9304var 9305 h: TLazSyntaxHighlighter; 9306begin 9307 // fetch the resourcestrings before they are translated 9308 EnglishGPLNotice:=lisGPLNotice; 9309 EnglishLGPLNotice:=lisLGPLNotice; 9310 EnglishModifiedLGPLNotice:=lisModifiedLGPLNotice; 9311 EnglishMITNotice:=lisMITNotice; 9312 9313 for h:=Low(TLazSyntaxHighlighter) to High(TLazSyntaxHighlighter) do 9314 Highlighters[h]:=nil; 9315 IDESearchInText:=@SearchInText; 9316 PasBeautifier := TSynBeautifierPascal.Create(nil); 9317 9318 SRCED_LOCK := DebugLogger.RegisterLogGroup('SRCED_LOCK' {$IFDEF SRCED_LOCK} , True {$ENDIF} ); 9319 SRCED_OPEN := DebugLogger.RegisterLogGroup('SRCED_OPEN' {$IFDEF SRCED_OPEN} , True {$ENDIF} ); 9320 SRCED_CLOSE := DebugLogger.RegisterLogGroup('SRCED_CLOSE' {$IFDEF SRCED_CLOSE} , True {$ENDIF} ); 9321 SRCED_PAGES := DebugLogger.RegisterLogGroup('SRCED_PAGES' {$IFDEF SRCED_PAGES} , True {$ENDIF} ); 9322 9323 IDEWindowsGlobalOptions.Add(NonModalIDEWindowNames[nmiwSourceNoteBook], False); 9324end; 9325 9326procedure InternalFinal; 9327var 9328 h: TLazSyntaxHighlighter; 9329begin 9330 for h:=Low(TLazSyntaxHighlighter) to High(TLazSyntaxHighlighter) do 9331 FreeThenNil(Highlighters[h]); 9332 FreeThenNil(aWordCompletion); 9333 FreeAndNil(PasBeautifier); 9334end; 9335 9336{ TSourceEditorManagerBase } 9337 9338procedure TSourceEditorManagerBase.DoMacroRecorderState(Sender: TObject); 9339var 9340 i: Integer; 9341begin 9342 For i := 0 to SourceWindowCount - 1 do 9343 TSourceNotebook(SourceWindows[i]).UpdateStatusBar; 9344 DoEditorMacroStateChanged; 9345end; 9346 9347procedure TSourceEditorManagerBase.FreeSourceWindows; 9348var 9349 s: TSourceEditorWindowInterface; 9350begin 9351 PasBeautifier.OnGetDesiredIndent := nil; 9352 FSourceWindowByFocusList.Clear; 9353 while FSourceWindowList.Count > 0 do begin 9354 s := TSourceEditorWindowInterface(FSourceWindowList[0]); 9355 FSourceWindowList.Delete(0); 9356 s.Free; 9357 end; 9358 FSourceWindowList.Clear; 9359end; 9360 9361function TSourceEditorManagerBase.GetActiveSourceWindowIndex: integer; 9362begin 9363 Result := IndexOfSourceWindow(ActiveSourceWindow); 9364end; 9365 9366function TSourceEditorManagerBase.GetSourceWindowByLastFocused(Index: Integer): TSourceEditorWindowInterface; 9367begin 9368 Result := TSourceEditorWindowInterface(FSourceWindowByFocusList[Index]); 9369end; 9370 9371procedure TSourceEditorManagerBase.SetActiveSourceWindowIndex(const AValue: integer); 9372begin 9373 ActiveSourceWindow := SourceWindows[AValue]; 9374end; 9375 9376procedure TSourceEditorManagerBase.SetShowTabs(const AShowTabs: Boolean); 9377begin 9378 FShowTabs := AShowTabs; 9379end; 9380 9381function TSourceEditorManagerBase.GetActiveSourceWindow: TSourceEditorWindowInterface; 9382begin 9383 Result := FActiveWindow; 9384end; 9385 9386procedure TSourceEditorManagerBase.SetActiveSourceWindow( 9387 const AValue: TSourceEditorWindowInterface); 9388var 9389 NewWindow: TSourceNotebook; 9390begin 9391 NewWindow:= AValue as TSourceNotebook; 9392 if NewWindow = FActiveWindow then exit; 9393 9394 //debugln(['TSourceEditorManagerBase.SetActiveSourceWindow ',dbgSourceNoteBook(FActiveWindow),' ',dbgSourceNoteBook(NewWindow)]); 9395 if (FActiveWindow <> nil) and (NewWindow <> nil) and (FActiveWindow.Focused) then 9396 NewWindow.SetFocus; 9397 9398 FActiveWindow := NewWindow; 9399 FSourceWindowByFocusList.Remove(NewWindow); 9400 FSourceWindowByFocusList.Insert(0, NewWindow); 9401 9402 if Assigned(OnCurrentCodeBufferChanged) then 9403 OnCurrentCodeBufferChanged(nil); 9404 FChangeNotifyLists[semWindowActivate].CallNotifyEvents(FActiveWindow); 9405 DoActiveEditorChanged; 9406end; 9407 9408function TSourceEditorManagerBase.GetSourceWindows(Index: integer 9409 ): TSourceEditorWindowInterface; 9410begin 9411 Result := TSourceEditorWindowInterface(FSourceWindowList[Index]); 9412end; 9413 9414procedure TSourceEditorManagerBase.DoWindowFocused(AWindow: TSourceNotebook); 9415begin 9416 FChangeNotifyLists[semWindowFocused].CallNotifyEvents(FActiveWindow); 9417end; 9418 9419function TSourceEditorManagerBase.GetActiveEditor: TSourceEditorInterface; 9420begin 9421 If FActiveWindow <> nil then 9422 Result := FActiveWindow.ActiveEditor 9423 else 9424 Result := nil; 9425end; 9426 9427procedure TSourceEditorManagerBase.SetActiveEditor(const AValue: TSourceEditorInterface); 9428var 9429 Window: TSourceEditorWindowInterface; 9430begin 9431 inc(FActiveEditorLock); 9432 try 9433 if (FActiveWindow <> nil) and (FActiveWindow.IndexOfEditor(AValue) >= 0) then 9434 Window := FActiveWindow 9435 else 9436 Window := SourceWindowWithEditor(AValue); 9437 if Window = nil then exit; 9438 ActiveSourceWindow := TSourceNotebook(Window); 9439 Window.ActiveEditor := AValue; 9440 finally 9441 dec(FActiveEditorLock); 9442 DoActiveEditorChanged; 9443 end; 9444end; 9445 9446procedure TSourceEditorManagerBase.DoActiveEditorChanged; 9447begin 9448 if FActiveEditorLock > 0 then exit; 9449 if FUpdateLock > 0 then begin 9450 include(FUpdateFlags, ufMgrActiveEditorChanged); 9451 exit; 9452 end; 9453 exclude(FUpdateFlags, ufMgrActiveEditorChanged); 9454 FChangeNotifyLists[semEditorActivate].CallNotifyEvents(ActiveEditor); 9455end; 9456 9457procedure TSourceEditorManagerBase.DoEditorStatusChanged(AEditor: TSourceEditor); 9458begin 9459 CodeToolsToSrcEditTimer.Enabled:=false; 9460 FChangeNotifyLists[semEditorStatus].CallNotifyEvents(AEditor); 9461end; 9462 9463function TSourceEditorManagerBase.GetSourceEditors(Index: integer): TSourceEditorInterface; 9464var 9465 i: Integer; 9466begin 9467 i := 0; 9468 while (i < SourceWindowCount) and (Index >= SourceWindows[i].Count) do begin 9469 Index := Index - SourceWindows[i].Count; 9470 inc(i); 9471 end; 9472 if (i < SourceWindowCount) then 9473 Result := SourceWindows[i].Items[Index] 9474 else 9475 Result := nil; 9476end; 9477 9478function TSourceEditorManagerBase.GetUniqueSourceEditors(Index: integer): TSourceEditorInterface; 9479var 9480 i: Integer; 9481begin 9482 for i := 0 to SourceEditorCount - 1 do begin 9483 Result := SourceEditors[i]; 9484 if (TSourceEditor(Result).SharedEditorCount = 0) or 9485 (TSourceEditor(Result).SharedEditors[0] = Result) 9486 then 9487 dec(Index); 9488 if Index < 0 then exit; 9489 end; 9490 Result := nil; 9491end; 9492 9493function TSourceEditorManagerBase.SourceWindowWithEditor( 9494 const AEditor: TSourceEditorInterface): TSourceEditorWindowInterface; 9495var 9496 i: Integer; 9497begin 9498 Result := nil; 9499 for i := FSourceWindowList.Count-1 downto 0 do begin 9500 if TSourceNotebook(SourceWindows[i]).IndexOfEditor(AEditor) >= 0 then begin 9501 Result := SourceWindows[i]; 9502 break; 9503 end; 9504 end; 9505end; 9506 9507function TSourceEditorManagerBase.SourceWindowCount: integer; 9508begin 9509 if assigned(FSourceWindowList) then 9510 Result := FSourceWindowList.Count 9511 else 9512 Result := 0; 9513end; 9514 9515function TSourceEditorManagerBase.IndexOfSourceWindow( 9516 AWindow: TSourceEditorWindowInterface): integer; 9517begin 9518 Result := SourceWindowCount - 1; 9519 while Result >= 0 do Begin 9520 if SourceWindows[Result] = AWindow then 9521 exit; 9522 dec(Result); 9523 end; 9524end; 9525 9526function TSourceEditorManagerBase.IndexOfSourceWindowByLastFocused(AWindow: TSourceEditorWindowInterface): integer; 9527begin 9528 Result := FSourceWindowByFocusList.IndexOf(AWindow); 9529end; 9530 9531function TSourceEditorManagerBase.SourceEditorIntfWithFilename( 9532 const Filename: string): TSourceEditorInterface; 9533var 9534 i: Integer; 9535begin 9536 for i:=0 to SourceWindowCount-1 do 9537 begin 9538 Result:=SourceWindows[i].SourceEditorIntfWithFilename(Filename); 9539 if Result<>nil then exit; 9540 end; 9541 Result:=nil; 9542end; 9543 9544function TSourceEditorManagerBase.SourceEditorCount: integer; 9545var 9546 i: Integer; 9547begin 9548 Result := 0; 9549 for i := 0 to SourceWindowCount - 1 do 9550 Result := Result + SourceWindows[i].Count; 9551end; 9552 9553function TSourceEditorManagerBase.UniqueSourceEditorCount: integer; 9554var 9555 SrcEdit: TSourceEditor; 9556 i: Integer; 9557begin 9558 Result := 0; 9559 for i := 0 to SourceEditorCount - 1 do begin 9560 SrcEdit := TSourceEditor(SourceEditors[i]); 9561 if (SrcEdit.SharedEditorCount = 0) or (SrcEdit.SharedEditors[0] = SrcEdit) then 9562 inc(Result); 9563 end; 9564end; 9565 9566function TSourceEditorManagerBase.GetEditorControlSettings(EditControl: TControl): boolean; 9567begin 9568 Result:=true; 9569 if EditControl is TSynEdit then begin 9570 EditorOpts.GetSynEditSettings(TSynEdit(EditControl)); 9571 Result:=true; 9572 end else begin 9573 Result:=false; 9574 end; 9575end; 9576 9577function TSourceEditorManagerBase.GetHighlighterSettings(Highlighter: TObject): boolean; 9578begin 9579 Result:=true; 9580 if Highlighter is TSynCustomHighlighter then begin 9581 EditorOpts.GetHighlighterSettings(TSynCustomHighlighter(Highlighter)); 9582 Result:=true; 9583 end else begin 9584 Result:=false; 9585 end; 9586end; 9587 9588function TSourceEditorManagerBase.GetDefaultCompletionForm: TSourceEditCompletion; 9589var 9590 i: Integer; 9591begin 9592 Result := FDefaultCompletionForm; 9593 if Result <> nil then exit; 9594 FDefaultCompletionForm := TSourceEditCompletion.Create(Self); 9595 FDefaultCompletionForm.LongLineHintTime := EditorOpts.CompletionLongLineHintInMSec; 9596 FDefaultCompletionForm.LongLineHintType := EditorOpts.CompletionLongLineHintType; 9597 Result := FDefaultCompletionForm; 9598 for i:=0 to SourceEditorCount - 1 do 9599 FDefaultCompletionForm.AddEditor(TSourceEditor(SourceEditors[i]).EditorComponent); 9600end; 9601 9602function TSourceEditorManagerBase.GetDefaultSynCompletionForm: TCustomForm; 9603begin 9604 if Assigned(GetDefaultCompletionForm) then 9605 Result := GetDefaultCompletionForm.TheForm 9606 else 9607 Result := nil; 9608end; 9609 9610function TSourceEditorManagerBase.GetSynCompletionLinesInWindow: integer; 9611var 9612 ComplForm: TCustomForm; 9613begin 9614 ComplForm := GetDefaultSynCompletionForm; 9615 if Assigned(ComplForm) then 9616 Result := TSynBaseCompletionForm(ComplForm).NbLinesInWindow 9617 else 9618 Result := -1; 9619end; 9620 9621procedure TSourceEditorManagerBase.SetSynCompletionLinesInWindow(LineCnt: integer); 9622var 9623 ComplForm: TCustomForm; 9624begin 9625 ComplForm := GetDefaultSynCompletionForm; 9626 if Assigned(ComplForm) then 9627 TSynBaseCompletionForm(ComplForm).NbLinesInWindow := LineCnt; 9628end; 9629 9630procedure TSourceEditorManagerBase.FreeCompletionPlugins; 9631var 9632 p: TSourceEditorCompletionPlugin; 9633begin 9634 while FCompletionPlugins.Count > 0 do begin 9635 p := TSourceEditorCompletionPlugin(FCompletionPlugins[0]); 9636 FCompletionPlugins.Delete(0); 9637 p.Free; 9638 end; 9639 FCompletionPlugins.Clear; 9640end; 9641 9642function TSourceEditorManagerBase.GetScreenRectForToken(AnEditor: TCustomSynEdit; 9643 PhysColumn, PhysRow, EndColumn: Integer): TRect; 9644begin 9645 Result.TopLeft := AnEditor.ClientToScreen(AnEditor.RowColumnToPixels(Point(PhysColumn, PhysRow))); 9646 Result.BottomRight := AnEditor.ClientToScreen(AnEditor.RowColumnToPixels(Point(EndColumn+1, PhysRow+1))); 9647end; 9648 9649function TSourceEditorManagerBase.GetShowTabs: Boolean; 9650begin 9651 Result := FShowTabs; 9652end; 9653 9654function TSourceEditorManagerBase.GetMarklingProducers(Index: integer 9655 ): TSourceMarklingProducer; 9656begin 9657 Result:=TSourceMarklingProducer(fProducers[Index]); 9658end; 9659 9660procedure TSourceEditorManagerBase.DoWindowShow(AWindow: TSourceNotebook); 9661begin 9662 FChangeNotifyLists[semWindowShow].CallNotifyEvents(AWindow); 9663end; 9664 9665procedure TSourceEditorManagerBase.DoWindowHide(AWindow: TSourceNotebook); 9666begin 9667 FChangeNotifyLists[semWindowHide].CallNotifyEvents(AWindow); 9668end; 9669 9670procedure TSourceEditorManagerBase.SyncMessageWnd(Sender: TObject); 9671begin 9672 MessagesView.MessagesFrame1.ApplyMultiSrcChanges(Sender as TETMultiSrcChanges); 9673end; 9674 9675procedure TSourceEditorManagerBase.BeginAutoFocusLock; 9676begin 9677 inc(FAutoFocusLock); 9678end; 9679 9680procedure TSourceEditorManagerBase.EndAutoFocusLock; 9681begin 9682 dec(FAutoFocusLock); 9683end; 9684 9685function TSourceEditorManagerBase.HasAutoFocusLock: Boolean; 9686begin 9687 Result := FAutoFocusLock > 0; 9688end; 9689 9690function TSourceEditorManagerBase.GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; 9691begin 9692 Result := FActiveCompletionPlugin; 9693end; 9694 9695function TSourceEditorManagerBase.GetCompletionBoxPosition: integer; 9696begin 9697 Result:=-1; 9698 if (FDefaultCompletionForm<>nil) and FDefaultCompletionForm.IsActive then 9699 Result := FDefaultCompletionForm.Position; 9700end; 9701 9702function TSourceEditorManagerBase.GetCompletionPlugins(Index: integer 9703 ): TSourceEditorCompletionPlugin; 9704begin 9705 Result:=TSourceEditorCompletionPlugin(fCompletionPlugins[Index]); 9706end; 9707 9708function TSourceEditorManagerBase.FindIdentCompletionPlugin( 9709 SrcEdit: TSourceEditor; JumpToError: boolean; var s: string; var BoxX, 9710 BoxY: integer; var UseWordCompletion: boolean): boolean; 9711var 9712 i: Integer; 9713 Plugin: TSourceEditorCompletionPlugin; 9714 Handled: Boolean; 9715 Cancel: Boolean; 9716begin 9717 for i:=0 to CompletionPluginCount-1 do begin 9718 Plugin := CompletionPlugins[i]; 9719 Handled:=false; 9720 Cancel:=false; 9721 Plugin.Init(SrcEdit,JumpToError,Handled,Cancel,s,BoxX,BoxY); 9722 if Cancel then begin 9723 DeactivateCompletionForm; 9724 exit(false); 9725 end; 9726 if Handled then begin 9727 FActiveCompletionPlugin:=Plugin; 9728 exit(true); 9729 end; 9730 end; 9731 9732 if not (SrcEdit.SyntaxHighlighterType in [lshFreePascal, lshDelphi]) then 9733 UseWordCompletion:=true; 9734 Result:=true; 9735end; 9736 9737function TSourceEditorManagerBase.CompletionPluginCount: integer; 9738begin 9739 Result:=fCompletionPlugins.Count; 9740end; 9741 9742procedure TSourceEditorManagerBase.DeactivateCompletionForm; 9743var 9744 PluginFocused: Boolean; 9745begin 9746 {$IFDEF VerboseIDECompletionBox} 9747 DebugLnEnter(['>> TSourceEditorManagerBase.DeactivateCompletionForm']); 9748 try 9749 {$ENDIF} 9750 if ActiveCompletionPlugin<>nil then begin 9751 ActiveCompletionPlugin.Cancel; 9752 FActiveCompletionPlugin:=nil; 9753 end; 9754 9755 if (FDefaultCompletionForm=nil) or 9756 (FDefaultCompletionForm.CurrentCompletionType = ctNone) 9757 then 9758 exit; 9759 9760 // Do not move focus, if it was moved by user 9761 PluginFocused := FDefaultCompletionForm.TheForm.Focused; 9762 {$IFDEF VerboseIDECompletionBox} 9763 DebugLn(['DeactivateCompletionForm PluginFocused=', dbgs(PluginFocused), ' ActiveEditor=', DbgSName(ActiveEditor)]); 9764 {$ENDIF} 9765 9766 // clear the IdentifierList (otherwise it would try to update everytime 9767 // the codetools are used) 9768 CodeToolBoss.IdentifierList.Clear; 9769 FDefaultCompletionForm.CurrentCompletionType:=ctNone; 9770 9771 // SetFocus and Deactivate will all trigger this proc to be reentered. 9772 // Setting "CurrentCompletionType:=ctNone" ensures an immediate exit 9773 9774 // Due to a bug under XFCE we must move focus before we close the form 9775 // This is relevant if the form is closed by enter/escape key 9776 if PluginFocused and (ActiveEditor<>nil) then 9777 TSourceEditor(ActiveEditor).FocusEditor; 9778 9779 // hide/close the form 9780 FDefaultCompletionForm.Deactivate; 9781 9782 // Ensure focus *after* the form was closed. 9783 // This is the normal implementation (all but XFCE) 9784 if PluginFocused and (ActiveEditor<>nil) then 9785 TSourceEditor(ActiveEditor).FocusEditor; 9786 {$IFDEF VerboseIDECompletionBox} 9787 finally 9788 DebugLnExit(['<< TSourceEditorManagerBase.DeactivateCompletionForm']); 9789 end; 9790 {$ENDIF} 9791end; 9792 9793procedure TSourceEditorManagerBase.RegisterCompletionPlugin( 9794 Plugin: TSourceEditorCompletionPlugin); 9795begin 9796 fCompletionPlugins.Add(Plugin); 9797 Plugin.FreeNotification(Self); 9798end; 9799 9800procedure TSourceEditorManagerBase.UnregisterCompletionPlugin( 9801 Plugin: TSourceEditorCompletionPlugin); 9802begin 9803 Plugin.RemoveFreeNotification(Self); 9804 fCompletionPlugins.Remove(Plugin); 9805end; 9806 9807procedure TSourceEditorManagerBase.Notification(AComponent: TComponent; 9808 Operation: TOperation); 9809begin 9810 inherited Notification(AComponent, Operation); 9811 if Operation=opRemove then 9812 begin 9813 if Assigned(fCompletionPlugins) then 9814 fCompletionPlugins.Remove(AComponent); 9815 if ActiveCompletionPlugin = AComponent then 9816 DeactivateCompletionForm; 9817 if AComponent is TSourceMarklingProducer then 9818 fProducers.Remove(AComponent); 9819 end; 9820end; 9821 9822constructor TSourceEditorManagerBase.Create(AOwner: TComponent); 9823var 9824 i: TsemChangeReason; 9825 h: TSrcEditMangerHandlerType; 9826begin 9827 FMacroRecorder := TIdeEditorMacro.Create(Self); 9828 FMacroRecorder.OnStateChange := @DoMacroRecorderState; 9829 OnEditorMacroStateChange := @DoMacroRecorderState; 9830 if EditorMacroForRecording = nil then 9831 EditorMacroForRecording := FMacroRecorder; 9832 9833 FShowTabs := True; 9834 FUpdateFlags := []; 9835 FAutoFocusLock := 0; 9836 for i := low(TsemChangeReason) to high(TsemChangeReason) do 9837 FChangeNotifyLists[i] := TMethodList.Create; 9838 for h:=low(FHandlers) to high(FHandlers) do 9839 FHandlers[h] := TMethodList.Create; 9840 SrcEditorIntf.SourceEditorManagerIntf := Self; 9841 FSourceWindowList := TFPList.Create; 9842 FSourceWindowByFocusList := TFPList.Create; 9843 FCompletionPlugins := TFPList.Create; 9844 FUpdateLock := 0; 9845 FActiveEditorLock := 0; 9846 fProducers := TFPList.Create; 9847 FChangesQueuedForMsgWnd:=TETMultiSrcChanges.Create(Self); 9848 FChangesQueuedForMsgWnd.AutoSync:=true; 9849 FChangesQueuedForMsgWnd.OnSync:=@SyncMessageWnd; 9850 inherited; 9851end; 9852 9853destructor TSourceEditorManagerBase.Destroy; 9854var 9855 i: integer; 9856 cr: TsemChangeReason; 9857 h: TSrcEditMangerHandlerType; 9858begin 9859 FreeAndNil(FChangesQueuedForMsgWnd); 9860 for i:=MarklingProducerCount-1 downto 0 do 9861 MarklingProducers[i].Free; 9862 FreeAndNil(fProducers); 9863 FActiveWindow := nil; 9864 FreeCompletionPlugins; 9865 FreeSourceWindows; 9866 SrcEditorIntf.SourceEditorManagerIntf := nil; // xx move down 9867 if EditorMacroForRecording = FMacroRecorder then 9868 EditorMacroForRecording := nil; 9869 FreeAndNil(FMacroRecorder); 9870 FreeAndNil(FCompletionPlugins); 9871 FreeAndNil(FSourceWindowList); 9872 FreeAndNil(FSourceWindowByFocusList); 9873 inherited Destroy; 9874 for cr := low(TsemChangeReason) to high(TsemChangeReason) do 9875 FreeAndNil(FChangeNotifyLists[cr]); 9876 for h:=low(FHandlers) to high(FHandlers) do 9877 FreeAndNil(FHandlers[h]); 9878end; 9879 9880procedure TSourceEditorManagerBase.RegisterChangeEvent( 9881 AReason: TsemChangeReason; AHandler: TNotifyEvent); 9882begin 9883 FChangeNotifyLists[AReason].Add(TMethod(AHandler)); 9884end; 9885 9886procedure TSourceEditorManagerBase.UnRegisterChangeEvent( 9887 AReason: TsemChangeReason; AHandler: TNotifyEvent); 9888begin 9889 FChangeNotifyLists[AReason].Remove(TMethod(AHandler)); 9890end; 9891 9892procedure TSourceEditorManagerBase.RegisterCopyPasteEvent( 9893 AHandler: TSemCopyPasteEvent); 9894begin 9895 FHandlers[semhtCopyPaste].Add(TMethod(AHandler)); 9896end; 9897 9898procedure TSourceEditorManagerBase.UnRegisterCopyPasteEvent( 9899 AHandler: TSemCopyPasteEvent); 9900begin 9901 FHandlers[semhtCopyPaste].Remove(TMethod(AHandler)); 9902end; 9903 9904function TSourceEditorManagerBase.MarklingProducerCount: integer; 9905begin 9906 Result:=fProducers.Count; 9907end; 9908 9909procedure TSourceEditorManagerBase.RegisterMarklingProducer( 9910 aProducer: TSourceMarklingProducer); 9911begin 9912 if fProducers.IndexOf(aProducer)>=0 then 9913 RaiseGDBException('TSourceEditorManagerBase.RegisterProducer already registered'); 9914 fProducers.Add(aProducer); 9915 FreeNotification(aProducer); 9916end; 9917 9918procedure TSourceEditorManagerBase.UnregisterMarklingProducer( 9919 aProducer: TSourceMarklingProducer); 9920var 9921 i: LongInt; 9922begin 9923 i:=fProducers.IndexOf(aProducer); 9924 if i<0 then exit; 9925 fProducers.Delete(i); 9926 RemoveFreeNotification(aProducer); 9927end; 9928 9929procedure TSourceEditorManagerBase.InvalidateMarklingsOfAllFiles( 9930 aProducer: TSourceMarklingProducer); 9931var 9932 SrcWnd: TSourceEditorWindowInterface; 9933 i, j: Integer; 9934 SrcEdit: TSourceEditor; 9935begin 9936 if aProducer=nil then exit; 9937 for i := 0 to SourceWindowCount - 1 do 9938 begin 9939 SrcWnd:=SourceWindows[i]; 9940 for j:=0 to SrcWnd.Count-1 do 9941 begin 9942 SrcEdit:=TSourceEditor(SrcWnd[j]); 9943 SrcEdit.FSharedValues.FMarklingsValid:=false; 9944 end; 9945 end; 9946end; 9947 9948procedure TSourceEditorManagerBase.InvalidateMarklings( 9949 aProducer: TSourceMarklingProducer; aFilename: string); 9950var 9951 SrcWnd: TSourceEditorWindowInterface; 9952 i: Integer; 9953 SrcEdit: TSourceEditor; 9954begin 9955 if aProducer=nil then exit; 9956 for i := 0 to SourceWindowCount - 1 do 9957 begin 9958 SrcWnd:=SourceWindows[i]; 9959 SrcEdit:=TSourceEditor(SrcWnd.SourceEditorIntfWithFilename(aFilename)); 9960 if SrcEdit<>nil then 9961 SrcEdit.FSharedValues.FMarklingsValid:=false; 9962 end; 9963end; 9964 9965procedure TSourceEditorManagerBase.IncUpdateLockInternal; 9966begin 9967 if FUpdateLock = 0 then begin 9968 FUpdateFlags := []; 9969 // Debugger cause ProcessMessages, which could lead to entering methods in unexpected order 9970 DebugBoss.LockCommandProcessing; 9971 Screen.BeginWaitCursor; 9972 end; 9973 inc(FUpdateLock); 9974end; 9975 9976procedure TSourceEditorManagerBase.DecUpdateLockInternal; 9977begin 9978 dec(FUpdateLock); 9979 if FUpdateLock = 0 then begin 9980 try 9981 Screen.EndWaitCursor; 9982 if (ufShowWindowOnTop in FUpdateFlags) then 9983 ShowActiveWindowOnTop(ufShowWindowOnTopFocus in FUpdateFlags); 9984 if (ufMgrActiveEditorChanged in FUpdateFlags) then 9985 DoActiveEditorChanged; 9986 finally 9987 DebugBoss.UnLockCommandProcessing; 9988 end; 9989 end; 9990end; 9991 9992procedure TSourceEditorManagerBase.IncUpdateLock; 9993var 9994 i: Integer; 9995begin 9996 IncUpdateLockInternal; 9997 for i := 0 to SourceWindowCount - 1 do 9998 TSourceNotebook(SourceWindows[i]).IncUpdateLockInternal; 9999end; 10000 10001procedure TSourceEditorManagerBase.DecUpdateLock; 10002var 10003 i: Integer; 10004begin 10005 try 10006 for i := 0 to SourceWindowCount - 1 do 10007 TSourceNotebook(SourceWindows[i]).DecUpdateLockInternal; 10008 finally 10009 DecUpdateLockInternal; 10010 end; 10011end; 10012 10013procedure TSourceEditorManagerBase.ShowActiveWindowOnTop(Focus: Boolean); 10014begin 10015 if ActiveSourceWindow = nil then exit; 10016 if FUpdateLock > 0 then begin 10017 include(FUpdateFlags, ufShowWindowOnTop); 10018 if Focus then 10019 include(FUpdateFlags, ufShowWindowOnTopFocus); 10020 exit; 10021 end; 10022 IDEWindowCreators.ShowForm(ActiveSourceWindow,true); 10023 if Focus and ActiveSourceWindow.IsVisible then 10024 TSourceNotebook(ActiveSourceWindow).FocusEditor; 10025end; 10026 10027{ TSourceEditorManager } 10028 10029function TSourceEditorManager.GetActiveSourceNotebook: TSourceNotebook; 10030begin 10031 Result := TSourceNotebook(inherited ActiveSourceWindow); 10032end; 10033 10034function TSourceEditorManager.GetActiveSrcEditor: TSourceEditor; 10035begin 10036 Result := TSourceEditor(inherited ActiveEditor); 10037end; 10038 10039function TSourceEditorManager.GetSourceEditorsByPage(WindowIndex, 10040 PageIndex: integer): TSourceEditor; 10041begin 10042 if SourceWindows[WindowIndex] <> nil then 10043 Result := SourceWindows[WindowIndex].FindSourceEditorWithPageIndex(PageIndex) 10044 else 10045 Result := nil; 10046end; 10047 10048function TSourceEditorManager.GetSourceNbByLastFocused(Index: Integer): TSourceNotebook; 10049begin 10050 Result := TSourceNotebook(inherited SourceWindowByLastFocused[Index]); 10051end; 10052 10053function TSourceEditorManager.GetSrcEditors(Index: integer): TSourceEditor; 10054begin 10055 Result := TSourceEditor(inherited SourceEditors[Index]); 10056end; 10057 10058procedure TSourceEditorManager.SetActiveSourceNotebook(const AValue: TSourceNotebook); 10059begin 10060 inherited ActiveSourceWindow := AValue; 10061end; 10062 10063function TSourceEditorManager.GetSourceNotebook(Index: integer): TSourceNotebook; 10064begin 10065 Result := TSourceNotebook(inherited SourceWindows[Index]); 10066end; 10067 10068procedure TSourceEditorManager.SetActiveSrcEditor(const AValue: TSourceEditor); 10069begin 10070 inherited ActiveEditor := AValue; 10071end; 10072 10073function TSourceEditorManager.SourceWindowWithEditor( 10074 const AEditor: TSourceEditorInterface): TSourceNotebook; 10075begin 10076 Result := TSourceNotebook(inherited SourceWindowWithEditor(AEditor)); 10077end; 10078 10079function TSourceEditorManager.ActiveOrNewSourceWindow: TSourceNotebook; 10080var 10081 i: Integer; 10082begin 10083 Result := ActiveSourceWindow; 10084 if Result <> nil then exit; 10085 if SourceWindowCount>0 then begin 10086 for i:=0 to SourceWindowCount-1 do 10087 begin 10088 Result:=SourceWindows[i]; 10089 if Result.FIsClosing then continue; 10090 ActiveSourceWindow := Result; 10091 exit; 10092 end; 10093 end; 10094 10095 Result := CreateNewWindow(True); 10096 ActiveSourceWindow := Result; 10097end; 10098 10099procedure TSourceEditorManager.AddCustomJumpPoint(ACaretXY: TPoint; 10100 ATopLine: integer; AEditor: TSourceEditor; DeleteForwardHistory: boolean); 10101begin 10102 if Assigned(OnAddJumpPoint) then 10103 OnAddJumpPoint(ACaretXY, ATopLine, AEditor, DeleteForwardHistory); 10104end; 10105 10106function TSourceEditorManager.NewSourceWindow: TSourceNotebook; 10107begin 10108 Result := CreateNewWindow(True); 10109 ActiveSourceWindow := Result; 10110end; 10111 10112procedure TSourceEditorManager.CreateSourceWindow(Sender: TObject; 10113 aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean); 10114var 10115 i: integer; 10116begin 10117 {$IFDEF VerboseIDEDocking} 10118 debugln(['TSourceEditorManager.CreateSourceWindow Sender=',DbgSName(Sender),' FormName="',aFormName,'"']); 10119 {$ENDIF} 10120 // Get ID from Name 10121 i := length(aFormName); 10122 while (i >= 1) and (aFormName[i] in ['0'..'9']) do 10123 dec(i); 10124 inc(i); 10125 i := StrToIntDef(copy(aFormName, i, MaxInt), 1)-1; 10126 AForm := CreateNewWindow(false,DoDisableAutoSizing, i); 10127 AForm.Name:=aFormName; 10128end; 10129 10130procedure TSourceEditorManager.GetDefaultLayout(Sender: TObject; aFormName: string; 10131 out aBounds: TRect; out DockSibling: string; out DockAlign: TAlign); 10132var 10133 i: LongInt; 10134 ScreenR: TRect; 10135begin 10136 DockSibling:=''; 10137 DockAlign:=alNone; 10138 i:=StrToIntDef( 10139 copy(aFormName,length(NonModalIDEWindowNames[nmiwSourceNoteBook])+1,length(aFormName)), 10140 0); 10141 {$IFDEF VerboseIDEDocking} 10142 debugln(['TSourceEditorManager.GetDefaultLayout ',aFormName,' i=',i]); 10143 {$ENDIF} 10144 ScreenR:=IDEWindowCreators.GetScreenrectForDefaults; 10145 if ObjectInspector1<>nil then 10146 begin 10147 aBounds.Left := ObjectInspector1.Left + ObjectInspector1.Width + ObjectInspector1.Scale96ToForm(5); 10148 aBounds.Top := ObjectInspector1.Top; 10149 end 10150 else 10151 begin 10152 aBounds.Left := ScreenR.Left+MulDiv(200, Screen.PixelsPerInch, 96); 10153 aBounds.Top := ScreenR.Top+MulDiv(120, Screen.PixelsPerInch, 96); 10154 end; 10155 Inc(aBounds.Left,MulDiv(30, Screen.PixelsPerInch, 96)*i); 10156 Inc(aBounds.Top, MulDiv(30, Screen.PixelsPerInch, 96)*i); 10157 aBounds.Right:=ScreenR.Right-MulDiv(30, Screen.PixelsPerInch, 96); 10158 aBounds.Bottom:=ScreenR.Bottom-MulDiv(200, Screen.PixelsPerInch, 96); 10159 if (i=0) and (IDEDockMaster<>nil) then begin 10160 DockSibling:=NonModalIDEWindowNames[nmiwMainIDE]; 10161 DockAlign:=alBottom; 10162 end; 10163end; 10164 10165function TSourceEditorManager.SourceWindowWithPage(const APage: TTabSheet): TSourceNotebook; 10166var 10167 i: Integer; 10168begin 10169 Result := nil; 10170 for i := FSourceWindowList.Count-1 downto 0 do begin 10171 if TSourceNotebook(SourceWindows[i]).FNoteBook.IndexOf(APage) >= 0 then begin 10172 Result := SourceWindows[i]; 10173 break; 10174 end; 10175 end; 10176end; 10177 10178procedure TSourceEditorManager.SrcEditMenuProcedureJumpGetCaption( 10179 Sender: TObject; var ACaption, AHint: string); 10180var 10181 ShortFileName, CurFilename: String; 10182 MainCodeBuf: TCodeBuffer; 10183 CodeTool: TCodeTool; 10184 CaretXY: TCodeXYPosition; 10185 CleanPos: integer; 10186 CodeNode: TCodeTreeNode; 10187 ProcNode: TCodeTreeNode; 10188 ProcName: String; 10189 SrcEdit: TSourceEditor; 10190begin 10191 // ask Codetools 10192 SrcEdit:=GetActiveSE; 10193 if not Assigned(SrcEdit) then Exit; 10194 CurFilename:=SrcEdit.FileName; 10195 ShortFileName:=ExtractFileName(CurFilename); 10196 MainCodeBuf:=nil; 10197 if FilenameHasPascalExt(ShortFileName) or FilenameExtIs(ShortFileName,'inc') then 10198 MainCodeBuf:=CodeToolBoss.GetMainCode(SrcEdit.CodeBuffer) 10199 else if FilenameIsPascalSource(ShortFileName) then 10200 MainCodeBuf:=SrcEdit.CodeBuffer; 10201 CodeTool:=nil; 10202 CaretXY:=CleanCodeXYPosition; 10203 CaretXY.Code:=SrcEdit.CodeBuffer; 10204 CaretXY.X:=SrcEdit.CursorTextXY.X; 10205 CaretXY.Y:=SrcEdit.CursorTextXY.Y; 10206 CodeNode:=nil; 10207 if MainCodeBuf<>nil then begin 10208 CodeToolBoss.Explore(MainCodeBuf,CodeTool,true); 10209 if CodeTool<>nil then begin 10210 CodeTool.CaretToCleanPos(CaretXY,CleanPos); 10211 CodeNode:=CodeTool.FindDeepestNodeAtPos(CleanPos,false); 10212 end; 10213 end; 10214 10215 ProcName:=''; 10216 if CodeNode<>nil then begin 10217 ProcNode:=CodeNode.GetNodeOfType(ctnProcedure); 10218 if ProcNode<>nil then 10219 ProcName:=CodeTool.ExtractProcName(ProcNode,[]); 10220 end; 10221 if ProcName<>'' then 10222 ACaption:=Format(lisJumpToProcedure, [ProcName]) 10223 else 10224 ACaption:=uemProcedureJump; 10225end; 10226 10227function TSourceEditorManager.IndexOfSourceWindowWithID(const AnID: Integer): Integer; 10228begin 10229 Result := SourceWindowCount - 1; 10230 while Result >= 0 do begin 10231 if SourceWindows[Result].WindowID = AnID then break; 10232 dec(Result); 10233 end; 10234end; 10235 10236function TSourceEditorManager.SourceWindowWithID(const AnID: Integer): TSourceNotebook; 10237var 10238 i: Integer; 10239begin 10240 i := IndexOfSourceWindowWithID(AnID); 10241 if i >= 0 then 10242 Result := SourceWindows[i] 10243 else 10244 Result := CreateNewWindow(False, False, AnID); 10245end; 10246 10247function TSourceEditorManager.SourceEditorCount: integer; 10248var 10249 i: Integer; 10250begin 10251 Result := 0; 10252 for i := 0 to SourceWindowCount - 1 do 10253 Result := Result + SourceWindows[i].Count; 10254end; 10255 10256function TSourceEditorManager.GetActiveSE: TSourceEditor; 10257begin 10258 Result := TSourceEditor(ActiveEditor); 10259end; 10260 10261procedure TSourceEditorManager.SetWindowByIDAndPage(AWindowID, APageIndex: integer); 10262begin 10263 ActiveSourceWindowIndex := IndexOfSourceWindowWithID(AWindowID); 10264 ActiveSourceWindow.PageIndex:= APageIndex; 10265end; 10266 10267function TSourceEditorManager.SourceEditorIntfWithFilename( 10268 const Filename: string): TSourceEditor; 10269begin 10270 Result := TSourceEditor(inherited SourceEditorIntfWithFilename(Filename)); 10271end; 10272 10273function TSourceEditorManager.FindSourceEditorWithEditorComponent( 10274 EditorComp: TComponent): TSourceEditor; 10275var 10276 i: Integer; 10277begin 10278 Result := nil; 10279 i := SourceWindowCount - 1; 10280 while i >= 0 do begin 10281 Result := SourceWindows[i].FindSourceEditorWithEditorComponent(EditorComp); 10282 if Result <> nil then break; 10283 dec(i); 10284 end; 10285end; 10286 10287procedure TSourceEditorManager.NewEditorCreated(AEditor: TSourceEditor); 10288begin 10289 if FDefaultCompletionForm <> nil then 10290 FDefaultCompletionForm.AddEditor(AEditor.EditorComponent); 10291end; 10292 10293procedure TSourceEditorManager.EditorRemoved(AEditor: TSourceEditor); 10294begin 10295 if FDefaultCompletionForm <> nil then begin 10296 if FDefaultCompletionForm.Editor = AEditor.EditorComponent then 10297 DeactivateCompletionForm; 10298 FDefaultCompletionForm.RemoveEditor(AEditor.EditorComponent); 10299 end; 10300end; 10301 10302procedure TSourceEditorManager.SendEditorCreated(AEditor: TSourceEditor); 10303begin 10304 FChangeNotifyLists[semEditorCreate].CallNotifyEvents(AEditor); 10305end; 10306 10307procedure TSourceEditorManager.SendEditorDestroyed(AEditor: TSourceEditor); 10308begin 10309 FChangeNotifyLists[semEditorDestroy].CallNotifyEvents(AEditor); 10310end; 10311 10312procedure TSourceEditorManager.Notification(AComponent: TComponent; 10313 Operation: TOperation); 10314begin 10315 inherited Notification(AComponent, Operation); 10316 if Operation=opRemove then 10317 begin 10318 if AComponent is TSourceNotebook then 10319 RemoveWindow(TSourceNotebook(AComponent)); 10320 end; 10321end; 10322 10323procedure TSourceEditorManager.ClearErrorLines; 10324var 10325 i, j: Integer; 10326 SrcWin: TSourceNotebook; 10327begin 10328 for i := FSourceWindowList.Count - 1 downto 0 do 10329 begin 10330 SrcWin := SourceWindows[i]; 10331 for j := 0 to SrcWin.EditorCount - 1 do 10332 SrcWin.Editors[j].ErrorLine := -1; 10333 end; 10334end; 10335 10336procedure TSourceEditorManager.ClearExecutionLines; 10337var 10338 i: Integer; 10339begin 10340 for i := FSourceWindowList.Count - 1 downto 0 do 10341 SourceWindows[i].ClearExecutionLines; 10342end; 10343 10344procedure TSourceEditorManager.ClearExecutionMarks; 10345var 10346 i: Integer; 10347begin 10348 for i := FSourceWindowList.Count - 1 downto 0 do 10349 SourceWindows[i].ClearExecutionMarks; 10350end; 10351 10352procedure TSourceEditorManager.FillExecutionMarks; 10353var 10354 i: Integer; 10355 SE: TSourceEditor; 10356begin 10357 for i := FSourceWindowList.Count - 1 downto 0 do begin 10358 SE := SourceWindows[i].GetActiveSE; 10359 if SE <> nil then 10360 SE.FillExecutionMarks; 10361 end; 10362end; 10363 10364procedure TSourceEditorManager.ReloadEditorOptions; 10365var 10366 i: Integer; 10367begin 10368 for i := FSourceWindowList.Count - 1 downto 0 do 10369 SourceWindows[i].ReloadEditorOptions; 10370 10371 AutoStartCompletionBoxTimer.Interval:=EditorOpts.AutoDelayInMSec; 10372 // reload code templates 10373 EditorOpts.LoadCodeTemplates(CodeTemplateModul); 10374 CodeTemplateModul.IndentToTokenStart:=EditorOpts.CodeTemplateIndentToTokenStart; 10375 10376 FHints.AutoHintTimer.Interval:=EditorOpts.AutoHintDelayInMSec; 10377 10378 if FDefaultCompletionForm <> nil then begin 10379 FDefaultCompletionForm.LongLineHintTime := EditorOpts.CompletionLongLineHintInMSec; 10380 FDefaultCompletionForm.LongLineHintType := EditorOpts.CompletionLongLineHintType; 10381 end; 10382end; 10383 10384function TSourceEditorManager.Beautify(const Src: string; 10385 const Flags: TSemBeautyFlags): string; 10386var 10387 NewIndent, NewTabWidth: Integer; 10388 Beauty: TBeautifyCodeOptions; 10389 OldDoNotSplitLineInFront, OldDoNotSplitLineAfter: TAtomTypes; 10390begin 10391 Beauty:=CodeToolBoss.SourceChangeCache.BeautifyCodeOptions; 10392 OldDoNotSplitLineInFront:=Beauty.DoNotSplitLineInFront; 10393 OldDoNotSplitLineAfter:=Beauty.DoNotSplitLineAfter; 10394 try 10395 if sembfNotBreakDots in Flags then 10396 begin 10397 Include(Beauty.DoNotSplitLineInFront,atPoint); 10398 Include(Beauty.DoNotSplitLineAfter,atPoint); 10399 end; 10400 Result:=CodeToolBoss.Beautifier.BeautifyStatement(Src,2,[bcfDoNotIndentFirstLine]); 10401 10402 if (eoTabsToSpaces in EditorOpts.SynEditOptions) 10403 or (EditorOpts.BlockTabIndent=0) then 10404 NewTabWidth:=0 10405 else 10406 NewTabWidth:=EditorOpts.TabWidth; 10407 NewIndent:=EditorOpts.BlockTabIndent*EditorOpts.TabWidth+EditorOpts.BlockIndent; 10408 10409 Result:=BasicCodeTools.ReIndent(Result,2,0,NewIndent,NewTabWidth); 10410 finally 10411 Beauty.DoNotSplitLineInFront:=OldDoNotSplitLineInFront; 10412 Beauty.DoNotSplitLineAfter:=OldDoNotSplitLineAfter; 10413 end; 10414end; 10415 10416procedure TSourceEditorManager.FindClicked(Sender: TObject); 10417begin 10418 if ActiveEditor <> nil then ActiveEditor.StartFindAndReplace(false); 10419end; 10420 10421procedure TSourceEditorManager.FindNextClicked(Sender: TObject); 10422begin 10423 if ActiveEditor <> nil then ActiveEditor.FindNextUTF8; 10424end; 10425 10426procedure TSourceEditorManager.FindPreviousClicked(Sender: TObject); 10427begin 10428 if ActiveEditor <> nil then ActiveEditor.FindPrevious; 10429end; 10430 10431procedure TSourceEditorManager.ReplaceClicked(Sender: TObject); 10432begin 10433 if ActiveEditor <> nil then ActiveEditor.StartFindAndReplace(true); 10434end; 10435 10436procedure TSourceEditorManager.IncrementalFindClicked(Sender: TObject); 10437begin 10438 if ActiveSourceWindow <> nil then ActiveSourceWindow.BeginIncrementalFind; 10439end; 10440 10441procedure TSourceEditorManager.GotoLineClicked(Sender: TObject); 10442begin 10443 if ActiveEditor <> nil then ActiveEditor.ShowGotoLineDialog; 10444end; 10445 10446procedure TSourceEditorManager.HideHint; 10447begin 10448 FHints.HideHint; 10449end; 10450 10451procedure TSourceEditorManager.JumpBackClicked(Sender: TObject); 10452begin 10453 if ActiveSourceWindow <> nil then HistoryJump(Sender,jhaBack); 10454end; 10455 10456procedure TSourceEditorManager.JumpForwardClicked(Sender: TObject); 10457begin 10458 if ActiveSourceWindow <> nil then HistoryJump(Sender,jhaForward); 10459end; 10460 10461procedure TSourceEditorManager.JumpToNextErrorClicked(Sender: TObject); 10462begin 10463 LazarusIDE.DoJumpToNextError(true); 10464end; 10465 10466procedure TSourceEditorManager.JumpToPrevErrorClicked(Sender: TObject); 10467begin 10468 LazarusIDE.DoJumpToNextError(false); 10469end; 10470 10471procedure TSourceEditorManager.JumpToImplementationClicked(Sender: TObject); 10472begin 10473 JumpToSection(jmpImplementation); 10474end; 10475 10476procedure TSourceEditorManager.JumpToImplementationUsesClicked(Sender: TObject); 10477begin 10478 JumpToSection(jmpImplementationUses); 10479end; 10480 10481procedure TSourceEditorManager.JumpToInitializationClicked(Sender: TObject); 10482begin 10483 JumpToSection(jmpInitialization); 10484end; 10485 10486procedure TSourceEditorManager.JumpToInterfaceClicked(Sender: TObject); 10487begin 10488 JumpToSection(jmpInterface); 10489end; 10490 10491procedure TSourceEditorManager.JumpToInterfaceUsesClicked(Sender: TObject); 10492begin 10493 JumpToSection(jmpInterfaceUses); 10494end; 10495 10496procedure TSourceEditorManager.JumpToPos(FileName: string; 10497 Pos: TCodeXYPosition; TopLine, BlockTopLine, BlockBottomLine: Integer); 10498begin 10499 if (LazarusIDE.DoOpenFileAndJumpToPos(Filename 10500 ,Point(Pos.X,Pos.Y), TopLine, BlockTopLine, BlockBottomLine, -1,-1 10501 ,[ofRegularFile,ofUseCache]) = mrOk) 10502 then 10503 ActiveEditor.EditorControl.SetFocus; 10504end; 10505 10506procedure TSourceEditorManager.JumpToPos(FileName: string; 10507 Pos: TCodeXYPosition; TopLine: Integer); 10508begin 10509 JumpToPos(FileName, Pos, TopLine, TopLine, TopLine); 10510end; 10511 10512procedure TSourceEditorManager.JumpToProcedure(const JumpType: TJumpToProcedureType); 10513const 10514 cJumpNames: array[TJumpToProcedureType] of string = ( 10515 'procedure header', 'procedure begin'); 10516var 10517 SrcEditor: TSourceEditorInterface; 10518 ProcNode: TCodeTreeNode; 10519 Tool: TCodeTool; 10520 CleanPos: integer; 10521 NewPos: TCodeXYPosition; 10522 NewTopLine, BlockTopLine, BlockBottomLine: integer; 10523 JumpFound: Boolean; 10524begin 10525 if not LazarusIDE.BeginCodeTools then Exit; //==> 10526 10527 SrcEditor := SourceEditorManagerIntf.ActiveEditor; 10528 if not Assigned(SrcEditor) then Exit; //==> 10529 10530 if CodeToolBoss.Explore(SrcEditor.CodeToolsBuffer as TCodeBuffer, Tool, false, false) then 10531 begin 10532 if Tool.CaretToCleanPos( 10533 CodeXYPosition(SrcEditor.CursorTextXY.X, SrcEditor.CursorTextXY.Y, SrcEditor.CodeToolsBuffer as TCodeBuffer), 10534 CleanPos) <> 0 10535 then 10536 Exit; 10537 ProcNode := Tool.FindDeepestNodeAtPos(CleanPos{%H-},true); 10538 while (ProcNode <> nil) and (ProcNode.Desc <> ctnProcedure) do 10539 ProcNode := ProcNode.Parent; 10540 10541 if (ProcNode <> nil) and (ProcNode.Desc = ctnProcedure) then 10542 begin 10543 if JumpType = jmpBegin then 10544 JumpFound := Tool.FindJumpPointInProcNode(ProcNode, NewPos, NewTopLine, BlockTopLine, BlockBottomLine) 10545 else 10546 JumpFound := Tool.JumpToCleanPos(ProcNode.StartPos, ProcNode.StartPos, ProcNode.EndPos, NewPos, NewTopLine, BlockTopLine, BlockBottomLine, True); 10547 end else 10548 JumpFound := False; 10549 10550 if JumpFound then 10551 JumpToPos(NewPos.Code.Filename, NewPos, NewTopLine, BlockTopLine, BlockBottomLine) 10552 else 10553 begin 10554 CodeToolBoss.SetError(20170421203224, nil, 0, 0, 10555 Format(lisCannotFind, [cJumpNames[JumpType]])); 10556 LazarusIDE.DoJumpToCodeToolBossError; 10557 end; 10558 end 10559 else 10560 LazarusIDE.DoJumpToCodeToolBossError; 10561end; 10562 10563procedure TSourceEditorManager.JumpToProcedureBeginClicked(Sender: TObject); 10564begin 10565 JumpToProcedure(jmpBegin); 10566end; 10567 10568procedure TSourceEditorManager.JumpToProcedureHeaderClicked(Sender: TObject); 10569begin 10570 JumpToProcedure(jmpHeader); 10571end; 10572 10573procedure TSourceEditorManager.JumpToSection(JumpType: TJumpToSectionType); 10574const 10575 cJumpNames: array[TJumpToSectionType] of string = ( 10576 'Interface', 'Interface uses', 'Implementation', 'Implementation uses', 'Initialization'); 10577var 10578 SrcEditor: TSourceEditorInterface; 10579 Node: TCodeTreeNode; 10580 Tool: TCodeTool; 10581 NewTopLine: Integer; 10582 NewCodePos: TCodeXYPosition; 10583begin 10584 if not LazarusIDE.BeginCodeTools then Exit; //==> 10585 10586 SrcEditor := SourceEditorManagerIntf.ActiveEditor; 10587 if not Assigned(SrcEditor) then Exit; //==> 10588 10589 if CodeToolBoss.Explore(SrcEditor.CodeToolsBuffer as TCodeBuffer, Tool, false, false) then 10590 begin 10591 case JumpType of 10592 jmpInterface: Node := Tool.FindInterfaceNode; 10593 jmpInterfaceUses: 10594 begin 10595 Node := Tool.FindMainUsesNode; 10596 if Node = nil then//if the uses section is missing, jump to interface 10597 Node := Tool.FindInterfaceNode; 10598 end; 10599 jmpImplementation: Node := Tool.FindImplementationNode; 10600 jmpImplementationUses: 10601 begin 10602 Node := Tool.FindImplementationUsesNode; 10603 if Node = nil then//if the uses section is missing, jump to implementation 10604 Node := Tool.FindImplementationNode; 10605 end; 10606 jmpInitialization: 10607 begin 10608 Node := Tool.FindInitializationNode; 10609 if Node = nil then//if initialization is missing, jump to last end 10610 Node := Tool.FindRootNode(ctnEndPoint); 10611 end; 10612 end; 10613 10614 if (Node <> nil) and Tool.CleanPosToCaretAndTopLine(Node.StartPos, NewCodePos, NewTopLine) then 10615 JumpToPos(NewCodePos.Code.Filename, NewCodePos, NewTopLine) 10616 else 10617 begin 10618 CodeToolBoss.SetError(20170421203236, nil, 0, 0, 10619 Format(lisCannotFind, [cJumpNames[JumpType]])); 10620 LazarusIDE.DoJumpToCodeToolBossError; 10621 end; 10622 end 10623 else 10624 LazarusIDE.DoJumpToCodeToolBossError; 10625end; 10626 10627procedure TSourceEditorManager.AddJumpPointClicked(Sender: TObject); 10628begin 10629 if Assigned(OnAddJumpPoint) and (ActiveEditor <> nil) then 10630 with ActiveEditor.EditorComponent do 10631 OnAddJumpPoint(LogicalCaretXY, TopLine, ActiveEditor, true); 10632end; 10633 10634procedure TSourceEditorManager.DeleteLastJumpPointClicked(Sender: TObject); 10635begin 10636 if Assigned(OnDeleteLastJumpPoint) then 10637 OnDeleteLastJumpPoint(Sender); 10638end; 10639 10640procedure TSourceEditorManager.ViewJumpHistoryClicked(Sender: TObject); 10641begin 10642 if Assigned(OnViewJumpHistory) then 10643 OnViewJumpHistory(Sender); 10644end; 10645 10646procedure TSourceEditorManager.BookMarkToggleClicked(Sender: TObject); 10647begin 10648 if Assigned(OnSetBookmark) then 10649 OnSetBookmark(ActiveEditor, (Sender as TIDEMenuItem).SectionIndex, True); 10650end; 10651 10652procedure TSourceEditorManager.BookMarkGotoClicked(Sender: TObject); 10653begin 10654 if Assigned(OnGotoBookmark) then 10655 OnGotoBookmark(ActiveEditor, (Sender as TIDEMenuItem).SectionIndex, False); 10656end; 10657 10658procedure TSourceEditorManager.BookMarkNextClicked(Sender: TObject); 10659begin 10660 if Assigned(OnGotoBookmark) then 10661 OnGotoBookmark(ActiveEditor, -1, False); 10662end; 10663 10664procedure TSourceEditorManager.BookMarkPrevClicked(Sender: TObject); 10665begin 10666 if Assigned(OnGotoBookmark) then 10667 OnGotoBookmark(ActiveEditor, -1, True); 10668end; 10669 10670function TSourceEditorManager.MacroFuncCol(const s: string; const Data: PtrInt; 10671 var Abort: boolean): string; 10672begin 10673 if (ActiveEditor <> nil) then 10674 Result:=IntToStr(ActiveEditor.EditorComponent.CaretX) 10675 else 10676 Result:=''; 10677end; 10678 10679function TSourceEditorManager.MacroFuncRow(const s: string; const Data: PtrInt; 10680 var Abort: boolean): string; 10681begin 10682 if (ActiveEditor <> nil) then 10683 Result:=IntToStr(ActiveEditor.EditorComponent.CaretY) 10684 else 10685 Result:=''; 10686end; 10687 10688function TSourceEditorManager.MacroFuncEdFile(const s: string; 10689 const Data: PtrInt; var Abort: boolean): string; 10690begin 10691 if (ActiveEditor <> nil) then 10692 Result := ActiveEditor.FileName 10693 else 10694 Result := ''; 10695end; 10696 10697function TSourceEditorManager.MacroFuncCurToken(const s: string; 10698 const Data: PtrInt; var Abort: boolean): string; 10699begin 10700 if (ActiveEditor <> nil) then begin 10701 with ActiveEditor.EditorComponent do 10702 Result := GetWordAtRowCol(LogicalCaretXY) 10703 end else 10704 Result := ''; 10705end; 10706 10707function TSourceEditorManager.MacroFuncConfirm(const s: string; const Data: PtrInt; 10708 var Abort: boolean): string; 10709begin 10710 Result:=s; 10711 Abort:=(ShowMacroConfirmDialog(Result)<>mrOk); 10712end; 10713 10714function TSourceEditorManager.MacroFuncPrompt(const s: string; 10715 const Data: PtrInt; var Abort: boolean): string; 10716begin 10717 Result:=s; 10718 Abort:=(ShowMacroPromptDialog(Result)<>mrOk); 10719end; 10720 10721function TSourceEditorManager.MacroFuncSave(const s: string; 10722 const Data: PtrInt; var Abort: boolean): string; 10723begin 10724 Result:=''; 10725 if SourceEditorCount > 0 then 10726 Abort:=LazarusIDE.DoSaveEditorFile(ActiveEditor,[sfCheckAmbiguousFiles]) <> mrOk; 10727end; 10728 10729function TSourceEditorManager.MacroFuncSaveAll(const s: string; 10730 const Data: PtrInt; var Abort: boolean): string; 10731begin 10732 Result:=''; 10733 Abort:=LazarusIDE.DoSaveAll([sfCheckAmbiguousFiles])<>mrOk; 10734end; 10735 10736procedure TSourceEditorManager.InitMacros(AMacroList: TTransferMacroList); 10737begin 10738 AMacroList.Add(TTransferMacro.Create('Col','', 10739 lisCursorColumnInCurrentEditor,@MacroFuncCol,[])); 10740 AMacroList.Add(TTransferMacro.Create('Row','', 10741 lisCursorRowInCUrrentEditor,@MacroFuncRow,[])); 10742 AMacroList.Add(TTransferMacro.Create('CurToken','', 10743 lisWordAtCursorInCurrentEditor,@MacroFuncCurToken,[])); 10744 AMacroList.Add(TTransferMacro.Create('EdFile','', 10745 lisExpandedFilenameOfCurrentEditor,@MacroFuncEdFile,[])); 10746 AMacroList.Add(TTransferMacro.Create('Confirm','', 10747 lisConfirmation,@MacroFuncConfirm,[tmfInteractive])); 10748 AMacroList.Add(TTransferMacro.Create('Prompt','', 10749 lisPromptForValue,@MacroFuncPrompt,[tmfInteractive])); 10750 AMacroList.Add(TTransferMacro.Create('Save','', 10751 lisSaveCurrentEditorFile,@MacroFuncSave,[tmfInteractive])); 10752 AMacroList.Add(TTransferMacro.Create('SaveAll','', 10753 lisSaveAllModified,@MacroFuncSaveAll,[tmfInteractive])); 10754end; 10755 10756procedure TSourceEditorManager.SetupShortCuts; 10757 10758 function GetCommand(ACommand: word; ToolButtonClass: TIDEToolButtonClass): TIDECommand; 10759 var 10760 ToolButton: TIDEButtonCommand; 10761 begin 10762 Result:=GetIdeCmdAndToolBtn(ACommand, ToolButton); 10763 if ToolButton<>nil then 10764 ToolButton.ToolButtonClass := ToolButtonClass; 10765 end; 10766 10767 // See also in ToolBarIntf: 10768 // function GetCommand_DropDown 10769 // function GetCommand_ButtonDrop 10770 10771var 10772 i: Integer; 10773begin 10774 {%region *** first static section *** } 10775 SrcEditMenuFindDeclaration.Command := GetIdeCmdRegToolBtn(ecFindDeclaration); 10776 {%region *** Submenu: Find Section *** } 10777 SrcEditMenuProcedureJump.Command := GetIdeCmdRegToolBtn(ecFindProcedureDefinition); 10778 SrcEditMenuProcedureJump.OnRequestCaptionHint := @SrcEditMenuProcedureJumpGetCaption; 10779 SrcEditMenuFindNextWordOccurrence.Command := GetIdeCmdRegToolBtn(ecFindNextWordOccurrence); 10780 SrcEditMenuFindPrevWordOccurrence.Command := GetIdeCmdRegToolBtn(ecFindPrevWordOccurrence); 10781 SrcEditMenuFindInFiles.Command := GetIdeCmdRegToolBtn(ecFindInFiles); 10782 SrcEditMenuFindIdentifierReferences.Command:=GetIdeCmdRegToolBtn(ecFindIdentifierRefs); 10783 SrcEditMenuFindUsedUnitReferences.Command:=GetIdeCmdRegToolBtn(ecFindUsedUnitRefs); 10784 {%endregion} 10785 {%endregion} 10786 10787 {%region *** Pages section ***} 10788 SrcEditMenuClosePage.Command := GetIdeCmdRegToolBtn(ecClose); 10789 SrcEditMenuCloseOtherPages.OnClick := @SourceEditorManager.CloseOtherPagesClicked; 10790 SrcEditMenuCloseOtherPagesToRight.OnClick := @SourceEditorManager.CloseRightPagesClicked; 10791 10792 {$IFnDEF SingleSrcWindow} 10793 SrcEditMenuEditorLock.Command := GetIdeCmdRegToolBtn(ecLockEditor); 10794 SrcEditMenuMoveToNewWindow.SyncProperties := False; 10795 SrcEditMenuMoveToNewWindow.Command := GetIdeCmdRegToolBtn(ecMoveEditorNewWindow); 10796 SrcEditMenuMoveToOtherWindowNew.SyncProperties := False; 10797 SrcEditMenuMoveToOtherWindowNew.Command := GetIdeCmdRegToolBtn(ecMoveEditorNewWindow); 10798 SrcEditMenuCopyToNewWindow.SyncProperties := False; 10799 SrcEditMenuCopyToNewWindow.Command := GetIdeCmdRegToolBtn(ecCopyEditorNewWindow); 10800 SrcEditMenuCopyToOtherWindowNew.SyncProperties := False; 10801 SrcEditMenuCopyToOtherWindowNew.Command := GetIdeCmdRegToolBtn(ecCopyEditorNewWindow); 10802 {$ENDIF} 10803 {%endregion} 10804 10805 {%region * Move Page (left/right) *} 10806 SrcEditMenuMoveEditorLeft.Command := GetIdeCmdRegToolBtn(ecMoveEditorLeft); 10807 SrcEditMenuMoveEditorRight.Command := GetIdeCmdRegToolBtn(ecMoveEditorRight); 10808 SrcEditMenuMoveEditorFirst.Command := GetIdeCmdRegToolBtn(ecMoveEditorLeftmost); 10809 SrcEditMenuMoveEditorLast.Command := GetIdeCmdRegToolBtn(ecMoveEditorRightmost); 10810 {%endregion} 10811 10812 SrcEditMenuOpenFileAtCursor.Command := GetIdeCmdRegToolBtn(ecOpenFileAtCursor); 10813 10814 {%region * sub menu Flags section *} 10815 SrcEditMenuReadOnly.OnClick := @ReadOnlyClicked; 10816 SrcEditMenuShowLineNumbers.OnClick := @ToggleLineNumbersClicked; 10817 SrcEditMenuDisableI18NForLFM.OnClick := @ToggleI18NForLFMClicked; 10818 SrcEditMenuShowUnitInfo.OnClick := @ShowUnitInfo; 10819 {%endregion} 10820 10821 {%region *** Clipboard section ***} 10822 SrcEditMenuCut.Command:=GetIdeCmdRegToolBtn(ecCut); 10823 SrcEditMenuCopy.Command:=GetIdeCmdRegToolBtn(ecCopy); 10824 SrcEditMenuPaste.Command:=GetIdeCmdRegToolBtn(ecPaste); 10825 SrcEditMenuMultiPaste.Command:=GetIdeCmdRegToolBtn(ecMultiPaste); 10826 SrcEditMenuCopyFilename.OnClick:=@CopyFilenameClicked; 10827 SrcEditMenuSelectAll.Command:=GetIdeCmdRegToolBtn(ecSelectAll); 10828 {%endregion} 10829 10830 SrcEditMenuNextBookmark.Command:=GetIdeCmdRegToolBtn(ecNextBookmark); 10831 SrcEditMenuPrevBookmark.Command:=GetIdeCmdRegToolBtn(ecPrevBookmark); 10832 SrcEditMenuSetFreeBookmark.Command:=GetIdeCmdRegToolBtn(ecSetFreeBookmark); 10833 SrcEditMenuClearFileBookmark.Command:=GetIdeCmdRegToolBtn(ecClearBookmarkForFile); 10834 SrcEditMenuClearAllBookmark.Command:=GetIdeCmdRegToolBtn(ecClearAllBookmark); 10835 10836 for i in TBookmarkNumRange do 10837 SrcEditMenuGotoBookmark[i].Command := GetIdeCmdRegToolBtn(ecGotoMarker0 + i); 10838 GetCommand_ButtonDrop(ecGotoBookmarks ,SrcEditSubMenuGotoBookmarks); // [ ▼] 10839 10840 for i in TBookmarkNumRange do 10841 SrcEditMenuToggleBookmark[i].Command := GetIdeCmdRegToolBtn(ecToggleMarker0 + i); 10842 GetCommand_ButtonDrop(ecToggleBookmarks ,SrcEditSubMenuToggleBookmarks); // [ ▼] 10843 10844 {%region *** Source Section ***} 10845 SrcEditMenuEncloseSelection.Command:=GetIdeCmdRegToolBtn(ecSelectionEnclose); 10846 SrcEditMenuEncloseInIFDEF.Command:=GetIdeCmdRegToolBtn(ecSelectionEncloseIFDEF); 10847 SrcEditMenuCompleteCode.Command:=GetIdeCmdRegToolBtn(ecCompleteCode); 10848 SrcEditMenuUseUnit.Command:=GetIdeCmdRegToolBtn(ecUseUnit); 10849 {%endregion} 10850 10851 {%region *** Refactoring Section ***} 10852 SrcEditMenuRenameIdentifier.Command:=GetIdeCmdRegToolBtn(ecRenameIdentifier); 10853 SrcEditMenuExtractProc.Command:=GetIdeCmdRegToolBtn(ecExtractProc); 10854 SrcEditMenuInvertAssignment.Command:=GetIdeCmdRegToolBtn(ecInvertAssignment); 10855 SrcEditMenuShowAbstractMethods.Command:=GetIdeCmdRegToolBtn(ecShowAbstractMethods); 10856 SrcEditMenuShowEmptyMethods.Command:=GetIdeCmdRegToolBtn(ecRemoveEmptyMethods); 10857 SrcEditMenuShowUnusedUnits.Command:=GetIdeCmdRegToolBtn(ecRemoveUnusedUnits); 10858 SrcEditMenuFindOverloads.Command:=GetIdeCmdRegToolBtn(ecFindOverloads); 10859 SrcEditMenuMakeResourceString.Command:=GetIdeCmdRegToolBtn(ecMakeResourceString); 10860 {%endregion} 10861 10862 SrcEditMenuEditorProperties.OnClick:=@EditorPropertiesClicked; 10863 10864 DebugBoss.SetupSourceMenuShortCuts; 10865end; 10866 10867function TSourceEditorManager.FindUniquePageName(FileName: string; 10868 IgnoreEditor: TSourceEditor): string; 10869var 10870 I:integer; 10871 ShortName:string; 10872 10873 function PageNameExists(const AName:string):boolean; 10874 var a:integer; 10875 begin 10876 Result:=false; 10877 for a := 0 to SourceEditorCount - 1 do begin 10878 if (SourceEditors[a] <> IgnoreEditor) and 10879 (not SourceEditors[a].IsSharedWith(IgnoreEditor)) and 10880 (CompareText(AName, SourceEditors[a].PageName) = 0) 10881 then begin 10882 Result:=true; 10883 exit; 10884 end; 10885 end; 10886 end; 10887 10888begin 10889 if FileName='' then begin 10890 FileName:='unit1'; 10891 if not PageNameExists(FileName) then begin 10892 Result:=Filename; 10893 exit; 10894 end; 10895 end; 10896 if FilenameHasPascalExt(FileName) then 10897 ShortName:=ExtractFileNameOnly(Filename) 10898 else 10899 ShortName:=ExtractFileName(FileName); 10900 Result:=ShortName; 10901 if PageNameExists(Result) then begin 10902 i:=1; 10903 repeat 10904 inc(i); 10905 Result:=ShortName+'('+IntToStr(i)+')'; 10906 until PageNameExists(Result)=false; 10907 end; 10908end; 10909 10910function TSourceEditorManager.SomethingModified(Verbose: boolean): boolean; 10911var 10912 i: integer; 10913begin 10914 for i:=0 to SourceEditorCount - 1 do 10915 begin 10916 if SourceEditors[i].Modified then 10917 begin 10918 if Verbose then 10919 debugln(['TSourceEditorManager.SomethingModified ',SourceEditors[i].FileName]); 10920 exit(true); 10921 end; 10922 end; 10923 Result:=false; 10924end; 10925 10926procedure TSourceEditorManager.OnIdle(Sender: TObject; var Done: Boolean); 10927var 10928 SrcEdit: TSourceEditor; 10929 i, j: Integer; 10930 aFilename: String; 10931 FreeList, FreeMarklings: boolean; 10932 Marklings: TFPList; 10933 Markling: TSourceMarkling; 10934begin 10935 SrcEdit:=ActiveEditor; 10936 if (SrcEdit<>nil) 10937 and (not SrcEdit.FSharedValues.FMarklingsValid) then 10938 begin 10939 //debugln(['TSourceEditorManager.OnIdle ',MarklingProducerCount]); 10940 aFilename:=SrcEdit.FileName; 10941 SrcEdit.EditorComponent.BeginUpdate(False); 10942 for i:=0 to MarklingProducerCount-1 do 10943 begin 10944 Marklings:=MarklingProducers[i].GetMarklings(aFilename,FreeList,FreeMarklings); 10945 for j:=0 to Marklings.Count-1 do 10946 begin 10947 Markling:=TSourceMarkling(Marklings[j]); 10948 if Markling=nil then ; 10949 // ToDo: add mark to synedit 10950 //debugln(['TSourceEditorManager.OnIdle ',Markling.Id,' ',Markling.Line,',',Markling.Column]); 10951 10952 end; 10953 if FreeMarklings then 10954 for j:=0 to Marklings.Count-1 do 10955 TObject(Marklings[j]).Free; 10956 if FreeList then 10957 Marklings.Free; 10958 end; 10959 SrcEdit.EditorComponent.EndUpdate; 10960 SrcEdit.FSharedValues.FMarklingsValid:=true; 10961 end; 10962end; 10963 10964procedure TSourceEditorManager.OnUserInput(Sender: TObject; Msg: Cardinal); 10965begin 10966 CodeToolsToSrcEditTimer.Enabled:=true; 10967 // Hints 10968 if FHints.HintIsComplex then 10969 begin 10970 // TODO: introduce property, to indicate if hint is interactive 10971 if FHints.PtIsOnHint(Mouse.CursorPos) then begin // ignore any action over Hint 10972 if FHints.CurHintWindow.Active then 10973 exit; 10974 if (Msg = WM_MOUSEMOVE) 10975 or (Msg = LM_MOUSELEAVE) 10976 {$IFDEF WINDOWS} 10977 or (Msg = WM_NCMOUSEMOVE) 10978 or ((Msg >= WM_MOUSEFIRST) and (Msg <= WM_MOUSELAST)) 10979 {$ENDIF} 10980 then 10981 exit; 10982 end; 10983 if (Msg = WM_MOUSEMOVE) {$IFDEF WINDOWS} or (Msg = WM_NCMOUSEMOVE){$ENDIF} then begin 10984 FHints.HideAutoHintAfterMouseMoved; 10985 exit; 10986 end; 10987 end; 10988 10989 //debugln('TSourceEditorManager.OnUserInput'); 10990 // don't hide hint if Sender is a hint window or child control 10991 if not FHints.SenderIsHintControl(Sender) then 10992 FHints.HideAutoHint; 10993end; 10994 10995procedure TSourceEditorManager.LockAllEditorsInSourceChangeCache; 10996// lock all sourceeditors that are to be modified by the CodeToolBoss 10997var 10998 i: integer; 10999begin 11000 for i:=0 to SourceEditorCount - 1 do begin 11001 if CodeToolBoss.SourceChangeCache.BufferIsModified(SourceEditors[i].CodeBuffer) 11002 then 11003 SourceEditors[i].BeginGlobalUpdate; 11004 end; 11005end; 11006 11007procedure TSourceEditorManager.UnlockAllEditorsInSourceChangeCache; 11008// unlock all sourceeditors that were modified by the CodeToolBoss 11009var 11010 i: integer; 11011begin 11012 for i:=0 to SourceEditorCount - 1 do begin 11013 if CodeToolBoss.SourceChangeCache.BufferIsModified(SourceEditors[i].CodeBuffer) 11014 then 11015 SourceEditors[i].EndGlobalUpdate; 11016 end; 11017end; 11018 11019procedure TSourceEditorManager.BeginGlobalUpdate; 11020var 11021 i: integer; 11022begin 11023 for i:=0 to SourceEditorCount - 1 do 11024 SourceEditors[i].BeginGlobalUpdate; 11025end; 11026 11027procedure TSourceEditorManager.EndGlobalUpdate; 11028var 11029 i: integer; 11030begin 11031 for i:=0 to SourceEditorCount - 1 do 11032 SourceEditors[i].EndGlobalUpdate; 11033end; 11034 11035procedure TSourceEditorManager.CloseFile(AEditor: TSourceEditorInterface); 11036var 11037 i, j: Integer; 11038begin 11039 i := SourceWindowCount - 1; 11040 while i >= 0 do begin 11041 j := SourceWindows[i].FindPageWithEditor(TSourceEditor(AEditor)); 11042 if j >= 0 then begin 11043 SourceWindows[i].CloseFile(j); 11044 break; 11045 end; 11046 dec(i); 11047 end; 11048end; 11049 11050procedure TSourceEditorManager.HistoryJump(Sender: TObject; 11051 JumpAction: TJumpHistoryAction); 11052var 11053 NewCaretXY: TPoint; 11054 NewTopLine: integer; 11055 NewEditor: TSourceEditor; 11056begin 11057 if Assigned(OnJumpToHistoryPoint) then begin 11058 NewCaretXY.X:=-1; 11059 NewEditor:=nil; 11060 OnJumpToHistoryPoint(NewCaretXY,NewTopLine,NewEditor,JumpAction); 11061 if NewEditor<>nil then begin 11062 ActiveEditor := NewEditor; 11063 ShowActiveWindowOnTop(True); 11064 with NewEditor.EditorComponent do begin 11065 if not NewEditor.IsLocked then 11066 TopLine:=NewTopLine; 11067 LogicalCaretXY:=NewCaretXY; 11068 end; 11069 end; 11070 end; 11071end; 11072 11073procedure TSourceEditorManager.ActivateHint(const ScreenPos: TPoint; 11074 const BaseURL, TheHint: string; AutoShown: Boolean; AMouseOffset: Boolean); 11075begin 11076 if csDestroying in ComponentState then exit; 11077 11078 FHints.ActivateHint(ScreenPos, BaseURL, TheHint, AutoShown, AMouseOffset); 11079end; 11080 11081procedure TSourceEditorManager.ActivateHint(const ScreenRect: TRect; 11082 const BaseURL, TheHint: string; AutoShown: Boolean; AMouseOffset: Boolean); 11083begin 11084 if csDestroying in ComponentState then exit; 11085 11086 FHints.ActivateHint(ScreenRect, BaseURL, TheHint, AutoShown, AMouseOffset); 11087end; 11088 11089procedure TSourceEditorManager.OnCodeTemplateTokenNotFound(Sender: TObject; 11090 AToken: string; AnEditor: TCustomSynEdit; var Index: integer); 11091begin 11092 if Index=0 then ; 11093 //debugln('TSourceNotebook.OnCodeTemplateTokenNotFound ',AToken,',',AnEditor.ReadOnly,',',DefaultCompletionForm.CurrentCompletionType=ctNone); 11094 if (AnEditor.ReadOnly=false) and 11095 (DefaultCompletionForm.CurrentCompletionType=ctNone) 11096 then begin 11097 DefaultCompletionForm.CurrentCompletionType:=ctTemplateCompletion; 11098 DefaultCompletionForm.Editor:=AnEditor; 11099 DefaultCompletionForm.Execute 11100 (AToken, GetScreenRectForToken(AnEditor, AnEditor.CaretX-length(AToken), 11101 AnEditor.CaretY, AnEditor.CaretX-1)); 11102 end; 11103end; 11104 11105procedure TSourceEditorManager.OnCodeTemplateExecuteCompletion( 11106 ASynAutoComplete: TCustomSynAutoComplete; Index: integer); 11107var 11108 SrcEdit: TSourceEditorInterface; 11109 TemplateName: string; 11110 TemplateValue: string; 11111 TemplateComment: string; 11112 TemplateAttr: TStrings; 11113begin 11114 SrcEdit:=FindSourceEditorWithEditorComponent(ASynAutoComplete.Editor); 11115 if SrcEdit=nil then 11116 SrcEdit := ActiveEditor; 11117 //debugln('TSourceNotebook.OnCodeTemplateExecuteCompletion A ',dbgsName(SrcEdit),' ',dbgsName(ASynAutoComplete.Editor)); 11118 11119 TemplateName:=ASynAutoComplete.Completions[Index]; 11120 TemplateValue:=ASynAutoComplete.CompletionValues[Index]; 11121 TemplateComment:=ASynAutoComplete.CompletionComments[Index]; 11122 TemplateAttr:=ASynAutoComplete.CompletionAttributes[Index]; 11123 ExecuteCodeTemplate(SrcEdit,TemplateName,TemplateValue,TemplateComment, 11124 ASynAutoComplete.EndOfTokenChr,TemplateAttr, 11125 ASynAutoComplete.IndentToTokenStart); 11126end; 11127 11128procedure TSourceEditorManager.CodeToolsToSrcEditTimerTimer(Sender: TObject); 11129var 11130 i: Integer; 11131 SrcEdit: TSourceEditor; 11132begin 11133 CodeToolsToSrcEditTimer.Enabled:=false; 11134 11135 for i:=0 to SourceEditorCount-1 do begin 11136 SrcEdit:=SourceEditors[i]; 11137 if not SrcEdit.EditorComponent.IsVisible then continue; 11138 SrcEdit.UpdateIfDefNodeStates; 11139 end; 11140end; 11141 11142procedure TSourceEditorManager.OnSourceCompletionTimer(Sender: TObject); 11143 11144 function CheckCodeAttribute (XY: TPoint; out CodeAttri: String): Boolean; 11145 var 11146 SrcEdit: TSourceEditor; 11147 begin 11148 Result := False; 11149 11150 SrcEdit := ActiveEditor; 11151 if SrcEdit = nil then exit; 11152 11153 dec(XY.X); 11154 CodeAttri := SrcEdit.GetCodeAttributeName(XY); 11155 Result := CodeAttri <> ''; 11156 end; 11157 11158 function CheckStartIdentCompletion: boolean; 11159 var 11160 Line: String; 11161 LogCaret: TPoint; 11162 SrcEdit: TSourceEditor; 11163 CodeAttribute: String; 11164 begin 11165 Result := false; 11166 SrcEdit := ActiveEditor; 11167 if SrcEdit = nil then exit; 11168 if not (SrcEdit.FEditor.Highlighter is TSynPasSyn) then 11169 exit; // only start completion automatically for pascal sources 11170 11171 Line := SrcEdit.FEditor.LineText; 11172 LogCaret := SrcEdit.FEditor.LogicalCaretXY; 11173 //DebugLn(['CheckStartIdentCompletion Line="',Line,'" LogCaret=',dbgs(LogCaret)]); 11174 11175 // check if last character is a point 11176 if (Line='') or (LogCaret.X<=1) or (LogCaret.X-1>length(Line)) 11177 or ((SrcEdit.FCodeCompletionState.State = ccsDot) and (Line[LogCaret.X-1]<>'.')) 11178 then 11179 exit; 11180 11181 if not CheckCodeAttribute(LogCaret, CodeAttribute) then 11182 Exit; 11183 11184 if (CodeAttribute = SYNS_XML_AttrComment) or 11185 (CodeAttribute = SYNS_XML_AttrString) 11186 then 11187 Exit; 11188 11189 // check if range operator '..' 11190 if (LogCaret.X>2) and (Line[LogCaret.X-2]='.') then 11191 exit; // this is a double point .. 11192 11193 // invoke identifier completion 11194 SrcEdit.StartIdentCompletionBox(false,false); 11195 Result:=true; 11196 end; 11197 11198 function CheckTemplateCompletion: boolean; 11199 begin 11200 Result:=false; 11201 // execute context sensitive templates 11202 //FCodeTemplateModul.ExecuteCompletion(Value,GetActiveSE.EditorComponent); 11203 end; 11204 11205var 11206 TempEditor: TSourceEditor; 11207begin 11208 AutoStartCompletionBoxTimer.Enabled:=false; 11209 AutoStartCompletionBoxTimer.AutoEnabled:=false; 11210 TempEditor := ActiveEditor; 11211 if (TempEditor <> nil) and TempEditor.EditorComponent.Focused and 11212 (ComparePoints(TempEditor.EditorComponent.LogicalCaretXY, SourceCompletionCaretXY) = 0) 11213 then begin 11214 if CheckStartIdentCompletion then begin 11215 end 11216 else if CheckTemplateCompletion then begin 11217 end; 11218 end; 11219end; 11220 11221procedure TSourceEditorManager.OnSourceMarksAction(AMark: TSourceMark; 11222 AAction: TMarksAction); 11223var 11224 Editor: TSourceEditor; 11225begin 11226 Editor := TSourceEditor(AMark.SourceEditor); 11227 if Editor = nil then 11228 Exit; 11229 11230 if ( AMark.IsBreakPoint and (Editor.FSharedValues.ExecutionMark <> nil) and 11231 (AMark.Line = Editor.ExecutionLine) 11232 ) or (AMark = Editor.FSharedValues.ExecutionMark) 11233 then 11234 Editor.UpdateExecutionSourceMark; 11235end; 11236 11237procedure TSourceEditorManager.OnSourceMarksGetSynEdit(Sender: TObject; 11238 aFilename: string; var aSynEdit: TSynEdit); 11239var 11240 SrcEdit: TSourceEditor; 11241begin 11242 SrcEdit:=SourceEditorIntfWithFilename(aFilename); 11243 if SrcEdit=nil then exit; 11244 aSynEdit:=SrcEdit.EditorComponent; 11245end; 11246 11247function TSourceEditorManager.GotoDialog: TfrmGoto; 11248begin 11249 if FGotoDialog=nil then 11250 FGotoDialog := TfrmGoto.Create(self); 11251 Result := FGotoDialog; 11252end; 11253 11254procedure TSourceEditorManager.DoConfigureEditorToolbar(Sender: TObject); 11255begin 11256 LazarusIDE.DoOpenIDEOptions(TEditorToolbarOptionsFrame, '', [], []); 11257end; 11258 11259constructor TSourceEditorManager.Create(AOwner: TComponent); 11260begin 11261 inherited Create(AOwner); 11262 11263 FDefaultCompletionForm := nil; 11264 11265 // word completion 11266 if aWordCompletion=nil then begin 11267 AWordCompletion:=TSourceEditorWordCompletion.Create; 11268 AWordCompletion.WordBufferCapacity:=100; 11269 end; 11270 11271 // timer for auto start identifier completion 11272 AutoStartCompletionBoxTimer := TIdleTimer.Create(Self); 11273 with AutoStartCompletionBoxTimer do begin 11274 Name:='AutoStartCompletionBoxTimer'; 11275 AutoEnabled := False; 11276 Enabled := false; 11277 Interval := EditorOpts.AutoDelayInMSec; 11278 OnTimer := @OnSourceCompletionTimer; 11279 end; 11280 11281 // timer for syncing codetools changes to synedit 11282 // started on idle 11283 // ended on user input 11284 // when triggered updates ifdef node states 11285 CodeToolsToSrcEditTimer:=TTimer.Create(Self); 11286 with CodeToolsToSrcEditTimer do begin 11287 Name:='CodeToolsToSrcEditTimer'; 11288 Interval:=1000; // one second without user input 11289 Enabled:=false; 11290 OnTimer:=@CodeToolsToSrcEditTimerTimer; 11291 end; 11292 11293 // marks 11294 SourceEditorMarks:=TSourceMarks.Create(Self); 11295 SourceEditorMarks.OnAction:=@OnSourceMarksAction; 11296 SourceEditorMarks.ExtToolsMarks.OnGetSynEditOfFile:=@OnSourceMarksGetSynEdit; 11297 11298 // HintWindow 11299 FHints := TSourceEditorHintWindowManager.Create(Self); 11300 FHints.WindowName := Self.Name+'_HintWindow'; 11301 FHints.HideInterval := 4000; 11302 11303 // code templates 11304 FCodeTemplateModul:=TSynEditAutoComplete.Create(Self); 11305 11306 EditorOpts.LoadCodeTemplates(FCodeTemplateModul); 11307 with FCodeTemplateModul do begin 11308 IndentToTokenStart := EditorOpts.CodeTemplateIndentToTokenStart; 11309 OnTokenNotFound := @OnCodeTemplateTokenNotFound; 11310 OnExecuteCompletion := @OnCodeTemplateExecuteCompletion; 11311 EndOfTokenChr:=' ()[]{},.;:"+-*^@$\<>='''; 11312 end; 11313 11314 // EditorToolBar 11315 CreateEditorToolBar(@DoConfigureEditorToolbar); 11316 11317 // layout 11318 IDEWindowCreators.Add(NonModalIDEWindowNames[nmiwSourceNoteBook], 11319 nil,@CreateSourceWindow,'250','100','+70%','+70%', 11320 NonModalIDEWindowNames[nmiwMainIDE],alBottom,true,@GetDefaultLayout); 11321 11322 Application.AddOnIdleHandler(@OnIdle); 11323 Application.AddOnUserInputHandler(@OnUserInput); 11324end; 11325 11326destructor TSourceEditorManager.Destroy; 11327begin 11328 FreeAndNil(FHints); 11329 SourceEditorMarks.OnAction := nil; 11330 Application.RemoveAllHandlersOfObject(Self); 11331 // aWordCompletion is released in InternalFinal 11332 aWordCompletion.OnGetSource := nil; 11333 11334 inherited Destroy; 11335end; 11336 11337function SortSourceWindows(SrcWin1, SrcWin2: TSourceNotebook): Integer; 11338begin 11339 Result := AnsiStrComp(PChar(SrcWin1.Caption), PChar(SrcWin2.Caption)); 11340end; 11341 11342function TSourceEditorManager.CreateNewWindow(Activate: Boolean; DoDisableAutoSizing: boolean; 11343 AnID: Integer): TSourceNotebook; 11344var 11345 i: Integer; 11346begin 11347 Result := TSourceNotebook(TSourceNotebook.NewInstance); 11348 {$IFDEF DebugDisableAutoSizing} 11349 if DoDisableAutoSizing then 11350 Result.DisableAutoSizing('TAnchorDockMaster Delayed') 11351 else 11352 Result.DisableAutoSizing('TSourceEditorManager.CreateNewWindow'); 11353 {$ELSE} 11354 Result.DisableAutoSizing; 11355 {$ENDIF}; 11356 if AnID > 0 then 11357 Result.Create(Self, AnID) 11358 else 11359 Result.Create(Self); 11360 11361 for i := 1 to FUpdateLock do 11362 Result.IncUpdateLockInternal; 11363 FSourceWindowList.Add(Result); 11364 FSourceWindowList.Sort(TListSortCompare(@SortSourceWindows)); 11365 FSourceWindowByFocusList.Add(Result); 11366 PasBeautifier.OnGetDesiredIndent := 11367 @TSourceNotebook(FSourceWindowList[0]).EditorGetIndent; 11368 if Activate then begin 11369 ActiveSourceWindow := Result; 11370 ShowActiveWindowOnTop(False); 11371 end; 11372 FChangeNotifyLists[semWindowCreate].CallNotifyEvents(Result); 11373 if not DoDisableAutoSizing then 11374 Result.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TSourceEditorManager.CreateNewWindow'){$ENDIF}; 11375end; 11376 11377function TSourceEditorManager.SenderToEditor(Sender: TObject): TSourceEditor; 11378begin 11379 if Sender is TSourceEditor then 11380 Result:=TSourceEditor(Sender) 11381 else if Sender is TSourceNotebook then 11382 Result:=TSourceNotebook(Sender).ActiveEditor as TSourceEditor 11383 else 11384 Result:=ActiveEditor; 11385end; 11386 11387procedure TSourceEditorManager.RemoveWindow(AWindow: TSourceNotebook); 11388var 11389 i: Integer; 11390begin 11391 if FSourceWindowList = nil then exit; 11392 i := FSourceWindowList.IndexOf(AWindow); 11393 FSourceWindowList.Remove(AWindow); 11394 FSourceWindowByFocusList.Remove(AWindow); 11395 if SourceWindowCount = 0 then 11396 ActiveSourceWindow := nil 11397 else if ActiveSourceWindow = AWindow then 11398 ActiveSourceWindow := SourceWindows[Max(0, Min(i, SourceWindowCount-1))]; 11399 if FSourceWindowList.Count > 0 then 11400 PasBeautifier.OnGetDesiredIndent := 11401 @TSourceNotebook(FSourceWindowList[0]).EditorGetIndent 11402 else 11403 PasBeautifier.OnGetDesiredIndent := nil; 11404 if i >= 0 then 11405 FChangeNotifyLists[semWindowDestroy].CallNotifyEvents(AWindow); 11406end; 11407 11408(* Context Menu handlers *) 11409 11410procedure TSourceEditorManager.CloseOtherPagesClicked(Sender: TObject); 11411begin 11412 if Assigned(OnCloseClicked) then 11413 OnCloseClicked(Sender, [ceoCloseOthers]); 11414end; 11415 11416procedure TSourceEditorManager.CloseOtherPagesClickedAsync(Sender: PtrInt); 11417begin 11418 CloseOtherPagesClicked(TObject(Sender)); 11419end; 11420 11421procedure TSourceEditorManager.CloseRightPagesClicked(Sender: TObject); 11422begin 11423 if Assigned(OnCloseClicked) then 11424 OnCloseClicked(Sender, [ceoCloseOthersOnRightSide]); 11425end; 11426 11427procedure TSourceEditorManager.CloseRightPagesClickedAsync(Sender: PtrInt); 11428begin 11429 CloseRightPagesClicked(TObject(Sender)); 11430end; 11431 11432procedure TSourceEditorManager.ReadOnlyClicked(Sender: TObject); 11433var ActEdit: TSourceEditor; 11434begin 11435 ActEdit:=ActiveEditor; 11436 if ActEdit = nil then exit; 11437 11438 if ActEdit.ReadOnly and (ActEdit.CodeBuffer<>nil) 11439 and (not ActEdit.CodeBuffer.IsVirtual) 11440 and (not FileIsWritable(ActEdit.CodeBuffer.Filename)) then begin 11441 IDEMessageDialog(ueFileROCap, 11442 ueFileROText1+ActEdit.CodeBuffer.Filename+ueFileROText2, 11443 mtError,[mbCancel]); 11444 exit; 11445 end; 11446 ActEdit.EditorComponent.ReadOnly := not(ActEdit.EditorComponent.ReadOnly); 11447 if Assigned(OnReadOnlyChanged) then 11448 OnReadOnlyChanged(Self); 11449 ActEdit.SourceNotebook.UpdateStatusBar; 11450end; 11451 11452procedure TSourceEditorManager.ToggleLineNumbersClicked(Sender: TObject); 11453var 11454 MenuITem: TIDESpecialCommand; 11455 ActEdit:TSourceEditor; 11456 i: integer; 11457 ShowLineNumbers: boolean; 11458begin 11459 MenuItem := Sender as TIDESpecialCommand; 11460 ActEdit:=ActiveEditor; 11461 if ActEdit = nil then exit; 11462 11463 MenuItem.Checked := not EditorOpts.ShowLineNumbers; 11464 ShowLineNumbers:=MenuItem.Checked; 11465 11466 for i:=0 to SourceEditorCount-1 do 11467 SourceEditors[i].EditorComponent.Gutter.LineNumberPart.Visible := ShowLineNumbers; 11468 EditorOpts.ShowLineNumbers := ShowLineNumbers; 11469 EditorOpts.Save; 11470end; 11471 11472procedure TSourceEditorManager.ToggleI18NForLFMClicked(Sender: TObject); 11473begin 11474 // 11475end; 11476 11477procedure TSourceEditorManager.ShowUnitInfo(Sender: TObject); 11478begin 11479 if Assigned(OnShowUnitInfo) then 11480 OnShowUnitInfo(Sender); 11481end; 11482 11483procedure TSourceEditorManager.CopyFilenameClicked(Sender: TObject); 11484var ActSE: TSourceEditor; 11485begin 11486 ActSE := GetActiveSE; 11487 if ActSE <> nil then 11488 Clipboard.AsText:=ActSE.FileName; 11489end; 11490 11491procedure TSourceEditorManager.EditorPropertiesClicked(Sender: TObject); 11492begin 11493 LazarusIDE.DoOpenIDEOptions(TEditorGeneralOptionsFrame); 11494end; 11495 11496initialization 11497 InternalInit; 11498 11499finalization 11500 InternalFinal; 11501 11502end. 11503 11504