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