1 (*
2 This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6 Copyright (c) Alexey Torgashin
7 *)
8 unit FormFrame;
9
10 {$mode objfpc}{$H+}
11
12 interface
13
14 uses
15 Classes, SysUtils, Graphics, Forms, Controls, Dialogs,
16 ExtCtrls, Menus, StdCtrls, StrUtils, ComCtrls, Clipbrd,
17 LCLIntf, LCLProc, LCLType, LazUTF8, LazFileUtils, FileUtil,
18 IniFiles,
19 ATTabs,
20 ATGroups,
21 ATScrollBar,
22 ATSynEdit,
23 ATSynEdit_Finder,
24 ATSynEdit_Keymap_Init,
25 ATSynEdit_Adapters,
26 ATSynEdit_Adapter_EControl,
27 ATSynEdit_Adapter_LiteLexer,
28 ATSynEdit_Carets,
29 ATSynEdit_Gaps,
30 ATSynEdit_Markers,
31 ATSynEdit_LineParts,
32 ATSynEdit_Commands,
33 ATSynEdit_Bookmarks,
34 ATSynEdit_CanvasProc,
35 ATStrings,
36 ATStringProc,
37 ATStringProc_Separator,
38 ATStringProc_HtmlColor,
39 ATCanvasPrimitives,
40 ATButtons,
41 ATBinHex,
42 ATStreamSearch,
43 ATImageBox,
44 BGRABitmap,
45 BGRABitmapTypes,
46 proc_appvariant,
47 proc_globdata,
48 proc_editor,
49 proc_editor_saving,
50 proc_cmd,
51 proc_colors,
52 proc_files,
53 proc_msg,
54 proc_str,
55 proc_py,
56 proc_py_const,
57 proc_miscutils,
58 proc_lexer_styles,
59 proc_customdialog,
60 proc_customdialog_dummy,
61 ec_SyntAnal,
62 ec_proc_lexer,
63 ec_lexerlist,
64 formlexerstylemap,
65 at__jsonconf,
66 math;
67
68 type
Ednull69 TEditorFramePyEvent = function(AEd: TATSynEdit; AEvent: TAppPyEvent;
70 const AParams: TAppVariantArray): TAppPyEventResult of object;
71 TEditorFrameStringEvent = procedure(Sender: TObject; const S: string) of object;
72
73 type
74 TAppOpenMode = (
75 cOpenModeNone,
76 cOpenModeEditor,
77 cOpenModeViewText,
78 cOpenModeViewBinary,
79 cOpenModeViewHex,
80 cOpenModeViewUnicode,
81 cOpenModeViewUHex
82 );
83
84 TATEditorFrameKind = (
85 efkEditor,
86 efkBinaryViewer,
87 efkImageViewer
88 );
89
90 const
91 cATEditorFrameKindStr: array[TATEditorFrameKind] of string = (
92 'text',
93 'bin',
94 'pic'
95 );
96
97 type
98 TFrameGetSaveDialog = procedure(var ASaveDlg: TSaveDialog) of object;
99
100 type
101 { TEditorFrame }
102
103 TEditorFrame = class(TFrame)
104 MenuItem1: TMenuItem;
105 MenuItem2: TMenuItem;
106 TimerChange: TTimer;
107 procedure btnReloadNoneClick(Sender: TObject);
108 procedure btnReloadNoClick(Sender: TObject);
109 procedure btnReloadYesClick(Sender: TObject);
110 procedure TimerChangeTimer(Sender: TObject);
111 private
112 { private declarations }
113 FFormDummy: TFormDummy;
114 Adapter1: TATAdapterEControl;
115 Adapter2: TATAdapterEControl;
116 PanelInfo: TPanel;
117 PanelReload: array[0..1] of TPanel;
118 LabelReload: array[0..1] of TLabel;
119 btnReloadYes: array[0..1] of TATButton;
120 btnReloadNo: array[0..1] of TATButton;
121 btnReloadNone: array[0..1] of TATButton;
122 FTabCaption: string;
123 FTabCaptionAddon: string;
124 FTabCaptionUntitled: string;
125 FTabCaptionFromApi: boolean;
126 FTabImageIndex: integer;
127 FTabId: integer;
128 FFileName: string;
129 FFileName2: string;
130 FFileWasBig: array[0..1] of boolean;
131 FTextCharsTyped: integer;
132 FActivationTime: Int64;
133 FCodetreeFilter: string;
134 FCodetreeFilterHistory: TStringList;
135 FEnabledCodeTree: array[0..1] of boolean;
136 FNotifEnabled: boolean;
137 FOnCallAutoCompletion: TEditorBooleanEvent;
138 FOnChangeCaption: TNotifyEvent;
139 FOnChangeSlow: TNotifyEvent;
140 FOnProgress: TATFinderProgress;
141 FOnUpdateStatusbar: TNotifyEvent;
142 FOnUpdateState: TNotifyEvent;
143 FOnUpdateZoom: TNotifyEvent;
144 FOnFocusEditor: TNotifyEvent;
145 FOnEditorCommand: TATSynEditCommandEvent;
146 FOnEditorChangeCaretPos: TNotifyEvent;
147 FOnEditorScroll: TNotifyEvent;
148 FOnSaveFile: TNotifyEvent;
149 FOnAddRecent: TNotifyEvent;
150 FOnPyEvent: TEditorFramePyEvent;
151 FOnInitAdapter: TNotifyEvent;
152 FOnLexerChange: TATEditorEvent;
153 FSplitPos: double;
154 FSplitHorz: boolean;
155 FActiveSecondaryEd: boolean;
156 FLocked: boolean;
157 FTabColor: TColor;
158 FTabPinned: boolean;
159 FTabSizeChanged: boolean;
160 FTabKeyCollectMarkers: boolean;
161 FInSession: boolean;
162 FInHistory: boolean;
163 FMacroRecord: boolean;
164 FImageBox: TATImageBox;
165 FBin: TATBinHex;
166 FBinStream: TFileStream;
167 FCheckFilenameOpened: TStrFunction;
FOnMsgStatusnull168 FOnMsgStatus: TStrEvent;
169 FSaveDialog: TSaveDialog;
170 FWasVisible: boolean;
171 FInitialLexer1: TecSyntAnalyzer;
172 FInitialLexer2: TecSyntAnalyzer;
173 FSaveHistory: boolean;
174 FEditorsLinked: boolean;
175 FCachedTreeview: array[0..1] of TTreeView;
176 FLexerChooseFunc: TecLexerChooseFunc;
177 FBracketHilite: boolean;
178 FBracketHiliteUserChanged: boolean;
179 FBracketSymbols: string;
180 FBracketMaxDistance: integer;
181 FMicromapBmp: TBGRABitmap;
182 FOnGetSaveDialog: TFrameGetSaveDialog;
183 FOnAppClickLink: TATSynEditClickLinkEvent;
184
185 procedure ApplyThemeToInfoPanel(APanel: TPanel);
186 procedure BinaryOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
187 procedure BinaryOnScroll(Sender: TObject);
188 procedure BinaryOnProgress(const ACurrentPos, AMaximalPos: Int64;
189 var AContinueSearching: Boolean);
190 procedure CancelAutocompleteAutoshow(Ed: TATSynEdit);
191 procedure DoDeactivatePictureMode;
192 procedure DoDeactivateViewerMode;
193 procedure DoFileOpen_Ex(Ed: TATSynEdit; const AFileName: string;
194 AAllowLoadHistory, AAllowLoadHistoryEnc, AAllowLoadBookmarks,
195 AAllowLexerDetect, AAllowErrorMsgBox,
196 AKeepScroll, AAllowLoadUndo: boolean; AOpenMode: TAppOpenMode);
197 procedure DoImageboxScroll(Sender: TObject);
198 procedure DoOnChangeCaption;
199 procedure DoOnUpdateState;
200 procedure DoOnUpdateZoom;
201 procedure DoOnUpdateStatusbar;
202 procedure EditorClickEndSelect(Sender: TObject; APrevPnt, ANewPnt: TPoint);
203 procedure EditorClickMoveCaret(Sender: TObject; APrevPnt, ANewPnt: TPoint);
204 procedure EditorDrawMicromap(Sender: TObject; ACanvas: TCanvas; const ARect: TRect);
205 procedure EditorDrawScrollbarVert(Sender: TObject;
206 AType: TATScrollbarElemType; ACanvas: TCanvas; const ARect,
207 ARect2: TRect; var ACanDraw: boolean);
EditorObjToTreeviewIndexnull208 function EditorObjToTreeviewIndex(Ed: TATSynEdit): integer; inline;
209 procedure EditorOnChange(Sender: TObject);
210 procedure EditorOnChangeModified(Sender: TObject);
211 procedure EditorOnChangeCaretPos(Sender: TObject);
212 procedure EditorOnChangeState(Sender: TObject);
213 procedure EditorOnChangeBookmarks(Sender: TObject);
214 procedure EditorOnChangeZoom(Sender: TObject);
215 procedure EditorOnClick(Sender: TObject);
216 procedure EditorOnClickGap(Sender: TObject; AGapItem: TATGapItem; APos: TPoint);
217 procedure EditorOnClickGutter(Sender: TObject; ABand, ALine: integer);
218 procedure EditorOnClickDouble(Sender: TObject; var AHandled: boolean);
219 procedure EditorOnClickLink(Sender: TObject; const ALink: string);
220 procedure EditorOnClickMicroMap(Sender: TObject; AX, AY: integer);
221 procedure EditorOnCommand(Sender: TObject; ACmd: integer; AInvoke: TATEditorCommandInvoke; const AText: string; var AHandled: boolean);
222 procedure EditorOnCommandAfter(Sender: TObject; ACommand: integer; const AText: string);
223 procedure EditorOnDrawBookmarkIcon(Sender: TObject; C: TCanvas; ALineNum: integer; const ARect: TRect);
224 procedure EditorOnEnter(Sender: TObject);
225 procedure EditorOnDrawLine(Sender: TObject; C: TCanvas; ALineIndex, AX, AY: integer;
226 const AStr: atString; ACharSize: TATEditorCharSize; constref AExtent: TATIntFixedArray);
227 procedure EditorOnCalcBookmarkColor(Sender: TObject; ABookmarkKind: integer; var AColor: TColor);
228 procedure EditorOnHotspotEnter(Sender: TObject; AHotspotIndex: integer);
229 procedure EditorOnHotspotExit(Sender: TObject; AHotspotIndex: integer);
230 procedure EditorOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
231 procedure EditorOnPaste(Sender: TObject; var AHandled: boolean; AKeepCaret, ASelectThen: boolean);
232 procedure EditorOnScroll(Sender: TObject);
GetAdapternull233 function GetAdapter(Ed: TATSynEdit): TATAdapterEControl;
GetCachedTreeviewInitednull234 function GetCachedTreeviewInited(Ed: TATSynEdit): boolean;
GetCachedTreeviewnull235 function GetCachedTreeview(Ed: TATSynEdit): TTreeView;
GetCommentStringnull236 function GetCommentString(Ed: TATSynEdit): string;
GetEnabledCodeTreenull237 function GetEnabledCodeTree(Ed: TATSynEdit): boolean;
GetEnabledFoldingnull238 function GetEnabledFolding: boolean;
GetFileWasBignull239 function GetFileWasBig(Ed: TATSynEdit): boolean;
GetInitialLexernull240 function GetInitialLexer(Ed: TATSynEdit): TecSyntAnalyzer;
GetLineEndsnull241 function GetLineEnds(Ed: TATSynEdit): TATLineEnds;
GetPictureScalenull242 function GetPictureScale: integer;
GetReadOnlynull243 function GetReadOnly(Ed: TATSynEdit): boolean;
GetSaveDialognull244 function GetSaveDialog: TSaveDialog;
GetSplitPosCurrentnull245 function GetSplitPosCurrent: double;
GetSplittednull246 function GetSplitted: boolean;
GetTabKeyCollectMarkersnull247 function GetTabKeyCollectMarkers: boolean;
GetTabVisiblenull248 function GetTabVisible: boolean;
GetUnprintedEndsnull249 function GetUnprintedEnds: boolean;
GetUnprintedEndsDetailsnull250 function GetUnprintedEndsDetails: boolean;
GetUnprintedShownull251 function GetUnprintedShow: boolean;
GetUnprintedSpacesnull252 function GetUnprintedSpaces: boolean;
253 procedure InitEditor(var ed: TATSynEdit; const AName: string);
254 procedure InitPanelReload(Index: integer);
255 procedure InitPanelInfo(const AText: string; AOnClick: TNotifyEvent);
256 procedure PaintMicromap(Ed: TATSynEdit; ACanvas: TCanvas; const ARect: TRect);
257 procedure PanelInfoClick(Sender: TObject);
258 procedure SetBracketHilite(AValue: boolean);
259 procedure SetEnabledCodeTree(Ed: TATSynEdit; AValue: boolean);
260 procedure SetEnabledFolding(AValue: boolean);
261 procedure SetFileName(const AValue: string);
262 procedure SetFileName2(AValue: string);
263 procedure SetFileWasBig(Ed: TATSynEdit; AValue: boolean);
264 procedure SetInitialLexer(Ed: TATSynEdit; AValue: TecSyntAnalyzer);
265 procedure SetLocked(AValue: boolean);
266 procedure SetPictureScale(AValue: integer);
267 procedure SetReadOnly(Ed: TATSynEdit; AValue: boolean);
268 procedure SetTabCaptionAddon(const AValue: string);
269 procedure SetTabColor(AColor: TColor);
270 procedure SetTabPinned(AValue: boolean);
271 procedure SetTabImageIndex(AValue: integer);
272 procedure SetTabVisible(AValue: boolean);
273 procedure SetUnprintedEnds(AValue: boolean);
274 procedure SetUnprintedEndsDetails(AValue: boolean);
275 procedure SetUnprintedShow(AValue: boolean);
276 procedure SetSplitHorz(AValue: boolean);
277 procedure SetSplitPos(AValue: double);
278 procedure SetSplitted(AValue: boolean);
279 procedure SetTabCaption(const AValue: string);
280 procedure SetLineEnds(Ed: TATSynEdit; AValue: TATLineEnds);
281 procedure SetUnprintedSpaces(AValue: boolean);
282 procedure SetEditorsLinked(AValue: boolean);
283 procedure SplitterMoved(Sender: TObject);
284 procedure TreeOnDeletion(Sender: TObject; Node: TTreeNode);
285 procedure UpdateEds(AUpdateWrapInfo: boolean=false);
286 procedure UpdateCaptionFromFilename;
GetLexernull287 function GetLexer(Ed: TATSynEdit): TecSyntAnalyzer;
GetLexerLitenull288 function GetLexerLite(Ed: TATSynEdit): TATLiteLexer;
GetLexerNamenull289 function GetLexerName(Ed: TATSynEdit): string;
290 procedure SetLexer(Ed: TATSynEdit; an: TecSyntAnalyzer);
291 procedure SetLexerLite(Ed: TATSynEdit; an: TATLiteLexer);
292 procedure SetLexerName(Ed: TATSynEdit; const AValue: string);
293 procedure UpdateTabTooltip;
GetIsPreviewnull294 function GetIsPreview: boolean;
295 procedure SetIsPreview(AValue: boolean);
296
297 procedure DoSaveUndo(Ed: TATSynEdit; const AFileName: string);
298 procedure DoLoadUndo(Ed: TATSynEdit);
299 procedure DoSaveHistory_Caret(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
300 procedure DoSaveHistory_Bookmarks(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
301
302 protected
303 procedure DoOnResize; override;
304 public
305 { public declarations }
306 Ed1: TATSynEdit;
307 Ed2: TATSynEdit;
308 Splitter: TSplitter;
309 Groups: TATGroups;
310 FileProps: TAppFileProps;
311 FileProps2: TAppFileProps;
312 MacroStrings: TStringList;
313
314 constructor Create(AOwner: TComponent; AApplyCentering: boolean); reintroduce;
315 destructor Destroy; override;
Editornull316 function Editor: TATSynEdit;
EditorBronull317 function EditorBro: TATSynEdit;
Modifiednull318 function Modified: boolean;
319 property Adapter[Ed: TATSynEdit]: TATAdapterEControl read GetAdapter;
320 procedure EditorOnKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
321 procedure DoShow;
322
EditorIndexToObjnull323 function EditorIndexToObj(N: integer): TATSynEdit;
EditorObjToIndexnull324 function EditorObjToIndex(Ed: TATSynEdit): integer;
325 property ReadOnly[Ed: TATSynEdit]: boolean read GetReadOnly write SetReadOnly;
326 property TabCaption: string read FTabCaption write SetTabCaption;
327 property TabCaptionAddon: string read FTabCaptionAddon write SetTabCaptionAddon;
328 property TabCaptionUntitled: string read FTabCaptionUntitled write FTabCaptionUntitled;
329 property TabImageIndex: integer read FTabImageIndex write SetTabImageIndex;
330 property TabCaptionFromApi: boolean read FTabCaptionFromApi write FTabCaptionFromApi;
331 property TabId: integer read FTabId;
332 property TabIsPreview: boolean read GetIsPreview write SetIsPreview;
333 property TabVisible: boolean read GetTabVisible write SetTabVisible;
334
335 property CachedTreeViewInited[Ed: TATSynEdit]: boolean read GetCachedTreeviewInited;
336 property CachedTreeView[Ed: TATSynEdit]: TTreeView read GetCachedTreeview;
337 property SaveHistory: boolean read FSaveHistory write FSaveHistory;
338 procedure UpdateModified(Ed: TATSynEdit; AWithEvent: boolean= true);
339 procedure UpdatePinned(Ed: TATSynEdit; AWithEvent: boolean);
340 procedure UpdateReadOnlyFromFile(Ed: TATSynEdit);
341 procedure UpdateFrame(AUpdatedText: boolean);
342 procedure FixLexerIfDeleted(Ed: TATSynEdit; const ALexerName: string);
343
344 property NotifEnabled: boolean read FNotifEnabled write FNotifEnabled;
345 procedure NotifyAboutChange(Ed: TATSynEdit);
346
347 property FileName: string read FFileName write SetFileName;
348 property FileName2: string read FFileName2;
349 property LexerChooseFunc: TecLexerChooseFunc read FLexerChooseFunc write FLexerChooseFunc;
GetFileNamenull350 function GetFileName(Ed: TATSynEdit): string;
351 procedure SetFileName(Ed: TATSynEdit; const AFileName: string);
352 property FileWasBig[Ed: TATSynEdit]: boolean read GetFileWasBig write SetFileWasBig;
353
354 property Lexer[Ed: TATSynEdit]: TecSyntAnalyzer read GetLexer write SetLexer;
355 property LexerLite[Ed: TATSynEdit]: TATLiteLexer read GetLexerLite write SetLexerLite;
356 property LexerName[Ed: TATSynEdit]: string read GetLexerName write SetLexerName;
357 property LexerInitial[Ed: TATSynEdit]: TecSyntAnalyzer read GetInitialLexer write SetInitialLexer;
358
359 property Locked: boolean read FLocked write SetLocked;
360 property CommentString[Ed: TATSynEdit]: string read GetCommentString;
361 property TabColor: TColor read FTabColor write SetTabColor;
362 property TabPinned: boolean read FTabPinned write SetTabPinned;
363 property TabSizeChanged: boolean read FTabSizeChanged write FTabSizeChanged;
364 property TabKeyCollectMarkers: boolean read GetTabKeyCollectMarkers write FTabKeyCollectMarkers;
365 property InSession: boolean read FInSession write FInSession;
366 property InHistory: boolean read FInHistory write FInHistory;
367 property TextCharsTyped: integer read FTextCharsTyped write FTextCharsTyped;
368 property EnabledCodeTree[Ed: TATSynEdit]: boolean read GetEnabledCodeTree write SetEnabledCodeTree;
369 property CodetreeFilter: string read FCodetreeFilter write FCodetreeFilter;
370 property CodetreeFilterHistory: TStringList read FCodetreeFilterHistory;
371 property ActivationTime: Int64 read FActivationTime write FActivationTime;
IsEmptynull372 function IsEmpty: boolean;
373 procedure ApplyTheme;
IsEditorFocusednull374 function IsEditorFocused: boolean;
FrameKindnull375 function FrameKind: TATEditorFrameKind;
376 procedure SetFocus; reintroduce;
PictureSizesnull377 function PictureSizes: TPoint;
378 property PictureScale: integer read GetPictureScale write SetPictureScale;
379 property Binary: TATBinHex read FBin;
BinaryFindFirstnull380 function BinaryFindFirst(AFinder: TATEditorFinder; AShowAll: boolean): boolean;
BinaryFindNextnull381 function BinaryFindNext(ABack: boolean): boolean;
382 //
383 property BracketHilite: boolean read FBracketHilite write SetBracketHilite;
384 property BracketHiliteUserChanged: boolean read FBracketHiliteUserChanged write FBracketHiliteUserChanged;
385 property BracketSymbols: string read FBracketSymbols write FBracketSymbols;
386 property BracketDistance: integer read FBracketMaxDistance write FBracketMaxDistance;
387 procedure BracketJump(Ed: TATSynEdit);
388 procedure BracketSelect(Ed: TATSynEdit);
389 procedure BracketSelectInside(Ed: TATSynEdit);
390 //
391 property LineEnds[Ed: TATSynEdit]: TATLineEnds read GetLineEnds write SetLineEnds;
392 property UnprintedShow: boolean read GetUnprintedShow write SetUnprintedShow;
393 property UnprintedSpaces: boolean read GetUnprintedSpaces write SetUnprintedSpaces;
394 property UnprintedEnds: boolean read GetUnprintedEnds write SetUnprintedEnds;
395 property UnprintedEndsDetails: boolean read GetUnprintedEndsDetails write SetUnprintedEndsDetails;
396 property Splitted: boolean read GetSplitted write SetSplitted;
397 property SplitHorz: boolean read FSplitHorz write SetSplitHorz;
398 property SplitPos: double read FSplitPos write SetSplitPos;
399 property EditorsLinked: boolean read FEditorsLinked write SetEditorsLinked;
400 property EnabledFolding: boolean read GetEnabledFolding write SetEnabledFolding;
401 property SaveDialog: TSaveDialog read GetSaveDialog;
402 property WasVisible: boolean read FWasVisible;
GetTabPagesnull403 function GetTabPages: TATPages;
GetTabGroupsnull404 function GetTabGroups: TATGroups;
IsTreeBusynull405 function IsTreeBusy: boolean;
IsParsingBusynull406 function IsParsingBusy: boolean;
407 //file
408 procedure DoFileClose;
409 procedure DoFileOpen(const AFileName, AFileName2: string;
410 AAllowLoadHistory, AAllowLoadBookmarks, AAllowLexerDetect,
411 AAllowErrorMsgBox, AAllowLoadUndo: boolean; AOpenMode: TAppOpenMode);
412 procedure DoFileOpen_AsBinary(const AFileName: string; AMode: TATBinHexMode);
413 procedure DoFileOpen_AsPicture(const AFileName: string);
DoFileSavenull414 function DoFileSave(ASaveAs, AAllEditors: boolean): boolean;
DoFileSave_Exnull415 function DoFileSave_Ex(Ed: TATSynEdit; ASaveAs: boolean): boolean;
416 procedure DoFileReload_DisableDetectEncoding(Ed: TATSynEdit);
DoFileReloadnull417 function DoFileReload(Ed: TATSynEdit): boolean;
418 procedure DoLexerFromFilename(Ed: TATSynEdit; const AFileName: string);
419 //history
420 procedure DoSaveHistory(Ed: TATSynEdit);
421 procedure DoSaveHistoryEx(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString; AForSession: boolean);
422 procedure DoLoadHistory(Ed: TATSynEdit; AllowLoadEncoding, AllowLoadHistory,
423 AllowLoadBookmarks: boolean);
424 procedure DoLoadHistoryEx(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString; AllowEnc: boolean);
425 procedure DoLoadHistory_Bookmarks(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
426 //misc
DoPyEventnull427 function DoPyEvent(AEd: TATSynEdit; AEvent: TAppPyEvent; const AParams: TAppVariantArray): TAppPyEventResult;
428 procedure DoPyEventState(Ed: TATSynEdit; AState: integer);
DoPyEvent_Macronull429 function DoPyEvent_Macro(const AText: string): boolean;
430 procedure DoGotoPos(Ed: TATSynEdit; APosX, APosY: integer);
431 procedure DoRemovePreviewStyle;
432 procedure DoToggleFocusSplitEditors;
433 procedure DoFocusNotificationPanel;
434 procedure DoHideNotificationPanels;
435 procedure DoHideNotificationPanel(Index: integer);
436 //macro
437 procedure DoMacroStartOrStop;
438 procedure DoMacroStop(ACancel: boolean);
439 property MacroRecord: boolean read FMacroRecord;
440
441 //events
442 property OnGetSaveDialog: TFrameGetSaveDialog read FOnGetSaveDialog write FOnGetSaveDialog;
443 property OnProgress: TATFinderProgress read FOnProgress write FOnProgress;
readnull444 property OnCheckFilenameOpened: TStrFunction read FCheckFilenameOpened write FCheckFilenameOpened;
445 property OnMsgStatus: TStrEvent read FOnMsgStatus write FOnMsgStatus;
446 property OnFocusEditor: TNotifyEvent read FOnFocusEditor write FOnFocusEditor;
447 property OnChangeCaption: TNotifyEvent read FOnChangeCaption write FOnChangeCaption;
448 property OnChangeSlow: TNotifyEvent read FOnChangeSlow write FOnChangeSlow;
449 property OnUpdateStatusbar: TNotifyEvent read FOnUpdateStatusbar write FOnUpdateStatusbar;
450 property OnUpdateState: TNotifyEvent read FOnUpdateState write FOnUpdateState;
451 property OnUpdateZoom: TNotifyEvent read FOnUpdateZoom write FOnUpdateZoom;
452 property OnEditorCommand: TATSynEditCommandEvent read FOnEditorCommand write FOnEditorCommand;
453 property OnEditorChangeCaretPos: TNotifyEvent read FOnEditorChangeCaretPos write FOnEditorChangeCaretPos;
454 property OnEditorScroll: TNotifyEvent read FOnEditorScroll write FOnEditorScroll;
455 property OnSaveFile: TNotifyEvent read FOnSaveFile write FOnSaveFile;
456 property OnAddRecent: TNotifyEvent read FOnAddRecent write FOnAddRecent;
457 property OnPyEvent: TEditorFramePyEvent read FOnPyEvent write FOnPyEvent;
458 property OnInitAdapter: TNotifyEvent read FOnInitAdapter write FOnInitAdapter;
459 property OnLexerChange: TATEditorEvent read FOnLexerChange write FOnLexerChange;
460 property OnAppClickLink: TATSynEditClickLinkEvent read FOnAppClickLink write FOnAppClickLink;
461 property OnCallAutoCompletion: TEditorBooleanEvent read FOnCallAutoCompletion write FOnCallAutoCompletion;
462 end;
463
464 procedure GetFrameLocation(Frame: TEditorFrame;
465 out AGroups: TATGroups; out APages: TATPages;
466 out ALocalGroupIndex, AGlobalGroupIndex, ATabIndex: integer);
467
468 procedure UpdateTabPreviewStyle(D: TATTabData; AValue: boolean);
469
470
471 implementation
472
473 {$R *.lfm}
474
475 const
476 cSplitHorzToAlign: array[boolean] of TAlign = (alRight, alBottom);
477
478 const
479 cHistory_Lexer = '/lexer';
480 cHistory_Enc = '/enc';
481 cHistory_TopLine = '/top';
482 cHistory_TopLine2 = '/top2';
483 cHistory_Wrap = '/wrap_mode';
484 cHistory_ReadOnly = '/ro';
485 cHistory_Ruler = '/ruler';
486 cHistory_Minimap = '/minimap';
487 cHistory_Micromap = '/micromap';
488 cHistory_TabSize = '/tab_size';
489 cHistory_TabSpace = '/tab_spaces';
490 cHistory_LineNums = '/nums';
491 cHistory_FontScale = '/scale';
492 cHistory_Unpri = '/unprinted_show';
493 cHistory_Unpri_Spaces = '/unprinted_spaces';
494 cHistory_Unpri_Ends = '/unprinted_ends';
495 cHistory_Unpri_Detail = '/unprinted_end_details';
496 cHistory_Caret = '/crt';
497 cHistory_TabColor = '/color';
498 cHistory_FoldingShow = '/fold';
499 cHistory_FoldedRanges = '/folded';
500 cHistory_CodeTreeFilter = '/codetree_filter';
501 cHistory_CodeTreeFilters = '/codetree_filters';
502 cHistory_TabSplit = '/split';
503 cHistory_TabSplit_Mul = 1e5; //instead of float 0.6, save as int 0.6*1e5
504
505 var
506 FLastTabId: integer = 0;
507
msgSuggestOptionsEditornull508 function msgSuggestOptionsEditor: string;
509 var
510 ini: TIniFile;
511 fn: string;
512 s: string;
513 begin
514 S:= '"Options Editor" provides the dialog - click here to open';
515
516 fn:= GetAppLangFilename;
517 if FileExists(fn) then
518 begin
519 ini:= TIniFile.Create(fn);
520 try
521 S:= ini.ReadString('si', 'CallOptEditor', S);
522 finally
523 FreeAndNil(ini);
524 end;
525 end;
526
527 Result:= S;
528 end;
529
530
531 procedure GetFrameLocation(Frame: TEditorFrame;
532 out AGroups: TATGroups; out APages: TATPages;
533 out ALocalGroupIndex, AGlobalGroupIndex, ATabIndex: integer);
534 begin
535 Assert(Assigned(Frame.Parent));
536 APages:= Frame.GetTabPages;
537 AGroups:= Frame.GetTabGroups;
538 AGroups.FindPositionOfControl(Frame, ALocalGroupIndex, ATabIndex);
539
540 AGlobalGroupIndex:= ALocalGroupIndex;
541 if AGroups.Tag<>0 then
542 Inc(AGlobalGroupIndex, High(TATGroupsNums) + AGroups.Tag);
543 end;
544
545 procedure UpdateTabPreviewStyle(D: TATTabData; AValue: boolean);
546 begin
547 D.TabSpecial:= AValue;
548 if AValue then
549 D.TabFontStyle:= StringToFontStyles(UiOps.TabPreviewFontStyle)
550 else
551 D.TabFontStyle:= [];
552 end;
553
554
555 { TEditorFrame }
556
557 procedure TEditorFrame.SetTabCaption(const AValue: string);
558 var
559 bUpdate: boolean;
560 begin
561 if AValue='?' then Exit;
562 bUpdate:= FTabCaption<>AValue;
563
564 FTabCaption:= AValue; //don't check Upd here (for Win32)
565
566 if bUpdate then
567 DoPyEventState(Ed1, EDSTATE_TAB_TITLE);
568
569 DoOnChangeCaption;
570 end;
571
572 procedure TEditorFrame.SetTabCaptionAddon(const AValue: string);
573 var
574 Gr: TATGroups;
575 Pages: TATPages;
576 NLocalGroups, NGlobalGroup, NTab: integer;
577 D: TATTabData;
578 begin
579 if FTabCaptionAddon=AValue then Exit;
580 FTabCaptionAddon:= AValue;
581
582 GetFrameLocation(Self, Gr, Pages, NLocalGroups, NGlobalGroup, NTab);
583 D:= Pages.Tabs.GetTabData(NTab);
584 if Assigned(D) then
585 D.TabCaptionAddon:= FTabCaptionAddon;
586 end;
587
588
589 procedure TEditorFrame.UpdateCaptionFromFilename;
590 var
591 Name1, Name2: string;
592 begin
593 //avoid updating caption if API already had set it
594 if FTabCaptionFromApi then exit;
595
596 if EditorsLinked then
597 begin
598 if FFileName='' then
599 Name1:= FTabCaptionUntitled
600 else
601 Name1:= ExtractFileName_Fixed(FFileName);
602 Name1:= msgModified[Ed1.Modified]+Name1;
603
604 TabCaption:= Name1;
605 end
606 else
607 begin
608 if (FFileName='') and (FFileName2='') then
609 TabCaption:= FTabCaptionUntitled
610 else
611 begin
612 Name1:= ExtractFileName_Fixed(FFileName);
613 if Name1='' then Name1:= msgUntitledTab;
614 Name1:= msgModified[Ed1.Modified]+Name1;
615
616 Name2:= ExtractFileName_Fixed(FFileName2);
617 if Name2='' then Name2:= msgUntitledTab;
618 Name2:= msgModified[Ed2.Modified]+Name2;
619
620 TabCaption:= Name1+' | '+Name2;
621 end;
622 end;
623
624 UpdateTabTooltip;
625 end;
626
627 procedure TEditorFrame.EditorOnClick(Sender: TObject);
628 var
629 Ed: TATSynEdit;
630 StateString: string;
631 Params: TAppVariantArray;
632 begin
633 Ed:= Sender as TATSynEdit;
634
635 StateString:= ConvertShiftStateToString(KeyboardStateToShiftState);
636 CancelAutocompleteAutoshow(Ed);
637
638 if Ed.Markers.DeleteWithTag(UiOps.FindOccur_TagValue) then
639 Ed.Update;
640
641 if UiOps.MouseGotoDefinition<>'' then
642 if StateString=UiOps.MouseGotoDefinition then
643 begin
644 SetLength(Params, 0);
645 DoPyEvent(Ed, cEventOnGotoDef, Params);
646 exit;
647 end;
648
649 SetLength(Params, 1);
650 Params[0]:= AppVariant(StateString);
651 DoPyEvent(Ed, cEventOnClick, Params);
652 end;
653
GetSplitPosCurrentnull654 function TEditorFrame.GetSplitPosCurrent: double;
655 begin
656 if not Splitted then
657 Result:= 0
658 else
659 if FSplitHorz then
660 Result:= Ed2.Height/Max(Height, 1)
661 else
662 Result:= Ed2.Width/Max(Width, 1);
663 end;
664
GetSplittednull665 function TEditorFrame.GetSplitted: boolean;
666 begin
667 Result:= Ed2.Visible;
668 end;
669
670 procedure TEditorFrame.EditorOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
671 var
672 Params: TAppVariantArray;
673 Res: TAppPyEventResult;
674 begin
675 SetLength(Params, 2);
676 Params[0]:= AppVariant(Key);
677 Params[1]:= AppVariant(ConvertShiftStateToString(Shift));
678
679 //result=False: block the key
680 Res:= DoPyEvent(Sender as TATSynEdit, cEventOnKey, Params);
681 if Res.Val=evrFalse then
682 begin
683 Key:= 0;
684 Exit
685 end;
686 end;
687
688 procedure TEditorFrame.EditorOnKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
689 var
690 Params: TAppVariantArray;
691 begin
692 SetLength(Params, 2);
693 Params[0]:= AppVariant(Key);
694 Params[1]:= AppVariant(ConvertShiftStateToString(Shift));
695
696 //fire on_key_up only for keys Ctrl, Alt, Shift
697 //event result is ignored
698 case Key of
699 VK_CONTROL,
700 VK_MENU,
701 VK_SHIFT,
702 VK_RSHIFT:
703 DoPyEvent(Sender as TATSynEdit, cEventOnKeyUp, Params);
704 end;
705 end;
706
707 procedure TEditorFrame.EditorOnPaste(Sender: TObject; var AHandled: boolean;
708 AKeepCaret, ASelectThen: boolean);
709 var
710 Params: TAppVariantArray;
711 begin
712 SetLength(Params, 2);
713 Params[0]:= AppVariant(AKeepCaret);
714 Params[1]:= AppVariant(ASelectThen);
715
716 if DoPyEvent(Sender as TATSynEdit, cEventOnPaste, Params).Val = evrFalse then
717 AHandled:= true;
718 end;
719
720 procedure TEditorFrame.EditorOnScroll(Sender: TObject);
721 var
722 Params: TAppVariantArray;
723 begin
724 if Assigned(FOnEditorScroll) then
725 FOnEditorScroll(Sender);
726
727 SetLength(Params, 0);
728 DoPyEvent(Sender as TATSynEdit, cEventOnScroll, Params);
729 end;
730
GetTabPagesnull731 function TEditorFrame.GetTabPages: TATPages;
732 begin
733 Result:= Parent as TATPages;
734 end;
735
GetTabGroupsnull736 function TEditorFrame.GetTabGroups: TATGroups;
737 begin
738 Result:= (Parent as TATPages).Owner as TATGroups;
739 end;
740
741 procedure TEditorFrame.DoShow;
742 var
743 an: TecSyntAnalyzer;
744 begin
745 //analyze file, when frame is shown for the 1st time
746 if UiOps.AllowFrameParsing and not FWasVisible then
747 begin
748 FWasVisible:= true;
749
750 an:= LexerInitial[Ed1];
751 if Assigned(an) then
752 begin
753 Lexer[Ed1]:= an;
754 LexerInitial[Ed1]:= nil;
755 end;
756
757 if not EditorsLinked then
758 begin
759 an:= LexerInitial[Ed2];
760 if Assigned(an) then
761 begin
762 Lexer[Ed2]:= an;
763 LexerInitial[Ed2]:= nil;
764 end;
765 end;
766 end;
767 end;
768
769 procedure TEditorFrame.TimerChangeTimer(Sender: TObject);
770 begin
771 TimerChange.Enabled:= false;
772 if Assigned(FOnChangeSlow) then
773 FOnChangeSlow(Editor);
774 end;
775
776 procedure TEditorFrame.btnReloadYesClick(Sender: TObject);
777 var
778 Index: integer;
779 Ed: TATSynEdit;
780 begin
781 Index:= (Sender as TComponent).Tag;
782 Ed:= EditorIndexToObj(Index);
783 if Ed=nil then exit;
784 DoFileReload(Ed);
785 EditorFocus(Ed);
786 end;
787
788 procedure TEditorFrame.btnReloadNoClick(Sender: TObject);
789 var
790 Index: integer;
791 Ed: TATSynEdit;
792 begin
793 Index:= (Sender as TComponent).Tag;
794 Ed:= EditorIndexToObj(Index);
795 if Ed=nil then exit;
796 DoHideNotificationPanel(Index);
797 EditorFocus(Ed);
798 end;
799
800 procedure TEditorFrame.btnReloadNoneClick(Sender: TObject);
801 begin
802 NotifEnabled:= false;
803 btnReloadNoClick(Sender);
804 end;
805
806 procedure TEditorFrame.EditorOnCalcBookmarkColor(Sender: TObject;
807 ABookmarkKind: integer; var AColor: TColor);
808 begin
809 if ABookmarkKind>1 then
810 begin
811 AColor:= AppBookmarkSetup[ABookmarkKind].Color;
812 if AColor=clDefault then
813 AColor:= GetAppColor(apclEdBookmarkBg);
814 end;
815 end;
816
817 procedure TEditorFrame.EditorOnChangeCaretPos(Sender: TObject);
818 const
819 cMaxSelectedLinesForAutoCopy = 200;
820 var
821 Params: TAppVariantArray;
822 Ed: TATSynEdit;
823 begin
824 Ed:= Sender as TATSynEdit;
825 if Assigned(FOnEditorChangeCaretPos) then
826 FOnEditorChangeCaretPos(Sender);
827
828 DoOnUpdateStatusbar;
829
830 if FBracketHilite then
831 EditorBracket_Action(Ed,
832 bracketActionHilite,
833 FBracketSymbols,
834 FBracketMaxDistance
835 );
836
837 //support Primary Selection on Linux
838 {$ifdef linux}
839 EditorCopySelToPrimarySelection(Ed, cMaxSelectedLinesForAutoCopy);
840 {$endif}
841
842 SetLength(Params, 0);
843 DoPyEvent(Ed, cEventOnCaret, Params);
844 end;
845
846 procedure TEditorFrame.EditorOnHotspotEnter(Sender: TObject; AHotspotIndex: integer);
847 var
848 Params: TAppVariantArray;
849 begin
850 SetLength(Params, 2);
851 Params[0]:= AppVariant(true); //hotspot enter
852 Params[1]:= AppVariant(AHotspotIndex);
853
854 DoPyEvent(Sender as TATSynEdit, cEventOnHotspot, Params);
855 end;
856
857 procedure TEditorFrame.EditorOnHotspotExit(Sender: TObject; AHotspotIndex: integer);
858 var
859 Params: TAppVariantArray;
860 begin
861 SetLength(Params, 2);
862 Params[0]:= AppVariant(false); //hotspot exit
863 Params[1]:= AppVariant(AHotspotIndex);
864
865 DoPyEvent(Sender as TATSynEdit, cEventOnHotspot, Params);
866 end;
867
868 function _ContrastColor(AColor: TColor): TColor;
869 var
870 bLight: boolean;
871 red, green, blue: integer;
872 begin
873 red:= AColor and $FF;
874 green:= AColor shr 8 and $FF;
875 blue:= AColor shr 16 and $FF;
876 // Use different scaling with red, green, and blue to account
877 // for perceived intensity. Addresses issue #3624
878 // See https://www.w3.org/TR/AERT/#color-contrast
879 // Color brightness can determined by the following formula:
880 // ((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000
881 // ((299+587+114) * 128) = 128000
882 // ((299+587+114) * $80) = $1f400
883 bLight:= red*299 + green*587 + blue*114 > $1f400;
884 Result:= UiOps.HtmlBackgroundColorPair[bLight];
885 end;
886
887
888 procedure TEditorFrame.EditorOnDrawLine(Sender: TObject; C: TCanvas;
889 ALineIndex, AX, AY: integer; const AStr: atString; ACharSize: TATEditorCharSize;
890 constref AExtent: TATIntFixedArray);
891 var
892 Ed: TATSynEdit;
893 NLineWidth: integer;
894 bColorizeBack, bColorizeInBrackets, bFoundBrackets: boolean;
895 X1, X2, Y, NLen, NStartPos: integer;
896 NColor: TColor;
897 i: integer;
898 begin
899 if AStr='' then Exit;
900
901 if not IsFilenameListedInExtensionList(FileName, EditorOps.OpUnderlineColorFiles)
902 then exit;
903
904 //skip lines in binary files, e.g. *.dll
905 for i:= 1 to Length(AStr) do
906 case Ord(AStr[i]) of
907 0..8:
908 exit;
909 end;
910
911 NLineWidth:= EditorOps.OpUnderlineColorSize;
912 bColorizeBack:= NLineWidth>=10;
913 bColorizeInBrackets:= NLineWidth=11;
914
915 //avoid background hilite for lines with selection
916 if bColorizeBack then
917 begin
918 if Sender=nil then
919 raise Exception.Create('Sender=nil in TEditorFrame.EditorOnDrawLine');
920 Ed:= Sender as TATSynEdit;
921 if Ed.Carets.IsLineWithSelection(ALineIndex) then exit;
922 end;
923
924 for i:= 1 to Length(AStr)-3 do
925 begin
926 NColor:= clNone;
927 bFoundBrackets:= false;
928
929 case AStr[i] of
930 '#':
931 begin
932 //find #rgb, #rrggbb
933 if IsCharHexDigit(AStr[i+1]) then
934 begin
935 //don't allow word-char before
936 if (i>1) and IsCharWord(AStr[i-1], cDefaultNonWordChars) then Continue;
937
938 NColor:= TATHtmlColorParserW.ParseTokenRGB(@AStr[i+1], NLen, clNone);
939 Inc(NLen);
940 end;
941 end;
942 'r':
943 begin
944 //find rgb(...), rgba(...)
945 if (AStr[i+1]='g') and
946 (AStr[i+2]='b')
947 then
948 begin
949 //don't allow word-char before
950 if (i>1) and IsCharWord(AStr[i-1], cDefaultNonWordChars) then Continue;
951
952 NColor:= TATHtmlColorParserW.ParseFunctionRGB(AStr, i, NLen);
953 bFoundBrackets:= true;
954 end;
955 end;
956 'h':
957 begin
958 //find hsl(...), hsla(...)
959 if (AStr[i+1]='s') and
960 (AStr[i+2]='l')
961 then
962 begin
963 //don't allow word-char before
964 if (i>1) and IsCharWord(AStr[i-1], cDefaultNonWordChars) then Continue;
965
966 NColor:= TATHtmlColorParserW.ParseFunctionHSL(AStr, i, NLen);
967 bFoundBrackets:= true;
968 end;
969 end;
970 end;
971
972 //render the found color
973 if NColor<>clNone then
974 begin
975 if bColorizeInBrackets and bFoundBrackets then
976 begin
977 NStartPos:= PosEx('(', AStr, i+2)+1;
978 NLen:= Max(1, NLen-1-(NStartPos-i))
979 end
980 else
981 NStartPos:= i;
982
983 if (NStartPos-2>=0) and (NStartPos-2<cMaxFixedArray) then
984 X1:= AX+AExtent.Data[NStartPos-2]
985 else
986 X1:= AX;
987
988 if NStartPos-2+NLen<cMaxFixedArray then
989 X2:= AX+AExtent.Data[NStartPos-2+NLen]
990 else
991 X2:= 0;
992
993 Y:= AY+ACharSize.Y;
994
995 if bColorizeBack then
996 begin
997 C.Font.Color:= _ContrastColor(NColor);
998 C.Font.Style:= [];
999 C.Brush.Color:= NColor;
1000 CanvasTextOutSimplest(C, X1, AY, Copy(AStr, NStartPos, NLen));
1001 end
1002 else
1003 begin
1004 C.Brush.Color:= NColor;
1005 C.FillRect(X1, Y-NLineWidth, X2, Y);
1006 end;
1007 end;
1008 end;
1009 end;
1010
1011
GetLineEndsnull1012 function TEditorFrame.GetLineEnds(Ed: TATSynEdit): TATLineEnds;
1013 begin
1014 Result:= Ed.Strings.Endings;
1015 end;
1016
TEditorFrame.GetPictureScalenull1017 function TEditorFrame.GetPictureScale: integer;
1018 begin
1019 if Assigned(FImageBox) then
1020 Result:= FImageBox.ImageZoom
1021 else
1022 Result:= 100;
1023 end;
1024
GetReadOnlynull1025 function TEditorFrame.GetReadOnly(Ed: TATSynEdit): boolean;
1026 begin
1027 Result:= Ed.ModeReadOnly;
1028 end;
1029
GetSaveDialognull1030 function TEditorFrame.GetSaveDialog: TSaveDialog;
1031 begin
1032 if not Assigned(FSaveDialog) then
1033 if Assigned(FOnGetSaveDialog) then
1034 FOnGetSaveDialog(FSaveDialog);
1035 Result:= FSaveDialog;
1036 end;
1037
TEditorFrame.GetTabKeyCollectMarkersnull1038 function TEditorFrame.GetTabKeyCollectMarkers: boolean;
1039 begin
1040 Result:= FTabKeyCollectMarkers and (Editor.Markers.Count>0);
1041 end;
1042
TEditorFrame.GetUnprintedEndsnull1043 function TEditorFrame.GetUnprintedEnds: boolean;
1044 begin
1045 Result:= Ed1.OptUnprintedEnds;
1046 end;
1047
TEditorFrame.GetUnprintedEndsDetailsnull1048 function TEditorFrame.GetUnprintedEndsDetails: boolean;
1049 begin
1050 Result:= Ed1.OptUnprintedEndsDetails;
1051 end;
1052
TEditorFrame.GetUnprintedShownull1053 function TEditorFrame.GetUnprintedShow: boolean;
1054 begin
1055 Result:= Ed1.OptUnprintedVisible;
1056 end;
1057
GetUnprintedSpacesnull1058 function TEditorFrame.GetUnprintedSpaces: boolean;
1059 begin
1060 Result:= Ed1.OptUnprintedSpaces;
1061 end;
1062
1063 procedure TEditorFrame.SetFileName(const AValue: string);
1064 begin
1065 if SameFileName(FFileName, AValue) then Exit;
1066 FFileName:= AValue;
1067 AppGetFileProps(FFileName, FileProps);
1068 end;
1069
1070 procedure TEditorFrame.UpdateTabTooltip;
1071 var
1072 Gr: TATGroups;
1073 Pages: TATPages;
1074 NLocalGroups, NGlobalGroup, NTab: integer;
1075 D: TATTabData;
1076 SHint: string;
1077 begin
1078 GetFrameLocation(Self, Gr, Pages, NLocalGroups, NGlobalGroup, NTab);
1079 D:= Pages.Tabs.GetTabData(NTab);
1080 if Assigned(D) then
1081 begin
1082 SHint:= '';
1083 if EditorsLinked then
1084 begin
1085 if FFileName<>'' then
1086 SHint:= AppCollapseHomeDirInFilename(FFileName);
1087 end
1088 else
1089 begin
1090 if (FFileName<>'') or (FFileName2<>'') then
1091 SHint:= AppCollapseHomeDirInFilename(FFileName) + #10 +
1092 AppCollapseHomeDirInFilename(FFileName2);
1093 end;
1094
1095 D.TabHint:= SHint;
1096 end;
1097 end;
1098
1099 procedure TEditorFrame.SetFileName2(AValue: string);
1100 begin
1101 if SameFileName(FFileName2, AValue) then Exit;
1102 FFileName2:= AValue;
1103 AppGetFileProps(FFileName2, FileProps2);
1104 end;
1105
1106 procedure TEditorFrame.SetFileWasBig(Ed: TATSynEdit; AValue: boolean);
1107 var
1108 Index: integer;
1109 begin
1110 if EditorsLinked then
1111 begin
1112 FFileWasBig[0]:= AValue;
1113 FFileWasBig[1]:= AValue;
1114 if AValue then
1115 begin
1116 EditorAdjustForBigFile(Ed1);
1117 EditorAdjustForBigFile(Ed2);
1118 end;
1119 end
1120 else
1121 begin
1122 Index:= EditorObjToIndex(Ed);
1123 if Index<0 then exit;
1124 FFileWasBig[Index]:= AValue;
1125 if AValue then
1126 EditorAdjustForBigFile(Ed);
1127 end;
1128 end;
1129
1130 procedure TEditorFrame.SetInitialLexer(Ed: TATSynEdit; AValue: TecSyntAnalyzer);
1131 var
1132 Index: integer;
1133 begin
1134 if EditorsLinked then
1135 FInitialLexer1:= AValue
1136 else
1137 begin
1138 Index:= EditorObjToIndex(Ed);
1139 if Index=0 then
1140 FInitialLexer1:= AValue
1141 else
1142 FInitialLexer2:= AValue;
1143 end;
1144 end;
1145
1146 procedure TEditorFrame.SetLocked(AValue: boolean);
1147 begin
1148 if AValue=FLocked then exit;
1149 FLocked:= AValue;
1150
1151 if FLocked then
1152 begin
1153 Ed1.BeginUpdate;
1154 Ed2.BeginUpdate;
1155 end
1156 else
1157 begin
1158 Ed1.EndUpdate;
1159 Ed2.EndUpdate;
1160 end;
1161 end;
1162
1163 procedure TEditorFrame.SetPictureScale(AValue: integer);
1164 begin
1165 if Assigned(FImageBox) then
1166 begin
1167 if AValue>0 then
1168 FImageBox.ImageZoom:= AValue
1169 else
1170 if AValue=-1 then
1171 FImageBox.OptFitToWindow:= true;
1172 end;
1173 end;
1174
1175 procedure TEditorFrame.SetReadOnly(Ed: TATSynEdit; AValue: boolean);
1176 begin
1177 if Ed.ModeReadOnly=AValue then exit;
1178 Ed.ModeReadOnly:= AValue;
1179 if (Ed=Ed1) and EditorsLinked then
1180 Ed2.ModeReadOnly:= AValue;
1181 DoPyEventState(Ed, EDSTATE_READONLY);
1182 end;
1183
1184 procedure TEditorFrame.UpdateEds(AUpdateWrapInfo: boolean = false);
1185 begin
1186 Ed2.OptUnprintedVisible:= Ed1.OptUnprintedVisible;
1187 Ed2.OptUnprintedSpaces:= Ed1.OptUnprintedSpaces;
1188 Ed2.OptUnprintedEnds:= Ed1.OptUnprintedEnds;
1189 Ed2.OptUnprintedEndsDetails:= Ed1.OptUnprintedEndsDetails;
1190
1191 Ed1.Update(AUpdateWrapInfo);
1192 Ed2.Update(AUpdateWrapInfo);
1193 end;
1194
TEditorFrame.GetLexernull1195 function TEditorFrame.GetLexer(Ed: TATSynEdit): TecSyntAnalyzer;
1196 begin
1197 Result:= LexerInitial[Ed];
1198 if Assigned(Result) then exit;
1199
1200 if Ed.AdapterForHilite is TATAdapterEControl then
1201 Result:= TATAdapterEControl(Ed.AdapterForHilite).Lexer
1202 else
1203 Result:= nil;
1204 end;
1205
GetLexerLitenull1206 function TEditorFrame.GetLexerLite(Ed: TATSynEdit): TATLiteLexer;
1207 begin
1208 if Ed.AdapterForHilite is TATLiteLexer then
1209 Result:= TATLiteLexer(Ed.AdapterForHilite)
1210 else
1211 Result:= nil;
1212 end;
1213
TEditorFrame.GetLexerNamenull1214 function TEditorFrame.GetLexerName(Ed: TATSynEdit): string;
1215 var
1216 CurAdapter: TATAdapterHilite;
1217 an: TecSyntAnalyzer;
1218 begin
1219 Result:= '';
1220
1221 an:= LexerInitial[Ed];
1222 if Assigned(an) then
1223 exit(an.LexerName);
1224
1225 CurAdapter:= Ed.AdapterForHilite;
1226 if CurAdapter=nil then exit;
1227
1228 if CurAdapter is TATAdapterEControl then
1229 begin
1230 an:= TATAdapterEControl(CurAdapter).Lexer;
1231 if Assigned(an) then
1232 Result:= an.LexerName;
1233 end
1234 else
1235 if CurAdapter is TATLiteLexer then
1236 begin
1237 Result:= TATLiteLexer(CurAdapter).LexerName+msgLiteLexerSuffix;
1238 end;
1239 end;
1240
1241
1242 procedure TEditorFrame.SetLexerName(Ed: TATSynEdit; const AValue: string);
1243 var
1244 SName: string;
1245 anLite: TATLiteLexer;
1246 begin
1247 if AValue='' then
1248 begin
1249 if EditorsLinked then
1250 begin
1251 Ed1.AdapterForHilite:= nil;
1252 Ed2.AdapterForHilite:= nil;
1253 Adapter1.Lexer:= nil;
1254 end
1255 else
1256 begin
1257 Ed.AdapterForHilite:= nil;
1258 Lexer[Ed]:= nil;
1259 Ed.Update;
1260 end;
1261 exit;
1262 end;
1263
1264 if SEndsWith(AValue, msgLiteLexerSuffix) then
1265 begin
1266 SName:= Copy(AValue, 1, Length(AValue)-Length(msgLiteLexerSuffix));
1267 anLite:= AppManagerLite.FindLexerByName(SName);
1268 if Assigned(anLite) then
1269 LexerLite[Ed]:= anLite
1270 else
1271 Lexer[Ed]:= nil;
1272 end
1273 else
1274 begin
1275 Lexer[Ed]:= AppManager.FindLexerByName(AValue);
1276 end;
1277 end;
1278
1279 procedure TEditorFrame.SetSplitHorz(AValue: boolean);
1280 var
1281 al: TAlign;
1282 begin
1283 FSplitHorz:= AValue;
1284 if FrameKind<>efkEditor then exit;
1285
1286 al:= cSplitHorzToAlign[AValue];
1287 Splitter.Align:= al;
1288 Ed2.Align:= al;
1289
1290 //restore relative splitter ratio (e.g. 50%)
1291 SplitPos:= SplitPos;
1292 end;
1293
1294 procedure TEditorFrame.SetSplitPos(AValue: double);
1295 const
1296 Delta = 70;
1297 var
1298 N: integer;
1299 begin
1300 if FrameKind<>efkEditor then exit;
1301 if not Splitted then exit;
1302
1303 AValue:= Max(0.0, Min(1.0, AValue));
1304 FSplitPos:= AValue;
1305
1306 if FSplitHorz then
1307 begin
1308 N:= Round(AValue*Height);
1309 Ed2.Height:= Max(Delta, Min(Height-Delta, N));
1310 Splitter.Top:= 0;
1311 end
1312 else
1313 begin
1314 N:= Round(AValue*Width);
1315 Ed2.Width:= Max(Delta, Min(Width-Delta, N));
1316 Splitter.Left:= 0;
1317 end;
1318 end;
1319
1320 procedure TEditorFrame.SetSplitted(AValue: boolean);
1321 begin
1322 if FrameKind<>efkEditor then exit;
1323 if GetSplitted=AValue then exit;
1324
1325 if not AValue and Ed2.Focused then
1326 if Ed1.CanFocus then
1327 Ed1.SetFocus;
1328
1329 Ed2.Visible:= AValue;
1330 Splitter.Visible:= AValue;
1331
1332 if AValue then
1333 begin
1334 SplitPos:= 0.5;
1335 //enable linking
1336 if FEditorsLinked then
1337 begin
1338 Ed2.Strings:= Ed1.Strings;
1339 //Ed1.BrotherEditor:= Ed2;
1340 //Ed2.BrotherEditor:= Ed1;
1341 end;
1342 end
1343 else
1344 begin
1345 //disable linking
1346 Ed2.Strings:= nil;
1347 //Ed1.BrotherEditor:= nil;
1348 //Ed2.BrotherEditor:= nil;
1349 end;
1350
1351 Ed2.Update(true);
1352 end;
1353
1354 procedure TEditorFrame.EditorOnChange(Sender: TObject);
1355 var
1356 Ed, EdOther: TATSynEdit;
1357 Params: TAppVariantArray;
1358 b1, b2: boolean;
1359 begin
1360 Ed:= Sender as TATSynEdit;
1361
1362 b1:= Ed.Markers.DeleteWithTag(UiOps.FindOccur_TagValue);
1363 b2:= false;
1364 if FBracketHilite then
1365 b2:= EditorBracket_ClearHilite(Ed);
1366
1367 if b1 or b2 then
1368 Ed.Update;
1369
1370 //sync changes in 2 editors, when frame is splitted
1371 if Splitted and EditorsLinked then
1372 begin
1373 if Ed=Ed1 then
1374 EdOther:= Ed2
1375 else
1376 EdOther:= Ed1;
1377
1378 EdOther.DoCaretsFixIncorrectPos(false);
1379 EdOther.Update(true);
1380 end;
1381
1382 SetLength(Params, 0);
1383 DoPyEvent(Ed, cEventOnChange, Params);
1384
1385 TimerChange.Enabled:= false;
1386 TimerChange.Interval:= UiOps.PyChangeSlow;
1387 TimerChange.Enabled:= true;
1388 end;
1389
1390 procedure TEditorFrame.EditorOnChangeModified(Sender: TObject);
1391 begin
1392 UpdateModified(Sender as TATSynEdit);
1393 end;
1394
1395 procedure TEditorFrame.EditorOnChangeState(Sender: TObject);
1396 begin
1397 DoOnUpdateState;
1398 end;
1399
1400 procedure TEditorFrame.EditorOnChangeBookmarks(Sender: TObject);
1401 begin
1402 DoPyEventState(Sender as TATSynEdit, EDSTATE_BOOKMARK);
1403 end;
1404
1405 procedure TEditorFrame.EditorOnChangeZoom(Sender: TObject);
1406 begin
1407 DoOnUpdateZoom;
1408 DoPyEventState(Sender as TATSynEdit, EDSTATE_ZOOM);
1409 end;
1410
1411 procedure TEditorFrame.UpdateModified(Ed: TATSynEdit; AWithEvent: boolean);
1412 begin
1413 //when modified, remove "Preview tab" style (italic caption)
1414 if (Ed=Ed1) and Ed.Modified then
1415 DoRemovePreviewStyle;
1416
1417 UpdateCaptionFromFilename;
1418 DoOnChangeCaption;
1419
1420 if AWithEvent then
1421 DoPyEventState(Ed, EDSTATE_MODIFIED);
1422
1423 DoOnUpdateStatusbar;
1424 end;
1425
1426 procedure TEditorFrame.UpdatePinned(Ed: TATSynEdit; AWithEvent: boolean);
1427 var
1428 Params: TAppVariantArray;
1429 begin
1430 if TabPinned then
1431 DoRemovePreviewStyle;
1432
1433 if AWithEvent then
1434 DoPyEventState(Ed, EDSTATE_PINNED);
1435 end;
1436
1437
1438 procedure TEditorFrame.EditorOnEnter(Sender: TObject);
1439 var
1440 Params: TAppVariantArray;
1441 IsEd2: boolean;
1442 begin
1443 IsEd2:= Sender=Ed2;
1444 if IsEd2<>FActiveSecondaryEd then
1445 begin
1446 FActiveSecondaryEd:= IsEd2;
1447 DoOnUpdateStatusbar;
1448 end;
1449
1450 if Assigned(FOnFocusEditor) then
1451 FOnFocusEditor(Sender);
1452
1453 SetLength(Params, 0);
1454 DoPyEvent(Sender as TATSynEdit, cEventOnFocus, Params);
1455
1456 FActivationTime:= GetTickCount64;
1457 end;
1458
1459 procedure TEditorFrame.EditorOnCommand(Sender: TObject; ACmd: integer;
1460 AInvoke: TATEditorCommandInvoke; const AText: string; var AHandled: boolean);
1461 var
1462 Ed: TATSynEdit;
1463 NCarets: integer;
1464 ch: char;
1465 begin
1466 Ed:= Sender as TATSynEdit;
1467 NCarets:= Ed.Carets.Count;
1468 if NCarets=0 then exit;
1469
1470 case ACmd of
1471 cCommand_TextInsert:
1472 begin
1473 if NCarets>1 then
1474 if not Ed.OptAutoPairForMultiCarets then
1475 exit;
1476
1477 if Length(AText)=1 then
1478 begin
1479 ch:= AText[1];
1480
1481 //auto-close bracket
1482 if Pos(ch, Ed.OptAutoPairChars)>0 then
1483 if EditorAutoPairChar(Ed, ch) then
1484 begin
1485 AHandled:= true;
1486 Ed.DoEventCarets; //to highlight pair brackets after typing bracket
1487 exit
1488 end;
1489
1490 //auto-skip closing bracket in case 'f(|)'
1491 if EditorAutoSkipClosingBracket(Ed, ch) then
1492 begin
1493 AHandled:= true;
1494 Ed.Update;
1495 exit;
1496 end;
1497 end;
1498 end;
1499
1500 cCommand_KeyTab,
1501 cCommand_KeyEnter,
1502 cCommand_TextDeleteLine,
1503 cCommand_TextDeleteToLineBegin,
1504 cCommand_KeyUp,
1505 cCommand_KeyUp_Sel,
1506 cCommand_KeyDown,
1507 cCommand_KeyDown_Sel,
1508 cCommand_KeyLeft,
1509 cCommand_KeyLeft_Sel,
1510 cCommand_KeyRight,
1511 cCommand_KeyRight_Sel,
1512 cCommand_KeyHome,
1513 cCommand_KeyHome_Sel,
1514 cCommand_KeyEnd,
1515 cCommand_KeyEnd_Sel,
1516 cCommand_KeyPageUp,
1517 cCommand_KeyPageUp_Sel,
1518 cCommand_KeyPageDown,
1519 cCommand_KeyPageDown_Sel,
1520 cCommand_TextDeleteWordNext,
1521 cCommand_TextDeleteWordPrev:
1522 begin
1523 CancelAutocompleteAutoshow(Ed);
1524 end;
1525
1526 cCommand_ClipboardPaste,
1527 cCommand_ClipboardPaste_Select,
1528 cCommand_ClipboardPaste_KeepCaret,
1529 cCommand_ClipboardPaste_Column,
1530 cCommand_ClipboardPaste_ColumnKeepCaret:
1531 begin
1532 Adapter[Ed].StopTreeUpdate;
1533 Adapter[Ed].Stop;
1534 end;
1535 end;
1536
1537 if Assigned(FOnEditorCommand) then
1538 FOnEditorCommand(Sender, ACmd, AInvoke, AText, AHandled);
1539 end;
1540
1541 procedure TEditorFrame.EditorOnCommandAfter(Sender: TObject; ACommand: integer;
1542 const AText: string);
1543 var
1544 Ed: TATSynEdit;
1545 Caret: TATCaretItem;
1546 bTypedChar: boolean;
1547 NValue: integer;
1548 charW: WideChar;
1549 begin
1550 Ed:= Sender as TATSynEdit;
1551
1552 if FrameKind=efkBinaryViewer then
1553 begin
1554 case ACommand of
1555 cCommand_ZoomIn:
1556 begin
1557 Binary.IncreaseFontSize(true);
1558 end;
1559 cCommand_ZoomOut:
1560 begin
1561 Binary.IncreaseFontSize(false);
1562 end;
1563 cCommand_ZoomReset:
1564 begin
1565 Binary.Font.Size:= EditorOps.OpFontSize;
1566 Binary.Redraw;
1567 end;
1568 cCommand_ToggleUnprinted:
1569 begin
1570 Binary.TextNonPrintable:= not Binary.TextNonPrintable;
1571 Binary.Redraw;
1572 end;
1573 end;
1574 exit;
1575 end;
1576
1577 if Ed.Carets.Count=0 then exit; //allow multi-carets, for auto-pairing of tags
1578 Caret:= Ed.Carets[0];
1579 if not Ed.Strings.IsIndexValid(Caret.PosY) then exit;
1580 bTypedChar:= false;
1581
1582 //some commands affect FTextCharsTyped
1583 case ACommand of
1584 cCommand_KeyBackspace:
1585 begin
1586 if FTextCharsTyped>0 then
1587 begin
1588 Dec(FTextCharsTyped);
1589 CancelAutocompleteAutoshow(Ed);
1590 end;
1591 exit;
1592 end;
1593
1594 cCommand_ToggleReadOnly:
1595 begin
1596 DoPyEventState(Ed, EDSTATE_READONLY);
1597 exit;
1598 end;
1599
1600 cCommand_ToggleWordWrap,
1601 cCommand_ToggleWordWrapAlt:
1602 begin
1603 DoPyEventState(Ed, EDSTATE_WRAP);
1604 exit;
1605 end;
1606
1607 cCommand_ZoomIn,
1608 cCommand_ZoomOut,
1609 cCommand_ZoomReset:
1610 begin
1611 if ACommand=cCommand_ZoomReset then
1612 begin
1613 NValue:= EditorScaleFontPercents;
1614 if NValue=0 then
1615 NValue:= EditorScalePercents;
1616 end
1617 else
1618 NValue:= Ed.OptScaleFont;
1619 OnMsgStatus(Self, Format(msgStatusFontSizeChanged, [NValue]));
1620 exit;
1621 end;
1622
1623 cCommand_TextInsert:
1624 begin
1625 if AText='' then exit;
1626
1627 if AText='>' then
1628 begin
1629 EditorAutoCloseOpeningHtmlTag(Ed, Caret.PosX, Caret.PosY);
1630 Ed.Update; //fix missed repainting
1631 exit;
1632 end;
1633
1634 if AText='/' then
1635 begin
1636 EditorAutoCloseClosingHtmlTag(Ed, Caret.PosX, Caret.PosY);
1637 Ed.Update; //fix missed repainting
1638 exit;
1639 end;
1640
1641 //autoshow autocompletion after typing N letters
1642 bTypedChar:= (Length(AText)=1) or (UTF8Length(AText)=1);
1643 if bTypedChar then
1644 begin
1645 if Length(AText)=1 then
1646 charW:= WideChar(Ord(AText[1]))
1647 else
1648 charW:= UTF8Decode(AText)[1];
1649 if IsCharWord(charW, Ed.OptNonWordChars) then
1650 begin
1651 if EditorAutoCompletionAfterTypingChar(Ed, AText, FTextCharsTyped, OnCallAutoCompletion) then
1652 exit;
1653 end
1654 else
1655 CancelAutocompleteAutoshow(Ed);
1656 end;
1657 end;
1658 end; //case ACommand of
1659
1660 if Ed.LastCommandChangedLines>0 then
1661 if Assigned(FOnMsgStatus) then
1662 FOnMsgStatus(Self, Format(msgStatusChangedLinesCount, [Ed.LastCommandChangedLines]));
1663 end;
1664
1665 procedure TEditorFrame.EditorOnClickDouble(Sender: TObject; var AHandled: boolean);
1666 var
1667 Params: TAppVariantArray;
1668 Res: TAppPyEventResult;
1669 begin
1670 SetLength(Params, 1);
1671 Params[0]:= AppVariant(ConvertShiftStateToString(KeyboardStateToShiftState));
1672
1673 Res:= DoPyEvent(Sender as TATSynEdit, cEventOnClickDbl, Params);
1674 AHandled:= Res.Val=evrFalse;
1675 end;
1676
1677 procedure TEditorFrame.EditorOnClickLink(Sender: TObject; const ALink: string);
1678 var
1679 Params: TAppVariantArray;
1680 Res: TAppPyEventResult;
1681 bHandled: boolean;
1682 begin
1683 SetLength(Params, 2);
1684 Params[0]:= AppVariant(ConvertShiftStateToString(KeyboardStateToShiftState));
1685 Params[1]:= AppVariant(ALink);
1686
1687 Res:= DoPyEvent(Sender as TATSynEdit, cEventOnClickLink, Params);
1688 bHandled:= Res.Val=evrFalse;
1689 if not bHandled then
1690 if Assigned(FOnAppClickLink) then
1691 FOnAppClickLink(Sender, ALink);
1692 end;
1693
1694 procedure TEditorFrame.EditorOnClickMicroMap(Sender: TObject; AX, AY: integer);
1695 var
1696 Ed: TATSynEdit;
1697 begin
1698 Ed:= Sender as TATSynEdit;
1699 AY:= AY * Ed.Strings.Count div Ed.ClientHeight;
1700 Ed.DoGotoPos(
1701 Point(0, AY),
1702 Point(-1, -1),
1703 UiOps.FindIndentHorz,
1704 UiOps.FindIndentVert,
1705 false{APlaceCaret}, //user asked to not move caret on micromap click
1706 true
1707 );
1708 end;
1709
1710 procedure TEditorFrame.EditorOnClickGap(Sender: TObject;
1711 AGapItem: TATGapItem; APos: TPoint);
1712 var
1713 Params: TAppVariantArray;
1714 Ed: TATSynEdit;
1715 W, H: integer;
1716 begin
1717 if not Assigned(AGapItem) then exit;
1718 Ed:= Sender as TATSynEdit;
1719
1720 if Assigned(AGapItem.Bitmap) then
1721 begin
1722 W:= AGapItem.Bitmap.Width;
1723 H:= AGapItem.Bitmap.Height;
1724 end
1725 else
1726 begin
1727 W:= 0;
1728 H:= 0;
1729 end;
1730
1731 SetLength(Params, 7);
1732 Params[0]:= AppVariant(ConvertShiftStateToString(KeyboardStateToShiftState));
1733 Params[1]:= AppVariant(AGapItem.LineIndex);
1734 Params[2]:= AppVariant(AGapItem.Tag);
1735 Params[3]:= AppVariant(W);
1736 Params[4]:= AppVariant(H);
1737 Params[5]:= AppVariant(APos.X);
1738 Params[6]:= AppVariant(APos.Y);
1739
1740 DoPyEvent(Ed, cEventOnClickGap, Params);
1741 end;
1742
1743
1744 procedure TEditorFrame.DoOnResize;
1745 begin
1746 inherited;
1747
1748 //this keeps ratio of splitter (e.g. 50%) on form resize
1749 SplitPos:= SplitPos;
1750 end;
1751
1752 procedure TEditorFrame.InitEditor(var ed: TATSynEdit; const AName: string);
1753 begin
1754 ed:= TATSynEdit.Create(FFormDummy);
1755 ed.CudatextFrame:= Self;
1756 ed.Name:= AName;
1757 ed.Parent:= FFormDummy;
1758 DoControl_InitPropsObject(ed, FFormDummy, 'editor');
1759
1760 ed.DoubleBuffered:= UiOps.DoubleBuffered;
1761
1762 ed.Font.Name:= EditorOps.OpFontName;
1763 ed.FontItalic.Name:= EditorOps.OpFontName_i;
1764 ed.FontBold.Name:= EditorOps.OpFontName_b;
1765 ed.FontBoldItalic.Name:= EditorOps.OpFontName_bi;
1766
1767 ed.Font.Size:= EditorOps.OpFontSize;
1768 ed.FontItalic.Size:= EditorOps.OpFontSize_i;
1769 ed.FontBold.Size:= EditorOps.OpFontSize_b;
1770 ed.FontBoldItalic.Size:= EditorOps.OpFontSize_bi;
1771
1772 ed.Font.Quality:= EditorOps.OpFontQuality;
1773
1774 ed.BorderStyle:= bsNone;
1775 ed.Keymap:= AppKeymapMain;
1776 ed.TabStop:= false;
1777 ed.OptUnprintedVisible:= EditorOps.OpUnprintedShow;
1778 ed.OptRulerVisible:= EditorOps.OpRulerShow;
1779 ed.OptBorderVisible:= false;
1780 ed.CommandLog.MaxCount:= EditorOps.OpCommandLogMaxCount;
1781
1782 ed.OnClick:= @EditorOnClick;
1783 ed.OnClickLink:=@EditorOnClickLink;
1784 ed.OnClickDouble:= @EditorOnClickDouble;
1785 ed.OnClickMoveCaret:= @EditorClickMoveCaret;
1786 ed.OnClickEndSelect:= @EditorClickEndSelect;
1787 ed.OnClickGap:= @EditorOnClickGap;
1788 ed.OnClickMicromap:= @EditorOnClickMicroMap;
1789 ed.OnEnter:= @EditorOnEnter;
1790 ed.OnChange:= @EditorOnChange;
1791 ed.OnChangeModified:= @EditorOnChangeModified;
1792 ed.OnChangeCaretPos:= @EditorOnChangeCaretPos;
1793 ed.OnChangeState:= @EditorOnChangeState;
1794 ed.OnChangeZoom:= @EditorOnChangeZoom;
1795 ed.OnChangeBookmarks:= @EditorOnChangeBookmarks;
1796 ed.OnCommand:= @EditorOnCommand;
1797 ed.OnCommandAfter:= @EditorOnCommandAfter;
1798 ed.OnClickGutter:= @EditorOnClickGutter;
1799 ed.OnCalcBookmarkColor:= @EditorOnCalcBookmarkColor;
1800 ed.OnDrawBookmarkIcon:= @EditorOnDrawBookmarkIcon;
1801 ed.OnDrawLine:= @EditorOnDrawLine;
1802 ed.OnKeyDown:= @EditorOnKeyDown;
1803 ed.OnKeyUp:= @EditorOnKeyUp;
1804 ed.OnDrawMicromap:= @EditorDrawMicromap;
1805 ed.OnPaste:=@EditorOnPaste;
1806 ed.OnScroll:=@EditorOnScroll;
1807 ed.OnHotspotEnter:=@EditorOnHotspotEnter;
1808 ed.OnHotspotExit:=@EditorOnHotspotExit;
1809 ed.ScrollbarVert.OnOwnerDraw:= @EditorDrawScrollbarVert;
1810 end;
1811
1812 constructor TEditorFrame.Create(AOwner: TComponent; AApplyCentering: boolean);
1813 begin
1814 inherited Create(AOwner);
1815
1816 //we need TFormDummy object to allow working with controls via API dlg_proc
1817 FFormDummy:= TFormDummy.Create(Self);
1818 FFormDummy.Visible:= false;
1819 FFormDummy.BorderStyle:= bsNone;
1820 FFormDummy.KeyPreview:= false; //to not break the 'cancel carets (Esc)' command
1821 FFormDummy.Align:= alClient;
1822 FFormDummy.Parent:= Self;
1823 FFormDummy.Visible:= true;
1824
1825 Splitter:= TSplitter.Create(FFormDummy);
1826 Splitter.Parent:= FFormDummy;
1827 Splitter.Name:= 'split';
1828 Splitter.Align:= alBottom;
1829 Splitter.AutoSnap:= false;
1830 Splitter.ResizeStyle:= rsPattern;
1831 Splitter.MinSize:= 100;
1832 Splitter.Color:= GetAppColor(apclSplitMain);
1833 DoControl_InitPropsObject(Splitter, FFormDummy, 'splitter');
1834
1835 FFileName:= '';
1836 FFileName2:= '';
1837 FActiveSecondaryEd:= false;
1838 FTabColor:= clNone;
1839 Inc(FLastTabId);
1840 FTabId:= FLastTabId;
1841 FTabImageIndex:= -1;
1842 FInSession:= false;
1843 FEnabledCodeTree[0]:= true;
1844 FEnabledCodeTree[1]:= true;
1845 FSaveHistory:= true;
1846 FEditorsLinked:= true;
1847 FCodetreeFilterHistory:= TStringList.Create;
1848 FCachedTreeview[0]:= nil;
1849 FCachedTreeview[1]:= nil;
1850
1851 MacroStrings:= TStringList.Create;
1852 MacroStrings.TextLineBreakStyle:= tlbsLF;
1853
1854 FBracketHilite:= EditorOps.OpBracketHilite;
1855 FBracketSymbols:= EditorOps.OpBracketSymbols;
1856 FBracketMaxDistance:= EditorOps.OpBracketDistance;
1857
1858 InitEditor(Ed1, 'ed1');
1859 InitEditor(Ed2, 'ed2');
1860
1861 Ed1.Strings.GutterDecor1:= Ed1.GutterDecor;
1862 Ed1.Strings.GutterDecor2:= Ed2.GutterDecor;
1863
1864 Ed2.Visible:= false;
1865 Splitter.Visible:= false;
1866
1867 Ed1.EditorIndex:= 0;
1868 Ed2.EditorIndex:= 1;
1869
1870 FSplitHorz:= UiOps.DefaultTabSplitIsHorz;
1871 Splitted:= false;
1872 Ed1.Align:= alClient;
1873 Ed2.Align:= cSplitHorzToAlign[FSplitHorz];
1874 Splitter.Align:= cSplitHorzToAlign[FSplitHorz];
1875 Splitter.OnMoved:= @SplitterMoved;
1876
1877 Adapter1:= TATAdapterEControl.Create(Self);
1878 Adapter1.EnabledSublexerTreeNodes:= UiOps.TreeSublexers;
1879 Adapter1.AddEditor(Ed1);
1880 Adapter1.AddEditor(Ed2);
1881
1882 //load options
1883 EditorApplyOps(Ed1, EditorOps, true, true, AApplyCentering, false);
1884 EditorApplyOps(Ed2, EditorOps, true, true, AApplyCentering, false);
1885 EditorApplyTheme(Ed1);
1886 EditorApplyTheme(Ed2);
1887
1888 //newdoc props
1889 case UiOps.NewdocEnds of
1890 0: Ed1.Strings.Endings:= {$ifdef windows} cEndWin {$else} cEndUnix {$endif};
1891 1: Ed1.Strings.Endings:= cEndUnix;
1892 2: Ed1.Strings.Endings:= cEndWin;
1893 3: Ed1.Strings.Endings:= cEndMac;
1894 end;
1895 Ed2.Strings.Endings:= Ed1.Strings.Endings;
1896
1897 Ed1.Strings.ClearUndo;
1898 Ed1.Strings.EncodingDetectDefaultUtf8:= UiOps.DefaultEncUtf8;
1899
1900 Ed1.EncodingName:= AppEncodingShortnameToFullname(UiOps.NewdocEnc);
1901
1902 //must clear Modified, it was set on initing
1903 Ed1.Modified:= false;
1904 Ed2.Modified:= false;
1905 end;
1906
1907 destructor TEditorFrame.Destroy;
1908 var
1909 Params: TAppVariantArray;
1910 begin
1911 if Assigned(FBin) then
1912 begin
1913 FBin.OpenStream(nil, False); //ARedraw=False to not paint on Win desktop with DC=0
1914 FreeAndNil(FBin);
1915 end;
1916
1917 if Assigned(FMicromapBmp) then
1918 FreeAndNil(FMicromapBmp);
1919
1920 if Assigned(FBinStream) then
1921 FreeAndNil(FBinStream);
1922
1923 if Assigned(FImageBox) then
1924 FreeAndNil(FImageBox);
1925
1926 Ed1.AdapterForHilite:= nil;
1927 Ed2.AdapterForHilite:= nil;
1928
1929 Ed1.Strings.GutterDecor1:= nil;
1930 Ed1.Strings.GutterDecor2:= nil;
1931 if not FEditorsLinked then
1932 begin
1933 Ed2.Strings.GutterDecor1:= nil;
1934 Ed2.Strings.GutterDecor2:= nil;
1935 end;
1936
1937 if not Application.Terminated then //prevent crash on exit
1938 begin
1939 SetLength(Params, 0);
1940 DoPyEvent(Ed1, cEventOnClose, Params);
1941 end;
1942
1943 FreeAndNil(MacroStrings);
1944 FreeAndNil(FCodetreeFilterHistory);
1945
1946 inherited;
1947 end;
1948
Editornull1949 function TEditorFrame.Editor: TATSynEdit;
1950 begin
1951 if FActiveSecondaryEd then
1952 Result:= Ed2
1953 else
1954 Result:= Ed1;
1955 end;
1956
EditorBronull1957 function TEditorFrame.EditorBro: TATSynEdit;
1958 begin
1959 if not FActiveSecondaryEd then
1960 Result:= Ed2
1961 else
1962 Result:= Ed1;
1963 end;
1964
GetAdapternull1965 function TEditorFrame.GetAdapter(Ed: TATSynEdit): TATAdapterEControl;
1966 begin
1967 if (Ed=Ed1) or EditorsLinked then
1968 Result:= Adapter1
1969 else
1970 Result:= Adapter2;
1971 end;
1972
TEditorFrame.EditorObjToTreeviewIndexnull1973 function TEditorFrame.EditorObjToTreeviewIndex(Ed: TATSynEdit): integer;
1974 begin
1975 if (Ed=Ed1) or EditorsLinked then
1976 Result:= 0
1977 else
1978 Result:= 1;
1979 end;
1980
GetCachedTreeviewInitednull1981 function TEditorFrame.GetCachedTreeviewInited(Ed: TATSynEdit): boolean;
1982 var
1983 N: integer;
1984 begin
1985 N:= EditorObjToTreeviewIndex(Ed);
1986 Result:= Assigned(FCachedTreeview[N]);
1987 end;
1988
TEditorFrame.GetCachedTreeviewnull1989 function TEditorFrame.GetCachedTreeview(Ed: TATSynEdit): TTreeView;
1990 var
1991 N: integer;
1992 begin
1993 N:= EditorObjToTreeviewIndex(Ed);
1994 if FCachedTreeview[N]=nil then
1995 begin
1996 FCachedTreeview[N]:= TTreeView.Create(Self);
1997 FCachedTreeview[N].OnDeletion:=@TreeOnDeletion;
1998 end;
1999 Result:= FCachedTreeview[N];
2000 end;
2001
IsEmptynull2002 function TEditorFrame.IsEmpty: boolean;
2003 begin
2004 //dont check Modified here
2005 if EditorsLinked then
2006 Result:= (FFileName='') and EditorIsEmpty(Ed1)
2007 else
2008 Result:= (FFileName='') and (FFileName2='') and
2009 EditorIsEmpty(Ed1) and EditorIsEmpty(Ed2);
2010 end;
2011
2012 procedure TEditorFrame.ApplyThemeToInfoPanel(APanel: TPanel);
2013 begin
2014 APanel.Font.Name:= UiOps.VarFontName;
2015 APanel.Font.Size:= AppScaleFont(UiOps.VarFontSize);
2016 APanel.Color:= GetAppColor(apclListBg);
2017 APanel.Font.Color:= GetAppColor(apclListFont);
2018 end;
2019
2020 procedure TEditorFrame.ApplyTheme;
2021 begin
2022 EditorApplyTheme(Ed1);
2023 EditorApplyTheme(Ed2);
2024
2025 if Assigned(FBin) then
2026 begin
2027 ViewerApplyTheme(FBin);
2028 FBin.Redraw();
2029 end;
2030
2031 Splitter.Color:= GetAppColor(apclSplitMain);
2032
2033 if Assigned(PanelInfo) then
2034 ApplyThemeToInfoPanel(PanelInfo);
2035 end;
2036
IsEditorFocusednull2037 function TEditorFrame.IsEditorFocused: boolean;
2038 begin
2039 Result:= Ed1.Focused or Ed2.Focused;
2040 end;
2041
FrameKindnull2042 function TEditorFrame.FrameKind: TATEditorFrameKind;
2043 begin
2044 if Assigned(FBin) and FBin.Visible then
2045 Result:= efkBinaryViewer
2046 else
2047 if Assigned(FImageBox) and FImageBox.Visible then
2048 Result:= efkImageViewer
2049 else
2050 Result:= efkEditor;
2051 end;
2052
2053
2054 procedure TEditorFrame.SetLexer(Ed: TATSynEdit; an: TecSyntAnalyzer);
2055 var
2056 an2: TecSyntAnalyzer;
2057 Ada: TATAdapterEControl;
2058 Params: TAppVariantArray;
2059 begin
2060 {
2061 //it breaks code-tree, issue #3348
2062 ada:= Adapter[Ed];
2063 if Assigned(ada) and Assigned(ada.Lexer) then
2064 if not ada.Stop then exit;
2065 }
2066
2067 if (an=nil) or IsFileTooBigForLexer(GetFileName(Ed)) then
2068 begin
2069 if EditorsLinked then
2070 begin
2071 Ed1.AdapterForHilite:= nil;
2072 Ed2.AdapterForHilite:= nil;
2073 if Assigned(Adapter1) then
2074 Adapter1.Lexer:= nil;
2075 if Assigned(Adapter2) then
2076 Adapter2.Lexer:= nil;
2077 end
2078 else
2079 begin
2080 Ed.AdapterForHilite:= nil;
2081 if Ed=Ed1 then
2082 begin
2083 if Assigned(Adapter1) then
2084 Adapter1.Lexer:= nil;
2085 end
2086 else
2087 begin
2088 if Assigned(Adapter2) then
2089 Adapter2.Lexer:= nil;
2090 end;
2091 end;
2092 exit;
2093 end;
2094
2095 if UiOps.AllowFrameParsing then
2096 begin
2097 if Assigned(an) then
2098 begin
2099 if EditorsLinked then
2100 begin
2101 Ed1.AdapterForHilite:= Adapter1;
2102 Ed2.AdapterForHilite:= Adapter1;
2103 end
2104 else
2105 begin
2106 if Ed=Ed1 then
2107 Ed1.AdapterForHilite:= Adapter1
2108 else
2109 begin
2110 if Adapter2=nil then
2111 begin
2112 Adapter2:= TATAdapterEControl.Create(Self);
2113 Adapter2.EnabledSublexerTreeNodes:= UiOps.TreeSublexers;
2114 OnInitAdapter(Adapter2);
2115 end;
2116 Ed2.AdapterForHilite:= Adapter2;
2117 end;
2118 end;
2119
2120 if not DoApplyLexerStylesMap(an, an2) then
2121 DoDialogLexerStylesMap(an2);
2122 end
2123 else
2124 begin
2125 Ed.Fold.Clear;
2126 Ed.Update;
2127 if (Ed=Ed1) and EditorsLinked then
2128 begin
2129 Ed2.Fold.Clear;
2130 Ed2.Update;
2131 end;
2132 end;
2133
2134 if Ed.AdapterForHilite is TATAdapterEControl then
2135 begin
2136 Ada:= TATAdapterEControl(Ed.AdapterForHilite);
2137 Ada.Lexer:= an;
2138
2139 if Assigned(an) then
2140 EditorStartParse(Ed);
2141 end;
2142 end
2143 else
2144 begin
2145 LexerInitial[Ed]:= an;
2146 //support on_lexer
2147 SetLength(Params, 0);
2148 DoPyEvent(Ed, cEventOnLexer, Params);
2149 end;
2150 end;
2151
2152 procedure TEditorFrame.SetLexerLite(Ed: TATSynEdit; an: TATLiteLexer);
2153 begin
2154 Lexer[Ed]:= nil;
2155
2156 Ed.AdapterForHilite:= an;
2157 Ed.Update;
2158
2159 if (Ed=Ed1) and EditorsLinked then
2160 begin
2161 Ed2.AdapterForHilite:= an;
2162 Ed2.Update;
2163 end;
2164
2165 //to apply lexer-specific config
2166 OnLexerChange(Ed);
2167 end;
2168
2169 procedure TEditorFrame.DoFileOpen_AsBinary(const AFileName: string; AMode: TATBinHexMode);
2170 begin
2171 FFileName:= AFileName;
2172 UpdateCaptionFromFilename;
2173
2174 Ed1.Hide;
2175 Ed2.Hide;
2176 Splitter.Hide;
2177 ReadOnly[Ed1]:= true;
2178
2179 if Assigned(FImageBox) then
2180 FImageBox.Hide;
2181
2182 if Assigned(FBin) then
2183 FBin.OpenStream(nil)
2184 else
2185 begin
2186 FBin:= TATBinHex.Create(FFormDummy);
2187 FBin.Hide; //reduce flicker with initial size
2188 FBin.OnKeyDown:= @BinaryOnKeyDown;
2189 FBin.OnScroll:= @BinaryOnScroll;
2190 FBin.OnOptionsChange:= @BinaryOnScroll;
2191 FBin.OnSearchProgress:= @BinaryOnProgress;
2192 FBin.Parent:= FFormDummy;
2193 FBin.Align:= alClient;
2194 FBin.BorderStyle:= bsNone;
2195 FBin.ResizeFollowTail:= false; //fixes scrolling to the end on file loading
2196 FBin.TextGutter:= true;
2197 FBin.TextPopupCommands:= [vpCmdCopy, vpCmdCopyHex, vpCmdSelectAll];
2198 FBin.TextPopupCaption[vpCmdCopy]:= cStrMenuitemCopy;
2199 FBin.TextPopupCaption[vpCmdCopyHex]:= cStrMenuitemCopy+' (hex)';
2200 FBin.TextPopupCaption[vpCmdSelectAll]:= cStrMenuitemSelectAll;
2201 FBin.Show;
2202 end;
2203
2204 FBin.TextWidth:= UiOps.ViewerBinaryWidth;
2205 FBin.TextNonPrintable:= UiOps.ViewerNonPrintable;
2206 FBin.Mode:= AMode;
2207
2208 if Assigned(FBinStream) then
2209 FreeAndNil(FBinStream);
2210 FBinStream:= TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
2211
2212 ViewerApplyTheme(FBin);
2213 FBin.Show;
2214 FBin.OpenStream(FBinStream);
2215 FBin.PosBegin;
2216
2217 if Visible and FBin.Visible and FBin.CanFocus then
2218 FBin.SetFocus;
2219
2220 //DoOnChangeCaption; //needed?
2221 end;
2222
2223
2224 procedure TEditorFrame.DoFileOpen_AsPicture(const AFileName: string);
2225 begin
2226 FFileName:= AFileName;
2227 UpdateCaptionFromFilename;
2228
2229 Ed1.Hide;
2230 Ed2.Hide;
2231 Splitter.Hide;
2232 ReadOnly[Ed1]:= true;
2233
2234 if not Assigned(FImageBox) then
2235 begin
2236 FImageBox:= TATImageBox.Create(FFormDummy);
2237 FImageBox.Parent:= FFormDummy;
2238 FImageBox.Align:= alClient;
2239 FImageBox.BorderStyle:= bsNone;
2240 FImageBox.OptFitToWindow:= true;
2241 FImageBox.OnScroll:= @DoImageboxScroll;
2242 FImageBox.OnKeyDown:= @BinaryOnKeyDown;
2243 end;
2244
2245 try
2246 FImageBox.Show;
2247 FImageBox.LoadFromFile(AFileName);
2248 except
2249 end;
2250
2251 //DoOnChangeCaption; //needed?
2252 end;
2253
2254 procedure TEditorFrame.DoImageboxScroll(Sender: TObject);
2255 begin
2256 DoOnUpdateStatusbar;
2257 end;
2258
2259
2260 procedure TEditorFrame.DoDeactivatePictureMode;
2261 begin
2262 if Assigned(FImageBox) then
2263 begin
2264 FreeAndNil(FImageBox);
2265 Ed1.Show;
2266 ReadOnly[Ed1]:= false;
2267 end;
2268 end;
2269
2270 procedure TEditorFrame.DoDeactivateViewerMode;
2271 begin
2272 if Assigned(FBin) then
2273 begin
2274 FBin.OpenStream(nil, false);
2275 FreeAndNil(FBin);
2276
2277 if Assigned(FBinStream) then
2278 FreeAndNil(FBinStream);
2279
2280 Ed1.Show;
2281 ReadOnly[Ed1]:= false;
2282 end;
2283 end;
2284
2285 procedure TEditorFrame.DoFileOpen(const AFileName, AFileName2: string;
2286 AAllowLoadHistory, AAllowLoadBookmarks, AAllowLexerDetect, AAllowErrorMsgBox, AAllowLoadUndo: boolean;
2287 AOpenMode: TAppOpenMode);
2288 begin
2289 NotifEnabled:= false; //for binary-viewer and pictures, NotifEnabled must be False
2290 FileProps.Inited:= false; //loading of new filename must not trigger notif-thread
2291
2292 if Assigned(FBin) then
2293 FBin.Hide;
2294 if Assigned(FImageBox) then
2295 FImageBox.Hide;
2296
2297 if not FileExists(AFileName) then exit;
2298 if (AFileName2<>'') then
2299 if not FileExists(AFileName2) then exit;
2300
2301 if UiOps.InfoAboutOptionsEditor then
2302 if (CompareFilenames(AFileName, AppFile_OptionsUser)=0) or
2303 (CompareFilenames(AFileName, AppFile_OptionsDefault)=0) then
2304 InitPanelInfo(msgSuggestOptionsEditor, @PanelInfoClick);
2305
2306 Lexer[Ed1]:= nil;
2307 if not EditorsLinked then
2308 Lexer[Ed2]:= nil;
2309
2310 case AOpenMode of
2311 cOpenModeViewText:
2312 begin
2313 DoFileOpen_AsBinary(AFileName, vbmodeText);
2314 exit;
2315 end;
2316 cOpenModeViewBinary:
2317 begin
2318 DoFileOpen_AsBinary(AFileName, vbmodeBinary);
2319 exit;
2320 end;
2321 cOpenModeViewHex:
2322 begin
2323 DoFileOpen_AsBinary(AFileName, vbmodeHex);
2324 exit;
2325 end;
2326 cOpenModeViewUnicode:
2327 begin
2328 DoFileOpen_AsBinary(AFileName, vbmodeUnicode);
2329 exit;
2330 end;
2331 cOpenModeViewUHex:
2332 begin
2333 DoFileOpen_AsBinary(AFileName, vbmodeUHex);
2334 exit;
2335 end;
2336 end;
2337
2338 if IsFilenameListedInExtensionList(AFileName, UiOps.PictureTypes) then
2339 begin
2340 DoFileOpen_AsPicture(AFileName);
2341 exit;
2342 end;
2343
2344 DoDeactivatePictureMode;
2345 DoDeactivateViewerMode;
2346
2347 DoFileOpen_Ex(Ed1, AFileName,
2348 AAllowLoadHistory,
2349 AAllowLoadHistory,
2350 AAllowLoadBookmarks,
2351 AAllowLexerDetect,
2352 AAllowErrorMsgBox,
2353 false,
2354 AAllowLoadUndo,
2355 AOpenMode);
2356
2357 if AFileName2<>'' then
2358 begin
2359 EditorsLinked:= false;
2360 SplitHorz:= false;
2361 Splitted:= true;
2362 DoFileOpen_Ex(Ed2, AFileName2,
2363 AAllowLoadHistory,
2364 AAllowLoadHistory,
2365 AAllowLoadBookmarks,
2366 AAllowLexerDetect,
2367 AAllowErrorMsgBox,
2368 false,
2369 AAllowLoadUndo,
2370 AOpenMode);
2371 end;
2372
2373 DoOnUpdateStatusbar;
2374 end;
2375
2376 procedure TEditorFrame.DoFileOpen_Ex(Ed: TATSynEdit; const AFileName: string;
2377 AAllowLoadHistory, AAllowLoadHistoryEnc, AAllowLoadBookmarks, AAllowLexerDetect,
2378 AAllowErrorMsgBox, AKeepScroll, AAllowLoadUndo: boolean; AOpenMode: TAppOpenMode);
2379 begin
2380 try
2381 if AKeepScroll then
2382 Ed.Strings.EncodingDetect:= false;
2383 Ed.LoadFromFile(AFileName, AKeepScroll);
2384 Ed.Strings.EncodingDetect:= true;
2385 SetFileName(Ed, AFileName);
2386 UpdateCaptionFromFilename;
2387 except
2388 if AAllowErrorMsgBox then
2389 MsgBox(msgCannotOpenFile+#10+AFileName, MB_OK or MB_ICONERROR);
2390
2391 SetFileName(Ed, '');
2392 UpdateCaptionFromFilename;
2393
2394 EditorClear(Ed);
2395 exit
2396 end;
2397
2398 //turn off opts for huge files
2399 FileWasBig[Ed]:= Ed.Strings.Count>EditorOps.OpWrapEnabledMaxLines;
2400
2401 if AAllowLoadUndo then
2402 DoLoadUndo(Ed);
2403
2404 DoLoadHistory(Ed, AAllowLoadHistoryEnc, AAllowLoadHistory, AAllowLoadBookmarks);
2405
2406 //save temp-options, to later know which options are changed,
2407 //during loading of lexer-specific config
2408 EditorSaveTempOptions(Ed, Ed.InitialOptions);
2409
2410 if AAllowLexerDetect then
2411 DoLexerFromFilename(Ed, AFileName);
2412
2413 UpdateReadOnlyFromFile(Ed);
2414 NotifEnabled:= true;
2415 end;
2416
2417 procedure TEditorFrame.UpdateReadOnlyFromFile(Ed: TATSynEdit);
2418 var
2419 b: boolean;
2420 begin
2421 if Ed.IsReadOnlyChanged then exit;
2422 b:= AppIsFileReadonly(GetFileName(Ed));
2423 ReadOnly[Ed]:= b;
2424 if b then
2425 Ed.IsReadOnlyAutodetected:= true;
2426 end;
2427
2428 procedure TEditorFrame.UpdateFrame(AUpdatedText: boolean);
2429 var
2430 Ad: TATAdapterEControl;
2431 begin
2432 Ed1.DoCaretsFixIncorrectPos(false);
2433 Ed2.DoCaretsFixIncorrectPos(false);
2434
2435 Ed1.Update(AUpdatedText);
2436 Ed2.Update(AUpdatedText);
2437
2438 if AUpdatedText then
2439 begin
2440 Ad:= Adapter[Ed1];
2441 Ad.OnEditorChange(Ed1);
2442
2443 if not EditorsLinked then
2444 begin
2445 Ad:= Adapter[Ed2];
2446 if Assigned(Ad) then
2447 Ad.OnEditorChange(Ed2);
2448 end;
2449 end;
2450 end;
2451
2452 procedure TEditorFrame.FixLexerIfDeleted(Ed: TATSynEdit; const ALexerName: string);
2453 begin
2454 if LexerName[Ed]=ALexerName then
2455 Lexer[Ed]:= nil;
2456 //fix crash:
2457 //F.InitialLexer is C#, user deletes C# in lexer lib, and switches tab
2458 if Assigned(LexerInitial[Ed]) and (LexerInitial[Ed].LexerName=ALexerName) then
2459 LexerInitial[Ed]:= nil;
2460 end;
2461
GetFileNamenull2462 function TEditorFrame.GetFileName(Ed: TATSynEdit): string;
2463 begin
2464 if EditorsLinked or (Ed=Ed1) then
2465 Result:= FFileName
2466 else
2467 Result:= FFileName2;
2468 end;
2469
2470 procedure TEditorFrame.SetFileName(Ed: TATSynEdit; const AFileName: string);
2471 begin
2472 Ed.FileName:= AFileName;
2473 if EditorsLinked or (Ed=Ed1) then
2474 FFileName:= AFileName
2475 else
2476 FFileName2:= AFileName;
2477 end;
2478
TEditorFrame.DoFileSavenull2479 function TEditorFrame.DoFileSave(ASaveAs, AAllEditors: boolean): boolean;
2480 begin
2481 Result:= true;
2482 if not EditorsLinked and AAllEditors then
2483 begin
2484 Result:= DoFileSave_Ex(Ed1, ASaveAs);
2485 Result:= DoFileSave_Ex(Ed2, ASaveAs);
2486 end
2487 else
2488 begin
2489 Result:= DoFileSave_Ex(Editor, ASaveAs);
2490 end;
2491
2492 if ASaveAs then
2493 UpdateTabTooltip;
2494 end;
2495
DoFileSave_Exnull2496 function TEditorFrame.DoFileSave_Ex(Ed: TATSynEdit; ASaveAs: boolean): boolean;
2497 var
2498 An: TecSyntAnalyzer;
2499 bNameChanged, bNotifWasEnabled: boolean;
2500 NameCounter: integer;
2501 SFileName, NameTemp, NameInitial: string;
2502 EventRes: TAppPyEventResult;
2503 Params: TAppVariantArray;
2504 begin
2505 Result:= true;
2506 if FrameKind<>efkEditor then exit(true); //disable saving, but close
2507
2508 SetLength(Params, 0);
2509 EventRes:= DoPyEvent(Ed, cEventOnSaveBefore, Params);
2510 if EventRes.Val=evrFalse then exit(true); //disable saving, but close
2511
2512 DoHideNotificationPanel(EditorObjToIndex(Ed));
2513
2514 SFileName:= GetFileName(Ed);
2515 bNameChanged:= ASaveAs or (SFileName='');
2516
2517 if bNameChanged then
2518 begin
2519 An:= Lexer[Ed];
2520 if Assigned(An) then
2521 begin
2522 SaveDialog.DefaultExt:= DoGetLexerDefaultExt(An);
2523 SaveDialog.Filter:= DoGetLexerFileFilter(An, msgAllFiles);
2524 end
2525 else
2526 begin
2527 SaveDialog.DefaultExt:= '';
2528 SaveDialog.Filter:= '';
2529 end;
2530
2531 if SFileName='' then
2532 begin
2533 NameInitial:= '';
2534 EventRes:= DoPyEvent(Ed, cEventOnSaveNaming, Params);
2535 if EventRes.Val=evrString then
2536 NameInitial:= EventRes.Str;
2537 if NameInitial='' then
2538 NameInitial:= 'new';
2539
2540 //get first free filename: new.txt, new1.txt, new2.txt, ...
2541 NameCounter:= 0;
2542 repeat
2543 NameTemp:= SaveDialog.InitialDir+DirectorySeparator+
2544 NameInitial+IfThen(NameCounter>0, IntToStr(NameCounter))+
2545 SaveDialog.DefaultExt; //DefaultExt with dot
2546 if not FileExists(NameTemp) then
2547 begin
2548 SaveDialog.FileName:= ExtractFileName(NameTemp);
2549 Break
2550 end;
2551 Inc(NameCounter);
2552 until false;
2553 end
2554 else
2555 begin
2556 SaveDialog.FileName:= ExtractFileName(SFileName);
2557 SaveDialog.InitialDir:= ExtractFileDir(SFileName);
2558 end;
2559
2560 if not SaveDialog.Execute then
2561 exit(false);
2562
2563 if OnCheckFilenameOpened(SaveDialog.FileName) then
2564 begin
2565 MsgBox(
2566 msgStatusFilenameAlreadyOpened+#10+
2567 ExtractFileName(SaveDialog.FileName)+#10#10+
2568 msgStatusNeedToCloseTabSavedOrDup, MB_OK or MB_ICONWARNING);
2569 exit;
2570 end;
2571
2572 //add to recents previous filename
2573 if Assigned(FOnAddRecent) then
2574 FOnAddRecent(Ed);
2575
2576 SFileName:= SaveDialog.FileName;
2577
2578 //remove read-only (it may be set for original file)
2579 ReadOnly[Ed]:= false;
2580
2581 //add to recents new filename
2582 if Assigned(FOnAddRecent) then
2583 FOnAddRecent(Ed);
2584 end;
2585
2586 bNotifWasEnabled:= NotifEnabled;
2587 NotifEnabled:= false;
2588
2589 //EditorSaveFileAs is big:
2590 //handles save errors,
2591 //handles exception from encoding conversion (saves in UTF8 if exception)
2592 Result:= EditorSaveFileAs(Ed, SFileName);
2593
2594 if bNameChanged then
2595 DoLexerFromFilename(Ed, SFileName);
2596
2597 if Result then
2598 begin
2599 SetFileName(Ed, SFileName);
2600
2601 if not TabCaptionFromApi then
2602 UpdateCaptionFromFilename;
2603
2604 DoSaveUndo(Ed, SFileName);
2605 DoPyEvent(Ed, cEventOnSaveAfter, Params);
2606 if Assigned(FOnSaveFile) then
2607 FOnSaveFile(Self);
2608 end;
2609
2610 if EditorsLinked or (Ed=Ed1) then
2611 AppGetFileProps(GetFileName(Ed), FileProps)
2612 else
2613 AppGetFileProps(GetFileName(Ed), FileProps2);
2614
2615 NotifEnabled:= bNotifWasEnabled or bNameChanged;
2616 end;
2617
2618 procedure TEditorFrame.DoFileReload_DisableDetectEncoding(Ed: TATSynEdit);
2619 var
2620 SFileName: string;
2621 begin
2622 SFileName:= GetFileName(Ed);
2623 if SFileName='' then exit;
2624 if Ed.Modified then
2625 if MsgBox(
2626 Format(msgConfirmReopenModifiedTab, [ExtractFileName(SFileName)]),
2627 MB_OKCANCEL or MB_ICONWARNING
2628 ) <> ID_OK then exit;
2629
2630 Ed.Strings.EncodingDetect:= false;
2631 Ed.Strings.LoadFromFile(SFileName);
2632 Ed.Strings.EncodingDetect:= true;
2633 UpdateEds(true);
2634 end;
2635
TEditorFrame.DoFileReloadnull2636 function TEditorFrame.DoFileReload(Ed: TATSynEdit): boolean;
2637 var
2638 PrevCaretX, PrevCaretY: integer;
2639 PrevTail: boolean;
2640 Mode: TAppOpenMode;
2641 SFileName: string;
2642 Params: TAppVariantArray;
2643 begin
2644 Result:= true;
2645 SFileName:= GetFileName(Ed);
2646 if SFileName='' then exit(false);
2647
2648 if not FileExists(SFileName) then
2649 begin
2650 OnMsgStatus(Self, msgCannotFindFile+' '+ExtractFileName(SFileName));
2651 exit(false);
2652 end;
2653
2654 DoHideNotificationPanel(EditorObjToIndex(Ed));
2655
2656 //remember props
2657 PrevCaretX:= 0;
2658 PrevCaretY:= 0;
2659
2660 if Ed.Carets.Count>0 then
2661 with Ed.Carets[0] do
2662 begin
2663 PrevCaretX:= PosX;
2664 PrevCaretY:= PosY;
2665 end;
2666
2667 PrevTail:= UiOps.ReloadFollowTail and
2668 (Ed.Strings.Count>0) and
2669 (PrevCaretY=Ed.Strings.Count-1);
2670
2671 Mode:= cOpenModeEditor;
2672 if FrameKind=efkBinaryViewer then
2673 case FBin.Mode of
2674 vbmodeText:
2675 Mode:= cOpenModeViewText;
2676 vbmodeBinary:
2677 Mode:= cOpenModeViewBinary;
2678 vbmodeHex:
2679 Mode:= cOpenModeViewHex;
2680 vbmodeUnicode:
2681 Mode:= cOpenModeViewUnicode;
2682 vbmodeUHex:
2683 Mode:= cOpenModeViewUHex;
2684 else
2685 Mode:= cOpenModeViewHex;
2686 end;
2687
2688 //reopen
2689 DoSaveHistory(Ed);
2690 DoFileOpen_Ex(Ed, SFileName,
2691 true{AllowLoadHistory},
2692 false{AllowLoadHistoryEnc},
2693 false{AllowLoadBookmarks},
2694 false{AllowLexerDetect},
2695 false{AllowMsgBox},
2696 true{KeepScroll},
2697 true{AllowLoadUndo},
2698 Mode);
2699
2700 //fix issue #3394
2701 if EditorsLinked and Splitted and (Ed=Ed1) then
2702 begin
2703 Ed2.Update(true);
2704 Ed2.DoCaretsFixIncorrectPos(false);
2705 end;
2706
2707 if Ed.Strings.Count=0 then exit;
2708
2709 //restore props
2710 PrevCaretY:= Min(PrevCaretY, Ed.Strings.Count-1);
2711 if PrevTail then
2712 begin
2713 PrevCaretX:= 0;
2714 PrevCaretY:= Ed.Strings.Count-1;
2715 end;
2716
2717 Application.ProcessMessages; //for DoGotoPos
2718
2719 Ed.DoGotoPos(
2720 Point(PrevCaretX, PrevCaretY),
2721 Point(-1, -1),
2722 1,
2723 1, //indentVert must be >0
2724 true,
2725 false
2726 );
2727
2728 OnUpdateStatusbar(Self);
2729
2730 //fire 'on_change_slow' and disable its timer
2731 TimerChangeTimer(nil);
2732 end;
2733
2734 procedure TEditorFrame.SetLineEnds(Ed: TATSynEdit; AValue: TATLineEnds);
2735 begin
2736 if GetLineEnds(Ed)=AValue then Exit;
2737
2738 Ed.Strings.Endings:= AValue;
2739 Ed.Update;
2740 if (Ed=Ed1) and EditorsLinked then
2741 Ed2.Update;
2742 end;
2743
2744 procedure TEditorFrame.SetUnprintedShow(AValue: boolean);
2745 begin
2746 Ed1.OptUnprintedVisible:= AValue;
2747 UpdateEds;
2748 end;
2749
2750 procedure TEditorFrame.SetUnprintedSpaces(AValue: boolean);
2751 begin
2752 Ed1.OptUnprintedSpaces:= AValue;
2753 UpdateEds;
2754 end;
2755
2756 procedure TEditorFrame.SetEditorsLinked(AValue: boolean);
2757 begin
2758 if FEditorsLinked=AValue then exit;
2759 FEditorsLinked:= AValue;
2760
2761 if FEditorsLinked then
2762 Ed2.Strings:= Ed1.Strings
2763 else
2764 Ed2.Strings:= nil;
2765
2766 Ed1.Strings.GutterDecor1:= Ed1.GutterDecor;
2767 if FEditorsLinked then
2768 begin
2769 Ed1.Strings.GutterDecor2:= Ed2.GutterDecor;
2770 end
2771 else
2772 begin
2773 Ed1.Strings.GutterDecor2:= nil;
2774 Ed2.Strings.GutterDecor1:= Ed2.GutterDecor;
2775 Ed2.Strings.GutterDecor2:= nil;
2776 end;
2777
2778 Adapter1.AddEditor(nil);
2779 if Assigned(Adapter2) then
2780 Adapter2.AddEditor(nil);
2781
2782 if FEditorsLinked then
2783 begin
2784 Adapter1.AddEditor(Ed1);
2785 Adapter1.AddEditor(Ed2);
2786 end
2787 else
2788 begin
2789 if Adapter2=nil then
2790 begin
2791 Adapter2:= TATAdapterEControl.Create(Self);
2792 Adapter2.EnabledSublexerTreeNodes:= UiOps.TreeSublexers;
2793 OnInitAdapter(Adapter2);
2794 end;
2795 Adapter1.AddEditor(Ed1);
2796 Adapter2.AddEditor(Ed2);
2797 end;
2798
2799 Ed2.Fold.Clear;
2800 Ed2.Update(true);
2801 end;
2802
2803 procedure TEditorFrame.SplitterMoved(Sender: TObject);
2804 begin
2805 FSplitPos:= GetSplitPosCurrent;
2806 end;
2807
2808 procedure TEditorFrame.TreeOnDeletion(Sender: TObject; Node: TTreeNode);
2809 begin
2810 if Assigned(Node.Data) then
2811 begin
2812 TObject(Node.Data).Free;
2813 Node.Data:= nil;
2814 end;
2815 end;
2816
2817 procedure TEditorFrame.SetUnprintedEnds(AValue: boolean);
2818 begin
2819 Ed1.OptUnprintedEnds:= AValue;
2820 UpdateEds;
2821 end;
2822
2823 procedure TEditorFrame.SetUnprintedEndsDetails(AValue: boolean);
2824 begin
2825 Ed1.OptUnprintedEndsDetails:= AValue;
2826 UpdateEds;
2827 end;
2828
2829 procedure TEditorFrame.EditorOnClickGutter(Sender: TObject; ABand, ALine: integer);
2830 var
2831 Ed: TATSynEdit;
2832 Params: TAppVariantArray;
2833 begin
2834 Ed:= Sender as TATSynEdit;
2835
2836 SetLength(Params, 3);
2837 Params[0]:= AppVariant(ConvertShiftStateToString(KeyboardStateToShiftState));
2838 Params[1]:= AppVariant(ALine);
2839 Params[2]:= AppVariant(ABand);
2840
2841 if DoPyEvent(Ed, cEventOnClickGutter, Params).Val = evrFalse then exit;
2842
2843 if ABand=Ed.GutterBandBookmarks then
2844 ed.BookmarkToggleForLine(ALine, 1, '', bmadOption, true, 0);
2845 end;
2846
2847 procedure TEditorFrame.EditorOnDrawBookmarkIcon(Sender: TObject; C: TCanvas; ALineNum: integer;
2848 const ARect: TRect);
2849 var
2850 Ed: TATSynEdit;
2851 r: TRect;
2852 dx: integer;
2853 index, kind: integer;
2854 begin
2855 r:= ARect;
2856 if r.Left>=r.Right then exit;
2857
2858 Ed:= Sender as TATSynEdit;
2859 index:= Ed.Strings.Bookmarks.Find(ALineNum);
2860 if index<0 then exit;
2861
2862 kind:= Ed.Strings.Bookmarks[index]^.Data.Kind;
2863 if kind<=1 then
2864 begin
2865 c.brush.color:= GetAppColor(apclEdBookmarkIcon);
2866 c.pen.color:= c.brush.color;
2867 inc(r.top, 1);
2868 inc(r.left, 4);
2869 dx:= r.Height div 2-1;
2870 c.Polygon([Point(r.left, r.top), Point(r.left+dx, r.top+dx), Point(r.left, r.top+2*dx)]);
2871 end
2872 else
2873 if (kind>=Low(AppBookmarkSetup)) and (kind<=High(AppBookmarkSetup)) then
2874 begin
2875 AppBookmarkImagelist.Draw(c, r.left, r.top,
2876 AppBookmarkSetup[kind].ImageIndex);
2877 end;
2878 end;
2879
2880
GetCommentStringnull2881 function TEditorFrame.GetCommentString(Ed: TATSynEdit): string;
2882 var
2883 an: TecSyntAnalyzer;
2884 begin
2885 Result:= '';
2886 an:= Adapter[Ed].Lexer;
2887 if Assigned(an) then
2888 Result:= an.LineComment;
2889 end;
2890
TEditorFrame.GetEnabledCodeTreenull2891 function TEditorFrame.GetEnabledCodeTree(Ed: TATSynEdit): boolean;
2892 begin
2893 if (Ed=Ed1) or EditorsLinked then
2894 Result:= FEnabledCodeTree[0]
2895 else
2896 Result:= FEnabledCodeTree[1];
2897 end;
2898
GetEnabledFoldingnull2899 function TEditorFrame.GetEnabledFolding: boolean;
2900 begin
2901 Result:= Editor.OptFoldEnabled;
2902 end;
2903
GetFileWasBignull2904 function TEditorFrame.GetFileWasBig(Ed: TATSynEdit): boolean;
2905 var
2906 Index: integer;
2907 begin
2908 Index:= EditorObjToIndex(Ed);
2909 if Index>=0 then
2910 Result:= FFileWasBig[Index]
2911 else
2912 Result:= false;
2913 end;
2914
TEditorFrame.GetInitialLexernull2915 function TEditorFrame.GetInitialLexer(Ed: TATSynEdit): TecSyntAnalyzer;
2916 var
2917 Index: integer;
2918 begin
2919 if EditorsLinked then
2920 Result:= FInitialLexer1
2921 else
2922 begin
2923 Index:= EditorObjToIndex(Ed);
2924 if Index=0 then
2925 Result:= FInitialLexer1
2926 else
2927 Result:= FInitialLexer2;
2928 end;
2929 end;
2930
2931 procedure TEditorFrame.DoOnChangeCaption;
2932 begin
2933 if Assigned(FOnChangeCaption) then
2934 FOnChangeCaption(Self);
2935 end;
2936
2937 procedure TEditorFrame.DoMacroStartOrStop;
2938 begin
2939 if FMacroRecord then
2940 begin
2941 FMacroRecord:= false;
2942 DoPyEvent_Macro(MacroStrings.Text);
2943 end
2944 else
2945 begin
2946 FMacroRecord:= true;
2947 MacroStrings.Clear;
2948 end;
2949
2950 Ed1.ModeMacroRecording:= FMacroRecord;
2951 Ed1.Update;
2952 Ed2.ModeMacroRecording:= FMacroRecord;
2953 Ed2.Update;
2954 end;
2955
2956 procedure TEditorFrame.DoMacroStop(ACancel: boolean);
2957 begin
2958 FMacroRecord:= false;
2959
2960 Ed1.ModeMacroRecording:= FMacroRecord;
2961 Ed1.Update;
2962 Ed2.ModeMacroRecording:= FMacroRecord;
2963 Ed2.Update;
2964
2965 if ACancel then
2966 MacroStrings.Clear
2967 else
2968 DoPyEvent_Macro(MacroStrings.Text);
2969 end;
2970
2971 procedure TEditorFrame.DoOnUpdateStatusbar;
2972 begin
2973 if Assigned(FOnUpdateStatusbar) then
2974 FOnUpdateStatusbar(Self);
2975 end;
2976
2977 procedure TEditorFrame.DoOnUpdateState;
2978 begin
2979 if Assigned(FOnUpdateState) then
2980 FOnUpdateState(Self);
2981 end;
2982
2983 procedure TEditorFrame.DoOnUpdateZoom;
2984 begin
2985 if Assigned(FOnUpdateZoom) then
2986 FOnUpdateZoom(Self);
2987 end;
2988
2989 procedure TEditorFrame.EditorClickMoveCaret(Sender: TObject; APrevPnt, ANewPnt: TPoint);
2990 var
2991 Pnt: TPoint;
2992 begin
2993 if MacroRecord then
2994 begin
2995 Pnt:= ConvertTwoPointsToDiffPoint(APrevPnt, ANewPnt);
2996 MacroStrings.Add(Format('%d,%d,%d', [cmd_MouseClickNearCaret, Pnt.X, Pnt.Y]));
2997 end;
2998 end;
2999
3000 procedure TEditorFrame.EditorDrawMicromap(Sender: TObject; ACanvas: TCanvas; const ARect: TRect);
3001 begin
3002 PaintMicromap(Sender as TATSynEdit, ACanvas, ARect);
3003 end;
3004
3005 procedure TEditorFrame.EditorDrawScrollbarVert(Sender: TObject;
3006 AType: TATScrollbarElemType; ACanvas: TCanvas; const ARect, ARect2: TRect;
3007 var ACanDraw: boolean);
3008 var
3009 Ed: TATSynEdit;
3010 begin
3011 Ed:= (Sender as TATScrollBar).Parent as TATSynEdit;
3012 if Ed.OptMicromapVisible and Ed.OptMicromapOnScrollbar and (AType=aseBackAndThumbV) then
3013 begin
3014 ACanDraw:= false;
3015 PaintMicromap(Ed, ACanvas, ARect);
3016 end
3017 else
3018 ACanDraw:= true;
3019 end;
3020
3021 procedure TEditorFrame.PaintMicromap(Ed: TATSynEdit; ACanvas: TCanvas; const ARect: TRect);
3022 {
3023 micromap has columns:
3024 column_0: width 50% of char cell, it's used for line states
3025 column_1: width 50% of char cell, it's used for boomkarks + plugins marks
3026 right edge column: width 50% of char cell, it's used for selections
3027 so, for different micromap rect widths, some columns may overlap, e.g. right_edge and column_1
3028 }
3029 type
3030 TAppMicromapMarkPos = (markColumn, markFull, markRight);
3031 const
3032 cTagOccurrences = 101; //see plugin 'Highlight Occurrences'
3033 cTagSpellChecker = 105; //see plugin 'Spell Checker'
3034 cTagColumnFullsized = -2;
3035 var
3036 NWidthSmall: integer;
3037 //
GetItemRectnull3038 function GetItemRect(AColumn, NLine1, NLine2: integer; AMarkPos: TAppMicromapMarkPos): TRect;
3039 begin
3040 Result:= Ed.RectMicromapMark(AColumn, NLine1, NLine2, ARect.Height, EditorOps.OpMicromapMinMarkHeight);
3041 case AMarkPos of
3042 markRight:
3043 begin
3044 Result.Right:= ARect.Width;
3045 Result.Left:= Result.Right - NWidthSmall;
3046 end;
3047 markFull:
3048 begin
3049 Result.Left:= 0;
3050 Result.Right:= ARect.Width;
3051 end;
3052 end;
3053 end;
3054 //
3055 var
3056 St: TATStrings;
3057 Caret: TATCaretItem;
3058 LineState: TATLineState;
3059 Marker: TATMarkerItem;
3060 Bookmarks: TATBookmarks;
3061 BookmarkPtr: PATBookmarkItem;
3062 LinePartObj: TATLinePartClass;
3063 XColor, XColorSelected, XColorOccur, XColorSpell: TBGRAPixel;
3064 NColor: TColor;
3065 RectMark: TRect;
3066 NLine1, NLine2, NIndex, i: integer;
3067 begin
3068 St:= Ed.Strings;
3069 if St.Count=0 then exit;
3070 NWidthSmall:= Ed.TextCharSize.XScaled * EditorOps.OpMicromapSmallMarkSizePercents div 100 div ATEditorCharXScale;
3071
3072 if FMicromapBmp=nil then
3073 FMicromapBmp:= TBGRABitmap.Create;
3074 FMicromapBmp.SetSize(ARect.Width, ARect.Height);
3075
3076 XColor.FromColor(GetAppColor(apclEdMicromapBg));
3077 FMicromapBmp.Fill(XColor);
3078
3079 //paint full-width area of current visible area
3080 RectMark:= GetItemRect(0, Ed.LineTop, Ed.LineBottom, markFull);
3081 XColor.FromColor(GetAppColor(apclEdMicromapViewBg));
3082 FMicromapBmp.FillRect(RectMark, XColor);
3083
3084 XColorSelected.FromColor(Ed.Colors.TextSelBG);
3085 XColorOccur.FromColor(GetAppColor(apclEdMicromapOccur));
3086 XColorSpell.FromColor(GetAppColor(apclEdMicromapSpell));
3087
3088 //paint line states
3089 if Ed.OptMicromapLineStates and (St.Count>=Ed.OptMicromapShowForMinCount) then
3090 for i:= 0 to St.Count-1 do
3091 begin
3092 //if Ed.IsLineFolded(i) then
3093 // Continue;
3094 LineState:= St.LinesState[i];
3095 case LineState of
3096 cLineStateNone: Continue;
3097 cLineStateAdded: XColor.FromColor(Ed.Colors.StateAdded);
3098 cLineStateChanged: XColor.FromColor(Ed.Colors.StateChanged);
3099 cLineStateSaved: XColor.FromColor(Ed.Colors.StateSaved);
3100 else Continue;
3101 end;
3102 RectMark:= GetItemRect(0{column_0}, i, i, markColumn);
3103 FMicromapBmp.FillRect(RectMark, XColor);
3104 end;
3105
3106 //paint selections
3107 if Ed.OptMicromapSelections then
3108 for i:= 0 to Ed.Carets.Count-1 do
3109 begin
3110 Caret:= Ed.Carets[i];
3111 Caret.GetSelLines(NLine1, NLine2, false);
3112 if NLine1<0 then Continue;
3113 RectMark:= GetItemRect(0, NLine1, NLine2, markRight);
3114 FMicromapBmp.FillRect(RectMark, XColorSelected);
3115 end;
3116
3117 //paint background of columns added from Py API
3118 for i:= 2{after default columns} to Length(Ed.Micromap.Columns)-1 do
3119 begin
3120 NColor:= Ed.Micromap.Columns[i].NColor;
3121 if NColor<>clNone then
3122 begin
3123 XColor.FromColor(NColor);
3124 RectMark:= Ed.RectMicromapMark(i, -1, -1, ARect.Height, EditorOps.OpMicromapMinMarkHeight);
3125 FMicromapBmp.FillRect(RectMark, XColor);
3126 end;
3127 end;
3128
3129 //paint bookmarks
3130 if Ed.OptMicromapBookmarks then
3131 begin
3132 Bookmarks:= Ed.Strings.Bookmarks;
3133 XColor.FromColor(Ed.Colors.StateAdded); //not sure what color to take
3134 for i:= 0 to Bookmarks.Count-1 do
3135 begin
3136 BookmarkPtr:= Bookmarks.ItemPtr[i];
3137 NIndex:= BookmarkPtr^.Data.LineNum;
3138 //if Ed.IsLineFolded(NIndex) then
3139 // Continue;
3140 RectMark:= Ed.RectMicromapMark(1{column}, NIndex, NIndex, ARect.Height, EditorOps.OpMicromapMinMarkHeight);
3141 FMicromapBmp.FillRect(RectMark, XColor);
3142 end;
3143 end;
3144
3145 //paint marks for plugins
3146 for i:= 0 to Ed.Attribs.Count-1 do
3147 begin
3148 Marker:= Ed.Attribs[i];
3149 LinePartObj:= TATLinePartClass(Marker.Ptr);
3150
3151 NLine1:= Marker.PosY;
3152 NLine2:= NLine1;
3153 //negative LenX means we need multiline Marker, its height is abs(LenX)
3154 if Marker.SelX<0 then
3155 Inc(NLine2, -Marker.SelX-1);
3156
3157 case Marker.Tag of
3158 cTagSpellChecker:
3159 begin
3160 RectMark:= GetItemRect(1{column_1}, NLine1, NLine2, markColumn);
3161 FMicromapBmp.FillRect(RectMark, XColorSpell);
3162 end;
3163 cTagOccurrences:
3164 begin
3165 RectMark:= GetItemRect(1{column_1}, NLine1, NLine2, markColumn);
3166 FMicromapBmp.FillRect(RectMark, XColorOccur);
3167 end;
3168 else
3169 begin
3170 if LinePartObj.ColumnTag>0 then
3171 begin
3172 NIndex:= Ed.Micromap.ColumnFromTag(LinePartObj.ColumnTag);
3173 if NIndex>=0 then
3174 begin
3175 //if ColorBG=none, it may be find-all-matches with custom border color, use border color
3176 if LinePartObj.Data.ColorBG<>clNone then
3177 XColor.FromColor(LinePartObj.Data.ColorBG)
3178 else
3179 XColor.FromColor(LinePartObj.Data.ColorBorder);
3180 RectMark:= GetItemRect(NIndex, NLine1, NLine2, markColumn);
3181 FMicromapBmp.FillRect(RectMark, XColor);
3182 end;
3183 end
3184 else
3185 if LinePartObj.ColumnTag=cTagColumnFullsized then
3186 begin
3187 RectMark:= GetItemRect(0, NLine1, NLine2, markFull);
3188 //todo: not tested with BGRABitmap - it must give inverted colors
3189 XColor.FromColor(LinePartObj.Data.ColorBG);
3190 FMicromapBmp.FillRect(RectMark, XColor, dmDrawWithTransparency, $8000);
3191 end;
3192 end;
3193 end;
3194 end;
3195
3196 FMicromapBmp.Draw(ACanvas, ARect.Left, ARect.Top);
3197 end;
3198
3199 procedure TEditorFrame.EditorClickEndSelect(Sender: TObject; APrevPnt, ANewPnt: TPoint);
3200 var
3201 Pnt: TPoint;
3202 begin
3203 if MacroRecord then
3204 begin
3205 Pnt:= ConvertTwoPointsToDiffPoint(APrevPnt, ANewPnt);
3206 MacroStrings.Add(Format('%d,%d,%d', [cmd_MouseClickNearCaretAndSelect, Pnt.X, Pnt.Y]));
3207 end;
3208 end;
3209
3210
3211 procedure TEditorFrame.DoSaveHistory(Ed: TATSynEdit);
3212 var
3213 cfg: TJSONConfig;
3214 SFileName: string;
3215 path: string;
3216 items: TStringlist;
3217 begin
3218 if not FSaveHistory then exit;
3219 if UiOps.MaxHistoryFiles<2 then exit;
3220
3221 SFileName:= GetFileName(Ed);
3222 if SFileName='' then exit;
3223 path:= SMaskFilenameSlashes(SFileName);
3224
3225 cfg:= TJsonConfig.Create(nil);
3226 try
3227 try
3228 cfg.Formatted:= true;
3229 cfg.Filename:= AppFile_HistoryFiles;
3230 except
3231 on E: Exception do
3232 begin
3233 MsgBadConfig(AppFile_HistoryFiles, E.Message);
3234 exit
3235 end;
3236 end;
3237
3238 items:= TStringList.Create;
3239 try
3240 cfg.DeletePath(path);
3241 cfg.EnumSubKeys('/', items);
3242 while items.Count>=UiOps.MaxHistoryFiles do
3243 begin
3244 cfg.DeletePath('/'+items[0]);
3245 items.Delete(0);
3246 end;
3247 finally
3248 FreeAndNil(items);
3249 end;
3250
3251 DoSaveHistoryEx(Ed, cfg, path, false);
3252
3253 //bookmarks are always saved to 'history files.json'
3254 if UiOps.HistoryItems[ahhBookmarks] then
3255 DoSaveHistory_Bookmarks(Ed, cfg, path);
3256 finally
3257 cfg.Free;
3258 end;
3259 end;
3260
3261 procedure TEditorFrame.DoSaveHistory_Caret(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
3262 var
3263 Caret: TATCaretItem;
3264 EndX, EndY: integer;
3265 begin
3266 if Ed.Carets.Count>0 then
3267 begin
3268 Caret:= Ed.Carets[0];
3269 if UiOps.HistoryItems[ahhCaretSel] then
3270 begin
3271 EndX:= Caret.EndX;
3272 EndY:= Caret.EndY;
3273 end
3274 else
3275 begin
3276 EndX:= -1;
3277 EndY:= -1;
3278 end;
3279
3280 //note: don't use c.SetDeleteValue here because non-empty value is always needed:
3281 //app loads file from session and skips history if key is empty
3282 c.SetValue(path+cHistory_Caret,
3283 Format('%d,%d,%d,%d,', [Caret.PosX, Caret.PosY, EndX, EndY])
3284 );
3285 end;
3286 end;
3287
3288 procedure TEditorFrame.DoLoadHistory_Bookmarks(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
3289 var
3290 SKey, SValue: UnicodeString;
3291 begin
3292 if Ed.FileName<>'' then
3293 begin
3294 SKey:= AppConfigKeyForBookmarks(Ed);
3295 SValue:= c.GetValue(SKey, '');
3296 if SValue<>'' then
3297 EditorStringToBookmarks(Ed, SValue);
3298 end;
3299 end;
3300
3301 procedure TEditorFrame.DoSaveHistory_Bookmarks(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString);
3302 var
3303 SKey: UnicodeString;
3304 begin
3305 if Ed.FileName<>'' then
3306 begin
3307 SKey:= AppConfigKeyForBookmarks(Ed);
3308 if Ed.Strings.Bookmarks.Count>0 then
3309 c.SetValue(SKey, EditorBookmarksToString(Ed))
3310 else
3311 c.DeleteValue(SKey);
3312 end;
3313 end;
3314
3315 procedure TEditorFrame.DoSaveHistoryEx(Ed: TATSynEdit; c: TJsonConfig; const path: UnicodeString;
3316 AForSession: boolean);
3317 begin
3318 //save 'split' value only when we have single file splitted,
3319 //but not 2 different files (like user.json + default.json)
3320 if FileName2='' then
3321 if UiOps.HistoryItems[ahhTabSplit] then
3322 begin
3323 if Splitted then
3324 c.SetValue(path+cHistory_TabSplit, Format('%s,%d', [
3325 BoolToStr(SplitHorz, '1', '0'),
3326 Round(SplitPos*cHistory_TabSplit_Mul)
3327 ]))
3328 else
3329 c.DeleteValue(path+cHistory_TabSplit);
3330 end;
3331
3332 if UiOps.HistoryItems[ahhLexer] then
3333 c.SetDeleteValue(path+cHistory_Lexer, LexerName[Ed], '');
3334
3335 if UiOps.HistoryItems[ahhEncoding] then
3336 c.SetValue(path+cHistory_Enc, Ed.EncodingName);
3337
3338 if UiOps.HistoryItems[ahhTopLine] then
3339 begin
3340 c.SetDeleteValue(path+cHistory_TopLine, Ed.LineTop, 0);
3341 if EditorsLinked and Splitted then
3342 c.SetDeleteValue(path+cHistory_TopLine2, Ed2.LineTop, 0);
3343 end;
3344
3345 if UiOps.HistoryItems[ahhWordWrap] then
3346 c.SetDeleteValue(path+cHistory_Wrap, Ord(Ed.OptWrapMode), Ord(EditorOps.OpWrapMode));
3347
3348 if not Ed.IsReadOnlyAutodetected then
3349 c.SetDeleteValue(path+cHistory_ReadOnly, ReadOnly[Ed], false);
3350
3351 if UiOps.HistoryItems[ahhRuler] then
3352 c.SetDeleteValue(path+cHistory_Ruler, Ord(Ed.OptRulerVisible), Ord(EditorOps.OpRulerShow));
3353
3354 if UiOps.HistoryItems[ahhMinimap] then
3355 c.SetDeleteValue(path+cHistory_Minimap, Ord(Ed.OptMinimapVisible), Ord(EditorOps.OpMinimapShow));
3356
3357 if UiOps.HistoryItems[ahhMicromap] then
3358 c.SetDeleteValue(path+cHistory_Micromap, Ord(Ed.OptMicromapVisible), Ord(EditorOps.OpMicromapShow));
3359
3360 if UiOps.HistoryItems[ahhTabSize] then
3361 begin
3362 c.SetValue(path+cHistory_TabSize, Ed.OptTabSize);
3363 c.SetValue(path+cHistory_TabSpace, Ed.OptTabSpaces);
3364 end;
3365
3366 if UiOps.HistoryItems[ahhUnprinted] then
3367 begin
3368 c.SetDeleteValue(path+cHistory_Unpri, Ord(Ed.OptUnprintedVisible), Ord(EditorOps.OpUnprintedShow));
3369 c.SetDeleteValue(path+cHistory_Unpri_Spaces, Ord(Ed.OptUnprintedSpaces), Ord(Pos('s', EditorOps.OpUnprintedContent)>0));
3370 c.SetDeleteValue(path+cHistory_Unpri_Ends, Ord(Ed.OptUnprintedEnds), Ord(Pos('e', EditorOps.OpUnprintedContent)>0));
3371 c.SetDeleteValue(path+cHistory_Unpri_Detail, Ord(Ed.OptUnprintedEndsDetails), Ord(Pos('d', EditorOps.OpUnprintedContent)>0));
3372 end;
3373
3374 if UiOps.HistoryItems[ahhLineNumbers] then
3375 c.SetDeleteValue(path+cHistory_LineNums, Ord(Ed.Gutter[Ed.GutterBandNumbers].Visible), 1);
3376
3377 if UiOps.HistoryItems[ahhScale] then
3378 c.SetDeleteValue(path+cHistory_FontScale, Ed.OptScaleFont, 0);
3379
3380 if UiOps.HistoryItems[ahhFolding] then
3381 begin
3382 c.SetDeleteValue(path+cHistory_FoldingShow, Ord(Ed.Gutter[Ed.GutterBandFolding].Visible), 1);
3383 c.SetDeleteValue(path+cHistory_FoldedRanges, Ed.FoldingAsString, '');
3384 end;
3385
3386 if UiOps.HistoryItems[ahhTabColor] then
3387 begin
3388 if TabColor=clNone then
3389 c.DeleteValue(path+cHistory_TabColor)
3390 else
3391 c.SetValue(path+cHistory_TabColor, ColorToString(TabColor));
3392 end;
3393
3394 if UiOps.HistoryItems[ahhCaret] then
3395 DoSaveHistory_Caret(Ed, c, path);
3396
3397 {
3398 //it's bad to save markers along with other history items,
3399 //because if a snippet (with markers) inserted + file was not saved after it,
3400 //we have wrong markers to save
3401 if UiOps.HistoryItems[ahhMarkers] then
3402 c.SetDeleteValue(path+cHistory_Markers, Ed.Markers.AsString, '');
3403 }
3404
3405 if UiOps.HistoryItems[ahhCodeTreeFilter] then
3406 begin
3407 c.SetDeleteValue(path+cHistory_CodeTreeFilter, FCodetreeFilter, '');
3408
3409 if FCodetreeFilterHistory.Count>0 then
3410 c.SetValue(path+cHistory_CodeTreeFilters, FCodetreeFilterHistory)
3411 else
3412 c.DeleteValue(path+cHistory_CodeTreeFilters);
3413 end;
3414 end;
3415
3416 procedure _WriteStringToFileInHiddenDir(const fn, s: string);
3417 var
3418 dir: string;
3419 begin
3420 if s<>'' then
3421 begin
3422 dir:= ExtractFileDir(fn);
3423 if not DirectoryExists(dir) then
3424 begin
3425 CreateDir(dir);
3426 {$ifdef windows}
3427 FileSetAttr(dir, faHidden);
3428 {$endif}
3429 end;
3430 DoWriteStringToFile(fn, s);
3431 end
3432 else
3433 begin
3434 if FileExists(fn) then
3435 DeleteFile(fn);
3436 end;
3437 end;
3438
3439 procedure TEditorFrame.DoSaveUndo(Ed: TATSynEdit; const AFileName: string);
3440 begin
3441 if IsFilenameListedInExtensionList(AFileName, UiOps.UndoPersistent) then
3442 begin
3443 _WriteStringToFileInHiddenDir(GetAppUndoFilename(AFileName, false), Ed.UndoAsString);
3444 _WriteStringToFileInHiddenDir(GetAppUndoFilename(AFileName, true), Ed.RedoAsString);
3445 end;
3446 end;
3447
3448 procedure TEditorFrame.DoLoadHistory(Ed: TATSynEdit; AllowLoadEncoding, AllowLoadHistory, AllowLoadBookmarks: boolean);
3449 var
3450 cfg: TJSONConfig;
3451 SFileName: string;
3452 path: string;
3453 begin
3454 SFileName:= GetFileName(Ed);
3455 if SFileName='' then exit;
3456
3457 path:= SMaskFilenameSlashes(SFileName);
3458
3459 if not (AllowLoadHistory or AllowLoadBookmarks) then exit;
3460 if UiOps.MaxHistoryFiles<2 then exit;
3461
3462 AppFileCheckForNullBytes(AppFile_HistoryFiles);
3463
3464 cfg:= TJsonConfig.Create(nil);
3465 try
3466 try
3467 cfg.Formatted:= true;
3468 cfg.Filename:= AppFile_HistoryFiles;
3469 except
3470 on E: Exception do
3471 begin
3472 MsgBadConfig(AppFile_HistoryFiles, E.Message);
3473 exit
3474 end;
3475 end;
3476
3477 if AllowLoadHistory then
3478 DoLoadHistoryEx(Ed, cfg, path, AllowLoadEncoding);
3479
3480 if AllowLoadBookmarks then
3481 DoLoadHistory_Bookmarks(Ed, cfg, path);
3482 finally
3483 cfg.Free;
3484 end;
3485 end;
3486
3487
3488 procedure TEditorFrame.DoLoadHistoryEx(Ed: TATSynEdit; c: TJsonConfig;
3489 const path: UnicodeString; AllowEnc: boolean);
3490 var
3491 str, str0, sFileName, sCaretString: string;
3492 Caret: TATCaretItem;
3493 NCaretPosX, NCaretPosY,
3494 NCaretEndX, NCaretEndY: integer;
3495 nTop, i: integer;
3496 Sep: TATStringSeparator;
3497 NFlag: integer;
3498 begin
3499 sFileName:= GetFileName(Ed);
3500
3501 //file not listed in history file? exit
3502 sCaretString:= c.GetValue(path+cHistory_Caret, '');
3503 if sCaretString='' then exit;
3504
3505 {
3506 //markers
3507 //it's bad to save markers along with other history items,
3508 //so this is commented
3509 Ed.Markers.AsString:= c.GetValue(path+cHistory_Markers, '');
3510 }
3511
3512 //split state
3513 str:= c.GetValue(path+cHistory_TabSplit, '');
3514 if str<>'' then
3515 begin
3516 Sep.Init(str);
3517 Sep.GetItemInt(i, 0);
3518 SplitHorz:= i=1;
3519 Splitted:= true;
3520 Sep.GetItemInt(i, 0);
3521 if i>0 then
3522 SplitPos:= i/cHistory_TabSplit_Mul;
3523 end;
3524
3525 //lexer
3526 str0:= LexerName[Ed];
3527 str:= c.GetValue(path+cHistory_Lexer, ''); //missed value means none-lexer (for Cud 1.104 or older)
3528 if (str='') or (str<>str0) then //better call it for none-lexer to apply "keys lexer -.json"
3529 LexerName[Ed]:= str;
3530
3531 //encoding
3532 if AllowEnc then
3533 begin
3534 str0:= Ed.EncodingName;
3535 str:= c.GetValue(path+cHistory_Enc, str0);
3536 if str<>str0 then
3537 begin
3538 Ed.EncodingName:= str;
3539 //reread in encoding
3540 //but only if not modified (modified means other text is loaded)
3541 if sFileName<>'' then
3542 if not Ed.Modified then
3543 begin
3544 Ed.Strings.EncodingDetect:= false;
3545 Ed.LoadFromFile(sFileName);
3546 Ed.Strings.EncodingDetect:= true;
3547 end;
3548 end;
3549 end;
3550
3551 TabColor:= StringToColorDef(c.GetValue(path+cHistory_TabColor, ''), clNone);
3552
3553 if not Ed.IsReadOnlyAutodetected then
3554 ReadOnly[Ed]:= c.GetValue(path+cHistory_ReadOnly, ReadOnly[Ed]);
3555
3556 if not FileWasBig[Ed] then
3557 begin
3558 NFlag:= c.GetValue(path+cHistory_Wrap, -1);
3559 if NFlag>=0 then
3560 if Ed.OptWrapMode<>TATEditorWrapMode(NFlag) then
3561 begin
3562 Ed.OptWrapMode:= TATEditorWrapMode(NFlag);
3563 Ed.IsModifiedWrapMode:= true;
3564 //DoPyEventState(Ed, EDSTATE_WRAP); //is not needed for session loading
3565 end;
3566
3567 NFlag:= c.GetValue(path+cHistory_Minimap, -1);
3568 if NFlag>=0 then
3569 begin
3570 Ed.OptMinimapVisible:= NFlag=1;
3571 Ed.IsModifiedMinimapVisible:= true;
3572 end;
3573
3574 NFlag:= c.GetValue(path+cHistory_Micromap, -1);
3575 if NFlag>=0 then
3576 begin
3577 Ed.OptMicromapVisible:= NFlag=1;
3578 Ed.IsModifiedMicromapVisible:= true;
3579 end;
3580 end;
3581
3582 NFlag:= c.GetValue(path+cHistory_Ruler, -1);
3583 if NFlag>=0 then
3584 begin
3585 Ed.OptRulerVisible:= NFlag=1;
3586 Ed.IsModifiedRulerVisible:= true;
3587 end;
3588
3589 Ed.OptTabSize:= c.GetValue(path+cHistory_TabSize, Ed.OptTabSize);
3590 Ed.OptTabSpaces:= c.GetValue(path+cHistory_TabSpace, Ed.OptTabSpaces);
3591
3592 NFlag:= c.GetValue(path+cHistory_Unpri, -1);
3593 if NFlag>=0 then
3594 begin
3595 Ed.OptUnprintedVisible:= NFlag=1;
3596 Ed.IsModifiedUnprintedVisible:= true;
3597 end;
3598
3599 NFlag:= c.GetValue(path+cHistory_Unpri_Spaces, -1);
3600 if NFlag>=0 then
3601 begin
3602 Ed.OptUnprintedSpaces:= NFlag=1;
3603 Ed.IsModifiedUnprintedSpaces:= true;
3604 end;
3605
3606 NFlag:= c.GetValue(path+cHistory_Unpri_Ends, -1);
3607 if NFlag>=0 then
3608 begin
3609 Ed.OptUnprintedEnds:= NFlag=1;
3610 Ed.IsModifiedUnprintedEnds:= true;
3611 end;
3612
3613 NFlag:= c.GetValue(path+cHistory_Unpri_Detail, -1);
3614 if NFlag>=0 then
3615 begin
3616 Ed.OptUnprintedEndsDetails:= NFlag=1;
3617 Ed.IsModifiedUnprintedEndDetails:= true;
3618 end;
3619
3620 with Ed.Gutter[Ed.GutterBandNumbers] do
3621 begin
3622 NFlag:= c.GetValue(path+cHistory_LineNums, -1);
3623 if NFlag>=0 then
3624 begin
3625 Visible:= NFlag=1;
3626 Ed.IsModifiedGutterNumbersVisible:= true;
3627 end;
3628 end;
3629
3630 with Ed.Gutter[Ed.GutterBandFolding] do
3631 begin
3632 NFlag:= c.GetValue(path+cHistory_FoldingShow, -1);
3633 if NFlag>=0 then
3634 begin
3635 Visible:= NFlag=1;
3636 Ed.IsModifiedGutterFoldingVisible:= true;
3637 end;
3638 end;
3639
3640 Ed.OptScaleFont:= c.GetValue(path+cHistory_FontScale, 0);
3641
3642 if Assigned(Lexer[Ed]) then
3643 Ed.FoldingAsStringTodo:= c.GetValue(path+cHistory_FoldedRanges, '');
3644
3645 nTop:= c.GetValue(path+cHistory_TopLine, 0);
3646 if nTop>0 then
3647 Ed.LineTop:= nTop;
3648
3649 if EditorsLinked and Splitted then
3650 begin
3651 nTop:= c.GetValue(path+cHistory_TopLine2, 0);
3652 if nTop>0 then
3653 Ed2.LineTop:= nTop;
3654 end;
3655
3656 //caret
3657 Sep.Init(sCaretString);
3658 Sep.GetItemInt(NCaretPosX, 0);
3659 Sep.GetItemInt(NCaretPosY, 0);
3660 Sep.GetItemInt(NCaretEndX, -1);
3661 Sep.GetItemInt(NCaretEndY, -1);
3662
3663 if Ed.Carets.Count<>1 then
3664 Ed.DoCaretSingle(0, 0);
3665 Caret:= Ed.Carets[0];
3666 if Caret.Change(NCaretPosX, NCaretPosY, NCaretEndX, NCaretEndY) then
3667 begin
3668 Ed.DoCaretsFixIncorrectPos(true);
3669 Ed.DoEventCarets;
3670 end;
3671
3672 //solve CudaText #3288, so Undo jumps to initial caret pos
3673 Ed.Strings.ActionSaveLastEditionPos(NCaretPosX, NCaretPosY);
3674
3675 FCodetreeFilter:= c.GetValue(path+cHistory_CodeTreeFilter, '');
3676 c.GetValue(path+cHistory_CodeTreeFilters, FCodetreeFilterHistory, '');
3677
3678 Ed.Update;
3679 if Splitted and EditorsLinked then
3680 Ed2.Update;
3681 end;
3682
3683 procedure TEditorFrame.DoLoadUndo(Ed: TATSynEdit);
3684 var
3685 SFileName, STemp: string;
3686 begin
3687 SFileName:= GetFileName(Ed);
3688 if SFileName='' then exit;
3689 if IsFilenameListedInExtensionList(SFileName, UiOps.UndoPersistent) then
3690 begin
3691 STemp:= GetAppUndoFilename(SFileName, false);
3692 if FileExists(STemp) then
3693 Ed.UndoAsString:= DoReadContentFromFile(STemp);
3694
3695 STemp:= GetAppUndoFilename(SFileName, true);
3696 if FileExists(STemp) then
3697 Ed.RedoAsString:= DoReadContentFromFile(STemp);
3698 end;
3699 end;
3700
TEditorFrame.DoPyEventnull3701 function TEditorFrame.DoPyEvent(AEd: TATSynEdit; AEvent: TAppPyEvent;
3702 const AParams: TAppVariantArray): TAppPyEventResult;
3703 begin
3704 if Assigned(FOnPyEvent) then
3705 Result:= FOnPyEvent(AEd, AEvent, AParams)
3706 else
3707 begin
3708 Result.Val:= evrOther;
3709 Result.Str:= '';
3710 end;
3711 end;
3712
3713 procedure TEditorFrame.DoPyEventState(Ed: TATSynEdit; AState: integer);
3714 var
3715 Params: TAppVariantArray;
3716 begin
3717 SetLength(Params, 1);
3718 Params[0]:= AppVariant(AState);
3719 DoPyEvent(Ed, cEventOnStateEd, Params);
3720 end;
3721
DoPyEvent_Macronull3722 function TEditorFrame.DoPyEvent_Macro(const AText: string): boolean;
3723 var
3724 Params: TAppVariantArray;
3725 begin
3726 SetLength(Params, 1);
3727 Params[0]:= AppVariant(AText);
3728 Result:= DoPyEvent(Editor, cEventOnMacro, Params).Val <> evrFalse;
3729 end;
3730
3731
3732 procedure TEditorFrame.SetTabColor(AColor: TColor);
3733 var
3734 Gr: TATGroups;
3735 Pages: TATPages;
3736 NLocalGroups, NGlobalGroup, NTab: integer;
3737 D: TATTabData;
3738 begin
3739 FTabColor:= AColor;
3740 GetFrameLocation(Self, Gr, Pages, NLocalGroups, NGlobalGroup, NTab);
3741 D:= Pages.Tabs.GetTabData(NTab);
3742 if Assigned(D) then
3743 begin
3744 D.TabColor:= AColor;
3745 Pages.Tabs.Invalidate;
3746 end;
3747 end;
3748
3749 procedure TEditorFrame.SetTabPinned(AValue: boolean);
3750 var
3751 Gr: TATGroups;
3752 Pages: TATPages;
3753 NLocalGroups, NGlobalGroup, NTab: integer;
3754 D: TATTabData;
3755 begin
3756 if FTabPinned=AValue then exit;
3757 FTabPinned:= AValue;
3758
3759 GetFrameLocation(Self, Gr, Pages, NLocalGroups, NGlobalGroup, NTab);
3760 D:= Pages.Tabs.GetTabData(NTab);
3761 if Assigned(D) then
3762 begin
3763 D.TabPinned:= AValue;
3764 Pages.Tabs.Invalidate;
3765 end;
3766
3767 UpdatePinned(Ed1, true);
3768 end;
3769
3770 procedure TEditorFrame.DoRemovePreviewStyle;
3771 var
3772 Gr: TATGroups;
3773 Pages: TATPages;
3774 NLocalGroup, NGlobalGroup, NTab: integer;
3775 D: TATTabData;
3776 begin
3777 GetFrameLocation(Self, Gr, Pages, NLocalGroup, NGlobalGroup, NTab);
3778 D:= Pages.Tabs.GetTabData(NTab);
3779 if Assigned(D) then
3780 begin
3781 UpdateTabPreviewStyle(D, false);
3782 Pages.Tabs.Invalidate;
3783 end;
3784 end;
3785
3786 procedure TEditorFrame.SetTabImageIndex(AValue: integer);
3787 var
3788 Gr: TATGroups;
3789 Pages: TATPages;
3790 NLocalGroup, NGlobalGroup, NTab: integer;
3791 D: TATTabData;
3792 begin
3793 if FTabImageIndex=AValue then exit;
3794 FTabImageIndex:= AValue;
3795
3796 GetFrameLocation(Self, Gr, Pages, NLocalGroup, NGlobalGroup, NTab);
3797 D:= Pages.Tabs.GetTabData(NTab);
3798 if Assigned(D) then
3799 begin
3800 D.TabImageIndex:= AValue;
3801 Pages.Tabs.Invalidate;
3802 end;
3803 end;
3804
3805
GetTabVisiblenull3806 function TEditorFrame.GetTabVisible: boolean;
3807 var
3808 Gr: TATGroups;
3809 Pages: TATPages;
3810 NLocalGroup, NGlobalGroup, NTab: integer;
3811 D: TATTabData;
3812 begin
3813 GetFrameLocation(Self, Gr, Pages, NLocalGroup, NGlobalGroup, NTab);
3814 D:= Pages.Tabs.GetTabData(NTab);
3815 if Assigned(D) then
3816 Result:= D.TabVisible
3817 else
3818 Result:= true;
3819 end;
3820
3821 procedure TEditorFrame.SetTabVisible(AValue: boolean);
3822 var
3823 Gr: TATGroups;
3824 Pages: TATPages;
3825 NLocalGroup, NGlobalGroup, NTab: integer;
3826 D: TATTabData;
3827 begin
3828 GetFrameLocation(Self, Gr, Pages, NLocalGroup, NGlobalGroup, NTab);
3829 D:= Pages.Tabs.GetTabData(NTab);
3830 if Assigned(D) then
3831 if D.TabVisible<>AValue then
3832 begin
3833 D.TabVisible:= AValue;
3834 Pages.Tabs.Invalidate;
3835 end;
3836 end;
3837
3838 procedure TEditorFrame.InitPanelInfo(const AText: string; AOnClick: TNotifyEvent);
3839 begin
3840 if not AppPython.Inited then exit;
3841
3842 if not Assigned(PanelInfo) then
3843 begin
3844 PanelInfo:= TPanel.Create(Self);
3845 PanelInfo.Parent:= Self;
3846 PanelInfo.Align:= alTop;
3847 PanelInfo.Visible:= false;
3848 PanelInfo.Height:= AppScale(26);
3849 PanelInfo.BevelOuter:= bvNone;
3850 end;
3851
3852 ApplyThemeToInfoPanel(PanelInfo);
3853
3854 PanelInfo.Caption:= AText;
3855 PanelInfo.OnClick:= AOnClick;
3856
3857 PanelInfo.Show;
3858 end;
3859
3860 procedure TEditorFrame.InitPanelReload(Index: integer);
3861 var
3862 NPanelHeight, NBtnHeight: integer;
3863 begin
3864 if Assigned(PanelReload[Index]) then exit;
3865
3866 NPanelHeight:= AppScale(31);
3867 NBtnHeight:= AppScale(25);
3868
3869 PanelReload[Index]:= TPanel.Create(Self);
3870 PanelReload[Index].Parent:= Self;
3871 PanelReload[Index].Align:= alTop;
3872 PanelReload[Index].Visible:= false;
3873 PanelReload[Index].Height:= NPanelHeight;
3874 PanelReload[Index].BevelOuter:= bvNone;
3875
3876 LabelReload[Index]:= TLabel.Create(Self);
3877 LabelReload[Index].Parent:= PanelReload[Index];
3878 LabelReload[Index].BorderSpacing.Left:= 4;
3879 LabelReload[Index].ParentColor:= false;
3880 LabelReload[Index].AnchorSideLeft.Control:= PanelReload[Index];
3881 LabelReload[Index].AnchorSideTop.Control:= PanelReload[Index];
3882 LabelReload[Index].AnchorSideTop.Side:= asrCenter;
3883
3884 btnReloadNone[Index]:= TATButton.Create(Self);
3885 btnReloadNone[Index].Tag:= Index;
3886 btnReloadNone[Index].Parent:= PanelReload[Index];
3887 btnReloadNone[Index].AnchorSideTop.Control:= PanelReload[Index];
3888 btnReloadNone[Index].AnchorSideTop.Side:= asrCenter;
3889 btnReloadNone[Index].AnchorSideRight.Control:= PanelReload[Index];
3890 btnReloadNone[Index].AnchorSideRight.Side:= asrBottom;
3891 btnReloadNone[Index].Anchors:= [akTop, akRight];
3892 btnReloadNone[Index].Height:= NBtnHeight;
3893 btnReloadNone[Index].BorderSpacing.Right:= 4;
3894 btnReloadNone[Index].OnClick:= @btnReloadNoneClick;
3895
3896 btnReloadNo[Index]:= TATButton.Create(Self);
3897 btnReloadNo[Index].Tag:= Index;
3898 btnReloadNo[Index].Parent:= PanelReload[Index];
3899 btnReloadNo[Index].AnchorSideTop.Control:= btnReloadNone[Index];
3900 btnReloadNo[Index].AnchorSideRight.Control:= btnReloadNone[Index];
3901 btnReloadNo[Index].Anchors:= [akTop, akRight];
3902 btnReloadNo[Index].Height:= NBtnHeight;
3903 btnReloadNo[Index].BorderSpacing.Right:= 0;
3904 btnReloadNo[Index].OnClick:= @btnReloadNoClick;
3905
3906 btnReloadYes[Index]:= TATButton.Create(Self);
3907 btnReloadYes[Index].Tag:= Index;
3908 btnReloadYes[Index].Parent:= PanelReload[Index];
3909 btnReloadYes[Index].AnchorSideTop.Control:= btnReloadNone[Index];
3910 btnReloadYes[Index].AnchorSideRight.Control:= btnReloadNo[Index];
3911 btnReloadYes[Index].Anchors:= [akTop, akRight];
3912 btnReloadYes[Index].Height:= NBtnHeight;
3913 btnReloadYes[Index].BorderSpacing.Right:= 0;
3914 btnReloadYes[Index].OnClick:= @btnReloadYesClick;
3915
3916 btnReloadYes[Index].TabOrder:= 0;
3917 btnReloadNo[Index].TabOrder:= 1;
3918 btnReloadNone[Index].TabOrder:= 2;
3919 end;
3920
3921 procedure TEditorFrame.NotifyAboutChange(Ed: TATSynEdit);
3922 var
3923 bMsg: boolean;
3924 Index: integer;
3925 begin
3926 case UiOps.NotificationConfirmReload of
3927 1:
3928 bMsg:= Ed.Modified or not Ed.Strings.UndoEmpty;
3929 2:
3930 bMsg:= Ed.Modified; //like Notepad++
3931 else
3932 bMsg:= true;
3933 end;
3934
3935 if not bMsg then
3936 begin
3937 DoFileReload(Ed);
3938 exit
3939 end;
3940
3941 Index:= EditorObjToIndex(Ed);
3942 if Index<0 then exit;
3943 InitPanelReload(Index);
3944 ApplyThemeToInfoPanel(PanelReload[Index]);
3945
3946 btnReloadYes[Index].Caption:= msgConfirmReloadYes;
3947 btnReloadNo[Index].Caption:= msgButtonCancel;
3948 btnReloadNone[Index].Caption:= msgConfirmReloadNoMore;
3949
3950 btnReloadYes[Index].AutoSize:= true;
3951 btnReloadNo[Index].AutoSize:= true;
3952 btnReloadNone[Index].AutoSize:= true;
3953
3954 LabelReload[Index].Caption:= msgConfirmFileChangedOutside+' '+ExtractFileName(GetFileName(Ed));
3955 PanelReload[Index].Show;
3956 end;
3957
3958 procedure TEditorFrame.SetEnabledCodeTree(Ed: TATSynEdit; AValue: boolean);
3959 var
3960 N: integer;
3961 begin
3962 N:= EditorObjToTreeviewIndex(Ed);
3963 if FEnabledCodeTree[N]=AValue then Exit;
3964 FEnabledCodeTree[N]:= AValue;
3965
3966 if not AValue then
3967 if Assigned(FCachedTreeview[N]) then
3968 FCachedTreeview[N].Items.Clear;
3969 end;
3970
3971 procedure TEditorFrame.SetEnabledFolding(AValue: boolean);
3972 begin
3973 Ed1.OptFoldEnabled:= AValue;
3974 Ed2.OptFoldEnabled:= AValue;
3975 end;
3976
PictureSizesnull3977 function TEditorFrame.PictureSizes: TPoint;
3978 begin
3979 if Assigned(FImageBox) then
3980 Result:= Point(FImageBox.ImageWidth, FImageBox.ImageHeight)
3981 else
3982 Result:= Point(0, 0);
3983 end;
3984
3985
3986 procedure TEditorFrame.DoGotoPos(Ed: TATSynEdit; APosX, APosY: integer);
3987 begin
3988 if APosY<0 then exit;
3989 if APosX<0 then APosX:= 0; //allow x<0
3990
3991 Ed.LineTop:= APosY;
3992 Ed.DoGotoPos(
3993 Point(APosX, APosY),
3994 Point(-1, -1),
3995 UiOps.FindIndentHorz,
3996 UiOps.FindIndentVert,
3997 true,
3998 true
3999 );
4000 Ed.Update;
4001 end;
4002
4003 procedure TEditorFrame.DoLexerFromFilename(Ed: TATSynEdit; const AFileName: string);
4004 var
4005 TempLexer: TecSyntAnalyzer;
4006 TempLexerLite: TATLiteLexer;
4007 SName: string;
4008 begin
4009 if AFileName='' then exit;
4010 DoLexerDetect(AFileName, TempLexer, TempLexerLite, SName, FLexerChooseFunc);
4011 if Assigned(TempLexer) then
4012 Lexer[Ed]:= TempLexer
4013 else
4014 if Assigned(TempLexerLite) then
4015 LexerLite[Ed]:= TempLexerLite;
4016 end;
4017
4018 procedure TEditorFrame.SetFocus;
4019 begin
4020 DoOnChangeCaption;
4021 DoShow;
4022
4023 //dont focus while API dialog is shown
4024 //not finished work
4025 ////if AppApiDialogCounter>0 then exit;
4026
4027 if Visible and Enabled then
4028 begin
4029 case FrameKind of
4030 efkEditor:
4031 begin
4032 if Editor.Visible and Editor.Enabled then
4033 EditorFocus(Editor);
4034 end;
4035 efkBinaryViewer:
4036 begin
4037 if Assigned(FBin) and FBin.Visible and FBin.CanFocus then
4038 EditorFocus(FBin);
4039 end;
4040 efkImageViewer:
4041 begin
4042 if Assigned(FImageBox) and FImageBox.Visible and FImageBox.CanFocus then
4043 FImageBox.SetFocus;
4044 end;
4045 end;
4046 end;
4047 end;
4048
4049 type
4050 TATSynEdit_Hack = class(TATSynEdit);
4051
4052 procedure TEditorFrame.BinaryOnKeyDown(Sender: TObject; var Key: Word;
4053 Shift: TShiftState);
4054 begin
4055 if (Shift=[]) then
4056 if (Key=VK_UP) or
4057 (Key=VK_DOWN) or
4058 (Key=VK_LEFT) or
4059 (Key=VK_RIGHT) or
4060 (Key=VK_HOME) or
4061 (Key=VK_END) then
4062 exit;
4063
4064 TATSynEdit_Hack(Editor).KeyDown(Key, Shift);
4065 end;
4066
4067 procedure TEditorFrame.BinaryOnScroll(Sender: TObject);
4068 begin
4069 DoOnUpdateStatusbar;
4070 end;
4071
4072 procedure TEditorFrame.BinaryOnProgress(const ACurrentPos,
4073 AMaximalPos: Int64; var AContinueSearching: Boolean);
4074 begin
4075 if Assigned(FOnProgress) then
4076 FOnProgress(nil, ACurrentPos, AMaximalPos, AContinueSearching);
4077 end;
4078
TEditorFrame.BinaryFindFirstnull4079 function TEditorFrame.BinaryFindFirst(AFinder: TATEditorFinder; AShowAll: boolean): boolean;
4080 var
4081 Ops: TATStreamSearchOptions;
4082 begin
4083 Ops:= [];
4084 if AFinder.OptCase then Include(Ops, asoCaseSens);
4085 if AFinder.OptWords then Include(Ops, asoWholeWords);
4086 if AShowAll then Include(Ops, asoShowAll);
4087
4088 Result:= FBin.FindFirst(
4089 UTF8Encode(AFinder.StrFind), Ops, 0);
4090 end;
4091
TEditorFrame.BinaryFindNextnull4092 function TEditorFrame.BinaryFindNext(ABack: boolean): boolean;
4093 begin
4094 if FBinStream=nil then
4095 Result:= false
4096 else
4097 Result:= FBin.FindNext(ABack);
4098 end;
4099
4100 procedure TEditorFrame.DoFileClose;
4101 begin
4102 //clear adapters
4103 Lexer[Ed1]:= nil;
4104 if not EditorsLinked then
4105 Lexer[Ed2]:= nil;
4106
4107 FFileName:= '';
4108 FFileName2:= '';
4109 UpdateCaptionFromFilename;
4110
4111 //clear viewer
4112 DoDeactivateViewerMode;
4113
4114 //clear picture
4115 DoDeactivatePictureMode;
4116
4117 //clear editors
4118 EditorClear(Ed1);
4119 if not EditorsLinked then
4120 EditorClear(Ed2);
4121
4122 UpdateModified(Ed1);
4123 end;
4124
4125 procedure TEditorFrame.DoToggleFocusSplitEditors;
4126 var
4127 Ed: TATSynEdit;
4128 begin
4129 if Splitted then
4130 begin
4131 Ed:= EditorBro;
4132 if Ed.Enabled and Ed.Visible then
4133 begin
4134 FActiveSecondaryEd:= Ed=Ed2;
4135 Ed.SetFocus;
4136 end;
4137 end;
4138 end;
4139
4140 procedure TEditorFrame.DoFocusNotificationPanel;
4141 var
4142 i: integer;
4143 begin
4144 if not Visible then exit;
4145 for i:= Low(PanelReload) to High(PanelReload) do
4146 if Assigned(PanelReload[i]) then
4147 if PanelReload[i].Visible then
4148 btnReloadYes[i].SetFocus;
4149 end;
4150
4151 procedure TEditorFrame.DoHideNotificationPanel(Index: integer);
4152 begin
4153 if Index<0 then exit;
4154 if Assigned(PanelReload[Index]) then
4155 if PanelReload[Index].Visible then
4156 begin
4157 if Visible then
4158 if btnReloadYes[Index].Focused or
4159 btnReloadNo[Index].Focused or
4160 btnReloadNone[Index].Focused then
4161 EditorFocus(EditorIndexToObj(Index));
4162 PanelReload[Index].Hide;
4163 end;
4164 end;
4165
4166 procedure TEditorFrame.DoHideNotificationPanels;
4167 var
4168 i: integer;
4169 begin
4170 for i:= Low(PanelReload) to High(PanelReload) do
4171 DoHideNotificationPanel(i);
4172 end;
4173
GetIsPreviewnull4174 function TEditorFrame.GetIsPreview: boolean;
4175 var
4176 Gr: TATGroups;
4177 Pages: TATPages;
4178 NLocalGroups, NGlobalGroup, NTab: integer;
4179 D: TATTabData;
4180 begin
4181 Result:= false;
4182 GetFrameLocation(Self, Gr, Pages, NLocalGroups, NGlobalGroup, NTab);
4183 if NTab>=0 then
4184 begin
4185 D:= Pages.Tabs.GetTabData(NTab);
4186 if Assigned(D) then
4187 Result:= D.TabSpecial;
4188 end;
4189 end;
4190
4191 procedure TEditorFrame.SetIsPreview(AValue: boolean);
4192 var
4193 Gr: TATGroups;
4194 Pages: TATPages;
4195 NLocalGroups, NGlobalGroup, NTab: integer;
4196 D: TATTabData;
4197 begin
4198 //can change only to False!
4199 if AValue then exit;
4200
4201 GetFrameLocation(Self, Gr, Pages, NLocalGroups, NGlobalGroup, NTab);
4202 if NTab>=0 then
4203 begin
4204 D:= Pages.Tabs.GetTabData(NTab);
4205 if Assigned(D) then
4206 begin
4207 UpdateTabPreviewStyle(D, AValue);
4208 Pages.Tabs.Invalidate;
4209 end;
4210 end;
4211 end;
4212
4213
IsTreeBusynull4214 function TEditorFrame.IsTreeBusy: boolean;
4215 begin
4216 if EditorsLinked then
4217 Result:=
4218 Assigned(Adapter1) and Adapter1.TreeBusy
4219 else
4220 Result:=
4221 (Assigned(Adapter1) and Adapter1.TreeBusy) or
4222 (Assigned(Adapter2) and Adapter2.TreeBusy);
4223 end;
4224
TEditorFrame.IsParsingBusynull4225 function TEditorFrame.IsParsingBusy: boolean;
4226 begin
4227 if EditorsLinked then
4228 Result:=
4229 Assigned(Adapter1) and Adapter1.IsParsingBusy
4230 else
4231 Result:=
4232 (Assigned(Adapter1) and Adapter1.IsParsingBusy) or
4233 (Assigned(Adapter2) and Adapter2.IsParsingBusy);
4234 end;
4235
EditorObjToIndexnull4236 function TEditorFrame.EditorObjToIndex(Ed: TATSynEdit): integer;
4237 begin
4238 if Ed=Ed1 then
4239 Result:= 0
4240 else
4241 if Ed=Ed2 then
4242 Result:= 1
4243 else
4244 Result:= -1;
4245 end;
4246
TEditorFrame.EditorIndexToObjnull4247 function TEditorFrame.EditorIndexToObj(N: integer): TATSynEdit;
4248 begin
4249 if N=0 then
4250 Result:= Ed1
4251 else
4252 if N=1 then
4253 Result:= Ed2
4254 else
4255 Result:= nil;
4256 end;
4257
4258 procedure TEditorFrame.BracketJump(Ed: TATSynEdit);
4259 begin
4260 EditorBracket_Action(Ed,
4261 bracketActionJump,
4262 FBracketSymbols,
4263 MaxInt
4264 );
4265 end;
4266
4267 procedure TEditorFrame.BracketSelect(Ed: TATSynEdit);
4268 begin
4269 EditorBracket_Action(Ed,
4270 bracketActionSelect,
4271 FBracketSymbols,
4272 MaxInt
4273 );
4274 end;
4275
4276 procedure TEditorFrame.BracketSelectInside(Ed: TATSynEdit);
4277 begin
4278 EditorBracket_Action(Ed,
4279 bracketActionSelectInside,
4280 FBracketSymbols,
4281 MaxInt
4282 );
4283 end;
4284
4285 procedure TEditorFrame.SetBracketHilite(AValue: boolean);
4286 begin
4287 if FBracketHilite=AValue then Exit;
4288 FBracketHilite:= AValue;
4289
4290 EditorBracket_ClearHilite(Ed1);
4291 EditorBracket_ClearHilite(Ed2);
4292
4293 if FBracketHilite then
4294 begin
4295 EditorOnChangeCaretPos(Ed1);
4296 EditorOnChangeCaretPos(Ed2);
4297 end;
4298 end;
4299
Modifiednull4300 function TEditorFrame.Modified: boolean;
4301 begin
4302 if FEditorsLinked then
4303 Result:= EditorIsModifiedEx(Ed1)
4304 else
4305 Result:= EditorIsModifiedEx(Ed1) or EditorIsModifiedEx(Ed2);
4306 end;
4307
4308 procedure TEditorFrame.PanelInfoClick(Sender: TObject);
4309 begin
4310 PanelInfo.Hide;
4311 AppPython.RunCommand('cuda_prefs', 'dlg_cuda_options', []);
4312 end;
4313
4314 procedure TEditorFrame.CancelAutocompleteAutoshow(Ed: TATSynEdit);
4315 begin
4316 FTextCharsTyped:= 0;
4317 OnCallAutoCompletion(Ed, false);
4318 end;
4319
4320 end.
4321