1{
2 ***************************************************************************
3 *                                                                         *
4 *   This source is free software; you can redistribute it and/or modify   *
5 *   it under the terms of the GNU General Public License as published by  *
6 *   the Free Software Foundation; either version 2 of the License, or     *
7 *   (at your option) any later version.                                   *
8 *                                                                         *
9 *   This code is distributed in the hope that it will be useful, but      *
10 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
12 *   General Public License for more details.                              *
13 *                                                                         *
14 *   A copy of the GNU General Public License is available on the World    *
15 *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
16 *   obtain it by writing to the Free Software Foundation,                 *
17 *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
18 *                                                                         *
19 ***************************************************************************
20
21  Author: Mattias Gaertner
22
23  Abstract:
24    Editor options container and editor options dialog.
25    The editor options are stored in XML format in the
26     ~/.lazarus/editoroptions.xml file.
27    Currently only for TSynEdit.
28}
29unit EditorOptions;
30
31{$mode objfpc}{$H+}
32
33{$IFDEF Windows}
34  {$IFnDEF WithoutWinIME}
35    {$DEFINE WinIME}
36  {$ENDIF}
37{$ENDIF}
38
39interface
40
41uses
42  // RTL, FCL
43  Classes, SysUtils, typinfo, resource,
44  // LCL
45  Graphics, LCLProc, LResources, Forms, Dialogs, ComCtrls, LCLType, Controls,
46  // LazUtils
47  FileUtil, LazFileUtils, LazUTF8, LazClasses, Laz2_XMLCfg, LazStringUtils,
48  // Synedit
49  SynEdit, SynEditAutoComplete, SynEditKeyCmds, SynEditTypes,
50  SynEditMiscClasses, SynBeautifier, SynEditTextTrimmer, SynEditMouseCmds,
51  SynPluginTemplateEdit, SynPluginSyncroEdit,
52  SynGutter, SynGutterBase, SynGutterCodeFolding, SynGutterLineNumber,
53  SynGutterChanges, SynCompletion,
54  SynEditMarkupBracket, SynEditMarkupHighAll, SynEditMarkupWordGroup,
55  SynEditMarkupSpecialChar,
56  SourceSynEditor,
57  // SynEdit Highlighters
58  SynEditHighlighter, SynEditHighlighterFoldBase, SynHighlighterCPP,
59  SynHighlighterHTML, SynHighlighterJava, SynHighlighterLFM, SynHighlighterPas,
60  SynHighlighterPerl, SynHighlighterPHP, SynHighlighterSQL, SynHighlighterCss,
61  SynHighlighterPython, SynHighlighterUNIXShellScript, SynHighlighterXML,
62  SynHighlighterJScript, SynHighlighterDiff, SynHighlighterBat,
63  SynHighlighterIni, SynHighlighterPo, SynHighlighterPike, SynPluginMultiCaret,
64  SynEditMarkupFoldColoring, SynEditMarkup, SynGutterLineOverview, SynBeautifierPascal,
65  // codetools
66  LinkScanner, CodeToolManager,
67  // IDEIntf
68  IDECommands, SrcEditorIntf, IDEOptionsIntf, IDEOptEditorIntf, IDEDialogs,
69  EditorSyntaxHighlighterDef, MacroIntf,
70  // IDE
71  SourceMarks, LazarusIDEStrConsts, KeyMapping, LazConf;
72
73const
74  DefaultCompletionLongLineHintType = sclpExtendRightOnly;
75  DefaultEditorDisableAntiAliasing = false;
76
77type
78  TPreviewPasSyn = TIDESynFreePasSyn;
79  TSrcIDEHighlighter = TSynCustomHighlighter;
80  TSynHighlightElement = TSynHighlighterAttributes;
81  TCustomSynClass = class of TSrcIDEHighlighter;
82
83  TLazSynPluginTemplateMultiCaret = class(TForm)   end;
84  TLazSynPluginTemplateEditForm = class(TForm)     end;
85  TLazSynPluginTemplateEditFormOff = class(TForm)  end;
86  TLazSynPluginSyncroEditFormSel = class(TForm)    end;
87  TLazSynPluginSyncroEditForm = class(TForm)       end;
88  TLazSynPluginSyncroEditFormOff = class(TForm)    end;
89
90  TColorSchemeAttributeFeature =
91    ( hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior,
92      hafStyle, hafStyleMask,
93      hafFrameStyle, hafFrameEdges,
94      hafMarkupFoldColor // for the MarkupFoldColor module
95    );
96  TColorSchemeAttributeFeatures = set of TColorSchemeAttributeFeature;
97
98const
99  SynEditPreviewIncludeOptions = [eoNoCaret, eoNoSelection];
100  SynEditPreviewExcludeOptions = [eoDragDropEditing, eoDropFiles,
101                                  eoScrollPastEof];
102  SynEditPreviewIncludeOptions2 = [];
103  SynEditPreviewExcludeOptions2 = [eoAlwaysVisibleCaret];
104
105  DefaultCodeTemplatesFilename = 'lazarus.dci'; // in directory GetPrimaryConfigPath
106
107  // Do not localize: those are used for the config XML
108  ahaXmlNames: array[TAdditionalHilightAttribute] of String =
109  (
110    '',                    'Text block',                'Execution point',
111    'Enabled breakpoint',  'Disabled breakpoint',       'Invalid breakpoint',
112    'Unknown breakpoint',  'Error line',                'Incremental search match',
113    'Highlight all',       'Brackets highlight',        'Mouse link',
114    'Line number',         'Line highlight',            'Modified line',
115    'Code folding tree',   'Highlight current word',    'Folded code',
116    'Folded code Line',    'Hidden code Line',
117    'Word-Brackets',       'TemplateEdit Current',      'TemplateEdit Sync',
118    'TemplateEdit Cells',  'SyncronEdit Current Cells', 'SyncronEdit Syncron Cells',
119    'SyncronEdit Other Cells', 'SyncronEdit Range',
120    '', // scaGutterSeparator => uses RTTI only
121    '', // ahaGutter
122    '',  // ahaRightMargin
123    '',  // ahaSpecialVisibleChars
124    '',  // ahaTopInfoHint
125    '', '', // ahaCaretColor, ahaOverviewGutter
126    '', '', '',  // ahaIfDefBlockInactive, ahaIfDefBlockActive, ahaIfDefBlockTmpActive
127    '', '', '',  // ahaIfDefNodeInactive, ahaIfDefNodeActive, ahaIfDefNodeTmpActive
128    '', '', '', '', // ahaIdentComplWindow, ahaIdentComplWindowBorder, ahaIdentComplWindowSelection, ahaIdentComplWindowHighlight
129    '', '', '', '', '', '', '', '', '', '' // ahaOutlineLevel1Color..ahaOutlineLevel10Color
130  );
131
132  ahaGroupMap: array[TAdditionalHilightAttribute] of TAhaGroupName = (
133    { ahaNone }                agnText,
134    { ahaTextBlock }           agnText,
135    { ahaExecutionPoint }      agnLine,
136    { ahaEnabledBreakpoint }   agnLine,
137    { ahaDisabledBreakpoint }  agnLine,
138    { ahaInvalidBreakpoint }   agnLine,
139    { ahaUnknownBreakpoint }   agnLine,
140    { ahaErrorLine }           agnLine,
141    { ahaIncrementalSearch }   agnText,
142    { ahaHighlightAll }        agnText,
143    { ahaBracketMatch }        agnText,
144    { ahaMouseLink }           agnText,
145    { ahaLineNumber }          agnGutter,
146    { ahaLineHighlight }       agnLine,
147    { ahaModifiedLine }        agnGutter,
148    { ahaCodeFoldingTree }     agnGutter,
149    { ahaHighlightWord }       agnText,
150    { ahaFoldedCode }          agnGutter,
151    { ahaFoldedCodeLine }      agnGutter,
152    { ahaHiddenCodeLine }      agnGutter,
153    { ahaWordGroup }           agnText,
154    { ahaTemplateEditCur }     agnTemplateMode,
155    { ahaTemplateEditSync }    agnTemplateMode,
156    { ahaTemplateEditOther }   agnTemplateMode,
157    { ahaSyncroEditCur }       agnSyncronMode,
158    { ahaSyncroEditSync }      agnSyncronMode,
159    { ahaSyncroEditOther }     agnSyncronMode,
160    { ahaSyncroEditArea }      agnSyncronMode,
161    { ahaGutterSeparator }     agnGutter,
162    { ahaGutter }              agnGutter,
163    { ahaRightMargin}          agnGutter,
164    { ahaSpecialVisibleChars } agnText,
165    { ahaTopInfoHint }         agnLine,
166    { ahaCaretColor }          agnText,
167    { ahaOverviewGutter }      agnGutter,
168    { ahaIfDefBlockInactive }  agnIfDef,
169    { ahaIfDefBlockActive }    agnIfDef,
170    { ahaIfDefBlockTmpActive } agnIfDef,
171    { ahaIfDefNodeInactive }   agnIfDef,
172    { ahaIfDefNodeActive }     agnIfDef,
173    { ahaIfDefNodeTmpActive }  agnIfDef,
174    { ahaIdentComplWindow }           agnIdentComplWindow,
175    { ahaIdentComplWindowBorder }     agnIdentComplWindow,
176    { ahaIdentComplWindowSelection }  agnIdentComplWindow,
177    { ahaIdentComplWindowHighlight }  agnIdentComplWindow,
178    { ahaOutlineLevel1Color }  agnOutlineColors,
179    { ahaOutlineLevel2Color }  agnOutlineColors,
180    { ahaOutlineLevel3Color }  agnOutlineColors,
181    { ahaOutlineLevel4Color }  agnOutlineColors,
182    { ahaOutlineLevel5Color }  agnOutlineColors,
183    { ahaOutlineLevel6Color }  agnOutlineColors,
184    { ahaOutlineLevel7Color }  agnOutlineColors,
185    { ahaOutlineLevel8Color }  agnOutlineColors,
186    { ahaOutlineLevel9Color }  agnOutlineColors,
187    { ahaOutlineLevel10Color } agnOutlineColors
188
189  );
190  ahaSupportedFeatures: array[TAdditionalHilightAttribute] of TColorSchemeAttributeFeatures =
191  (
192    { ahaNone }               [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
193    { ahaTextBlock }          [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
194    { ahaExecutionPoint }     [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
195    { ahaEnabledBreakpoint }  [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
196    { ahaDisabledBreakpoint } [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
197    { ahaInvalidBreakpoint }  [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
198    { ahaUnknownBreakpoint }  [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
199    { ahaErrorLine }          [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
200    { ahaIncrementalSearch }  [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
201    { ahaHighlightAll }       [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
202    { ahaBracketMatch }       [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
203    { ahaMouseLink }          [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
204    { ahaLineNumber }         [hafBackColor, hafForeColor, hafFrameColor, hafStyle],
205    { ahaLineHighlight }      [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
206    { ahaModifiedLine }       [hafBackColor, hafForeColor, hafFrameColor],
207    { ahaCodeFoldingTree }    [hafBackColor, hafForeColor, hafFrameColor],
208    { ahaHighlightWord }      [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
209    { ahaFoldedCode }         [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
210    { ahaFoldedCodeLine }     [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
211    { ahaHiddenCodeLine }     [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
212    { ahaWordGroup }          [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
213    { ahaTemplateEditCur }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
214    { ahaTemplateEditSync }   [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
215    { ahaTemplateEditOther }  [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
216    { ahaSyncroEditCur }      [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
217    { ahaSyncroEditSync }     [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
218    { ahaSyncroEditOther }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
219    { ahaSyncroEditArea }     [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
220    { ahaGutterSeparator }    [hafBackColor, hafForeColor],
221    { ahaGutter }             [hafBackColor],
222    { ahaRightMargin}         [hafForeColor],
223    { ahaSpecialVisibleChars }[hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
224    { ahaTopInfoHint }        [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
225    { ahaCaretColor }         [hafBackColor, hafForeColor],
226    { ahaOverviewGutter }     [hafBackColor, hafForeColor, hafFrameColor],
227    { ahaIfDefBlockInactive } [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
228    { ahaIfDefBlockActive }   [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
229    { ahaIfDefBlockTmpActive }[hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
230    { ahaIfDefNodeInactive }  [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
231    { ahaIfDefNodeActive }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
232    { ahaIfDefNodeTmpActive } [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask],
233    { ahaIdentComplWindow }   [hafBackColor, hafForeColor],
234    { ahaIdentComplWindowBorder }    [hafForeColor],
235    { ahaIdentComplWindowSelection } [hafBackColor, hafForeColor],
236    { ahaIdentComplWindowHighlight } [hafForeColor],
237    { ahaFoldLevel1Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
238    { ahaFoldLevel2Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
239    { ahaFoldLevel3Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
240    { ahaFoldLevel4Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
241    { ahaFoldLevel5Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
242    { ahaFoldLevel6Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
243    { ahaFoldLevel7Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
244    { ahaFoldLevel8Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
245    { ahaFoldLevel9Color }    [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor],
246    { ahaFoldLevel10Color }   [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior, hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask, hafMarkupFoldColor]
247  );
248
249
250var
251  AdditionalHighlightAttributes: array[TAdditionalHilightAttribute] of String;
252  AdditionalHighlightGroupNames: array[TAhaGroupName] of String;
253
254type
255  (* ***  ColorSchemes  *** *)
256
257  { TQuickStringlist }
258
259  TQuickStringlist=class(TStringlist)
260    Function DoCompareText(const s1,s2 : string) : PtrInt; override;
261  end;
262
263  TColorScheme = class;
264  TColorSchemeLanguage = class;
265
266  { TColorSchemeAttribute }
267
268  TColorSchemeAttribute = class(TSynHighlighterAttributesModifier)
269  private
270    FFeatures: TColorSchemeAttributeFeatures;
271    FGroup: TAhaGroupName;
272    FMarkupFoldLineAlpha: Byte;
273    FMarkupFoldLineColor: TColor;
274    FMarkupFoldLineStyle: TSynLineStyle;
275    FOwner: TColorSchemeLanguage;
276    FAlreadyGotSchemeGlobal: Boolean;
277    FSchemeGlobalCache: TColorSchemeAttribute;
278    FUseSchemeGlobals: Boolean;
279    function GetIsUsingSchemeGlobals: Boolean;
280    procedure SetMarkupFoldLineAlpha(AValue: Byte);
281    procedure SetMarkupFoldLineColor(AValue: TColor);
282    procedure SetMarkupFoldLineStyle(AValue: TSynLineStyle);
283  protected
284    procedure Init; override;
285  public
286    constructor Create(ASchemeLang: TColorSchemeLanguage; attribName: PString;
287                       const aStoredName: String = '');
288    function IsEnabled: boolean; override;
289    procedure ApplyTo(aDest: TSynHighlighterAttributes; aDefault: TColorSchemeAttribute = nil);
290    procedure Assign(Src: TPersistent); override;
291    function Equals(Other: TColorSchemeAttribute): Boolean; reintroduce;
292    function GetStoredValuesForAttrib: TColorSchemeAttribute; // The IDE default colors from the resources
293    function GetSchemeGlobal: TColorSchemeAttribute;
294    procedure LoadFromXml(aXMLConfig: TRttiXMLConfig; aPath: String;
295                          Defaults: TColorSchemeAttribute; Version: Integer);
296    procedure SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String;
297                        Defaults: TColorSchemeAttribute);
298    property Group: TAhaGroupName read FGroup write FGroup;
299    property IsUsingSchemeGlobals: Boolean read GetIsUsingSchemeGlobals;
300    property Features: TColorSchemeAttributeFeatures read FFeatures write FFeatures;
301  published
302    property UseSchemeGlobals: Boolean read FUseSchemeGlobals write FUseSchemeGlobals;
303    // For markup fold color
304    property MarkupFoldLineColor: TColor read FMarkupFoldLineColor write SetMarkupFoldLineColor default clNone; // clDefault will take Color[].Frame or Color[].Foreground
305    property MarkupFoldLineStyle: TSynLineStyle read FMarkupFoldLineStyle write SetMarkupFoldLineStyle default slsSolid;
306    property MarkupFoldLineAlpha: Byte read FMarkupFoldLineAlpha write SetMarkupFoldLineAlpha default 0;
307  end;
308
309  { TColorSchemeLanguage }
310
311  TColorSchemeLanguage = class(TObject)
312  private
313    FDefaultAttribute: TColorSchemeAttribute;
314    FAttributes: TQuickStringlist; // TColorSchemeAttribute
315    FHighlighter: TSynCustomHighlighter;
316    FLanguage: TLazSyntaxHighlighter;
317    FOwner: TColorScheme;
318    FLanguageName: String;
319    FIsSchemeDefault: Boolean;
320    FFormatVersion: integer;
321    function GetAttribute(Index: String): TColorSchemeAttribute;
322    function GetAttributeAtPos(Index: Integer): TColorSchemeAttribute;
323    function GetAttributeByEnum(Index: TAdditionalHilightAttribute): TColorSchemeAttribute;
324    function GetName: String;
325  public
326    constructor Create(AGroup: TColorScheme; ALang: TLazSyntaxHighlighter;
327      IsSchemeDefault: Boolean);
328    constructor CreateWithDefColor(AGroup: TColorScheme; ALang: TLazSyntaxHighlighter;
329      IsSchemeDefault: Boolean);
330    constructor CreateFromXml(AGroup: TColorScheme; ALang: TLazSyntaxHighlighter;
331      aXMLConfig: TRttiXMLConfig; const aPath: String; IsSchemeDefault: Boolean);
332    destructor  Destroy; override;
333    procedure Clear;
334    procedure Assign(Src: TColorSchemeLanguage); reintroduce;
335    function Equals(Other: TColorSchemeLanguage): Boolean; reintroduce;
336    function GetStoredValuesForLanguage: TColorSchemeLanguage; // The IDE default colors from the resources
337    function IndexOfAttr(AnAttr: TColorSchemeAttribute): Integer;
338    procedure LoadFromXml(aXMLConfig: TRttiXMLConfig; const aPath: String;
339      Defaults: TColorSchemeLanguage; ColorVersion: Integer; const aOldPath: String = '');
340    procedure SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String;
341      Defaults: TColorSchemeLanguage);
342    procedure ApplyTo(ASynEdit: TSynEdit); // Write markup, etc
343    procedure ApplyTo(AHLighter: TSynCustomHighlighter);
344    function  AttributeCount: Integer;
345    property  Name: String read GetName;
346    property  Language: TLazSyntaxHighlighter read FLanguage;
347    property  LanguageName: String read FLanguageName;
348    property  Attribute[Index: String]: TColorSchemeAttribute read GetAttribute;
349    property  AttributeByEnum[Index: TAdditionalHilightAttribute]: TColorSchemeAttribute
350              read GetAttributeByEnum;
351    property  AttributeAtPos[Index: Integer]: TColorSchemeAttribute read GetAttributeAtPos;
352    property  DefaultAttribute: TColorSchemeAttribute read FDefaultAttribute;
353    property  Highlighter: TSynCustomHighlighter read FHighlighter;
354  end;
355
356  { TColorScheme }
357
358  TColorScheme = class(TObject)
359  private
360    FName: String;
361    FColorSchemes: Array [TLazSyntaxHighlighter] of TColorSchemeLanguage;
362    FDefaultColors: TColorSchemeLanguage;
363    function GetColorScheme(Index: TLazSyntaxHighlighter): TColorSchemeLanguage;
364    function GetColorSchemeBySynClass(Index: TClass): TColorSchemeLanguage;
365  public
366    constructor Create(const AName: String);
367    constructor CreateFromXml(aXMLConfig: TRttiXMLConfig; const AName, aPath: String);
368    destructor  Destroy; override;
369    procedure Assign(Src: TColorScheme); reintroduce;
370    function GetStoredValuesForScheme: TColorScheme; // The IDE default colors from the resources
371    procedure LoadFromXml(aXMLConfig: TRttiXMLConfig; aPath: String;
372                          Defaults: TColorScheme; aOldPath: String = '');
373    procedure SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String; Defaults: TColorScheme);
374    property  Name: string read FName;
375    property  DefaultColors: TColorSchemeLanguage read FDefaultColors;
376    property  ColorScheme[Index: TLazSyntaxHighlighter]: TColorSchemeLanguage read GetColorScheme;
377    property  ColorSchemeBySynClass[Index: TClass]: TColorSchemeLanguage read GetColorSchemeBySynClass;
378  end;
379
380  { TColorSchemeFactory }
381
382  TColorSchemeFactory = class(TObject)
383  private
384    FMappings: TQuickStringlist; // TColorScheme
385    function GetColorSchemeGroup(Index: String): TColorScheme;
386    function GetColorSchemeGroupAtPos(Index: Integer): TColorScheme;
387  public
388    constructor Create;
389    destructor  Destroy; override;
390    procedure Clear;
391    procedure Assign(Src: TColorSchemeFactory); reintroduce;
392    procedure LoadFromXml(aXMLConfig: TRttiXMLConfig; const aPath: String;
393      Defaults: TColorSchemeFactory; const aOldPath: String = '');
394    procedure SaveToXml(aXMLConfig: TRttiXMLConfig; const aPath: String;
395      Defaults: TColorSchemeFactory);
396    procedure RegisterScheme(aXMLConfig: TRttiXMLConfig; AName, aPath: String);
397    procedure GetRegisteredSchemes(AList: TStrings);
398    property  ColorSchemeGroup[Index: String]: TColorScheme read GetColorSchemeGroup;
399    property  ColorSchemeGroupAtPos[Index: Integer]: TColorScheme read GetColorSchemeGroupAtPos;
400  end;
401
402type
403
404  TEditorOptionsDividerInfo = record
405    Name: String;      // Name for display
406    Xml: String;       // Name for XML
407    BoolOpt: Boolean;  // Checkbox only
408    MaxLevel: Integer;
409  end;
410  TEditorOptionsDividerInfoList = Array [0..999] of TEditorOptionsDividerInfo;
411  PEditorOptionsDividerInfoList = ^TEditorOptionsDividerInfoList;
412
413  TEditorOptionsDividerRecord = record
414    Count: Integer;
415    Info: PEditorOptionsDividerInfoList;
416  end;
417
418var
419
420  (* When adding new entries, ensure that resourcestrings are re-assigned in InitLocale *)
421  EditorOptionsDividerInfoPas: Array [0..8] of TEditorOptionsDividerInfo
422  = (
423      (Name: dlgDivPasUnitSectionName;  Xml: 'Sect';    BoolOpt: True;  MaxLevel: 1),
424      (Name: dlgDivPasUsesName;         Xml: 'Uses';    BoolOpt: True;  MaxLevel: 0),
425      (Name: dlgDivPasVarGlobalName;    Xml: 'GVar';    BoolOpt: True;  MaxLevel: 1),
426      (Name: dlgDivPasVarLocalName;     Xml: 'LVar';    BoolOpt: False; MaxLevel: 0),
427      (Name: dlgDivPasStructGlobalName; Xml: 'GStruct'; BoolOpt: False; MaxLevel: 1),
428      (Name: dlgDivPasStructLocalName;  Xml: 'LStruct'; BoolOpt: False; MaxLevel: 0),
429      (Name: dlgDivPasProcedureName;    Xml: 'Proc';    BoolOpt: False; MaxLevel: 1),
430      (Name: dlgDivPasBeginEndName;     Xml: 'Begin';   BoolOpt: False; MaxLevel: 0),
431      (Name: dlgDivPasTryName;          Xml: 'Try';     BoolOpt: False; MaxLevel: 0)
432    );
433
434const
435
436  (* When adding new entries, ensure that resourcestrings are re-assigned in InitLocale *)
437  EditorOptionsDividerDefaults: array[TLazSyntaxHighlighter] of
438    TEditorOptionsDividerRecord =
439    ( (Count: 0; Info: nil), // none
440      (Count: 0; Info: nil), // text
441      (Count: 9; Info: @EditorOptionsDividerInfoPas[0]), // Freepas
442      (Count: 9; Info: @EditorOptionsDividerInfoPas[0]), // pas
443      (Count: 0; Info: nil), // lfm
444      (Count: 0; Info: nil), // xml
445      (Count: 0; Info: nil), // html
446      (Count: 0; Info: nil), // cpp
447      (Count: 0; Info: nil), // perl
448      (Count: 0; Info: nil), // java
449      (Count: 0; Info: nil), // shell
450      (Count: 0; Info: nil), // python
451      (Count: 0; Info: nil), // php
452      (Count: 0; Info: nil), // sql
453      (Count: 0; Info: nil), // css
454      (Count: 0; Info: nil), // jscript
455      (Count: 0; Info: nil), // Diff
456      (Count: 0; Info: nil), // Ini
457      (Count: 0; Info: nil), // Bat
458      (Count: 0; Info: nil), // PO
459      (Count: 0; Info: nil)  // Pike
460    );
461
462type
463
464  TEditorOptionsFoldInfo = record
465    Name: String;      // Name for display
466    Xml: String;       // Name for XML
467    Index: Integer;    // FHighlighter.FoldConf[index]
468    Enabled: Boolean;
469  end;
470  TEditorOptionsFoldInfoList = Array [0..999] of TEditorOptionsFoldInfo;
471  PEditorOptionsFoldInfoList = ^TEditorOptionsFoldInfoList;
472
473  TEditorOptionsFoldRecord = record
474    Count: Integer;
475    HasMarkup: Boolean;
476    Info: PEditorOptionsFoldInfoList;
477  end;
478
479type
480
481  { TSynEditMouseActionKeyCmdHelper }
482
483  TSynEditMouseActionKeyCmdHelper = class(TSynEditMouseAction)
484  private
485    function GetOptionKeyCmd: TSynEditorCommand;
486    procedure SetOptionKeyCmd(const AValue: TSynEditorCommand);
487  published
488    property Option: TSynEditorCommand read GetOptionKeyCmd write SetOptionKeyCmd;
489  end;
490
491
492const
493
494  (* When adding new entries, ensure that resourcestrings are re-assigned in InitLocale *)
495  EditorOptionsFoldInfoPas: Array [0..26] of TEditorOptionsFoldInfo
496  = (
497      (Name:  dlgFoldPasProcedure;     Xml:     'Procedure';
498       Index: ord(cfbtProcedure);    Enabled: True),
499      (Name:  dlgFoldLocalPasVarType;  Xml:     'LocalVarType';
500       Index: ord(cfbtLocalVarType); Enabled: True),
501      (Name:  dlgFoldPasProcBeginEnd;  Xml:     'ProcBeginEnd';
502       Index: ord(cfbtTopBeginEnd);  Enabled: True),
503      (Name:  dlgFoldPasBeginEnd;      Xml:     'BeginEnd';
504       Index: ord(cfbtBeginEnd);     Enabled: True),
505      (Name:  dlgFoldPasRepeat;        Xml:     'Repeat';
506       Index: ord(cfbtRepeat);       Enabled: False),
507      (Name:  dlgFoldPasCase;          Xml:     'Case';
508       Index: ord(cfbtCase);         Enabled: False),
509      (Name:  dlgFoldPasTry;           Xml:     'Try';
510       Index: ord(cfbtTry);          Enabled: False),
511      (Name:  dlgFoldPasExcept;        Xml:     'Except';
512       Index: ord(cfbtExcept);       Enabled: False),
513      (Name:  dlgFoldPasAsm;           Xml:     'Asm';
514       Index: ord(cfbtAsm);          Enabled: True),
515
516      (Name:  dlgFoldPasProgram;       Xml:     'Program';
517       Index: ord(cfbtProgram);      Enabled: False),
518      (Name:  dlgFoldPasUnit;          Xml:     'Unit';
519       Index: ord(cfbtUnit);         Enabled: False),
520      (Name:  dlgFoldPasUnitSection;   Xml:     'UnitSection';
521       Index: ord(cfbtUnitSection);  Enabled: False),
522      (Name:  dlgFoldPasUses;          Xml:     'Uses';
523       Index: ord(cfbtUses);         Enabled: True),
524
525      (Name:  dlgFoldPasVarType;       Xml:     'VarType';
526       Index: ord(cfbtVarType);      Enabled: False),
527      (Name:  dlgFoldPasClass;         Xml:     'Class';
528       Index: ord(cfbtClass);        Enabled: True),
529      (Name:  dlgFoldPasClassSection;  Xml:     'ClassSection';
530       Index: ord(cfbtClassSection); Enabled: True),
531      (Name:  dlgFoldPasRecord;        Xml:     'Record';
532       Index: ord(cfbtRecord);       Enabled: True),
533
534      (Name:  dlgFoldPasIfDef;         Xml:     'IfDef';
535       Index: ord(cfbtIfDef);        Enabled: False),
536      (Name:  dlgFoldPasUserRegion;    Xml:     'UserRegion';
537       Index: ord(cfbtRegion);       Enabled: True),
538
539      (Name:  dlgFoldPasAnsiComment;   Xml:     'AnsiComment';
540       Index: ord(cfbtAnsiComment);  Enabled: True),
541      (Name:  dlgFoldPasBorComment;    Xml:     'BorComment';
542       Index: ord(cfbtBorCommand);   Enabled: True),
543      (Name:  dlgFoldPasSlashComment;    Xml:     'SlashComment';
544       Index: ord(cfbtSlashComment); Enabled: True),
545
546      (Name:  dlgFoldPasNestedComment; Xml:     'NestedComment';
547       Index: ord(cfbtNestedComment);Enabled: True),
548
549      (Name:  dlgFoldPasIfThen; Xml:     'IfThen';
550       Index: ord(cfbtIfThen); Enabled: False),
551      (Name:  dlgFoldPasForDo; Xml:     'ForDo';
552       Index: ord(cfbtForDo); Enabled: False),
553      (Name:  dlgFoldPasWhileDo; Xml:     'WhileDo';
554       Index: ord(cfbtWhileDo); Enabled: False),
555      (Name:  dlgFoldPasWithDo; Xml:     'WithDo';
556       Index: ord(cfbtWithDo); Enabled: False)
557    );
558
559  EditorOptionsFoldInfoLFM: Array [0..2] of TEditorOptionsFoldInfo
560  = (
561      ( Name:    dlgFoldLfmObject;
562        Xml:    'Object';
563        Index:   ord(cfbtLfmObject);
564        Enabled: True
565      ),
566      ( Name:    dlgFoldLfmList;
567        Xml:     'List';
568        Index:   ord(cfbtLfmList);
569        Enabled: True
570      ),
571      ( Name:    dlgFoldLfmItem;
572        Xml:     'Item';
573        Index:   ord(cfbtLfmItem);
574        Enabled: True
575      )
576    );
577
578  EditorOptionsFoldInfoXML: Array [0..4] of TEditorOptionsFoldInfo
579  = (
580      ( Name:    dlgFoldXmlNode;
581        Xml:    'Node';
582        Index:   ord(cfbtXmlNode);
583        Enabled: True
584      ),
585      ( Name:    dlgFoldXmlComment;
586        Xml:    'Comment';
587        Index:   ord(cfbtXmlComment);
588        Enabled: True
589      ),
590      ( Name:    dlgFoldXmlCData;
591        Xml:    'CData';
592        Index:   ord(cfbtXmlCData);
593        Enabled: True
594      ),
595      ( Name:    dlgFoldXmlDocType;
596        Xml:    'DocType';
597        Index:   ord(cfbtXmlDocType);
598        Enabled: True
599      ),
600      ( Name:    dlgFoldXmlProcess;
601        Xml:    'ProcessInstr';
602        Index:   ord(cfbtXmlProcess);
603        Enabled: True
604      )
605    );
606
607  EditorOptionsFoldInfoHTML: Array [0..2] of TEditorOptionsFoldInfo
608  = (
609      ( Name:    dlgFoldHtmlNode;
610        Xml:    'Node';
611        Index:   ord(cfbtHtmlNode);
612        Enabled: True
613      ),
614      ( Name:    dlgFoldHtmlComment;
615        Xml:    'Comment';
616        Index:   ord(cfbtXmlComment);
617        Enabled: True
618      ),
619      ( Name:    dlgFoldHtmlAsp;
620        Xml:    'ASP';
621        Index:   ord(cfbtHtmlAsp);
622        Enabled: True
623      )
624    );
625
626  EditorOptionsFoldInfoDiff: Array [0..2] of TEditorOptionsFoldInfo
627  = (
628      ( Name:    lisFile;
629        Xml:    'File';
630        Index:   ord(cfbtDiffFile);
631        Enabled: True
632      ),
633      ( Name:    dlgFoldDiffChunk;
634        Xml:    'Chunk';
635        Index:   ord(cfbtDiffChunk);
636        Enabled: True
637      ),
638      ( Name:    dlgFoldDiffChunkSect;
639        Xml:    'ChunkSect';
640        Index:   ord(cfbtDiffChunkSect);
641        Enabled: True
642      )
643    );
644
645  (* When adding new entries, ensure that resourcestrings are re-assigned in InitLocale *)
646  EditorOptionsFoldDefaults: array[TLazSyntaxHighlighter] of
647    TEditorOptionsFoldRecord =
648    ( (Count:  0; HasMarkup: False; Info: nil), // none
649      (Count:  0; HasMarkup: False; Info: nil), // text
650      (Count: 27; HasMarkup: True; Info: @EditorOptionsFoldInfoPas[0]), // Freepas
651      (Count: 27; HasMarkup: True; Info: @EditorOptionsFoldInfoPas[0]), // pas
652      (Count:  3; HasMarkup: True; Info: @EditorOptionsFoldInfoLFM[0]), // lfm
653      (Count:  5; HasMarkup: True; Info: @EditorOptionsFoldInfoXML[0]), // xml
654      (Count:  3; HasMarkup: True; Info: @EditorOptionsFoldInfoHTML[0]), // html
655      (Count:  0; HasMarkup: False; Info: nil), // cpp
656      (Count:  0; HasMarkup: False; Info: nil), // perl
657      (Count:  0; HasMarkup: False; Info: nil), // java
658      (Count:  0; HasMarkup: False; Info: nil), // shell
659      (Count:  0; HasMarkup: False; Info: nil), // python
660      (Count:  0; HasMarkup: False; Info: nil), // php
661      (Count:  0; HasMarkup: False; Info: nil), // sql
662      (Count:  0; HasMarkup: False; Info: nil), // css
663      (Count:  0; HasMarkup: False; Info: nil), // jscript
664      (Count:  3; HasMarkup: False; Info: @EditorOptionsFoldInfoDiff[0]), // Diff
665      (Count:  0; HasMarkup: False; Info: nil), // Bat
666      (Count:  0; HasMarkup: False; Info: nil), // Ini
667      (Count:  0; HasMarkup: False; Info: nil), // PO
668      (Count:  0; HasMarkup: False; Info: nil)  // Pike
669    );
670
671const
672  EditorOptsFormatVersion = 13;
673  { * Changes in Version 6:
674       - ColorSchemes now have a Global settings part.
675         Language specific changes must save UseSchemeGlobals=False (Default is true)
676         Since Version 5 did not have this setting, in Version 5 the default is false.
677    * Changes in Version 7:
678         DisableAntialiasing default true to false
679    * Changes in Version 8:
680         Replaced EditorFontHeight with EditorFontSize.
681    * Changes in Version 9:
682         Fix ahaMouseLink. It only used Foreground, and would underline with it too.
683         It now uses all fields. Old entries will copy Foreground to Frame and
684         set sfeBottom
685    * Changes in Version 10:
686         eoTabIndent was added to SynEditDefaultOptions
687    * Changes in Version 11:
688         Default for GutterLeft set to moglUpClickAndSelect (was moGLDownClick)
689    * Changes in Version 12:
690         Used in Colorscheme/Version
691         Colors for MarkupFoldColor can now have gaps (before unset colors were filtered)
692    * Changes in Version 13:
693         CtrlMiddleTabClickClosesOthers was replaced by MiddleTabClickClosesOthersModifier
694  }
695  EditorMouseOptsFormatVersion = 1;
696  { * Changes in Version 6:
697      - MouseWheel is nov configurable
698  }
699
700  LazSyntaxHighlighterClasses: array[TLazSyntaxHighlighter] of
701    TCustomSynClass =
702    (nil, nil, TIDESynFreePasSyn, TIDESynPasSyn, TSynLFMSyn, TSynXMLSyn,
703    TSynHTMLSyn, TSynCPPSyn, TSynPerlSyn, TSynJavaSyn, TSynUNIXShellScriptSyn,
704    TSynPythonSyn, TSynPHPSyn, TSynSQLSyn,TSynCssSyn, TSynJScriptSyn, TSynDiffSyn,
705    TSynBatSyn, TSynIniSyn, TSynPoSyn, TSynPikeSyn);
706
707
708{ Comments }
709const
710  DefaultCommentTypes: array[TLazSyntaxHighlighter] of TCommentType = (
711    comtNone,  // lshNone
712    comtNone,  // lshText
713    comtPascal,// lshFreePascal
714    comtPascal,// lshDelphi
715    comtDelphi,// lshLFM
716    comtHtml,  // lshXML
717    comtHtml,  // lshHTML
718    comtCPP,   // lshCPP
719    comtPerl,  // lshPerl
720    comtCPP,   // lshJava
721    comtPerl,  // lshBash
722    comtPerl,  // lshPython
723    comtHTML,  // lshPHP
724    comtCPP,   // lshSQL
725    comtCPP,   // lshCss
726    comtCPP,   // lshJScript
727    comtNone,  // Diff
728    comtNone,  // Bat
729    comtNone,  // Ini
730    comtNone,  // po
731    comtCPP    // lshPike
732    );
733
734const
735  SynEditDefaultOptions = SYNEDIT_DEFAULT_OPTIONS - [eoShowScrollHint]
736                                                  + [eoHalfPageScroll, eoTabIndent];
737  SynEditDefaultOptions2 = SYNEDIT_DEFAULT_OPTIONS2;
738
739  EditorOptionsMinimumFontSize = 5;
740
741type
742  { TEditOptLanguageInfo stores lazarus IDE additional information
743    of a highlighter, such as samplesource, which sample lines are special
744    lines, file extensions
745    MappedAttributes is a list of the format "AttributName=PascalAttributName"
746      This mapping attributes are used for default values. For example:
747      The comment attribute of HTML is mapped to the comment attribute of
748      pascal "Comment=Comment". If there is no mapping attribute for an
749      attribute the default values are taken from an untouched highlighter.
750      For example Symbol in HTML is not mapped and therefore has as default
751      value fo style [fsBold] as defined in synhighlighterhtml.pp.
752    }
753  TEditOptLanguageInfo = class
754  private
755    MappedAttributes: TStringList; // map attributes to pascal
756  protected
757    procedure prepare(Syntax :  TLazSyntaxHighlighter);virtual;
758  public
759    SynClass: TCustomSynClass;
760    TheType:  TLazSyntaxHighlighter;
761    FileExtensions: String; // divided by semicolon, e.g. 'pas;pp;inc'
762    DefaultFileExtensions: string;
763    ColorScheme: String;
764    SampleSource: String;
765    AddAttrSampleLines: array[TAdditionalHilightAttribute] of Integer; // first line = 1
766//    MappedAttributes: TStringList; // map attributes to pascal
767    DefaultCommentType: TCommentType;
768    CaretXY: TPoint;
769    constructor Create;
770    destructor Destroy; override;
771    function GetDefaultFilextension: String;
772    procedure SetBothFilextensions(const Extensions: string);
773    function SampleLineToAddAttr(Line: Integer): TAdditionalHilightAttribute;
774  end;
775
776  { TEditOptLangCssInfo }
777
778  TEditOptLangCssInfo = class(tEditOptLanguageInfo)
779  protected
780     procedure prepare(Syntax :  TLazSyntaxHighlighter);override;
781     function getSampleSource:string;
782     function getMappedAttributes: tStringList;
783  end;
784
785  { TEditOptLangList }
786
787  TEditOptLangList = class(TList)
788  private
789    function GetInfos(Index: Integer): TEditOptLanguageInfo;
790  public
791    constructor Create;
792    procedure Clear; override;
793    destructor Destroy; override;
794    function FindByName(const Name: String): Integer;
795    function FindByClass(CustomSynClass: TCustomSynClass): Integer;
796    function FindByHighlighter(Hilighter: TSynCustomHighlighter): Integer;
797    function FindByType(AType: TLazSyntaxHighlighter): Integer;
798    function GetDefaultFilextension(AType: TLazSyntaxHighlighter): String;
799    function GetInfoByType(AType: TLazSyntaxHighlighter): TEditOptLanguageInfo;
800    property Items[Index: Integer]: TEditOptLanguageInfo read GetInfos; default;
801  end;
802
803  TMouseOptGutterLeftType = (
804    moGLDownClick,
805    moglUpClickAndSelect,
806    moglUpClickAndSelectRighHalf   // Changes and fold gutter (parts close to the text)
807  );
808  TMouseOptButtonActionOld = (
809    mbaNone,
810    mbaSelect, mbaSelectColumn, mbaSelectLine,
811    //mbaSelectTokens,
812    mbaSelectWords,
813    //mbaSelectLines,
814    mbaSelectSetWord, mbaSelectSetLineSmart, mbaSelectSetLineFull, mbaSelectSetPara,
815    mbaPaste,
816    mbaDeclarationJump,
817    mbaDeclarationOrBlockJump,
818    mbaAddHistoryPoint,
819    mbaHistoryBack, mbaHistoryForw,
820    mbaSetFreeBookmark,
821    mbaZoomReset,
822    mbaContextMenu,
823    mbaContextMenuDebug,
824    mbaContextMenuTab,
825
826    mbaMultiCaretToggle,
827
828    // Old values, needed to load old config
829    moTCLNone, moTMIgnore,
830    moTMPaste,
831    moTMDeclarationJump, moTCLJump,
832    moTCLJumpOrBlock
833  );
834
835  TMouseOptButtonAction = mbaNone..mbaMultiCaretToggle;
836
837const
838  MouseOptButtonActionOld: Array [moTCLNone..moTCLJumpOrBlock] of TMouseOptButtonActionOld = (
839    mbaNone, mbaNone,
840    mbaPaste,
841    mbaDeclarationJump, mbaDeclarationJump,
842    mbaDeclarationOrBlockJump
843  );
844
845type
846  TMouseOptWheelAction = (
847    mwaNone,
848    mwaScroll, mwaScrollSingleLine,
849    mwaScrollPage, mwaScrollPageLessOne, mwaScrollHalfPage,
850    mwaScrollHoriz, mwaScrollHorizSingleLine,
851    mwaScrollHorizPage, mwaScrollHorizPageLessOne, mwaScrollHorizHalfPage,
852    mwaZoom
853  );
854
855  { TEditorMouseOptions }
856
857  TEditorMouseOptions = class(TPersistent)
858  private
859    FGutterLeft: TMouseOptGutterLeftType;
860    FTextDrag: Boolean;
861    FTextRightMoveCaret: Boolean;
862    FUserSchemes: TQuickStringlist;
863  private
864    FCustomSavedActions: Boolean;
865    FGutterActionsChanges: TSynEditMouseActions;
866    FMainActions, FSelActions, FTextActions: TSynEditMouseActions;
867    FSelectOnLineNumbers: Boolean;
868    FName: String;
869    FGutterActions: TSynEditMouseActions;
870    FGutterActionsFold, FGutterActionsFoldExp, FGutterActionsFoldCol: TSynEditMouseActions;
871    FGutterActionsLines: TSynEditMouseActions;
872    FGutterActionsOverView, FGutterActionsOverViewMarks: TSynEditMouseActions;
873    FSelectedUserScheme: String;
874    // left multi click
875    FTextDoubleLeftClick: TMouseOptButtonAction;
876    FTextTripleLeftClick: TMouseOptButtonAction;
877    FTextQuadLeftClick: TMouseOptButtonAction;
878    FTextShiftDoubleLeftClick: TMouseOptButtonAction;
879    FTextAltDoubleLeftClick: TMouseOptButtonAction;
880    FTextCtrlDoubleLeftClick: TMouseOptButtonAction;
881    // left + modifier click
882    FTextShiftLeftClick: TMouseOptButtonAction;
883    FTextAltLeftClick: TMouseOptButtonAction;
884    FTextCtrlLeftClick: TMouseOptButtonActionOld;
885    FTextAltCtrlLeftClick: TMouseOptButtonAction;
886    FTextShiftAltLeftClick: TMouseOptButtonAction;
887    FTextShiftCtrlLeftClick: TMouseOptButtonAction;
888    FTextShiftAltCtrlLeftClick: TMouseOptButtonAction;
889    // middle click
890    FTextMiddleClick: TMouseOptButtonActionOld;
891    FTextAltMiddleClick: TMouseOptButtonAction;
892    FTextCtrlMiddleClick: TMouseOptButtonAction;
893    FTextAltCtrlMiddleClick: TMouseOptButtonAction;
894    FTextShiftAltMiddleClick: TMouseOptButtonAction;
895    FTextShiftAltCtrlMiddleClick: TMouseOptButtonAction;
896    FTextShiftCtrlMiddleClick: TMouseOptButtonAction;
897    FTextShiftMiddleClick: TMouseOptButtonAction;
898    // right
899    FTextAltCtrlRightClick: TMouseOptButtonAction;
900    FTextAltRightClick: TMouseOptButtonAction;
901    FTextCtrlRightClick: TMouseOptButtonAction;
902    FTextRightClick: TMouseOptButtonAction;
903    FTextShiftAltCtrlRightClick: TMouseOptButtonAction;
904    FTextShiftAltRightClick: TMouseOptButtonAction;
905    FTextShiftCtrlRightClick: TMouseOptButtonAction;
906    FTextShiftRightClick: TMouseOptButtonAction;
907    // extra-1 click
908    FTextAltCtrlExtra1Click: TMouseOptButtonAction;
909    FTextAltExtra1Click: TMouseOptButtonAction;
910    FTextCtrlExtra1Click: TMouseOptButtonAction;
911    FTextExtra1Click: TMouseOptButtonAction;
912    FTextShiftAltCtrlExtra1Click: TMouseOptButtonAction;
913    FTextShiftAltExtra1Click: TMouseOptButtonAction;
914    FTextShiftCtrlExtra1Click: TMouseOptButtonAction;
915    FTextShiftExtra1Click: TMouseOptButtonAction;
916    // extra-2 click
917    FTextAltCtrlExtra2Click: TMouseOptButtonAction;
918    FTextAltExtra2Click: TMouseOptButtonAction;
919    FTextCtrlExtra2Click: TMouseOptButtonAction;
920    FTextExtra2Click: TMouseOptButtonAction;
921    FTextShiftAltCtrlExtra2Click: TMouseOptButtonAction;
922    FTextShiftAltExtra2Click: TMouseOptButtonAction;
923    FTextShiftCtrlExtra2Click: TMouseOptButtonAction;
924    FTextShiftExtra2Click: TMouseOptButtonAction;
925    FVersion: Integer;
926    // wheel
927    FWheel: TMouseOptWheelAction;
928    FAltWheel: TMouseOptWheelAction;
929    FCtrlWheel: TMouseOptWheelAction;
930    FAltCtrlWheel: TMouseOptWheelAction;
931    FShiftWheel: TMouseOptWheelAction;
932    FShiftAltWheel: TMouseOptWheelAction;
933    FShiftCtrlWheel: TMouseOptWheelAction;
934    FShiftAltCtrlWheel: TMouseOptWheelAction;
935
936    FHorizWheel: TMouseOptWheelAction;
937    FAltHorizWheel: TMouseOptWheelAction;
938    FCtrlHorizWheel: TMouseOptWheelAction;
939    FAltCtrlHorizWheel: TMouseOptWheelAction;
940    FShiftHorizWheel: TMouseOptWheelAction;
941    FShiftAltHorizWheel: TMouseOptWheelAction;
942    FShiftCtrlHorizWheel: TMouseOptWheelAction;
943    FShiftAltCtrlHorizWheel: TMouseOptWheelAction;
944
945    procedure ClearUserSchemes;
946    function GetUserSchemeNames(Index: Integer): String;
947    function GetUserSchemes(Index: String): TEditorMouseOptions;
948    function GetUserSchemesAtPos(Index: Integer): TEditorMouseOptions;
949    function  GetSelectedUserSchemeIndex: Integer;
950    procedure SetSelectedUserScheme(const AValue: String);
951    procedure SetSelectedUserSchemeIndex(const AValue: Integer);
952    procedure AssignActions(Src: TEditorMouseOptions);
953    procedure SetTextCtrlLeftClick(AValue: TMouseOptButtonActionOld);
954    procedure SetTextMiddleClick(AValue: TMouseOptButtonActionOld);
955  public
956    constructor Create;
957    destructor Destroy; override;
958    procedure Reset;
959    procedure ResetGutterToDefault;
960    procedure ResetTextToDefault;
961    procedure ResetToUserScheme;
962    procedure AssignEx(Src: TEditorMouseOptions; WithUserSchemes: Boolean);
963    procedure Assign(Src: TEditorMouseOptions); reintroduce;
964    function  IsPresetEqualToMouseActions: Boolean;
965    function  CalcCustomSavedActions: Boolean;
966    procedure LoadFromXml(aXMLConfig: TRttiXMLConfig; aPath: String; aOldPath: String; FileVersion: Integer);
967    procedure SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String);
968    procedure ImportFromXml(aXMLConfig: TRttiXMLConfig; aPath: String);
969    procedure ExportToXml(aXMLConfig: TRttiXMLConfig; aPath: String);
970    procedure LoadUserSchemes;
971    function  UserSchemeCount: Integer;
972    function  IndexOfUserScheme(SchemeName: String): Integer;
973
974    property Name: String read FName;
975    property UserSchemes[Index: String]: TEditorMouseOptions read GetUserSchemes;
976    property UserSchemesAtPos[Index: Integer]: TEditorMouseOptions read GetUserSchemesAtPos;
977    property UserSchemeNames[Index: Integer]: String read GetUserSchemeNames;
978    property SelectedUserSchemeIndex: Integer
979             read GetSelectedUserSchemeIndex write SetSelectedUserSchemeIndex;
980
981    property MainActions: TSynEditMouseActions read FMainActions;
982    property SelActions: TSynEditMouseActions read FSelActions;
983    property TextActions: TSynEditMouseActions read FTextActions;
984    property GutterActions: TSynEditMouseActions read FGutterActions;
985    property GutterActionsFold: TSynEditMouseActions read FGutterActionsFold;
986    property GutterActionsFoldExp: TSynEditMouseActions read FGutterActionsFoldExp;
987    property GutterActionsFoldCol: TSynEditMouseActions read FGutterActionsFoldCol;
988    property GutterActionsLines: TSynEditMouseActions read FGutterActionsLines;
989    property GutterActionsChanges: TSynEditMouseActions read FGutterActionsChanges;
990    property GutterActionsOverView: TSynEditMouseActions read FGutterActionsOverView;
991    property GutterActionsOverViewMarks: TSynEditMouseActions read FGutterActionsOverViewMarks;
992  published
993    property GutterLeft: TMouseOptGutterLeftType read FGutterLeft write FGutterLeft
994             default moglUpClickAndSelect;
995    property SelectOnLineNumbers: Boolean read FSelectOnLineNumbers write FSelectOnLineNumbers
996             default True;
997    property TextDrag: Boolean read FTextDrag write FTextDrag
998             default True;
999    property TextRightMoveCaret: Boolean read FTextRightMoveCaret  write FTextRightMoveCaret
1000             default False;
1001    // left multi click
1002    property TextDoubleLeftClick: TMouseOptButtonAction read FTextDoubleLeftClick write FTextDoubleLeftClick
1003             default mbaSelectSetWord;
1004    property TextTripleLeftClick: TMouseOptButtonAction read FTextTripleLeftClick write FTextTripleLeftClick
1005             default mbaSelectSetLineSmart;
1006    property TextQuadLeftClick: TMouseOptButtonAction read FTextQuadLeftClick write FTextQuadLeftClick
1007             default mbaSelectSetPara;
1008    property TextShiftDoubleLeftClick: TMouseOptButtonAction read FTextShiftDoubleLeftClick write FTextShiftDoubleLeftClick
1009             default mbaNone;
1010    property TextCtrlDoubleLeftClick: TMouseOptButtonAction read FTextCtrlDoubleLeftClick write FTextCtrlDoubleLeftClick
1011             default mbaNone;
1012    property TextAltDoubleLeftClick: TMouseOptButtonAction read FTextAltDoubleLeftClick write FTextAltDoubleLeftClick
1013             default mbaNone;
1014    // left + modifier click
1015    property TextShiftLeftClick: TMouseOptButtonAction read FTextShiftLeftClick write FTextShiftLeftClick
1016             default mbaNone;  // continue selection
1017    property TextCtrlLeftClick: TMouseOptButtonActionOld read FTextCtrlLeftClick write SetTextCtrlLeftClick
1018             default mbaDeclarationJump;
1019    property TextAltLeftClick: TMouseOptButtonAction read FTextAltLeftClick write FTextAltLeftClick
1020             default mbaSelectColumn;
1021    property TextShiftCtrlLeftClick: TMouseOptButtonAction read FTextShiftCtrlLeftClick write FTextShiftCtrlLeftClick
1022             default mbaMultiCaretToggle;  // continue selection
1023    property TextShiftAltLeftClick: TMouseOptButtonAction read FTextShiftAltLeftClick write FTextShiftAltLeftClick
1024             default mbaNone;  // continue selection
1025    property TextAltCtrlLeftClick: TMouseOptButtonAction read FTextAltCtrlLeftClick write FTextAltCtrlLeftClick
1026             default mbaNone;
1027    property TextShiftAltCtrlLeftClick: TMouseOptButtonAction read FTextShiftAltCtrlLeftClick write FTextShiftAltCtrlLeftClick
1028             default mbaNone;
1029    // middle click
1030    property TextMiddleClick: TMouseOptButtonActionOld read FTextMiddleClick write SetTextMiddleClick
1031             default mbaPaste;
1032    property TextShiftMiddleClick: TMouseOptButtonAction read FTextShiftMiddleClick write FTextShiftMiddleClick
1033             default mbaNone;
1034    property TextAltMiddleClick: TMouseOptButtonAction read FTextAltMiddleClick write FTextAltMiddleClick
1035             default mbaNone;
1036    property TextCtrlMiddleClick: TMouseOptButtonAction read FTextCtrlMiddleClick write FTextCtrlMiddleClick
1037             default mbaZoomReset;
1038    property TextShiftAltMiddleClick: TMouseOptButtonAction read FTextShiftAltMiddleClick write FTextShiftAltMiddleClick
1039             default mbaNone;
1040    property TextShiftCtrlMiddleClick: TMouseOptButtonAction read FTextShiftCtrlMiddleClick write FTextShiftCtrlMiddleClick
1041             default mbaNone;
1042    property TextAltCtrlMiddleClick: TMouseOptButtonAction read FTextAltCtrlMiddleClick write FTextAltCtrlMiddleClick
1043             default mbaNone;
1044    property TextShiftAltCtrlMiddleClick: TMouseOptButtonAction read FTextShiftAltCtrlMiddleClick write FTextShiftAltCtrlMiddleClick
1045             default mbaNone;
1046    // right click
1047    property TextRightClick: TMouseOptButtonAction read FTextRightClick write FTextRightClick
1048             default mbaContextMenu;
1049    property TextShiftRightClick: TMouseOptButtonAction read FTextShiftRightClick write FTextShiftRightClick
1050             default mbaNone;
1051    property TextAltRightClick: TMouseOptButtonAction read FTextAltRightClick write FTextAltRightClick
1052             default mbaNone;
1053    property TextCtrlRightClick: TMouseOptButtonAction read FTextCtrlRightClick write FTextCtrlRightClick
1054             default mbaContextMenuTab;
1055    property TextShiftAltRightClick: TMouseOptButtonAction read FTextShiftAltRightClick write FTextShiftAltRightClick
1056             default mbaNone;
1057    property TextShiftCtrlRightClick: TMouseOptButtonAction read FTextShiftCtrlRightClick write FTextShiftCtrlRightClick
1058             default mbaNone;
1059    property TextAltCtrlRightClick: TMouseOptButtonAction read FTextAltCtrlRightClick write FTextAltCtrlRightClick
1060             default mbaNone;
1061    property TextShiftAltCtrlRightClick: TMouseOptButtonAction read FTextShiftAltCtrlRightClick write FTextShiftAltCtrlRightClick
1062             default mbaNone;
1063    // extra-1 click
1064    property TextExtra1Click: TMouseOptButtonAction read FTextExtra1Click write FTextExtra1Click
1065             default mbaHistoryBack;
1066    property TextShiftExtra1Click: TMouseOptButtonAction read FTextShiftExtra1Click write FTextShiftExtra1Click
1067             default mbaNone;
1068    property TextAltExtra1Click: TMouseOptButtonAction read FTextAltExtra1Click write FTextAltExtra1Click
1069             default mbaNone;
1070    property TextCtrlExtra1Click: TMouseOptButtonAction read FTextCtrlExtra1Click write FTextCtrlExtra1Click
1071             default mbaNone;
1072    property TextShiftAltExtra1Click: TMouseOptButtonAction read FTextShiftAltExtra1Click write FTextShiftAltExtra1Click
1073             default mbaNone;
1074    property TextShiftCtrlExtra1Click: TMouseOptButtonAction read FTextShiftCtrlExtra1Click write FTextShiftCtrlExtra1Click
1075             default mbaNone;
1076    property TextAltCtrlExtra1Click: TMouseOptButtonAction read FTextAltCtrlExtra1Click write FTextAltCtrlExtra1Click
1077             default mbaNone;
1078    property TextShiftAltCtrlExtra1Click: TMouseOptButtonAction read FTextShiftAltCtrlExtra1Click write FTextShiftAltCtrlExtra1Click
1079             default mbaNone;
1080    // extra-2 click
1081    property TextExtra2Click: TMouseOptButtonAction read FTextExtra2Click write FTextExtra2Click
1082             default mbaHistoryForw;
1083    property TextShiftExtra2Click: TMouseOptButtonAction read FTextShiftExtra2Click write FTextShiftExtra2Click
1084             default mbaNone;
1085    property TextAltExtra2Click: TMouseOptButtonAction read FTextAltExtra2Click write FTextAltExtra2Click
1086             default mbaNone;
1087    property TextCtrlExtra2Click: TMouseOptButtonAction read FTextCtrlExtra2Click write FTextCtrlExtra2Click
1088             default mbaNone;
1089    property TextShiftAltExtra2Click: TMouseOptButtonAction read FTextShiftAltExtra2Click write FTextShiftAltExtra2Click
1090             default mbaNone;
1091    property TextShiftCtrlExtra2Click: TMouseOptButtonAction read FTextShiftCtrlExtra2Click write FTextShiftCtrlExtra2Click
1092             default mbaNone;
1093    property TextAltCtrlExtra2Click: TMouseOptButtonAction read FTextAltCtrlExtra2Click write FTextAltCtrlExtra2Click
1094             default mbaNone;
1095    property TextShiftAltCtrlExtra2Click: TMouseOptButtonAction read FTextShiftAltCtrlExtra2Click write FTextShiftAltCtrlExtra2Click
1096             default mbaNone;
1097    //
1098    property Wheel: TMouseOptWheelAction read FWheel write FWheel
1099             default mwaScroll;
1100    property CtrlWheel: TMouseOptWheelAction read FCtrlWheel write FCtrlWheel
1101             default mwaZoom;
1102    property AltWheel: TMouseOptWheelAction read FAltWheel write FAltWheel
1103             default mwaScrollPageLessOne;
1104    property ShiftWheel: TMouseOptWheelAction read FShiftWheel write FShiftWheel
1105             default mwaScrollSingleLine;
1106    property ShiftAltWheel: TMouseOptWheelAction read FShiftAltWheel write FShiftAltWheel
1107             default mwaNone;
1108    property ShiftCtrlWheel: TMouseOptWheelAction read FShiftCtrlWheel write FShiftCtrlWheel
1109             default mwaNone;
1110    property AltCtrlWheel: TMouseOptWheelAction read FAltCtrlWheel write FAltCtrlWheel
1111             default mwaNone;
1112    property ShiftAltCtrlWheel: TMouseOptWheelAction read FShiftAltCtrlWheel write FShiftAltCtrlWheel
1113             default mwaNone;
1114    //
1115    property HorizWheel: TMouseOptWheelAction read FHorizWheel write FHorizWheel
1116             default mwaScrollHoriz;
1117    property CtrlHorizWheel: TMouseOptWheelAction read FCtrlHorizWheel write FCtrlHorizWheel
1118             default mwaNone;
1119    property AltHorizWheel: TMouseOptWheelAction read FAltHorizWheel write FAltHorizWheel
1120             default mwaScrollHorizPageLessOne;
1121    property ShiftHorizWheel: TMouseOptWheelAction read FShiftHorizWheel write FShiftHorizWheel
1122             default mwaScrollHorizSingleLine;
1123    property ShiftAltHorizWheel: TMouseOptWheelAction read FShiftAltHorizWheel write FShiftAltHorizWheel
1124             default mwaNone;
1125    property ShiftCtrlHorizWheel: TMouseOptWheelAction read FShiftCtrlHorizWheel write FShiftCtrlHorizWheel
1126             default mwaNone;
1127    property AltCtrlHorizWheel: TMouseOptWheelAction read FAltCtrlHorizWheel write FAltCtrlHorizWheel
1128             default mwaNone;
1129    property ShiftAltCtrlHorizWheel: TMouseOptWheelAction read FShiftAltCtrlHorizWheel write FShiftAltCtrlHorizWheel
1130             default mwaNone;
1131
1132    // the flag below is set by CalcCustomSavedActions
1133    property CustomSavedActions: Boolean read FCustomSavedActions write FCustomSavedActions;
1134    property SelectedUserScheme: String read FSelectedUserScheme write SetSelectedUserScheme;
1135    property Version : Integer read FVersion write FVersion;
1136  end;
1137
1138  { TEditorMouseOptionPresets }
1139
1140  TEditorMouseOptionPresets = class
1141  public
1142    constructor Create;
1143  end;
1144
1145  TEditorOptionsEditAccessInViewState =
1146    (eoeaIgnoreInView,          // Find any editor
1147     eoeaInViewOnly,            // Only editors, with the jump-target in their current visible area
1148     eoeaInViewSoftCenterOnly   // Only editors, with the jump-target in their current visible soft center (exclude up to 5 lines top/bottom)
1149    );
1150  TEditorOptionsEditAccessLockedState =
1151    (eoeaIgnoreLock,     // Find any editor
1152     eoeaLockedOnly,     // Only use locked Editor (e.g for InView = eoeaInViewOnly)
1153     eoeaUnlockedOnly,   // Only use unlocked Editors (default)
1154     eoeaLockedFirst,    // Search locked Editors first (each group according to Order)
1155     eoeaLockedLast      // Search locked Editoes last
1156    );
1157  TEditorOptionsEditAccessOrder =
1158    (eoeaOrderByEditFocus,       // prefer the editors in the order they were last focused
1159     eoeaOrderByWindowFocus,     // prefer the editors in the order their window was last focused
1160     eoeaOrderByOldestEditFocus, // Reverse order by last focused
1161     eoeaOrderByOldestWindowFocus,
1162     eoeaOnlyCurrentEdit,        // search only the current-active editor (and only if it has the correct file)
1163     eoeaOnlyCurrentWindow,      // search only the current window (if it has an editor for the desired file)
1164     eoeaOrderByListPref         // follow global setting on the list
1165    );
1166  TEditorOptionsEditAccessOpenNew =
1167    (eoeaNoNewTab,                     // Do not open a new tab, if none found
1168     eoeaNewTabInExistingWindowOnly,   // Open a new tab in existing (last focus) window, if possible
1169     eoeaNewTabInNewWindowOnly,        // Open a new tab in new window
1170     eoeaNewTabInExistingOrNewWindow   // Open a new tab in existing or new window
1171    );
1172  TEditorOptionsEditAccessDefaultEntry = record
1173    SearchLocked: TEditorOptionsEditAccessLockedState;
1174    SearchInView: TEditorOptionsEditAccessInViewState;
1175    SearchOrder: TEditorOptionsEditAccessOrder;
1176    SearchOpenNew: TEditorOptionsEditAccessOpenNew;
1177    Enabled: Boolean;
1178    ID: String;
1179    Caption, Desc: String;
1180  end;
1181  TEditorOptionsEditAccessDefaults = Array [0..8] of TEditorOptionsEditAccessDefaultEntry;
1182
1183const
1184  // captions and desc are set in TEditorOptions.Create
1185  EditorOptionsEditAccessDefaults: TEditorOptionsEditAccessDefaults =
1186  ( // Find locked - InView
1187    (SearchLocked: eoeaLockedOnly;        SearchInView:  eoeaInViewOnly;
1188     SearchOrder:  eoeaOrderByListPref;   SearchOpenNew: eoeaNoNewTab;
1189     Enabled:      True;                  ID:            'Locked_InView';
1190     Caption: '';                         Desc: '' ),
1191    // Find unlocked
1192    (SearchLocked: eoeaUnlockedOnly;      SearchInView:  eoeaInViewSoftCenterOnly;
1193     SearchOrder:  eoeaOrderByListPref;   SearchOpenNew: eoeaNoNewTab;
1194     Enabled:      False;                 ID:            'UnLocked_InSoftView';
1195     Caption: '';                         Desc: '' ),
1196    (SearchLocked: eoeaUnlockedOnly;      SearchInView:  eoeaIgnoreInView;
1197     SearchOrder:  eoeaOrderByListPref;   SearchOpenNew: eoeaNoNewTab;
1198     Enabled:      True;                  ID:            'UnLocked';
1199     Caption: '';                         Desc: '' ),
1200    // open new tab
1201    (SearchLocked: eoeaUnlockedOnly;      SearchInView:  eoeaIgnoreInView;
1202     SearchOrder:  eoeaOrderByListPref;   SearchOpenNew: eoeaNewTabInExistingWindowOnly;
1203     Enabled:      False;                 ID:            'UnLocked_OpenNewInOldWin';
1204     Caption: '';                         Desc: '' ),
1205    (SearchLocked: eoeaUnlockedOnly;      SearchInView:  eoeaIgnoreInView;
1206     SearchOrder:  eoeaOrderByListPref;   SearchOpenNew: eoeaNewTabInNewWindowOnly;
1207     Enabled:      False;                 ID:            'UnLocked_OpenNewInNewWin';
1208     Caption: '';                         Desc: '' ),
1209    // Ignore locks
1210    (SearchLocked: eoeaIgnoreLock;        SearchInView:  eoeaIgnoreInView;
1211     SearchOrder:  eoeaOrderByOldestEditFocus; SearchOpenNew: eoeaNoNewTab;
1212     Enabled:      False;                 ID:            'IgnLocked_OldEdit';
1213     Caption: '';                         Desc: '' ),
1214    (SearchLocked: eoeaIgnoreLock;        SearchInView:  eoeaIgnoreInView;
1215     SearchOrder:  eoeaOnlyCurrentEdit;   SearchOpenNew: eoeaNoNewTab;
1216     Enabled:      False;                 ID:            'IgnLocked_OnlyActEdit';
1217     Caption: '';                         Desc: '' ),
1218    (SearchLocked: eoeaIgnoreLock;        SearchInView:  eoeaIgnoreInView;
1219     SearchOrder:  eoeaOnlyCurrentWindow; SearchOpenNew: eoeaNoNewTab;
1220     Enabled:      False;                 ID:            'IgnLocked_OnlyActWin';
1221     Caption: '';                         Desc: '' ),
1222    // Fallback (must be last)
1223    (SearchLocked: eoeaUnlockedOnly;      SearchInView:  eoeaIgnoreInView;
1224     SearchOrder:  eoeaOrderByListPref;   SearchOpenNew: eoeaNewTabInExistingOrNewWindow;
1225     Enabled:      True;                  ID:            'UnLocked_OpenNewInAnyWin';
1226     Caption: '';                         Desc: '' )
1227  );
1228  EditorOptionsEditAccessUserDef: TEditorOptionsEditAccessDefaultEntry =
1229    (SearchLocked: eoeaUnlockedOnly;      SearchInView:  eoeaIgnoreInView;
1230     SearchOrder:  eoeaOrderByListPref;   SearchOpenNew: eoeaNoNewTab;
1231     Enabled:      True;                  ID:            '';
1232     Caption: '';                         Desc: '' );
1233
1234type
1235
1236  TEditorOptionsEditAccessOrderList = class;
1237
1238  { TEditorOptionsEditAccessOrderEntry }
1239
1240  TEditorOptionsEditAccessOrderEntry = class(TPersistent)
1241  private
1242    FId: String;
1243    FList: TEditorOptionsEditAccessOrderList;
1244    FCaption: String;
1245    FDesc: String;
1246    FEnabled: Boolean;
1247    FIsFallback: Boolean;
1248    FDefaults: TEditorOptionsEditAccessOrderEntry;
1249    FSearchInView: TEditorOptionsEditAccessInViewState;
1250    FSearchLocked: TEditorOptionsEditAccessLockedState;
1251    FSearchOpenNew: TEditorOptionsEditAccessOpenNew;
1252    FSearchOrder: TEditorOptionsEditAccessOrder;
1253    procedure AssignFrom(AValue: TEditorOptionsEditAccessDefaultEntry);
1254    procedure SetEnabled(const AValue: Boolean);
1255  public
1256    constructor Create(AList: TEditorOptionsEditAccessOrderList);
1257    destructor Destroy; override;
1258    procedure Assign(Src: TEditorOptionsEditAccessOrderEntry); reintroduce;
1259    procedure InitFrom(AValue: TEditorOptionsEditAccessDefaultEntry);
1260  public
1261    function RealSearchOrder: TEditorOptionsEditAccessOrder;
1262    property Defaults: TEditorOptionsEditAccessOrderEntry read FDefaults;
1263    property ID: String read FId write FId;
1264    property IsFallback: Boolean read FIsFallback;
1265    property Desc: String read FDesc write FDesc;
1266  //published
1267    property Caption: String read FCaption write FCaption;
1268  published
1269    property Enabled: Boolean
1270             read FEnabled write SetEnabled;
1271  public
1272    property SearchLocked: TEditorOptionsEditAccessLockedState
1273             read FSearchLocked write FSearchLocked;
1274    property SearchInView: TEditorOptionsEditAccessInViewState
1275             read FSearchInView write FSearchInView;
1276    property SearchOrder: TEditorOptionsEditAccessOrder
1277             read FSearchOrder write FSearchOrder;
1278    property SearchOpenNew: TEditorOptionsEditAccessOpenNew
1279             read FSearchOpenNew write FSearchOpenNew;
1280    //property IgnoreTopLineAdjustment;
1281  end;
1282
1283  { TEditorOptionsEditAccessOrderList }
1284
1285  TEditorOptionsEditAccessOrderList = class(TPersistent)
1286  private
1287    FList: TFPList;
1288    FSearchOrder: TEditorOptionsEditAccessOrder;
1289    function GetItems(Index: Integer): TEditorOptionsEditAccessOrderEntry;
1290  public
1291    constructor Create;
1292    destructor Destroy; override;
1293    procedure Clear;
1294    procedure InitDefaults;
1295    procedure Assign(Src: TEditorOptionsEditAccessOrderList); reintroduce;
1296    procedure LoadFromXMLConfig(XMLConfig:TRttiXMLConfig; Path: String);
1297    procedure SaveToXMLConfig(XMLConfig:TRttiXMLConfig; Path: String);
1298    function Count: Integer;
1299    property Items[Index: Integer]: TEditorOptionsEditAccessOrderEntry
1300             read GetItems; default;
1301  published
1302    property SearchOrder: TEditorOptionsEditAccessOrder
1303             read FSearchOrder write FSearchOrder;
1304  end;
1305
1306const
1307  EditorUserDefinedWordsKeyCatName = 'User defined word markup';
1308  MARKUP_USER_DEF_PRIOR = 3500;
1309
1310var
1311  EditorUserDefinedWordsGlobalId: string = 'a';
1312
1313type
1314
1315  TEditorUserDefinedWordsList = class;
1316
1317  { TEditorUserDefinedWords }
1318
1319  TEditorUserDefinedWords = class(TSourceSynSearchTermList)
1320  private
1321    FGlobalList: Boolean;
1322    FGlobalTermsCache: TSynSearchTermDict;
1323    FId: String; // Used for TIDECommand.Name
1324    FKeyAddCase: Boolean;
1325    FKeyAddSelectBoundMaxLen: Integer;
1326    FKeyAddSelectSmart: Boolean;
1327    FKeyAddTermBounds: TSynSearchTermOptsBounds;
1328    FKeyAddWordBoundMaxLen: Integer;
1329    FList: TEditorUserDefinedWordsList;
1330    FColorAttr: TColorSchemeAttribute;
1331    FName: String;
1332    FAddTermCmd: TIDECommand;
1333    FRemoveTermCmd: TIDECommand;
1334    FToggleTermCmd: TIDECommand;
1335    procedure SetGlobalTermsCache(AValue: TSynSearchTermDict);
1336    procedure SetName(AValue: String);
1337    procedure UpdateIdeCommands;
1338    procedure ClearIdeCommands;
1339  protected
1340    property GlobalTermsCache: TSynSearchTermDict read FGlobalTermsCache write SetGlobalTermsCache;
1341  public
1342    constructor Create(AList: TEditorUserDefinedWordsList);
1343    destructor Destroy; override;
1344    procedure Assign(Source: TPersistent); override;
1345
1346    procedure LoadFromXMLConfig(XMLConfig:TRttiXMLConfig; Path: String);
1347    procedure SaveToXMLConfig(XMLConfig:TRttiXMLConfig; Path: String);
1348
1349    property ColorAttr: TColorSchemeAttribute read FColorAttr;
1350
1351    function HasKeyAssigned: Boolean;
1352    property AddTermCmd: TIDECommand read FAddTermCmd;
1353    property RemoveTermCmd: TIDECommand read FRemoveTermCmd;
1354    property ToggleTermCmd: TIDECommand read FToggleTermCmd;
1355
1356    //property MatchWordBounds: TSynSearchTermOptsBounds read FMatchWordBounds write SetMatchWordBounds;
1357    //property MatchCase: Boolean read FMatchCase write SetMatchCase;
1358  published
1359    property Name: String read FName write SetName;
1360    property KeyAddTermBounds: TSynSearchTermOptsBounds read FKeyAddTermBounds write FKeyAddTermBounds;
1361    property KeyAddCase: Boolean read FKeyAddCase write FKeyAddCase;
1362    property KeyAddWordBoundMaxLen: Integer read FKeyAddWordBoundMaxLen write FKeyAddWordBoundMaxLen;
1363    property KeyAddSelectBoundMaxLen: Integer read FKeyAddSelectBoundMaxLen write FKeyAddSelectBoundMaxLen;
1364    property KeyAddSelectSmart: Boolean read FKeyAddSelectSmart write FKeyAddSelectSmart;
1365    property GlobalList: Boolean read FGlobalList write FGlobalList;
1366  end;
1367
1368  { TEditorUserDefinedWordsList }
1369
1370  TEditorUserDefinedWordsList = class(TPersistent)
1371  private
1372    FList: TList;
1373    FKeyCommandList: TIDECommands;
1374    FUseGlobalIDECommandList: Boolean;
1375    function GetKeyCommandList: TIDECommands;
1376    function GetLists(AIndex: Integer): TEditorUserDefinedWords;
1377    procedure SetLists(AIndex: Integer; AValue: TEditorUserDefinedWords);
1378  public
1379    constructor Create;
1380    destructor Destroy; override;
1381    procedure Assign(Src: TEditorUserDefinedWordsList); reintroduce;
1382
1383    procedure LoadFromXMLConfig(XMLConfig:TRttiXMLConfig; Path: String);
1384    procedure SaveToXMLConfig(XMLConfig:TRttiXMLConfig; Path: String);
1385
1386    procedure Clear;
1387    function  Add(AList: TEditorUserDefinedWords): Integer;
1388    function  Add(AName: String): TEditorUserDefinedWords;
1389    function  IndexOf(AName: String): Integer;
1390    function  IndexOf(AList: TEditorUserDefinedWords): Integer;
1391    procedure Remove(AName: String; {%H-}FreeList: Boolean = True);
1392    procedure Remove(AList: TEditorUserDefinedWords; FreeList: Boolean = True);
1393    procedure Delete(AIndex: Integer);
1394    function  Count: Integer;
1395    property Lists[AIndex: Integer]: TEditorUserDefinedWords read GetLists write SetLists;
1396    property KeyCommandList: TIDECommands read GetKeyCommandList write FKeyCommandList;
1397    property UseGlobalIDECommandList: Boolean read FUseGlobalIDECommandList write FUseGlobalIDECommandList;
1398  end;
1399
1400  { TEditorOptionsBase }
1401
1402  TEditorOptionsBase = class(TIDEEditorOptions)
1403  private
1404    {$IFDEF WinIME}
1405    FUseMinimumIme: Boolean;
1406    {$ENDIF}
1407    // General options
1408    fMultiLineTab: Boolean;
1409    fTabPosition: TTabPosition;
1410    // Display options
1411    fShowOverviewGutter: boolean;
1412    fTopInfoView: boolean;
1413    // Code tools options
1414    fDbgHintAutoTypeCastClass: Boolean;
1415    fCompletionLongLineHintType: TSynCompletionLongHintType;
1416    // Code Folding
1417    fReverseFoldPopUpOrder: Boolean;
1418    fUseTabHistory: Boolean;
1419
1420    fMultiCaretOnColumnSelect: Boolean;
1421    fMultiCaretDefaultMode: TSynPluginMultiCaretDefaultMode;
1422    fMultiCaretDeleteSkipLineBreak: Boolean;
1423    fMultiCaretDefaultColumnSelectMode: TSynPluginMultiCaretDefaultMode;
1424    // Highlighter Pas
1425    fPasExtendedKeywordsMode: Boolean;
1426    fPasStringKeywordMode: TSynPasStringMode;
1427    // Multi window
1428    fCtrlMiddleTabClickClosesOthers: Boolean;
1429    fMiddleTabClickClosesOthersModifier: TShiftState;
1430    fMiddleTabClickClosesToRightModifier: TShiftState;
1431    fShowFileNameInCaption: Boolean;
1432    // Comment Continue
1433    FAnsiCommentContinueEnabled: Boolean;
1434    FAnsiCommentMatch: String;
1435    FAnsiCommentMatchMode: TSynCommentMatchMode;
1436    FAnsiCommentPrefix: String;
1437    FAnsiIndentMode: TSynCommentIndentFlags;
1438    FAnsiIndentAlignMax: integer;
1439    FCurlyCommentContinueEnabled: Boolean;
1440    FCurlyCommentMatch: String;
1441    FCurlyCommentMatchMode: TSynCommentMatchMode;
1442    FCurlyCommentPrefix: String;
1443    FCurlyIndentMode: TSynCommentIndentFlags;
1444    FCurlyIndentAlignMax: integer;
1445    FSlashCommentContinueEnabled: Boolean;
1446    FSlashCommentMatch: String;
1447    FSlashCommentMatchMode: TSynCommentMatchMode;
1448    FSlashCommentPrefix: String;
1449    FSlashIndentMode: TSynCommentIndentFlags;
1450    FSlashCommentExtend: TSynCommentExtendMode;
1451    FSlashIndentAlignMax: integer;
1452    FStringBreakAppend: String;
1453    FStringBreakEnabled: Boolean;
1454    FStringBreakPrefix: String;
1455    // Scroll
1456    FScrollOnEditLeftOptions: TSynScrollOnEditLeftOptions;
1457    FScrollOnEditRightOptions: TSynScrollOnEditRightOptions;
1458    procedure InitForRttiXmlConf;
1459  protected
1460    function GetTabPosition: TTabPosition; override;
1461  public
1462    constructor Create;
1463    destructor Destroy; override;
1464  published { use RTTIConf}
1465    // general options
1466    property MultiLineTab: Boolean read fMultiLineTab write fMultiLineTab default False;
1467    property TabPosition: TTabPosition read fTabPosition write fTabPosition default tpTop;
1468    // Code Tools options
1469    property DbgHintAutoTypeCastClass: Boolean              // declaration hints
1470      read fDbgHintAutoTypeCastClass write fDbgHintAutoTypeCastClass default True;
1471    property CompletionLongLineHintType: TSynCompletionLongHintType
1472      read fCompletionLongLineHintType write fCompletionLongLineHintType
1473      default sclpExtendRightOnly;
1474    // General - Misc
1475    {$IFDEF WinIME}
1476    property UseMinimumIme: Boolean read FUseMinimumIme write FUseMinimumIme default False;
1477    {$ENDIF}
1478    // Display
1479    property ShowOverviewGutter: boolean
1480      read fShowOverviewGutter write fShowOverviewGutter default True;
1481    property TopInfoView: boolean read fTopInfoView write fTopInfoView default True;
1482    // Code Folding
1483    property ReverseFoldPopUpOrder: Boolean
1484      read fReverseFoldPopUpOrder write fReverseFoldPopUpOrder default True;
1485    property UseTabHistory: Boolean read fUseTabHistory write fUseTabHistory;
1486
1487    property MultiCaretOnColumnSelect: Boolean
1488      read fMultiCaretOnColumnSelect write fMultiCaretOnColumnSelect default True;
1489    property MultiCaretDefaultMode: TSynPluginMultiCaretDefaultMode
1490      read fMultiCaretDefaultMode write fMultiCaretDefaultMode default mcmMoveAllCarets;
1491    property MultiCaretDeleteSkipLineBreak: Boolean
1492      read fMultiCaretDeleteSkipLineBreak write fMultiCaretDeleteSkipLineBreak default False;
1493    property MultiCaretDefaultColumnSelectMode: TSynPluginMultiCaretDefaultMode
1494      read fMultiCaretDefaultColumnSelectMode write fMultiCaretDefaultColumnSelectMode default mcmCancelOnCaretMove;
1495    // Highlighter Pas
1496    property PasExtendedKeywordsMode: Boolean
1497      read fPasExtendedKeywordsMode write fPasExtendedKeywordsMode default False;
1498    property PasStringKeywordMode: TSynPasStringMode
1499      read fPasStringKeywordMode write fPasStringKeywordMode default spsmDefault;
1500    // Multi window
1501    property CtrlMiddleTabClickClosesOthers: Boolean
1502      read fCtrlMiddleTabClickClosesOthers write fCtrlMiddleTabClickClosesOthers stored False default True;
1503    property MiddleTabClickClosesOthersModifier: TShiftState
1504      read fMiddleTabClickClosesOthersModifier write fMiddleTabClickClosesOthersModifier default [ssCtrl];
1505    property MiddleTabClickClosesToRightModifier: TShiftState
1506      read fMiddleTabClickClosesToRightModifier write fMiddleTabClickClosesToRightModifier default [];
1507    property ShowFileNameInCaption: Boolean
1508      read fShowFileNameInCaption write fShowFileNameInCaption default False;
1509    // Comment Continue
1510    property AnsiCommentContinueEnabled: Boolean
1511      read FAnsiCommentContinueEnabled write FAnsiCommentContinueEnabled;
1512    property AnsiCommentMatch: String read FAnsiCommentMatch write FAnsiCommentMatch;
1513    property AnsiCommentPrefix: String read FAnsiCommentPrefix write FAnsiCommentPrefix;
1514    property AnsiCommentMatchMode: TSynCommentMatchMode
1515      read FAnsiCommentMatchMode write FAnsiCommentMatchMode;
1516    property AnsiIndentMode: TSynCommentIndentFlags
1517      read FAnsiIndentMode write FAnsiIndentMode;
1518    property AnsiIndentAlignMax: integer
1519      read FAnsiIndentAlignMax write FAnsiIndentAlignMax;
1520    property CurlyCommentContinueEnabled: Boolean
1521      read FCurlyCommentContinueEnabled write FCurlyCommentContinueEnabled;
1522    property CurlyCommentMatch: String read FCurlyCommentMatch write FCurlyCommentMatch;
1523    property CurlyCommentPrefix: String read FCurlyCommentPrefix write FCurlyCommentPrefix;
1524    property CurlyCommentMatchMode: TSynCommentMatchMode
1525      read FCurlyCommentMatchMode write FCurlyCommentMatchMode;
1526    property CurlyIndentMode: TSynCommentIndentFlags
1527      read FCurlyIndentMode write FCurlyIndentMode;
1528    property CurlyIndentAlignMax: integer
1529      read FCurlyIndentAlignMax write FCurlyIndentAlignMax;
1530    property SlashCommentContinueEnabled: Boolean
1531      read FSlashCommentContinueEnabled write FSlashCommentContinueEnabled;
1532    property SlashCommentMatch: String
1533      read FSlashCommentMatch write FSlashCommentMatch;
1534    property SlashCommentPrefix: String
1535      read FSlashCommentPrefix write FSlashCommentPrefix;
1536    property SlashCommentMatchMode: TSynCommentMatchMode
1537      read FSlashCommentMatchMode write FSlashCommentMatchMode;
1538    property SlashIndentMode: TSynCommentIndentFlags
1539      read FSlashIndentMode write FSlashIndentMode;
1540    property SlashCommentExtend: TSynCommentExtendMode
1541      read FSlashCommentExtend write FSlashCommentExtend;
1542    property SlashIndentAlignMax: integer
1543      read FSlashIndentAlignMax write FSlashIndentAlignMax;
1544    property StringBreakEnabled: Boolean read FStringBreakEnabled write FStringBreakEnabled;
1545    property StringBreakAppend: String read FStringBreakAppend write FStringBreakAppend;
1546    property StringBreakPrefix: String read FStringBreakPrefix write FStringBreakPrefix;
1547    // Scroll
1548    property ScrollOnEditLeftOptions: TSynScrollOnEditLeftOptions
1549      read FScrollOnEditLeftOptions write FScrollOnEditLeftOptions;
1550    property ScrollOnEditRightOptions: TSynScrollOnEditRightOptions
1551      read FScrollOnEditRightOptions write FScrollOnEditRightOptions;
1552  end;
1553
1554  { TEditorOptionsDefaults }
1555
1556  TEditorOptionsDefaults = class(TEditorOptionsBase)
1557  private
1558  protected
1559  public
1560    constructor Create;
1561  end;
1562
1563  { TEditorOptions }
1564
1565  TEditorOptions = class(TEditorOptionsBase)
1566  private
1567    XMLConfig: TRttiXMLConfig;
1568    // General options
1569    fSynEditOptions: TSynEditorOptions;
1570    fSynEditOptions2: TSynEditorOptions2;
1571    fShowTabCloseButtons: Boolean;
1572    fHideSingleTabInWindow: Boolean;
1573    fShowTabNumbers: Boolean;
1574    fUndoAfterSave: Boolean;
1575    fFindTextAtCursor: Boolean;
1576    fUseSyntaxHighlight: Boolean;
1577    fCopyWordAtCursorOnCopyNone: Boolean;
1578    fShowGutterHints: Boolean;
1579    fBlockIndent: Integer;
1580    fBlockTabIndent: Integer;
1581    fBlockIndentType: TSynBeautifierIndentType;
1582    fTrimSpaceType: TSynEditStringTrimmingType;
1583    fUndoLimit: Integer;
1584    fTabWidth:  Integer;
1585    fBracketHighlightStyle: TSynEditBracketHighlightStyle;
1586    // Display options
1587    fVisibleRightMargin: Boolean;
1588    fVisibleGutter: Boolean;
1589    fShowLineNumbers: Boolean;
1590    fShowOnlyLineNumbersMultiplesOf: integer;
1591    fGutterWidth: Integer;
1592    fGutterSeparatorIndex: Integer;
1593    fRightMargin: Integer;
1594    fEditorFont:  String;
1595    fEditorFontSize:   Integer;
1596    fExtraCharSpacing: Integer;
1597    fExtraLineSpacing: Integer;
1598    fDisableAntialiasing: Boolean;
1599    fDoNotWarnForFont: string;
1600    // Key Mappings
1601    fKeyMappingScheme: String;
1602    fKeyMap: TKeyCommandRelationList;
1603    // Mouse Mappings
1604    fUserMouseSettings: TEditorMouseOptions;
1605    fTempMouseSettings: TEditorMouseOptions;
1606    // Color options
1607    fHighlighterList: TEditOptLangList;
1608    fUserColorSchemeGroup: TColorSchemeFactory;
1609    fUserDefinedColors: TEditorUserDefinedWordsList;
1610    // Markup Current Word
1611    fMarkupCurWordTime: Integer;
1612    fMarkupCurWordFullLen: Integer;
1613    fMarkupCurWordNoKeyword: Boolean;
1614    fMarkupCurWordTrim: Boolean;
1615    fMarkupCurWordNoTimer: Boolean;
1616    // Code Tools options
1617    fAutoBlockCompletion: Boolean;
1618    fAutoCodeParameters: Boolean;
1619    fAutoToolTipExprEval: Boolean;
1620    fAutoToolTipSymbTools: Boolean;
1621    fAutoDisplayFuncPrototypes: Boolean;
1622    fAutoDelayInMSec: Integer;
1623    fAutoHintDelayInMSec: Integer;
1624    fCodeTemplateFileNameRaw: String;
1625    fCTemplIndentToTokenStart: Boolean;
1626    fAutoRemoveEmptyMethods: Boolean;
1627    fCompletionLongLineHintInMSec: Integer;
1628    // Code Folding
1629    fUseCodeFolding: Boolean;
1630    fUseMarkupWordBracket: Boolean;
1631    fUseMarkupOutline: Boolean;
1632    // Multi window
1633    fMultiWinEditAccessOrder: TEditorOptionsEditAccessOrderList;
1634    // Default values for RttiXmlConfig using published properties.
1635    FDefaultValues: TEditorOptionsDefaults;
1636    procedure Init;
1637    function GetCodeTemplateFileNameExpand: String;
1638    function GetColorSchemeLanguage(aHighLighter: TSynCustomHighlighter;
1639                          SynColorSchemeName: String = ''): TColorSchemeLanguage;
1640  protected
1641  public
1642    class function GetGroupCaption: string; override;
1643    class function GetInstance: TAbstractIDEOptions; override;
1644    procedure DoAfterWrite(Restore: boolean); override;
1645  public
1646    constructor Create;
1647    destructor Destroy; override;
1648    procedure Load;
1649    procedure Save;
1650    function LoadCodeTemplates(AnAutoComplete: TSynEditAutoComplete): TModalResult;
1651    function SaveCodeTemplates(AnAutoComplete: TSynEditAutoComplete): TModalResult;
1652    procedure AssignKeyMapTo(ASynEdit: TSynEdit; SimilarEdit: TSynEdit = nil); // Or copy fromSimilarEdit
1653    function ReadColorScheme(const LanguageName: String): String; // TODO: rename ReadColorSchemeName
1654    function ReadPascalColorScheme: String;
1655    procedure WriteColorScheme(const LanguageName, SynColorScheme: String);
1656    procedure ReadHighlighterSettings(Syn: TSrcIDEHighlighter; SynColorScheme: String);
1657    procedure ReadHighlighterFoldSettings(Syn: TSrcIDEHighlighter; ReadForOptions: Boolean = False);
1658    procedure ReadDefaultsForHighlighterFoldSettings(Syn: TSrcIDEHighlighter);
1659    procedure WriteHighlighterFoldSettings(Syn: TSrcIDEHighlighter);
1660    procedure ReadHighlighterDivDrawSettings(Syn: TSrcIDEHighlighter);
1661    procedure ReadDefaultsForHighlighterDivDrawSettings(Syn: TSrcIDEHighlighter);
1662    procedure WriteHighlighterDivDrawSettings(Syn: TSrcIDEHighlighter);
1663    procedure GetHighlighterSettings(Syn: TSrcIDEHighlighter); // read highlight settings from config file
1664    procedure GetSynEditSettings(ASynEdit: TSynEdit; SimilarEdit: TSynEdit = nil); // read synedit settings from config file
1665    function CreateSyn(LazSynHilighter: TLazSyntaxHighlighter): TSrcIDEHighlighter;
1666    function CreateSynHighlighter(LazSynHilighter: TLazSyntaxHighlighter): TObject; override;
1667    procedure GetSynEditPreviewSettings(APreviewEditor: TObject);
1668    procedure SetMarkupColor(Syn: TSrcIDEHighlighter;
1669                             AddHilightAttr: TAdditionalHilightAttribute;
1670                             aMarkup: TSynSelectedColor);
1671    procedure SetMarkupColors(aSynEd: TSynEdit);
1672    procedure ApplyFontSettingsTo(ASynEdit: TSynEdit);
1673    function ExtensionToLazSyntaxHighlighter(Ext: String): TLazSyntaxHighlighter; override;
1674  public
1675    // general options
1676    property SynEditOptions: TSynEditorOptions
1677      read fSynEditOptions write fSynEditOptions default SynEditDefaultOptions;
1678    property SynEditOptions2: TSynEditorOptions2
1679      read fSynEditOptions2 write fSynEditOptions2 default SynEditDefaultOptions2;
1680    property ShowTabCloseButtons: Boolean
1681      read fShowTabCloseButtons write fShowTabCloseButtons;
1682    property HideSingleTabInWindow: Boolean
1683      read FHideSingleTabInWindow write FHideSingleTabInWindow;
1684    property ShowTabNumbers: Boolean read fShowTabNumbers write fShowTabNumbers;
1685    property UndoAfterSave: Boolean read fUndoAfterSave write fUndoAfterSave default True;
1686    property FindTextAtCursor: Boolean
1687      read fFindTextAtCursor write fFindTextAtCursor default True;
1688    property UseSyntaxHighlight: Boolean
1689      read fUseSyntaxHighlight write fUseSyntaxHighlight default True;
1690    property CopyWordAtCursorOnCopyNone: Boolean
1691      read FCopyWordAtCursorOnCopyNone write FCopyWordAtCursorOnCopyNone;
1692    property ShowGutterHints: Boolean read FShowGutterHints write FShowGutterHints;
1693    property BlockIndent: Integer read fBlockIndent write fBlockIndent default 2;
1694    property BlockTabIndent: Integer read FBlockTabIndent write FBlockTabIndent default 0;
1695    property BlockIndentType: TSynBeautifierIndentType
1696      read fBlockIndentType write fBlockIndentType default sbitCopySpaceTab;
1697    property TrimSpaceType: TSynEditStringTrimmingType
1698      read fTrimSpaceType write fTrimSpaceType default settLeaveLine;
1699    property UndoLimit: Integer read fUndoLimit write fUndoLimit default 32767;
1700    property TabWidth: Integer read fTabWidth write fTabWidth default 8;
1701    property BracketHighlightStyle: TSynEditBracketHighlightStyle
1702      read fBracketHighlightStyle write fBracketHighlightStyle default sbhsBoth;
1703    // Display options
1704    property VisibleRightMargin: Boolean
1705      read fVisibleRightMargin write fVisibleRightMargin default True;
1706    property VisibleGutter: Boolean read fVisibleGutter write fVisibleGutter default True;
1707    property ShowLineNumbers: Boolean read fShowLineNumbers
1708      write fShowLineNumbers default False;
1709    property ShowOnlyLineNumbersMultiplesOf: integer read fShowOnlyLineNumbersMultiplesOf
1710      write fShowOnlyLineNumbersMultiplesOf;
1711    property GutterWidth: Integer read fGutterWidth write fGutterWidth default 30;
1712    property GutterSeparatorIndex: Integer read FGutterSeparatorIndex
1713      write FGutterSeparatorIndex default 3;
1714    property RightMargin: Integer read fRightMargin write fRightMargin default 80;
1715    property EditorFont: String read fEditorFont write fEditorFont;
1716    property EditorFontSize: Integer read fEditorFontSize write fEditorFontSize;
1717    property ExtraCharSpacing: Integer
1718      read fExtraCharSpacing write fExtraCharSpacing default 0;
1719    property ExtraLineSpacing: Integer
1720      read fExtraLineSpacing write fExtraLineSpacing default 1;
1721    property DisableAntialiasing: Boolean read fDisableAntialiasing
1722      write fDisableAntialiasing default DefaultEditorDisableAntiAliasing;
1723    property DoNotWarnForFont: string read FDoNotWarnForFont write FDoNotWarnForFont;
1724    // Key Mappings
1725    property KeyMappingScheme: String read fKeyMappingScheme write fKeyMappingScheme;
1726    property KeyMap: TKeyCommandRelationList read fKeyMap;
1727    // Mouse Mappings
1728    // Current saved config
1729    property UserMouseSettings: TEditorMouseOptions read FUserMouseSettings;
1730    // Used by the 2 Mouse-option pages, so they share data (un-saved)
1731    property TempMouseSettings: TEditorMouseOptions read FTempMouseSettings;
1732    // Color options
1733    property HighlighterList: TEditOptLangList read fHighlighterList;
1734    property UserColorSchemeGroup: TColorSchemeFactory read fUserColorSchemeGroup;
1735    property UserDefinedColors: TEditorUserDefinedWordsList read fUserDefinedColors;
1736    // Markup Current Word
1737    property MarkupCurWordTime: Integer
1738      read fMarkupCurWordTime write fMarkupCurWordTime default 1500;
1739    property MarkupCurWordFullLen: Integer
1740      read fMarkupCurWordFullLen write fMarkupCurWordFullLen default 3;
1741    property MarkupCurWordNoKeyword: Boolean
1742      read fMarkupCurWordNoKeyword write fMarkupCurWordNoKeyword default False;
1743    property MarkupCurWordTrim: Boolean
1744      read fMarkupCurWordTrim write fMarkupCurWordTrim default True;
1745    property MarkupCurWordNoTimer: Boolean
1746      read fMarkupCurWordNoTimer write fMarkupCurWordNoTimer default False;
1747    // Code Tools options
1748    property AutoBlockCompletion: Boolean
1749      read fAutoBlockCompletion write FAutoBlockCompletion default True;
1750    property AutoCodeParameters: Boolean
1751      read fAutoCodeParameters write fAutoCodeParameters default True;
1752    property AutoToolTipExprEval: Boolean
1753      read fAutoToolTipExprEval write fAutoToolTipExprEval default True; // debugger hints
1754    property AutoToolTipSymbTools: Boolean
1755      read fAutoToolTipSymbTools write fAutoToolTipSymbTools default True; // declaration hints
1756    property AutoDisplayFunctionPrototypes: Boolean
1757      read fAutoDisplayFuncPrototypes write fAutoDisplayFuncPrototypes default True;
1758    property AutoDelayInMSec: Integer read fAutoDelayInMSec
1759      write fAutoDelayInMSec default 1000;
1760    property AutoHintDelayInMSec: Integer read fAutoHintDelayInMSec
1761      write fAutoHintDelayInMSec default 1000;
1762    property CodeTemplateFileNameRaw: String
1763      read fCodeTemplateFileNameRaw write fCodeTemplateFileNameRaw;
1764    property CodeTemplateFileNameExpand: String read GetCodeTemplateFileNameExpand;
1765    property CodeTemplateIndentToTokenStart: Boolean
1766      read fCTemplIndentToTokenStart write fCTemplIndentToTokenStart;
1767    property AutoRemoveEmptyMethods: Boolean
1768      read fAutoRemoveEmptyMethods write fAutoRemoveEmptyMethods default False;
1769    property CompletionLongLineHintInMSec: Integer
1770      read fCompletionLongLineHintInMSec write fCompletionLongLineHintInMSec;
1771    // Code Folding
1772    property UseCodeFolding: Boolean
1773      read fUseCodeFolding write fUseCodeFolding default True;
1774    property UseMarkupWordBracket: Boolean
1775      read fUseMarkupWordBracket write fUseMarkupWordBracket default True;
1776    property UseMarkupOutline: Boolean
1777      read fUseMarkupOutline write fUseMarkupOutline default False;
1778    // Multi window
1779    property MultiWinEditAccessOrder: TEditorOptionsEditAccessOrderList
1780        read FMultiWinEditAccessOrder write FMultiWinEditAccessOrder;
1781  end;
1782
1783var
1784  EditorOpts: TEditorOptions;
1785
1786procedure RepairEditorFontSize(var FontSize: integer);
1787function BuildBorlandDCIFile(ACustomSynAutoComplete: TCustomSynAutoComplete): Boolean;
1788function ColorSchemeFactory: TColorSchemeFactory;
1789function UserSchemeDirectory(CreateIfNotExists: Boolean = False): String;
1790procedure InitLocale;
1791
1792implementation
1793
1794{$R editoroptions.res}
1795
1796const
1797  ValidAttribChars = ['a'..'z', 'A'..'Z', '_', '0'..'9'];
1798
1799  // several language types can be redirected. For example there are FreePascal
1800  // and Delphi, but currently both are hilighted with the FreePascal
1801  // highlighter
1802  CompatibleLazSyntaxHilighter: array[TLazSyntaxHighlighter] of TLazSyntaxHighlighter = (
1803    lshNone,
1804    lshText,
1805    lshFreePascal,
1806    lshFreePascal,
1807    lshLFM,
1808    lshXML,
1809    lshHTML,
1810    lshCPP,
1811    lshPerl,
1812    lshJava,
1813    lshBash,
1814    lshPython,
1815    lshPHP,
1816    lshSQL,
1817    lshCSS,
1818    lshJScript,
1819    lshDiff,
1820    lshBat,
1821    lshIni,
1822    lshPo,
1823    lshPike
1824    );
1825
1826var
1827  DefaultColorSchemeName: String;
1828
1829function FontHeightToSize(Height: Integer): Integer;
1830var
1831  AFont: TFont;
1832begin
1833  AFont := TFont.Create;
1834  AFont.Height := Height;
1835  Result := AFont.Size;
1836  AFont.Free;
1837end;
1838
1839function OldAdditionalAttributeName(NewAha: String): string;
1840var
1841  AttriIdx: Integer;
1842begin
1843  AttriIdx := GetEnumValue(TypeInfo(TAdditionalHilightAttribute), NewAha);
1844  if AttriIdx < 0 then
1845    Result := NewAha
1846  else
1847    Result := ahaXmlNames[TAdditionalHilightAttribute(AttriIdx)];
1848end;
1849
1850function GetAddiHilightAttrName(aha: TAdditionalHilightAttribute): String;
1851begin
1852  Result := GetEnumName(TypeInfo(TAdditionalHilightAttribute), ord(aha));
1853end;
1854
1855function GetSynEditOptionName(SynOption: TSynEditorOption): string;
1856begin
1857  case SynOption of
1858    eoAutoIndent:
1859      Result := 'AutoIndent';
1860    eoBracketHighlight:
1861      Result := 'BracketHighlight';
1862    eoEnhanceHomeKey:
1863      Result := 'EnhanceHomeKey';
1864    eoGroupUndo:
1865      Result := 'GroupUndo';
1866    eoHalfPageScroll:
1867      Result := 'HalfPageScroll';
1868    eoKeepCaretX:
1869      Result := 'KeepCaretX';
1870    eoPersistentCaret:
1871      Result := 'PersistentCaret';
1872    eoScrollByOneLess:
1873      Result := 'ScrollByOneLess';
1874    eoScrollPastEof:
1875      Result := 'ScrollPastEof';
1876    eoScrollPastEol:
1877      Result := 'ScrollPastEol';
1878    eoShowScrollHint:
1879      Result := 'ShowScrollHint';
1880    eoShowSpecialChars:
1881      Result := 'ShowSpecialChars';
1882    eoSmartTabs:
1883      Result := 'SmartTabs';
1884    eoTabsToSpaces:
1885      Result := 'TabsToSpaces';
1886    eoTabIndent:
1887      Result := 'TabIndent';
1888    eoTrimTrailingSpaces:
1889      Result := 'TrimTrailingSpaces';
1890    else
1891      Result := '';
1892  end;
1893end;
1894
1895function GetSynBeautifierIndentName(IndentType: TSynBeautifierIndentType): string;
1896begin
1897  case IndentType of
1898    sbitSpace:
1899      Result := 'SpaceIndent';
1900    sbitCopySpaceTab:
1901      Result := 'CopySpaceTabIndent';
1902    sbitPositionCaret:
1903      Result := 'PositionIndent';
1904    else
1905      WriteStr(Result, IndentType);
1906  end;
1907end;
1908
1909function GetSynBeautifierIndentType(IndentName: String): TSynBeautifierIndentType;
1910begin
1911  case IndentName of
1912    'CopySpaceTabIndent':
1913      Result := sbitCopySpaceTab;
1914    'PositionIndent':
1915      Result := sbitPositionCaret;
1916    'sbitConvertToTabSpace':
1917      Result := sbitConvertToTabSpace;
1918    'sbitConvertToTabOnly':
1919      Result := sbitConvertToTabOnly;
1920    else
1921      Result := sbitSpace;
1922  end;
1923end;
1924
1925function GetTrimSpaceName(IndentType: TSynEditStringTrimmingType): string;
1926begin
1927  case IndentType of
1928    settLeaveLine:
1929      Result := 'LeaveLine';
1930    settEditLine:
1931      Result := 'EditLine';
1932    settMoveCaret:
1933      Result := 'MoveCaret';
1934    settIgnoreAll:
1935      Result := 'PosOnly';
1936    else
1937      Result := '';
1938  end;
1939end;
1940
1941function GetTrimSpaceType(IndentName: String): TSynEditStringTrimmingType;
1942begin
1943  case IndentName of
1944    'EditLine':
1945      Result := settEditLine;
1946    'MoveCaret':
1947      Result := settMoveCaret;
1948    'PosOnly':
1949      Result := settIgnoreAll;
1950    else
1951      Result := settLeaveLine;
1952  end;
1953end;
1954
1955{ TEditorUserDefinedWordsList }
1956
1957function TEditorUserDefinedWordsList.GetLists(AIndex: Integer): TEditorUserDefinedWords;
1958begin
1959  Result := TEditorUserDefinedWords(FList[AINdex]);
1960end;
1961
1962function TEditorUserDefinedWordsList.GetKeyCommandList: TIDECommands;
1963begin
1964  if FUseGlobalIDECommandList then
1965    Result := IDECommandList
1966  else
1967    Result := FKeyCommandList;
1968end;
1969
1970procedure TEditorUserDefinedWordsList.SetLists(AIndex: Integer;
1971  AValue: TEditorUserDefinedWords);
1972begin
1973  FList[AINdex] := AValue;
1974end;
1975
1976constructor TEditorUserDefinedWordsList.Create;
1977begin
1978  FList := TList.Create;
1979end;
1980
1981destructor TEditorUserDefinedWordsList.Destroy;
1982begin
1983  inherited Destroy;
1984  Clear;
1985  FreeAndNil(FList);
1986end;
1987
1988procedure TEditorUserDefinedWordsList.Assign(Src: TEditorUserDefinedWordsList);
1989var
1990  i: Integer;
1991begin
1992  Clear;
1993  for i := 0 to Src.Count - 1 do
1994    Add('').Assign(Src.Lists[i]);
1995end;
1996
1997procedure TEditorUserDefinedWordsList.LoadFromXMLConfig(XMLConfig: TRttiXMLConfig;
1998  Path: String);
1999var
2000  c, i: Integer;
2001begin
2002  Clear;
2003  Path := Path + 'Entry/';
2004  c := XMLConfig.GetValue(Path + 'Count', 0);
2005  for i := 0 to c - 1 do
2006    Add('').LoadFromXMLConfig(XMLConfig, Path + 'E' + IntToStr(i) + '/');
2007end;
2008
2009procedure TEditorUserDefinedWordsList.SaveToXMLConfig(XMLConfig: TRttiXMLConfig; Path: String);
2010var
2011  c, i: Integer;
2012begin
2013  Path := Path + 'Entry/';
2014  c := XMLConfig.GetValue(Path + 'Count', 0);
2015  XMLConfig.SetDeleteValue(Path + 'Count', Count, 0);
2016  for i := 0 to Count - 1 do
2017    Lists[i].SaveToXMLConfig(XMLConfig, Path + 'E' + IntToStr(i) + '/');
2018  for i := Count to c - 1 do
2019    XMLConfig.DeletePath(Path + 'E' + IntToStr(i));
2020end;
2021
2022procedure TEditorUserDefinedWordsList.Clear;
2023begin
2024  while Count > 0 do
2025    Remove(Lists[0], True);
2026end;
2027
2028function TEditorUserDefinedWordsList.Add(AList: TEditorUserDefinedWords): Integer;
2029begin
2030  Result := FList.Add(AList);
2031end;
2032
2033function TEditorUserDefinedWordsList.Add(AName: String): TEditorUserDefinedWords;
2034begin
2035  Result := TEditorUserDefinedWords.Create(Self);
2036  Result.Name := AName;
2037  FList.Add(Result);
2038end;
2039
2040function TEditorUserDefinedWordsList.IndexOf(AName: String): Integer;
2041begin
2042  Result := FList.Count - 1;
2043  while (Result >= 0) and (Lists[Result].Name <> AName) do
2044    dec(Result);
2045end;
2046
2047function TEditorUserDefinedWordsList.IndexOf(AList: TEditorUserDefinedWords): Integer;
2048begin
2049  Result := FList.IndexOf(AList);
2050end;
2051
2052procedure TEditorUserDefinedWordsList.Remove(AName: String; FreeList: Boolean);
2053var
2054  i: Integer;
2055begin
2056  i := IndexOf(AName);
2057  if i >= 0 then
2058    FList.Delete(i);
2059end;
2060
2061procedure TEditorUserDefinedWordsList.Remove(AList: TEditorUserDefinedWords;
2062  FreeList: Boolean);
2063begin
2064  FList.Remove(AList);
2065  if FreeList then
2066    FreeAndNil(AList);
2067end;
2068
2069procedure TEditorUserDefinedWordsList.Delete(AIndex: Integer);
2070begin
2071  FList.Delete(AIndex);
2072end;
2073
2074function TEditorUserDefinedWordsList.Count: Integer;
2075begin
2076  Result := FList.Count;
2077end;
2078
2079{ TEditorUserDefinedWords }
2080
2081procedure TEditorUserDefinedWords.SetName(AValue: String);
2082begin
2083  if FName = AValue then Exit;
2084  FName := AValue;
2085  UpdateIdeCommands;
2086end;
2087
2088procedure TEditorUserDefinedWords.SetGlobalTermsCache(AValue: TSynSearchTermDict);
2089begin
2090  if FGlobalTermsCache = AValue then Exit;
2091
2092  if FGlobalTermsCache <> nil then
2093    FGlobalTermsCache.ReleaseReference;
2094
2095  FGlobalTermsCache := AValue;
2096
2097  if FGlobalTermsCache <> nil then
2098    FGlobalTermsCache.AddReference;
2099end;
2100
2101procedure TEditorUserDefinedWords.UpdateIdeCommands;
2102var
2103  Keys: TKeyCommandRelationList;
2104  Cat: TIDECommandCategory;
2105begin
2106  if (FList = nil) or (FList.KeyCommandList = nil) or (FName = '') then
2107    exit;
2108
2109  Keys := FList.KeyCommandList as TKeyCommandRelationList;
2110  Cat := nil;
2111
2112  if FAddTermCmd = nil then
2113    FAddTermCmd := Keys.FindCommandByName('UserDefinedMarkup_Add_'+FId);
2114  if FAddTermCmd = nil then begin
2115    if Cat = nil then
2116      Cat := keys.FindCategoryByName(EditorUserDefinedWordsKeyCatName);
2117    FAddTermCmd := Keys.CreateCommand(
2118      Cat,
2119      'UserDefinedMarkup_Add_'+FId,
2120      Format(lisUserDefinedMarkupKeyAdd, [FName]),
2121      IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []),
2122      IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []),
2123      nil, nil
2124    );
2125    (FAddTermCmd as TKeyCommandRelation).SkipSaving := True;
2126  end
2127  else
2128    FAddTermCmd.LocalizedName := Format(lisUserDefinedMarkupKeyAdd, [FName]);
2129
2130  if FRemoveTermCmd = nil then
2131    FRemoveTermCmd := Keys.FindCommandByName('UserDefinedMarkup_Remove_'+FId);
2132  if FRemoveTermCmd = nil then begin
2133    if Cat = nil then
2134      Cat := keys.FindCategoryByName(EditorUserDefinedWordsKeyCatName);
2135    FRemoveTermCmd := Keys.CreateCommand(
2136      Cat,
2137      'UserDefinedMarkup_Remove_'+FId,
2138      Format(lisUserDefinedMarkupKeyRemove, [FName]),
2139      IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []),
2140      IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []),
2141      nil, nil
2142    );
2143    (FRemoveTermCmd as TKeyCommandRelation).SkipSaving := True;
2144  end
2145  else
2146    FRemoveTermCmd.LocalizedName := Format(lisUserDefinedMarkupKeyRemove, [FName]);
2147
2148  if FToggleTermCmd = nil then
2149    FToggleTermCmd := Keys.FindCommandByName('UserDefinedMarkup_Toggle_'+FId);
2150  if FToggleTermCmd = nil then begin
2151    if Cat = nil then
2152      Cat := keys.FindCategoryByName(EditorUserDefinedWordsKeyCatName);
2153    FToggleTermCmd := Keys.CreateCommand(
2154      Cat,
2155      'UserDefinedMarkup_Toggle_'+FId,
2156      Format(lisUserDefinedMarkupKeyToggle, [FName]),
2157      IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []),
2158      IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []),
2159      nil, nil
2160    );
2161    (FToggleTermCmd as TKeyCommandRelation).SkipSaving := True;
2162  end
2163  else
2164    FToggleTermCmd.LocalizedName := Format(lisUserDefinedMarkupKeyToggle, [FName]);
2165end;
2166
2167procedure TEditorUserDefinedWords.ClearIdeCommands;
2168begin
2169  if (FList <> nil) and (FList.KeyCommandList <> nil) then begin
2170    if (FAddTermCmd <> nil) then
2171      (FList.KeyCommandList as TKeyCommandRelationList).RemoveCommand(FAddTermCmd);
2172    if (FRemoveTermCmd <> nil) then
2173      (FList.KeyCommandList as TKeyCommandRelationList).RemoveCommand(FRemoveTermCmd);
2174    if (FToggleTermCmd <> nil) then
2175      (FList.KeyCommandList as TKeyCommandRelationList).RemoveCommand(FToggleTermCmd);
2176  end;
2177  FreeAndNil(FAddTermCmd);
2178  FreeAndNil(FRemoveTermCmd);
2179  FreeAndNil(FToggleTermCmd);
2180end;
2181
2182constructor TEditorUserDefinedWords.Create(AList: TEditorUserDefinedWordsList);
2183var
2184  i: Integer;
2185begin
2186  FList := AList;
2187  FId := EditorUserDefinedWordsGlobalId;
2188  i := 1;
2189  UniqueString(EditorUserDefinedWordsGlobalId);
2190  while i <= Length(EditorUserDefinedWordsGlobalId) do begin
2191    if EditorUserDefinedWordsGlobalId[i] < 'z' then begin
2192      inc(EditorUserDefinedWordsGlobalId[i]);
2193      break;
2194    end;
2195    inc(i);
2196  end;
2197  if i > Length(EditorUserDefinedWordsGlobalId) then
2198    EditorUserDefinedWordsGlobalId := EditorUserDefinedWordsGlobalId + 'a';
2199
2200  inherited Create;
2201  FColorAttr := TColorSchemeAttribute.Create(nil, nil);
2202  FColorAttr.Features := [hafBackColor, hafForeColor, hafFrameColor, hafAlpha, hafPrior,hafFrameStyle, hafFrameEdges, hafStyle, hafStyleMask];
2203  FColorAttr.Group := agnText;
2204  FColorAttr.SetAllPriorities(MARKUP_USER_DEF_PRIOR);
2205  FKeyAddSelectSmart := True;
2206end;
2207
2208destructor TEditorUserDefinedWords.Destroy;
2209begin
2210  ReleaseRefAndNil(FGlobalTermsCache);
2211  Clear;
2212  FreeAndNil(FColorAttr);
2213  ClearIdeCommands;
2214  inherited Destroy;
2215end;
2216
2217procedure TEditorUserDefinedWords.Assign(Source: TPersistent);
2218var
2219  SrcWords: TEditorUserDefinedWords;
2220begin
2221  inherited Assign(Source);
2222  if not (Source is TEditorUserDefinedWords) then exit;
2223  ClearIdeCommands;
2224  SrcWords := TEditorUserDefinedWords(Source);
2225  FId                      := SrcWords.FId;
2226  FName                    := SrcWords.FName;
2227  FGlobalList              := SrcWords.FGlobalList;
2228  FKeyAddCase              := SrcWords.FKeyAddCase;
2229  FKeyAddSelectBoundMaxLen := SrcWords.FKeyAddSelectBoundMaxLen;
2230  FKeyAddSelectSmart       := SrcWords.FKeyAddSelectSmart;
2231  FKeyAddTermBounds        := SrcWords.FKeyAddTermBounds;
2232  FKeyAddWordBoundMaxLen   := SrcWords.FKeyAddWordBoundMaxLen;
2233
2234  FColorAttr.Assign(SrcWords.FColorAttr);
2235  UpdateIdeCommands;
2236end;
2237
2238procedure TEditorUserDefinedWords.LoadFromXMLConfig(XMLConfig: TRttiXMLConfig; Path: String);
2239  procedure Load(SubPath: string; out Key: TIDEShortCut);
2240  begin
2241    key.Key1   := XMLConfig.GetValue(SubPath+'Key1',VK_UNKNOWN);
2242    key.Shift1 := CfgStrToShiftState(XMLConfig.GetValue(SubPath+'Shift1',''));
2243    key.Key2   := XMLConfig.GetValue(SubPath+'Key2',VK_UNKNOWN);
2244    key.Shift2 := CfgStrToShiftState(XMLConfig.GetValue(SubPath+'Shift2',''));
2245  end;
2246var
2247  c, i: Integer;
2248  def: TEditorUserDefinedWords;
2249  ColorDef: TColorSchemeAttribute;
2250  DefEntry: TSynSearchTerm;
2251  SCut: TIDEShortCut;
2252  Keys: TKeyCommandRelationList;
2253begin
2254  Clear;
2255  def := TEditorUserDefinedWords.Create(nil);
2256  XMLConfig.ReadObject(Path + 'Main/', self, def);
2257  def.Free;
2258
2259  ColorDef := TColorSchemeAttribute.Create(nil, nil);
2260  ColorDef.SetAllPriorities(MARKUP_USER_DEF_PRIOR);
2261  FColorAttr.StoredName := 'c1';
2262  FColorAttr.LoadFromXml(XMLConfig, Path + 'Color/', ColorDef, EditorOptsFormatVersion);
2263  ColorDef.Free;
2264
2265  c := XMLConfig.GetValue(Path + 'Count', 0);
2266  Path := Path + 'Entry/';
2267  DefEntry := TSynSearchTerm.Create(nil);
2268  for i := 0 to c - 1 do
2269    XMLConfig.ReadObject(Path + 'Entry' + IntToStr(i) + '/', Add, DefEntry);
2270  DefEntry.Free;
2271
2272  UpdateIdeCommands;
2273
2274  if (FList <> nil) and (FList.KeyCommandList <> nil) then begin
2275    Keys := FList.KeyCommandList as TKeyCommandRelationList;
2276
2277    if (FAddTermCmd <> nil) then begin
2278      Load(Path+'AddKeyA/', SCut);
2279      if Keys.Find(SCut, TSourceEditorWindowInterface) = nil then
2280        FAddTermCmd.ShortcutA := SCut;
2281      Load(Path+'AddKeyB/', SCut);
2282      if Keys.Find(SCut, TSourceEditorWindowInterface) = nil then
2283        FAddTermCmd.ShortcutB := SCut;
2284    end;
2285
2286    if (FRemoveTermCmd <> nil) then begin
2287      Load(Path+'RemoveKeyA/', SCut);
2288      if Keys.Find(SCut, TSourceEditorWindowInterface) = nil then
2289        FRemoveTermCmd.ShortcutA := SCut;
2290      Load(Path+'RemoveKeyB/', SCut);
2291      if Keys.Find(SCut, TSourceEditorWindowInterface) = nil then
2292        FRemoveTermCmd.ShortcutB := SCut;
2293    end;
2294
2295    if (FToggleTermCmd <> nil) then begin
2296      Load(Path+'ToggleKeyA/', SCut);
2297      if Keys.Find(SCut, TSourceEditorWindowInterface) = nil then
2298        FToggleTermCmd.ShortcutA := SCut;
2299      Load(Path+'ToggleKeyB/', SCut);
2300      if Keys.Find(SCut, TSourceEditorWindowInterface) = nil then
2301        FToggleTermCmd.ShortcutB := SCut;
2302    end;
2303  end;
2304end;
2305
2306procedure TEditorUserDefinedWords.SaveToXMLConfig(XMLConfig: TRttiXMLConfig; Path: String);
2307  procedure ClearKey(const SubPath: string);
2308  begin
2309    XMLConfig.DeleteValue(SubPath+'Key1');
2310    XMLConfig.DeleteValue(SubPath+'Shift1');
2311    XMLConfig.DeleteValue(SubPath+'Key2');
2312    XMLConfig.DeleteValue(SubPath+'Shift2');
2313  end;
2314  procedure Store(const SubPath: string; Key: TIDEShortCut);
2315  var
2316    s: TShiftState;
2317  begin
2318    XMLConfig.SetDeleteValue(SubPath+'Key1', key.Key1, VK_UNKNOWN);
2319    if key.Key1=VK_UNKNOWN then
2320      s:=[]
2321    else
2322      s:=key.Shift1;
2323    XMLConfig.SetDeleteValue(SubPath+'Shift1',ShiftStateToCfgStr(s),ShiftStateToCfgStr([]));
2324    XMLConfig.SetDeleteValue(SubPath+'Key2',key.Key2,VK_UNKNOWN);
2325    if key.Key2=VK_UNKNOWN then
2326      s:=[]
2327    else
2328      s:=key.Shift2;
2329    XMLConfig.SetDeleteValue(SubPath+'Shift2',ShiftStateToCfgStr(s),ShiftStateToCfgStr([]));
2330  end;
2331var
2332  i, c: Integer;
2333  def: TEditorUserDefinedWords;
2334  ColorDef: TColorSchemeAttribute;
2335  DefEntry: TSynSearchTerm;
2336begin
2337  def := TEditorUserDefinedWords.Create(nil);
2338  XMLConfig.WriteObject(Path + 'Main/', Self, def);
2339  def.Free;
2340
2341  ColorDef := TColorSchemeAttribute.Create(nil, nil);
2342  ColorDef.SetAllPriorities(MARKUP_USER_DEF_PRIOR);
2343  FColorAttr.StoredName := 'c1';
2344  FColorAttr.SaveToXml(XMLConfig, Path + 'Color/', ColorDef);
2345  ColorDef.Free;
2346
2347  c := XMLConfig.GetValue(Path + 'Count', 0);
2348  XMLConfig.SetDeleteValue(Path + 'Count', Count, 0);
2349  Path := Path + 'Entry/';
2350  DefEntry := TSynSearchTerm.Create(nil);
2351  for i := 0 to Count - 1 do
2352    XMLConfig.WriteObject(Path + 'Entry' + IntToStr(i) + '/', Items[i], DefEntry);
2353  DefEntry.Free;
2354  for i := Count to c - 1 do
2355    XMLConfig.DeletePath(Path + 'Entry' + IntToStr(i));
2356
2357  if (FAddTermCmd = nil) then begin
2358    ClearKey(Path + 'AddKeyA/');
2359    ClearKey(Path + 'AddKeyB/');
2360  end else begin
2361    Store(Path + 'AddKeyA/', FAddTermCmd.ShortcutA);
2362    Store(Path + 'AddKeyB/', FAddTermCmd.ShortcutB);
2363  end;
2364
2365  if (FRemoveTermCmd = nil) then begin
2366    ClearKey(Path + 'RemoveKeyA/');
2367    ClearKey(Path + 'RemoveKeyB/');
2368  end else begin
2369    Store(Path + 'RemoveKeyA/', FRemoveTermCmd.ShortcutA);
2370    Store(Path + 'RemoveKeyB/', FRemoveTermCmd.ShortcutB);
2371  end;
2372
2373  if (FToggleTermCmd = nil) then begin
2374    ClearKey(Path + 'ToggleKeyA/');
2375    ClearKey(Path + 'ToggleKeyB/');
2376  end else begin
2377    Store(Path + 'ToggleKeyA/', FToggleTermCmd.ShortcutA);
2378    Store(Path + 'ToggleKeyB/', FToggleTermCmd.ShortcutB);
2379  end;
2380
2381end;
2382
2383function TEditorUserDefinedWords.HasKeyAssigned: Boolean;
2384begin
2385  Result := (FAddTermCmd.ShortcutA.Key1 <> VK_UNKNOWN) or
2386            (FAddTermCmd.ShortcutB.Key1 <> VK_UNKNOWN) or
2387            (FRemoveTermCmd.ShortcutA.Key1 <> VK_UNKNOWN) or
2388            (FRemoveTermCmd.ShortcutB.Key1 <> VK_UNKNOWN) or
2389            (FToggleTermCmd.ShortcutA.Key1 <> VK_UNKNOWN) or
2390            (FToggleTermCmd.ShortcutB.Key1 <> VK_UNKNOWN);
2391end;
2392
2393{ TSynEditMouseActionKeyCmdHelper }
2394
2395function TSynEditMouseActionKeyCmdHelper.GetOptionKeyCmd: TSynEditorCommand;
2396begin
2397  Result := inherited Option;
2398end;
2399
2400procedure TSynEditMouseActionKeyCmdHelper.SetOptionKeyCmd(
2401  const AValue: TSynEditorCommand);
2402begin
2403  inherited Option := AValue;
2404end;
2405
2406procedure RepairEditorFontSize(var FontSize: integer);
2407begin
2408  if ((FontSize>=0) and (FontSize<=EditorOptionsMinimumFontSize))
2409  or ((FontSize<0) and (FontSize>=-EditorOptionsMinimumFontSize)) then
2410    FontSize := SynDefaultFontSize;
2411end;
2412
2413const
2414  EditOptsConfFileName = 'editoroptions.xml';
2415  DciFileVersion = 1;
2416  DciFileVersionName = '!FileVersion';
2417  DciVersionName = '!Version';
2418
2419function BuildBorlandDCIFile(
2420  ACustomSynAutoComplete: TCustomSynAutoComplete): Boolean;
2421  // returns if something has changed
2422var
2423  sl: TStringList;
2424  i, sp, ep, v: Integer;
2425  Token, Comment, Value: String;
2426  Attributes: TStrings;
2427begin
2428  Result := False;
2429  sl     := TStringList.Create;
2430  try
2431    for i := 0 to ACustomSynAutoComplete.Completions.Count - 1 do
2432    begin
2433      Token := ACustomSynAutoComplete.Completions[i];
2434      Comment := ACustomSynAutoComplete.CompletionComments[i];
2435      Value := ACustomSynAutoComplete.CompletionValues[i];
2436      sl.Add('[' + Token + ' | ' + Comment + ']');
2437      Attributes:=ACustomSynAutoComplete.CompletionAttributes[i];
2438
2439      // Store DciFileVersion as attribute to first macro
2440      v := Attributes.IndexOfName(DciFileVersionName);
2441      if v >= 0 then
2442        Attributes.Delete(v);
2443      if i = 0 then
2444        Attributes.Values[DciFileVersionName] := IntToStr(DciFileVersion);
2445
2446      if (Attributes<>nil) and (Attributes.Count>0) then begin
2447        sl.Add(CodeTemplateAttributesStartMagic);
2448        sl.AddStrings(Attributes);
2449        sl.Add(CodeTemplateAttributesEndMagic);
2450      end;
2451      sp    := 1;
2452      ep    := 1;
2453      while ep <= length(Value) do
2454        if Value[ep] in [#10, #13] then
2455        begin
2456          sl.Add(copy(Value, sp, ep - sp));
2457          inc(ep);
2458          if (ep <= length(Value)) and (Value[ep] in [#10, #13]) and
2459            (Value[ep] <> Value[ep - 1]) then
2460            inc(ep);
2461          sp := ep;
2462        end
2463        else
2464          inc(ep);
2465      if (ep > sp) or ((Value <> '') and (Value[length(Value)] in [#10, #13])) then
2466        sl.Add(copy(Value, sp, ep - sp));
2467    end;
2468    if ACustomSynAutoComplete.AutoCompleteList.Equals(sl) = False then
2469    begin
2470      Result := True;
2471      ACustomSynAutoComplete.AutoCompleteList := sl;
2472    end;
2473  finally
2474    sl.Free;
2475  end;
2476end;
2477
2478// The lazy-man color scheme factory
2479function ColorSchemeFactory: TColorSchemeFactory;
2480const
2481  Singleton: TColorSchemeFactory = nil;
2482var
2483  FileList: TStringList;
2484  i, j, c: Integer;
2485  XMLConfig: TRttiXMLConfig;
2486  n: String;
2487
2488  procedure AddFromResource(AResName, ASchemeName: String);
2489  var
2490    FPResource: TFPResourceHandle;
2491    Stream: TLazarusResourceStream;
2492  begin
2493    FPResource := FindResource(HInstance, PChar(AResName), PChar(RT_RCDATA));
2494    if FPResource = 0 then exit;
2495    Stream := TLazarusResourceStream.CreateFromHandle(HInstance, FPResource);
2496    XMLConfig := TRttiXMLConfig.Create('');
2497    XMLConfig.ReadFromStream(Stream);
2498    Singleton.RegisterScheme(XMLConfig, ASchemeName, 'Lazarus/ColorSchemes/');
2499    FreeAndNil(XMLConfig);
2500    FreeAndNil(Stream);
2501  end;
2502
2503begin
2504  if not Assigned(Singleton) then begin
2505    InitLocale;
2506    Singleton := TColorSchemeFactory.Create;
2507    // register all built-in color schemes
2508
2509    AddFromResource('ColorSchemeDefault', 'Default');
2510    AddFromResource('ColorSchemeTwilight', 'Twilight');
2511    AddFromResource('ColorSchemePascalClassic', 'Pascal Classic');
2512    AddFromResource('ColorSchemeOcean', 'Ocean');
2513    AddFromResource('ColorSchemeDelphi', 'Delphi');
2514    DefaultColorSchemeName := 'Default';
2515
2516    if DirectoryExistsUTF8(UserSchemeDirectory(False)) then begin
2517      FileList := FindAllFiles(UserSchemeDirectory(False), '*.xml', False);
2518      for i := 0 to FileList.Count - 1 do begin
2519        XMLConfig := nil;
2520        try
2521          XMLConfig := TRttiXMLConfig.Create(FileList[i]);
2522          c := XMLConfig.GetValue('Lazarus/ColorSchemes/Names/Count', 0);
2523          for j := 1 to c do begin
2524            n := XMLConfig.GetValue('Lazarus/ColorSchemes/Names/Item'+IntToStr(j)+'/Value', '');
2525            if n <> '' then
2526              Singleton.RegisterScheme(XMLConfig, n, 'Lazarus/ColorSchemes/');
2527          end;
2528        except
2529          ShowMessage(Format(dlgUserSchemeError, [FileList[i]]));
2530        end;
2531        XMLConfig.Free;
2532      end;
2533      FileList.Free;
2534    end;
2535  end;
2536  Result := Singleton;
2537end;
2538
2539function UserSchemeDirectory(CreateIfNotExists: Boolean): String;
2540begin
2541  Result := AppendPathDelim(GetPrimaryConfigPath) + 'userschemes';
2542  If CreateIfNotExists and (not DirectoryExistsUTF8(Result)) then
2543    CreateDirUTF8(Result);
2544end;
2545
2546function HighlighterListSingleton: TEditOptLangList;
2547const
2548  Singleton: TEditOptLangList = nil;
2549begin
2550  if not Assigned(Singleton) then
2551    Singleton := TEditOptLangList.Create;
2552  Result := Singleton;
2553end;
2554
2555procedure InitLocale;
2556const
2557  InitDone: Boolean = False;
2558begin
2559  if InitDone then exit;
2560  InitDone := true;
2561  EditorOptionsEditAccessDefaults[0].Caption := dlgEditAccessCaptionLockedInView;
2562  EditorOptionsEditAccessDefaults[0].Desc    := dlgEditAccessDescLockedInView;
2563  EditorOptionsEditAccessDefaults[1].Caption := dlgEditAccessCaptionUnLockedInSoftView;
2564  EditorOptionsEditAccessDefaults[1].Desc    := dlgEditAccessDescUnLockedInSoftView;
2565  EditorOptionsEditAccessDefaults[2].Caption := dlgEditAccessCaptionUnLocked;
2566  EditorOptionsEditAccessDefaults[2].Desc    := dlgEditAccessDescUnLocked;
2567  EditorOptionsEditAccessDefaults[3].Caption := dlgEditAccessCaptionUnLockedOpenNewInOldWin  ;
2568  EditorOptionsEditAccessDefaults[3].Desc    := dlgEditAccessDescUnLockedOpenNewInOldWin;
2569  EditorOptionsEditAccessDefaults[4].Caption := dlgEditAccessCaptionUnLockedOpenNewInNewWin;
2570  EditorOptionsEditAccessDefaults[4].Desc    := dlgEditAccessDescUnLockedOpenNewInNewWin;
2571  EditorOptionsEditAccessDefaults[5].Caption := dlgEditAccessCaptionIgnLockedOldEdit;
2572  EditorOptionsEditAccessDefaults[5].Desc    := dlgEditAccessDescIgnLockedOldEdit;
2573  EditorOptionsEditAccessDefaults[6].Caption := dlgEditAccessCaptionIgnLockedOnlyActEdit;
2574  EditorOptionsEditAccessDefaults[6].Desc    := dlgEditAccessDescIgnLockedOnlyActEdit;
2575  EditorOptionsEditAccessDefaults[7].Caption := dlgEditAccessCaptionIgnLockedOnlyActWin;
2576  EditorOptionsEditAccessDefaults[7].Desc    := dlgEditAccessDescIgnLockedOnlyActWin;
2577  EditorOptionsEditAccessDefaults[8].Caption := dlgEditAccessCaptionUnLockedOpenNewInAnyWin;
2578  EditorOptionsEditAccessDefaults[8].Desc    := dlgEditAccessDescUnLockedOpenNewInAnyWin;
2579
2580  // update translation
2581  EditorOptionsFoldInfoPas[ 0].Name := dlgFoldPasProcedure;
2582  EditorOptionsFoldInfoPas[ 1].Name := dlgFoldLocalPasVarType;
2583  EditorOptionsFoldInfoPas[ 2].Name := dlgFoldPasProcBeginEnd;
2584  EditorOptionsFoldInfoPas[ 3].Name := dlgFoldPasBeginEnd;
2585  EditorOptionsFoldInfoPas[ 4].Name := dlgFoldPasRepeat;
2586  EditorOptionsFoldInfoPas[ 5].Name := dlgFoldPasCase;
2587  EditorOptionsFoldInfoPas[ 6].Name := dlgFoldPasTry;
2588  EditorOptionsFoldInfoPas[ 7].Name := dlgFoldPasExcept;
2589  EditorOptionsFoldInfoPas[ 8].Name := dlgFoldPasAsm;
2590  EditorOptionsFoldInfoPas[ 9].Name := dlgFoldPasProgram;
2591  EditorOptionsFoldInfoPas[10].Name := dlgFoldPasUnit;
2592  EditorOptionsFoldInfoPas[11].Name := dlgFoldPasUnitSection;
2593  EditorOptionsFoldInfoPas[12].Name := dlgFoldPasUses;
2594  EditorOptionsFoldInfoPas[13].Name := dlgFoldPasVarType;
2595  EditorOptionsFoldInfoPas[14].Name := dlgFoldPasClass;
2596  EditorOptionsFoldInfoPas[15].Name := dlgFoldPasClassSection;
2597  EditorOptionsFoldInfoPas[16].Name := dlgFoldPasRecord;
2598  EditorOptionsFoldInfoPas[17].Name := dlgFoldPasIfDef;
2599  EditorOptionsFoldInfoPas[18].Name := dlgFoldPasUserRegion;
2600  EditorOptionsFoldInfoPas[19].Name := dlgFoldPasAnsiComment;
2601  EditorOptionsFoldInfoPas[20].Name := dlgFoldPasBorComment;
2602  EditorOptionsFoldInfoPas[21].Name := dlgFoldPasSlashComment;
2603  EditorOptionsFoldInfoPas[22].Name := dlgFoldPasNestedComment;
2604
2605  EditorOptionsFoldInfoHTML[0].Name := dlgFoldHtmlNode;
2606  EditorOptionsFoldInfoHTML[1].Name := dlgFoldHtmlComment;
2607  EditorOptionsFoldInfoHTML[2].Name := dlgFoldHtmlAsp;
2608
2609  EditorOptionsFoldInfoLFM[0].Name := dlgFoldLfmObject;
2610  EditorOptionsFoldInfoLFM[1].Name := dlgFoldLfmList;
2611  EditorOptionsFoldInfoLFM[2].Name := dlgFoldLfmItem;
2612
2613  EditorOptionsFoldInfoXML[0].Name := dlgFoldXmlNode;
2614  EditorOptionsFoldInfoXML[1].Name := dlgFoldXmlComment;
2615  EditorOptionsFoldInfoXML[2].Name := dlgFoldXmlCData;
2616  EditorOptionsFoldInfoXML[3].Name := dlgFoldXmlDocType;
2617  EditorOptionsFoldInfoXML[4].Name := dlgFoldXmlProcess;
2618
2619  EditorOptionsFoldInfoDiff[0].Name := lisFile;
2620  EditorOptionsFoldInfoDiff[1].Name := dlgFoldDiffChunk;
2621  EditorOptionsFoldInfoDiff[2].Name := dlgFoldDiffChunkSect;
2622
2623  EditorOptionsDividerInfoPas[0].Name:=dlgDivPasUnitSectionName;
2624  EditorOptionsDividerInfoPas[1].Name:=dlgDivPasUsesName;
2625  EditorOptionsDividerInfoPas[2].Name:=dlgDivPasVarGlobalName;
2626  EditorOptionsDividerInfoPas[3].Name:=dlgDivPasVarLocalName;
2627  EditorOptionsDividerInfoPas[4].Name:=dlgDivPasStructGlobalName;
2628  EditorOptionsDividerInfoPas[5].Name:=dlgDivPasStructLocalName;
2629  EditorOptionsDividerInfoPas[6].Name:=dlgDivPasProcedureName;
2630  EditorOptionsDividerInfoPas[7].Name:=dlgDivPasBeginEndName;
2631  EditorOptionsDividerInfoPas[8].Name:=dlgDivPasTryName;
2632
2633  AdditionalHighlightAttributes[ahaNone]                := '';
2634  AdditionalHighlightAttributes[ahaTextBlock]           := dlgAddHiAttrTextBlock;
2635  AdditionalHighlightAttributes[ahaExecutionPoint]      := dlgAddHiAttrExecutionPoint;
2636  AdditionalHighlightAttributes[ahaEnabledBreakpoint]   := dlgAddHiAttrEnabledBreakpoint;
2637  AdditionalHighlightAttributes[ahaDisabledBreakpoint]  := dlgAddHiAttrDisabledBreakpoint;
2638  AdditionalHighlightAttributes[ahaInvalidBreakpoint]   := dlgAddHiAttrInvalidBreakpoint;
2639  AdditionalHighlightAttributes[ahaUnknownBreakpoint]   := dlgAddHiAttrUnknownBreakpoint;
2640  AdditionalHighlightAttributes[ahaErrorLine]           := dlgAddHiAttrErrorLine;
2641  AdditionalHighlightAttributes[ahaIncrementalSearch]   := dlgAddHiAttrIncrementalSearch;
2642  AdditionalHighlightAttributes[ahaHighlightAll]        := dlgAddHiAttrHighlightAll;
2643  AdditionalHighlightAttributes[ahaBracketMatch]        := dlgAddHiAttrBracketMatch;
2644  AdditionalHighlightAttributes[ahaMouseLink]           := dlgAddHiAttrMouseLink;
2645  AdditionalHighlightAttributes[ahaLineNumber]          := dlgAddHiAttrLineNumber;
2646  AdditionalHighlightAttributes[ahaLineHighlight]       := dlgAddHiAttrLineHighlight;
2647  AdditionalHighlightAttributes[ahaModifiedLine]        := dlgAddHiAttrModifiedLine;
2648  AdditionalHighlightAttributes[ahaCodeFoldingTree]     := dlgAddHiAttrCodeFoldingTree;
2649  AdditionalHighlightAttributes[ahaHighlightWord]       := dlgAddHiAttrHighlightWord;
2650  AdditionalHighlightAttributes[ahaFoldedCode]          := dlgAddHiAttrFoldedCode;
2651  AdditionalHighlightAttributes[ahaFoldedCodeLine]      := dlgAddHiAttrFoldedCodeLine;
2652  AdditionalHighlightAttributes[ahaHiddenCodeLine]      := dlgAddHiAttrHiddenCodeLine;
2653  AdditionalHighlightAttributes[ahaWordGroup]           := dlgAddHiAttrWordGroup;
2654  AdditionalHighlightAttributes[ahaTemplateEditCur]     := dlgAddHiAttrTemplateEditCur;
2655  AdditionalHighlightAttributes[ahaTemplateEditSync]    := dlgAddHiAttrTemplateEditSync;
2656  AdditionalHighlightAttributes[ahaTemplateEditOther]   := dlgAddHiAttrTemplateEditOther;
2657  AdditionalHighlightAttributes[ahaSyncroEditCur]       := dlgAddHiAttrSyncroEditCur;
2658  AdditionalHighlightAttributes[ahaSyncroEditSync]      := dlgAddHiAttrSyncroEditSync;
2659  AdditionalHighlightAttributes[ahaSyncroEditOther]     := dlgAddHiAttrSyncroEditOther;
2660  AdditionalHighlightAttributes[ahaSyncroEditArea]      := dlgAddHiAttrSyncroEditArea;
2661  AdditionalHighlightAttributes[ahaGutterSeparator]     := dlgAddHiAttrGutterSeparator;
2662  AdditionalHighlightAttributes[ahaGutter]              := dlgGutter;
2663  AdditionalHighlightAttributes[ahaRightMargin]         := dlgRightMargin;
2664  AdditionalHighlightAttributes[ahaSpecialVisibleChars] := dlgAddHiSpecialVisibleChars;
2665  AdditionalHighlightAttributes[ahaTopInfoHint]         := dlgTopInfoHint;
2666  AdditionalHighlightAttributes[ahaCaretColor]          := dlgCaretColor;
2667  AdditionalHighlightAttributes[ahaOverviewGutter]      := dlgOverviewGutterColor;
2668  AdditionalHighlightAttributes[ahaIfDefBlockInactive]  := dlgIfDefBlockInactive;
2669  AdditionalHighlightAttributes[ahaIfDefBlockActive]    := dlgIfDefBlockActive;
2670  AdditionalHighlightAttributes[ahaIfDefBlockTmpActive] := dlgIfDefBlockTmpActive;
2671  AdditionalHighlightAttributes[ahaIfDefNodeInactive]   := dlgIfDefNodeInactive;
2672  AdditionalHighlightAttributes[ahaIfDefNodeActive]     := dlgIfDefNodeActive;
2673  AdditionalHighlightAttributes[ahaIfDefNodeTmpActive]  := dlgIfDefNodeTmpActive;
2674  AdditionalHighlightGroupNames[agnIfDef]        := dlgAddHiAttrGroupIfDef;
2675
2676  AdditionalHighlightAttributes[ahaIdentComplWindow]          := dlgAddHiAttrDefaultWindow;
2677  AdditionalHighlightAttributes[ahaIdentComplWindowBorder]    := dlgAddHiAttrWindowBorder;
2678  AdditionalHighlightAttributes[ahaIdentComplWindowSelection] := dlgBlockGroupOptions;
2679  AdditionalHighlightAttributes[ahaIdentComplWindowHighlight] := dlgAddHiAttrHighlightPrefix;
2680  AdditionalHighlightGroupNames[agnIdentComplWindow]          := dlgIdentifierCompletion;
2681
2682  AdditionalHighlightAttributes[ahaOutlineLevel1Color]  := dlgAddHiAttrOutlineLevel1Color;
2683  AdditionalHighlightAttributes[ahaOutlineLevel2Color]  := dlgAddHiAttrOutlineLevel2Color;
2684  AdditionalHighlightAttributes[ahaOutlineLevel3Color]  := dlgAddHiAttrOutlineLevel3Color;
2685  AdditionalHighlightAttributes[ahaOutlineLevel4Color]  := dlgAddHiAttrOutlineLevel4Color;
2686  AdditionalHighlightAttributes[ahaOutlineLevel5Color]  := dlgAddHiAttrOutlineLevel5Color;
2687  AdditionalHighlightAttributes[ahaOutlineLevel6Color]  := dlgAddHiAttrOutlineLevel6Color;
2688  AdditionalHighlightAttributes[ahaOutlineLevel7Color]  := dlgAddHiAttrOutlineLevel7Color;
2689  AdditionalHighlightAttributes[ahaOutlineLevel8Color]  := dlgAddHiAttrOutlineLevel8Color;
2690  AdditionalHighlightAttributes[ahaOutlineLevel9Color]  := dlgAddHiAttrOutlineLevel9Color;
2691  AdditionalHighlightAttributes[ahaOutlineLevel10Color] := dlgAddHiAttrOutlineLevel10Color;
2692  AdditionalHighlightGroupNames[agnOutlineColors]  := dlgAddHiAttrGroupOutlineColors;
2693
2694  AdditionalHighlightGroupNames[agnDefault]      := dlgAddHiAttrGroupDefault;
2695  AdditionalHighlightGroupNames[agnText]         := dlgAddHiAttrGroupText;
2696  AdditionalHighlightGroupNames[agnLine]         := dlgAddHiAttrGroupLine;
2697  AdditionalHighlightGroupNames[agnTemplateMode] := dlgAddHiAttrGroupTemplateEdit;
2698  AdditionalHighlightGroupNames[agnSyncronMode]  := dlgAddHiAttrGroupSyncroEdit;
2699  AdditionalHighlightGroupNames[agnGutter]       := dlgAddHiAttrGroupGutter;
2700end;
2701
2702function StrToValidXMLName(const s: String): String;
2703var
2704  i: Integer;
2705begin
2706  Result := s;
2707  // replace invalid characters
2708  for i := 1 to length(Result) do
2709    if (not (Result[i] in ValidAttribChars)) then
2710      Result[i] := '_';
2711end;
2712
2713{ TEditOptLanguageInfo }
2714
2715constructor TEditOptLanguageInfo.Create;
2716begin
2717  inherited Create;
2718end;
2719
2720destructor TEditOptLanguageInfo.Destroy;
2721begin
2722  MappedAttributes.Free;
2723  inherited Destroy;
2724end;
2725
2726function TEditOptLanguageInfo.SampleLineToAddAttr(Line: Integer): TAdditionalHilightAttribute;
2727begin
2728  if Line < 1 then
2729    exit(ahaNone);
2730  for Result := Low(TAdditionalHilightAttribute) to High(TAdditionalHilightAttribute) do
2731    if (Result <> ahaNone) and (AddAttrSampleLines[Result] = Line) then
2732      exit;
2733  Result := ahaNone;
2734end;
2735
2736function TEditOptLanguageInfo.GetDefaultFilextension: String;
2737var
2738  p: Integer;
2739begin
2740  // read the first file extension
2741  p := 1;
2742  while (p <= length(FileExtensions)) and (FileExtensions[p] <> ';') do
2743    inc(p);
2744  if p > 1 then
2745    Result := '.' + copy(FileExtensions, 1, p - 1)
2746  else
2747    Result := '';
2748end;
2749
2750procedure TEditOptLanguageInfo.SetBothFilextensions(const Extensions: string);
2751begin
2752  FileExtensions:=Extensions;
2753  DefaultFileExtensions:=Extensions;
2754end;
2755
2756procedure TEditOptLanguageInfo.prepare(Syntax: TLazSyntaxHighlighter);
2757begin
2758  TheType := Syntax;
2759  DefaultCommentType := DefaultCommentTypes[TheType];
2760  SynClass := LazSyntaxHighlighterClasses[TheType];
2761end;
2762
2763{ TEditOptLangCssInfo }
2764
2765procedure TEditOptLangCssInfo.prepare(Syntax: TLazSyntaxHighlighter);
2766begin
2767  inherited Prepare(syntax);
2768  SetBothFilextensions('css');
2769  SampleSource := getSampleSource;
2770  AddAttrSampleLines[ahaTextBlock] := 4;
2771  CaretXY := Point(1,1);
2772  MappedAttributes := getMappedAttributes;;
2773end;
2774
2775function TEditOptLangCssInfo.getSampleSource: string;
2776begin
2777  result :=
2778      '.field :hover {'#10 +
2779      '   display:inline;'#10+
2780      '   border:10px;'#10+
2781      '   color: #555;'#10+
2782      '/* comment */'#10+
2783      '}'#10+#10;
2784end;
2785
2786function TEditOptLangCssInfo.getMappedAttributes: tStringList;
2787begin
2788    result:=tStringList.create;
2789    with result do
2790    begin
2791      Add('Comment=Comment');
2792      Add('Selector=Reserved_word');
2793      Add('Identifier=Identifier');
2794      Add('Space=Space');
2795      Add('Symbol=Symbol');
2796      Add('Number=Number');
2797      Add('Key=Key');
2798      Add('String=String');
2799    end;
2800end;
2801
2802{ TEditOptLangList }
2803
2804function TEditOptLangList.GetInfos(Index: Integer): TEditOptLanguageInfo;
2805begin
2806  if (Index < 0) or (Index >= Count) then
2807    raise Exception.Create('TEditOptLangList.GetInfos Index '
2808      + IntToStr(Index) + ' out of bounds. Count=' + IntToStr(Count));
2809  Result := TEditOptLanguageInfo(inherited Items[Index]);
2810end;
2811
2812procedure TEditOptLangList.Clear;
2813var
2814  i: Integer;
2815begin
2816  for i := 0 to Count - 1 do
2817    Items[i].Free;
2818  inherited Clear;
2819end;
2820
2821constructor TEditOptLangList.Create;
2822var
2823  NewInfo: TEditOptLanguageInfo;
2824begin
2825  inherited Create;
2826
2827  { create the meta information for each available highlighter.
2828    Please keep the pascal highlighter at the top. The rest can be ordered as you
2829    like.
2830  }
2831
2832  // create info for pascal
2833  NewInfo := TEditOptLanguageInfo.Create;
2834  with NewInfo do
2835  begin
2836    TheType := lshFreePascal;
2837    DefaultCommentType := DefaultCommentTypes[TheType];
2838    SynClass := LazSyntaxHighlighterClasses[TheType];
2839    SetBothFilextensions('pp;pas;inc;lpr;lrs;dpr;dpk;fpd');
2840    SampleSource :=
2841      '{ Comment }'#13 +
2842      '{$R- compiler directive}'#13 +
2843      'procedure TForm1.Button1Click(Sender: TObject);'#13 +
2844      'var  // Delphi Comment'#13 +
2845      '  Number, I, X: Integer;'#13 +
2846      'begin'#13 +
2847      '  Number := 12345 * (2 + 9) // << Matching Brackets ;'#13 +
2848      '  Caption := ''The number is '' + IntToStr(Number);'#13 +
2849      '  asm'#13 + '    MOV AX,1234h'#13 +
2850      '    MOV Number,AX'#13 +
2851      '  end;'#13 +
2852      '  {%region /fold}'#13 +
2853      '  {%endregion}'#13 +
2854      '  X := 10;'#13 +
2855      '  inc(X); {$R+} { Search Match, Text Block }'#13 +
2856      '  for I := 0 to Number do {$R-} { execution point }'#13 +
2857      '  begin'#13 +
2858      '    Inc(X, 2); {$R+} { Enabled breakpoint }'#13 +
2859      '    Dec(X, 3); {$R+} { Disabled breakpoint }'#13 +
2860      '    {$R-} // { Invalid breakpoint }'#13 +
2861      '    WriteLN(X); {$R-} { Unknown breakpoint }'#13 +
2862      '    X := X + 1.0; {$R-} { Error line }'#13 +
2863      '    case ModalResult of'#13+
2864      '      mrOK: inc(X);'#13+
2865      '      mrCancel, mrIgnore: dec(X);'#13+
2866      '    end;'#13+
2867      '    ListBox1.Items.Add(IntToStr(X));'#13 +
2868//{$IFDEF WithSynMarkupIfDef}
2869//      '    {$IFDEF Foo}' +
2870//      '      X := X + 1.0; {$R-} { Error line }'#13 +
2871//      '      {$DEFINE a}' +
2872//      '      case ModalResult of'#13+
2873//      '        mrOK: inc(X);'#13+
2874//      '        mrCancel, mrIgnore: dec(X);'#13+
2875//      '      end;'#13+
2876//      '    {$ELSE}' +
2877//      '      {%region teset}'#13 +
2878//      '      {%endregion}'#13 +
2879//      '      with self do'#13 +
2880//      '        X := 10;'#13 +
2881//      '    {$ENDIF}' +
2882//{$ENDIF}
2883      '  end;'#13 +
2884      'end;'#13 + #13;
2885    AddAttrSampleLines[ahaDisabledBreakpoint] := 20;
2886    AddAttrSampleLines[ahaEnabledBreakpoint] := 19;
2887    AddAttrSampleLines[ahaInvalidBreakpoint] := 21;
2888    AddAttrSampleLines[ahaUnknownBreakpoint] := 22;
2889    AddAttrSampleLines[ahaErrorLine] := 23;
2890    AddAttrSampleLines[ahaExecutionPoint] := 17;
2891    AddAttrSampleLines[ahaTextBlock] := 16;
2892    AddAttrSampleLines[ahaFoldedCode] := 13;
2893    CaretXY := Point(21, 7);
2894  end;
2895  Add(NewInfo);
2896
2897  // create info for html
2898  NewInfo := TEditOptLanguageInfo.Create;
2899  with NewInfo do
2900  begin
2901    TheType := lshHTML;
2902    DefaultCommentType := DefaultCommentTypes[TheType];
2903    SynClass := LazSyntaxHighlighterClasses[TheType];
2904    SetBothFilextensions('htm;html;xhtml');
2905    SampleSource :=
2906      '<html>'#13 + '<title>Lazarus Sample source for html</title>'#13 +
2907      '<body bgcolor=#ffffff background="bg.jpg">'#13 +
2908      '<!-- Comment -->'#13 + '<img src="lazarus.jpg">'#13 +
2909      '<p>'#13 + '  Some Text'#13 +
2910      '  Ampersands: &nbsp;F&nbsp;P&nbsp;C'#13 + '</p>'#13 +
2911      '<invalid_tag>'#13 + '<!-- Text Block -->'#13 +
2912      '</body>'#13 + '</html>'#13 + #13;
2913    AddAttrSampleLines[ahaTextBlock] := 11;
2914    MappedAttributes := TStringList.Create;
2915    with MappedAttributes do
2916    begin
2917      Add('Comment=Comment');
2918      Add('Space=Space');
2919    end;
2920    CaretXY := Point(1,1);
2921  end;
2922  Add(NewInfo);
2923
2924  // create info for cpp
2925  NewInfo := TEditOptLanguageInfo.Create;
2926  with NewInfo do
2927  begin
2928    TheType := lshCPP;
2929    DefaultCommentType := DefaultCommentTypes[TheType];
2930    SynClass := LazSyntaxHighlighterClasses[TheType];
2931    SetBothFilextensions('c;cc;cpp;h;hpp;hh');
2932    SampleSource :=
2933      '/* Comment */'#13 + '#include <stdio.h>'#13 +
2934      '#include <stdlib.h>'#13 + #13 +
2935      'static char line_buf[LINE_BUF];'#13 + #13 +
2936      'int main(int argc,char **argv){'#13 + '  FILE *file;'#13 +
2937      '  line_buf[0]=0;'#13 + '  printf("\n");'#13 +
2938      '  return 0;'#13 + '}'#13 + ''#13 + #13;
2939    AddAttrSampleLines[ahaTextBlock] := 11;
2940    MappedAttributes := TStringList.Create;
2941    with MappedAttributes do
2942    begin
2943      Add('Assembler=Assembler');
2944      Add('Comment=Comment');
2945      Add('Preprocessor=Comment');
2946      Add('Identifier=Identifier');
2947      Add('Reserved_word=Reserved_word');
2948      Add('Number=Number');
2949      Add('Space=Space');
2950      Add('String=String');
2951      Add('Symbol=Symbol');
2952    end;
2953    CaretXY := Point(1,1);
2954  end;
2955  Add(NewInfo);
2956
2957  // create info for XML
2958  NewInfo := TEditOptLanguageInfo.Create;
2959  with NewInfo do
2960  begin
2961    TheType := lshXML;
2962    DefaultCommentType := DefaultCommentTypes[TheType];
2963    SynClass := LazSyntaxHighlighterClasses[TheType];
2964    SetBothFilextensions('xml;xsd;xsl;xslt;dtd;lpi;lps;lpk;wsdl;svg');
2965    SampleSource :=
2966      '<?xml version="1.0"?>'#13 + '<!DOCTYPE root ['#13 +
2967      '  ]>'#13 + '<!-- Comment -->'#13 + '<root version="&test;">'#13 +
2968      '  <![CDATA[ **CDATA section** ]]>'#13 + '</root>'#13 +
2969      '<!-- Text Block -->'#13 + ''#13 + #13;
2970    AddAttrSampleLines[ahaTextBlock] := 8;
2971    MappedAttributes := TStringList.Create;
2972    with MappedAttributes do
2973    begin
2974      Add('Element=Reserved_word');
2975      Add('Comment=Comment');
2976      Add('Text=Identifier');
2977      Add('Space=Space');
2978      Add('Symbol=Symbol');
2979    end;
2980    CaretXY := Point(1,1);
2981  end;
2982  Add(NewInfo);
2983
2984  // create info for LFM
2985  NewInfo := TEditOptLanguageInfo.Create;
2986  with NewInfo do
2987  begin
2988    TheType := lshLFM;
2989    DefaultCommentType := DefaultCommentTypes[TheType];
2990    SynClass := LazSyntaxHighlighterClasses[TheType];
2991    SetBothFilextensions('lfm;dfm;xfm');
2992    SampleSource :=
2993      '{ Lazarus Form Definitions }'#13 + 'object TestForm: TTestForm'#13 +
2994      '  Left = 273'#13 + '  Top = 103'#13 +
2995      '  Caption = ''sample source'''#13 + 'end'#13 +
2996      '{ Text Block }'#13 + ''#13 + #13;
2997    AddAttrSampleLines[ahaTextBlock] := 7;
2998    MappedAttributes := TStringList.Create;
2999    with MappedAttributes do
3000    begin
3001      Add('Element=Reserved_word');
3002      Add('Comment=Comment');
3003      Add('Identifier=Identifier');
3004      Add('Key=Reserved_word');
3005      Add('Number=Number');
3006      Add('Space=Space');
3007      Add('String=String');
3008      Add('Symbol=Symbol');
3009    end;
3010    CaretXY := Point(1,1);
3011  end;
3012  Add(NewInfo);
3013
3014  // create info for Perl
3015  NewInfo := TEditOptLanguageInfo.Create;
3016  with NewInfo do
3017  begin
3018    TheType := lshPerl;
3019    DefaultCommentType := DefaultCommentTypes[TheType];
3020    SynClass := LazSyntaxHighlighterClasses[TheType];
3021    SetBothFilextensions('pl;pm;cgi');
3022    SampleSource :=
3023      '#!/usr/bin/perl'#13 + '# Perl sample code'#13 +
3024      ''#13 + '$i = "10";'#13 + 'print "$ENV{PATH}\n";'#13 +
3025      '($i =~ /\d+/) || die "Error\n";'#13 + ''#13 +
3026      '# Text Block'#13 + ''#13 + #13;
3027    AddAttrSampleLines[ahaTextBlock] := 8;
3028    MappedAttributes := TStringList.Create;
3029    with MappedAttributes do
3030    begin
3031      Add('Comment=Comment');
3032      Add('Identifier=Identifier');
3033      Add('KeyAttri=Reserved_word');
3034      Add('NumberAttri=Number');
3035      Add('SpaceAttri=Space');
3036      Add('StringAttri=String');
3037      Add('Symbol=Symbol');
3038    end;
3039    CaretXY := Point(1,1);
3040  end;
3041  Add(NewInfo);
3042
3043  // create info for Java
3044  NewInfo := TEditOptLanguageInfo.Create;
3045  with NewInfo do
3046  begin
3047    TheType := lshJava;
3048    DefaultCommentType := DefaultCommentTypes[TheType];
3049    SynClass := LazSyntaxHighlighterClasses[TheType];
3050    SetBothFilextensions('java');
3051    SampleSource :=
3052      '/* Java syntax highlighting */'#13#10 +
3053      'import java.util.*;'#13#10 + #13#10 +
3054      '/** Example class */'#13#10 +
3055      'public class Sample {'#13#10 +
3056      '  public static void main(String[] args) {'#13#10 +
3057      '    int i = 0;'#13#10 +
3058      '    for(i = 0; i < 10; i++)'#13#10 +
3059      '      System.out.println("Hello world");'#13#10 +
3060      '  }'#13#10 + '}'#13#10 +
3061      '/* Text Block */'#13#10 + #13#10;
3062    AddAttrSampleLines[ahaTextBlock] := 12;
3063    MappedAttributes := TStringList.Create;
3064    with MappedAttributes do
3065    begin
3066      Add('Comment=Comment');
3067      Add('Documentation=Comment');
3068      Add('Identifier=Identifier');
3069      Add('Reserved_word=Reserved_word');
3070      Add('Number=Number');
3071      Add('Space=Space');
3072      Add('String=String');
3073      Add('Symbol=Symbol');
3074    end;
3075    CaretXY := Point(1,1);
3076  end;
3077  Add(NewInfo);
3078
3079  // create info for Bash
3080  NewInfo := TEditOptLanguageInfo.Create;
3081  with NewInfo do
3082  begin
3083    TheType := lshBash;
3084    DefaultCommentType := DefaultCommentTypes[TheType];
3085    SynClass := LazSyntaxHighlighterClasses[TheType];
3086    SetBothFilextensions('sh');
3087    SampleSource :=
3088      '#!/bin/bash'#13#13 +
3089      '# Bash syntax highlighting'#13#10 + 'set -x'#13#10 +
3090      'set -e'#13#10 +
3091      'Usage="Usage: $0 devel|stable"'#13#10 +
3092      'FPCVersion=$1'#13#10 +
3093      'for ver in devel stable; do'#13#10 +
3094      '  if [ "x$FPCVersion" = "x$ver" ]; then'#13#10 +
3095      '  fi'#13#10 + 'done'#13#10 +
3096      '# Text Block'#13#10 + #13#10;
3097    AddAttrSampleLines[ahaTextBlock] := 12;
3098    MappedAttributes := TStringList.Create;
3099    with MappedAttributes do
3100    begin
3101      Add('Comment=Comment');
3102      Add('Variable=Identifier');
3103      Add('Key=Reserved_word');
3104      Add('Number=Number');
3105      Add('Space=Space');
3106      Add('String=String');
3107      Add('Symbol=Symbol');
3108    end;
3109    CaretXY := Point(1,1);
3110  end;
3111  Add(NewInfo);
3112
3113  // create info for Python
3114  NewInfo := TEditOptLanguageInfo.Create;
3115  with NewInfo do
3116  begin
3117    TheType := lshPython;
3118    DefaultCommentType := DefaultCommentTypes[TheType];
3119    SynClass := LazSyntaxHighlighterClasses[TheType];
3120    SetBothFilextensions('py;pyw');
3121    SampleSource :=
3122      '# Python syntax highlighting'#13#10 +
3123      'import math'#13#10 + #13#10 +
3124      '""" Documentation """'#13#10 +
3125      'def DoSomething(Liste1,Liste2,param3=3):'#13#10 +
3126      '  for i in Liste1:'#13#10 +
3127      '    if i in Liste2:'#13#10 +
3128      '      Liste1.remove(i)'#13#10 +
3129      '/* Text Block */'#13#10 + #13#10;
3130    AddAttrSampleLines[ahaTextBlock] := 9;
3131    MappedAttributes := TStringList.Create;
3132    with MappedAttributes do
3133    begin
3134      Add('Comment=Comment');
3135      Add('Identifier=Identifier');
3136      Add('Documentation=Comment');
3137      Add('Reserved_word=Reserved_word');
3138      Add('Number=Number');
3139      Add('Space=Space');
3140      Add('String=String');
3141      Add('Symbol=Symbol');
3142    end;
3143    CaretXY := Point(1,1);
3144  end;
3145  Add(NewInfo);
3146
3147  // create info for PHP
3148  NewInfo := TEditOptLanguageInfo.Create;
3149  with NewInfo do
3150  begin
3151    TheType := lshPHP;
3152    DefaultCommentType := DefaultCommentTypes[TheType];
3153    SynClass := LazSyntaxHighlighterClasses[TheType];
3154    SetBothFilextensions('php;php3;php4');
3155    SampleSource :=
3156      '<?if ( ($HTTP_HOST == "www.lazarus.com") || ($HTTP_HOST == "lazarus.com") ){'#10 + '   HEADER("Location:http://www.lazarus.freepascal.org/\n\n");'#10
3157      + '};'#10 + '?>'#10 + #10;
3158    AddAttrSampleLines[ahaTextBlock] := 8;
3159    MappedAttributes := TStringList.Create;
3160    with MappedAttributes do
3161    begin
3162      Add('Element=Reserved_word');
3163      Add('Comment=Comment');
3164      Add('Variable=Identifier');
3165      Add('Space=Space');
3166      Add('Symbol=Symbol');
3167      Add('Number=Number');
3168      Add('Key=Key');
3169      Add('String=String');
3170    end;
3171    CaretXY := Point(1,1);
3172  end;
3173  Add(NewInfo);
3174
3175  // create info for SQL
3176  NewInfo := TEditOptLanguageInfo.Create;
3177  with NewInfo do
3178  begin
3179    TheType := lshSQL;
3180    DefaultCommentType := DefaultCommentTypes[TheType];
3181    SynClass := LazSyntaxHighlighterClasses[TheType];
3182    SetBothFilextensions('sql');
3183    SampleSource :=
3184      '-- ansi sql sample source'#10 +
3185        'select name , region'#10 +
3186        'from cia'#10 +
3187        'where area < 2000'#10 +
3188        'and gdp > 5000000000'#10 + #10;
3189    AddAttrSampleLines[ahaTextBlock] := 4;
3190    MappedAttributes := TStringList.Create;
3191    with MappedAttributes do
3192    begin
3193      Add('Comment=Comment');
3194      Add('Element=Reserved_word');
3195      Add('Variable=Identifier');
3196      Add('Space=Space');
3197      Add('Symbol=Symbol');
3198      Add('Number=Number');
3199      Add('Key=Key');
3200      Add('String=String');
3201    end;
3202    CaretXY := Point(1,1);
3203  end;
3204  Add(NewInfo);
3205
3206  // create info for CSS
3207  NewInfo := TEditOptLangCssInfo.Create;
3208  NewInfo.Prepare(lshCss);
3209  Add(NewInfo);
3210
3211  // create info for JScript
3212  NewInfo := TEditOptLanguageInfo.Create;
3213  with NewInfo do
3214  begin
3215    TheType := lshJScript;
3216    DefaultCommentType := DefaultCommentTypes[TheType];
3217    SynClass := LazSyntaxHighlighterClasses[TheType];
3218    SetBothFilextensions('js');
3219    SampleSource :=
3220      '/* JScript */'#13#10 +
3221      'var semafor={'#13#10 +
3222      '  semafor:0,'#13#10 +
3223      '  timer:null,'#13#10 +
3224      '  name:"Name",'#13#10 +
3225      '  clear: function(){'#13#10 +
3226      '    try{'#13#10 +
3227      '      this.semafor=0;'#13#10 +
3228      '      clearTimeout(this.timer);'#13#10 +
3229      '    }  catch (e)  { }'#13#10 +
3230      '  }'#13#10 +
3231      '};'#13#10 +
3232
3233      #13#10 +
3234      '/* Text Block */'#13#10 + #13#10;
3235    AddAttrSampleLines[ahaTextBlock] := 2;
3236    MappedAttributes := TStringList.Create;
3237    with MappedAttributes do
3238    begin
3239      Add('Comment=Comment');
3240      Add('Documentation=Comment');
3241      Add('Identifier=Identifier');
3242      Add('Reserved_word=Reserved_word');
3243      Add('Number=Number');
3244      Add('Space=Space');
3245      Add('String=String');
3246      Add('Symbol=Symbol');
3247    end;
3248    CaretXY := Point(1,1);
3249  end;
3250  Add(NewInfo);
3251
3252  // create info for Diff
3253  NewInfo := TEditOptLanguageInfo.Create;
3254  with NewInfo do
3255  begin
3256    TheType := lshDiff;
3257    DefaultCommentType := DefaultCommentTypes[TheType];
3258    SynClass := LazSyntaxHighlighterClasses[TheType];
3259    SetBothFilextensions('diff');
3260    SampleSource :=
3261      '*** /a/file'#13#10 +
3262      '--- /b/file'#13#10 +
3263      '***************'#13#10 +
3264      '*** 2,5 ****'#13#10 +
3265      '--- 2,5 ----'#13#10 +
3266      '  context'#13#10 +
3267      '- removed'#13#10 +
3268      '! Changed'#13#10 +
3269      '+ added'#13#10 +
3270      '  context'#13#10;
3271    MappedAttributes := TStringList.Create;
3272    //with MappedAttributes do
3273    //begin
3274    //  Add('Unknown_word=Comment');
3275    //end;
3276    CaretXY := Point(1,6);
3277  end;
3278  Add(NewInfo);
3279
3280  // create info for Bat
3281  NewInfo := TEditOptLanguageInfo.Create;
3282  with NewInfo do
3283  begin
3284    TheType := lshBat;
3285    DefaultCommentType := DefaultCommentTypes[TheType];
3286    SynClass := LazSyntaxHighlighterClasses[TheType];
3287    SetBothFilextensions('bat');
3288    SampleSource :=
3289      'rem MS-DOS batch file'#13#10 +
3290      'rem'#13#10 +
3291      '@echo off'#13#10 +
3292      'cls'#13#10 +
3293      'echo The command line is: %1 %2 %3 %4 %5'#13#10 +
3294      'rem'#13#10 +
3295      'rem now wait for the user ...'#13#10 +
3296      'pause'#13#10 +
3297      'copy c:\*.pas d:\'#13#10 +
3298      'if errorlevel 1 echo Error in copy action!';
3299    MappedAttributes := TStringList.Create;
3300    //with MappedAttributes do
3301    //begin
3302    //  Add('Comment=Comment');
3303    //  Add('Identifier=Identifier');
3304    //  Add('Key=Key');
3305    //  Add('Number=Number');
3306    //  Add('Space=Space');
3307    //end;
3308    CaretXY := Point(1,3);
3309  end;
3310  Add(NewInfo);
3311
3312  // create info for Diff
3313  NewInfo := TEditOptLanguageInfo.Create;
3314  with NewInfo do
3315  begin
3316    TheType := lshIni;
3317    DefaultCommentType := DefaultCommentTypes[TheType];
3318    SynClass := LazSyntaxHighlighterClasses[TheType];
3319    SetBothFilextensions('ini');
3320    SampleSource :=
3321      '; Syntax highlighting'#13#10+
3322      '[Section]'#13#10+
3323      'Key=value'#13#10+
3324      'String="Arial"'#13#10+
3325      'Number=123456';
3326    MappedAttributes := TStringList.Create;
3327    //with MappedAttributes do
3328    //begin
3329    //  Add('Comment=Comment');
3330    //  Add('String=String');
3331    //  Add('Key=Key');
3332    //  Add('Number=Number');
3333    //  Add('Space=Space');
3334    //end;
3335    CaretXY := Point(1,1);
3336  end;
3337  Add(NewInfo);
3338
3339  // create info for PO
3340  NewInfo := TEditOptLanguageInfo.Create;
3341  with NewInfo do
3342  begin
3343    TheType := lshPo;
3344    DefaultCommentType := DefaultCommentTypes[TheType];
3345    SynClass := LazSyntaxHighlighterClasses[TheType];
3346    SetBothFilextensions('po');
3347    SampleSource :=
3348      '#: foo.bar'#13#10 +
3349      '#, fuzzy'#13#10 +
3350      '#| msgid "abc"'#13#10 +
3351      'msgid "abc"'#13#10 +
3352      'msgstr "123"'#13#10;
3353    //MappedAttributes := TStringList.Create;
3354    //with MappedAttributes do
3355    //begin
3356    //  Add('Comment=Comment');
3357    //  Add('Key=Key');
3358    //  Add('Identifier=Identifier');
3359    //  Add('Space=Space');
3360    //  Add('String=String');
3361    //end;
3362    CaretXY := Point(3,1);
3363  end;
3364  Add(NewInfo);
3365
3366  // create info for Pike
3367  NewInfo := TEditOptLanguageInfo.Create;
3368  NewInfo.TheType := lshPike;
3369  NewInfo.DefaultCommentType := DefaultCommentTypes[NewInfo.TheType];
3370  NewInfo.SynClass := LazSyntaxHighlighterClasses[NewInfo.TheType];
3371  NewInfo.SetBothFilextensions('pike;pmod');
3372  NewInfo.SampleSource := TSynPikeSyn.Pike_GetSampleSource();
3373  with NewInfo do
3374  begin
3375    AddAttrSampleLines[ahaTextBlock] := 12;
3376    MappedAttributes := TStringList.Create;
3377    with MappedAttributes do
3378    begin
3379      Add('Comment=Comment');
3380      Add('Documentation=Comment');
3381      Add('Identifier=Identifier');
3382      Add('Reserved_word=Reserved_word');
3383      Add('Number=Number');
3384      Add('Space=Space');
3385      Add('String=String');
3386      Add('Symbol=Symbol');
3387    end;
3388    CaretXY := Point(1,1);
3389  end;
3390  Add(NewInfo);
3391
3392end;
3393
3394destructor TEditOptLangList.Destroy;
3395begin
3396  Clear;
3397  inherited Destroy;
3398end;
3399
3400function TEditOptLangList.FindByName(const Name: String): Integer;
3401begin
3402  Result := Count - 1;
3403  while (Result >= 0) and (UTF8CompareLatinTextFast(
3404      Items[Result].SynClass.GetLanguageName, Name) <> 0) do
3405    dec(Result);
3406end;
3407
3408function TEditOptLangList.FindByClass(CustomSynClass: TCustomSynClass): Integer;
3409begin
3410  Result := Count - 1;
3411  while (Result >= 0) and (Items[Result].SynClass <> CustomSynClass) do
3412    dec(Result);
3413end;
3414
3415function TEditOptLangList.FindByHighlighter(Hilighter: TSynCustomHighlighter): Integer;
3416begin
3417  if Hilighter <> Nil then
3418    Result := FindByClass(TCustomSynClass(Hilighter.ClassType))
3419  else
3420    Result := -1;
3421end;
3422
3423function TEditOptLangList.FindByType(AType: TLazSyntaxHighlighter): Integer;
3424begin
3425  AType := CompatibleLazSyntaxHilighter[AType];
3426  Result := Count - 1;
3427  while (Result >= 0) and (Items[Result].TheType <> AType) do
3428    dec(Result);
3429end;
3430
3431function TEditOptLangList.GetDefaultFilextension(
3432  AType: TLazSyntaxHighlighter): String;
3433var
3434  i: Integer;
3435begin
3436  i := FindByType(AType);
3437  if i >= 0 then
3438    Result := Items[i].GetDefaultFilextension
3439  else
3440    Result := '';
3441end;
3442
3443function TEditOptLangList.GetInfoByType(AType: TLazSyntaxHighlighter): TEditOptLanguageInfo;
3444var
3445  i: LongInt;
3446begin
3447  i:=FindByType(AType);
3448  if i>=0 then
3449    Result:=Items[i]
3450  else
3451    Result:=nil;
3452end;
3453
3454{ TEditorMouseOptions }
3455
3456procedure TEditorMouseOptions.ClearUserSchemes;
3457begin
3458  while FUserSchemes.Count > 0 do begin
3459    FUserSchemes.Objects[0].Free;
3460    FUserSchemes.Delete(0);
3461  end;
3462end;
3463
3464function TEditorMouseOptions.GetUserSchemeNames(Index: Integer): String;
3465begin
3466  Result := TEditorMouseOptions(FUserSchemes.Objects[Index]).Name;
3467end;
3468
3469function TEditorMouseOptions.GetUserSchemes(Index: String): TEditorMouseOptions;
3470var
3471  i: Integer;
3472begin
3473  i := IndexOfUserScheme(Index);
3474  if i >= 0 then
3475    Result := UserSchemesAtPos[i]
3476  else
3477    Result := nil;
3478end;
3479
3480function TEditorMouseOptions.GetUserSchemesAtPos(Index: Integer): TEditorMouseOptions;
3481begin
3482  Result := TEditorMouseOptions(FUserSchemes.Objects[Index]);
3483end;
3484
3485constructor TEditorMouseOptions.Create;
3486begin
3487  inherited Create;
3488  Reset;
3489  FMainActions          := TSynEditMouseActions.Create(nil);
3490  FSelActions           := TSynEditMouseActions.Create(nil);
3491  FTextActions          := TSynEditMouseActions.Create(nil);
3492  FGutterActions        := TSynEditMouseActions.Create(nil);
3493  FGutterActionsFold    := TSynEditMouseActions.Create(nil);
3494  FGutterActionsFoldExp := TSynEditMouseActions.Create(nil);
3495  FGutterActionsFoldCol := TSynEditMouseActions.Create(nil);
3496  FGutterActionsLines   := TSynEditMouseActions.Create(nil);
3497  FGutterActionsChanges := TSynEditMouseActions.Create(nil);
3498  FGutterActionsOverView:= TSynEditMouseActions.Create(nil);
3499  FGutterActionsOverViewMarks:= TSynEditMouseActions.Create(nil);
3500  FUserSchemes := TQuickStringlist.Create;
3501  FVersion := 0;
3502end;
3503
3504destructor TEditorMouseOptions.Destroy;
3505begin
3506  ClearUserSchemes;
3507  FUserSchemes.Free;
3508  FMainActions.Free;
3509  FTextActions.Free;
3510  FSelActions.Free;
3511  FGutterActions.Free;
3512  FGutterActionsFold.Free;
3513  FGutterActionsFoldExp.Free;
3514  FGutterActionsFoldCol.Free;
3515  FGutterActionsLines.Free;
3516  FGutterActionsChanges.Free;
3517  FGutterActionsOverView.Free;
3518  FGutterActionsOverViewMarks.Free;
3519  inherited Destroy;
3520end;
3521
3522procedure TEditorMouseOptions.Reset;
3523begin
3524  FCustomSavedActions  := False;
3525  FGutterLeft          := moglUpClickAndSelect;
3526  // left multi
3527  FTextDoubleLeftClick       := mbaSelectWords;
3528  FTextTripleLeftClick       := mbaSelectSetLineSmart;
3529  FTextQuadLeftClick         := mbaSelectSetPara;
3530  FTextShiftDoubleLeftClick  := mbaNone;
3531  FTextAltDoubleLeftClick    := mbaNone;
3532  FTextCtrlDoubleLeftClick   := mbaNone;
3533  // left
3534  FTextAltLeftClick          := mbaSelectColumn;
3535  FTextCtrlLeftClick         := mbaDeclarationJump;
3536  FTextAltCtrlLeftClick      := mbaNone;
3537  FTextShiftLeftClick        := mbaNone;
3538  FTextShiftAltLeftClick     := mbaNone;
3539  FTextShiftCtrlLeftClick    := mbaMultiCaretToggle;
3540  FTextShiftAltCtrlLeftClick := mbaNone;
3541  // middle
3542  FTextMiddleClick             := mbaPaste;
3543  FTextAltMiddleClick          := mbaNone;
3544  FTextCtrlMiddleClick         := mbaZoomReset;
3545  FTextShiftMiddleClick        := mbaNone;
3546  FTextAltCtrlMiddleClick      := mbaNone;
3547  FTextShiftAltMiddleClick     := mbaNone;
3548  FTextShiftAltCtrlMiddleClick := mbaNone;
3549  FTextShiftCtrlMiddleClick    := mbaNone;
3550  // wheel
3551  FWheel               := mwaScroll;
3552  FCtrlWheel           := mwaZoom;
3553  FAltWheel            := mwaScrollPageLessOne;
3554  FShiftWheel          := mwaScrollSingleLine;
3555  FAltCtrlWheel     := mwaNone;
3556  FShiftCtrlWheel       := mwaNone;
3557  FShiftAltWheel    := mwaNone;
3558  FShiftAltCtrlWheel    := mwaNone;
3559  // wheel
3560  FHorizWheel               := mwaScrollHoriz;
3561  FCtrlHorizWheel           := mwaNone;
3562  FAltHorizWheel            := mwaScrollHorizPageLessOne;
3563  FShiftHorizWheel          := mwaScrollHorizSingleLine;
3564  FAltCtrlHorizWheel     := mwaNone;
3565  FShiftCtrlHorizWheel       := mwaNone;
3566  FShiftAltHorizWheel    := mwaNone;
3567  FShiftAltCtrlHorizWheel    := mwaNone;
3568  // right
3569  FTextRightClick := mbaContextMenu;
3570  FTextAltCtrlRightClick := mbaNone;
3571  FTextAltRightClick := mbaNone;
3572  FTextCtrlRightClick := mbaContextMenuTab;
3573  FTextShiftAltCtrlRightClick := mbaNone;
3574  FTextShiftAltRightClick := mbaNone;
3575  FTextShiftCtrlRightClick := mbaNone;
3576  FTextShiftRightClick := mbaNone;
3577  // extra-1 click
3578  FTextExtra1Click := mbaHistoryBack;
3579  FTextAltCtrlExtra1Click := mbaNone;
3580  FTextAltExtra1Click := mbaNone;
3581  FTextCtrlExtra1Click := mbaNone;
3582  FTextShiftAltCtrlExtra1Click := mbaNone;
3583  FTextShiftAltExtra1Click := mbaNone;
3584  FTextShiftCtrlExtra1Click := mbaNone;
3585  FTextShiftExtra1Click := mbaNone;
3586  // extra-2 click
3587  FTextExtra2Click := mbaHistoryForw;
3588  FTextAltCtrlExtra2Click := mbaNone;
3589  FTextAltExtra2Click := mbaNone;
3590  FTextCtrlExtra2Click := mbaNone;
3591  FTextShiftAltCtrlExtra2Click := mbaNone;
3592  FTextShiftAltExtra2Click := mbaNone;
3593  FTextShiftCtrlExtra2Click := mbaNone;
3594  FTextShiftExtra2Click := mbaNone;
3595
3596  FTextRightMoveCaret  := False;
3597  FTextDrag            := True;
3598  FSelectOnLineNumbers := True;
3599end;
3600
3601procedure TEditorMouseOptions.ResetGutterToDefault;
3602  procedure AddStartSel(List: TSynEditMouseActions);
3603  begin
3604    with List do begin
3605      AddCommand(emcStartSelections,   True, mbXLeft, ccAny, cdDown, [],               [ssShift], emcoSelectionStart);
3606      AddCommand(emcStartSelections,   True, mbXLeft, ccAny, cdDown, [ssShift],        [ssShift], emcoSelectionContinue);
3607    end;
3608  end;
3609var
3610  CDir: TSynMAClickDir;
3611  R: TSynMAUpRestrictions;
3612begin
3613  FGutterActions.Clear;
3614  FGutterActionsFold.Clear;
3615  FGutterActionsFoldExp.Clear;
3616  FGutterActionsFoldCol.Clear;
3617  FGutterActionsLines.Clear;
3618  FGutterActionsChanges.Clear;
3619  FGutterActionsOverView.Clear;
3620  FGutterActionsOverViewMarks.Clear;
3621  //TMouseOptGutterLeftType = (moGLDownClick, moglUpClickAndSelect);
3622
3623  with FGutterActions do begin
3624    AddCommand(emcContextMenu,         False, mbXRight,  ccSingle, cdUp, [], []);
3625  end;
3626  with FGutterActionsFold do begin
3627    AddCommand(emcCodeFoldContextMenu, False, mbXRight,  ccSingle, cdUp, [], []);
3628  end;
3629
3630
3631  CDir := cdDown;
3632  R := [];
3633  if FGutterLeft = moglUpClickAndSelect then begin
3634    CDir := cdUp;
3635    R := crRestrictAll;
3636    AddStartSel(FGutterActions);
3637  end;
3638
3639  with FGutterActions do begin
3640    AddCommand(emcOnMainGutterClick,   False, mbXLeft,   ccAny,    CDir, R, [], []);  // breakpoint
3641  end;
3642
3643
3644  if FGutterLeft in [moglUpClickAndSelect, moglUpClickAndSelectRighHalf] then begin
3645    CDir := cdUp;
3646    R := crRestrictAll;
3647    AddStartSel(FGutterActionsChanges);
3648  end;
3649
3650  with FGutterActionsChanges do begin
3651    if FGutterLeft = moGLDownClick then
3652      AddCommand(emcNone,   False, mbXLeft,   ccAny,    cdDown, [], []);
3653    AddCommand(emcNone,   False, mbXLeft,   ccAny,    cdUp, [], []);
3654  end;
3655
3656
3657  if FGutterLeft = moglUpClickAndSelectRighHalf then begin
3658    if not FSelectOnLineNumbers then
3659      AddStartSel(FGutterActionsLines);
3660    AddStartSel(FGutterActionsFold);
3661  end;
3662
3663
3664  if FSelectOnLineNumbers then begin
3665    with FGutterActionsLines do begin
3666      AddCommand(emcStartLineSelectionsNoneEmpty,   True, mbXLeft, ccAny, cdDown, [],               [ssShift], emcoSelectionStart);
3667      AddCommand(emcStartLineSelectionsNoneEmpty,   True, mbXLeft, ccAny, cdDown, [ssShift],        [ssShift], emcoSelectionContinue);
3668      AddCommand(emcNone,   False, mbXLeft,   ccAny,    cdUp, [], []);
3669    end;
3670  end;
3671
3672  with FGutterActionsFold do begin
3673    AddCommand(emcNone,                False, mbXLeft,   ccAny,    CDir, R, [], []);
3674  end;
3675  with FGutterActionsFoldCol do begin
3676    AddCommand(emcCodeFoldCollaps,     False, mbXLeft,   ccAny,    CDir, R, [ssAlt],   [ssAlt, SYNEDIT_LINK_MODIFIER], emcoCodeFoldCollapsOne);
3677    AddCommand(emcCodeFoldExpand,      False, mbXLeft,   ccAny,    CDir, R, [SYNEDIT_LINK_MODIFIER],  [ssAlt, SYNEDIT_LINK_MODIFIER], emcoCodeFoldExpandAll);
3678    AddCommand(emcCodeFoldExpand,      False, mbXLeft,   ccAny,    CDir, R, [],        [],              emcoCodeFoldExpandOne);
3679    // TODO: why depend on FTextMiddleClick?
3680    if FTextMiddleClick <> mbaNone then
3681      AddCommand(emcCodeFoldCollaps,   False, mbXMiddle, ccAny,    CDir, R, [],       [],               emcoCodeFoldCollapsOne);
3682    // do not allow selection, over colapse/expand icons. Those may depend cursor pos (e.g. hide selected lines)
3683    if CDir = cdUp then
3684      AddCommand(emcNone,              False, mbXLeft,   ccAny,    cdDown, [], []);
3685  end;
3686  with FGutterActionsFoldExp do begin
3687    AddCommand(emcCodeFoldCollaps,     False, mbXLeft,   ccAny,    CDir, R, [],       [SYNEDIT_LINK_MODIFIER], emcoCodeFoldCollapsOne);
3688    AddCommand(emcCodeFoldCollaps,     False, mbXLeft,   ccAny,    CDir, R, [SYNEDIT_LINK_MODIFIER], [SYNEDIT_LINK_MODIFIER], emcoCodeFoldCollapsAll);
3689    // TODO: why depend on FTextMiddleClick?
3690    if FTextMiddleClick <> mbaNone then
3691      AddCommand(emcCodeFoldCollaps,   False, mbXMiddle, ccAny,    CDir, R, [],       [],       emcoCodeFoldCollapsOne);
3692    // do not allow selection, over colapse/expand icons. Those may depend cursor pos (e.g. hide selected lines)
3693    if CDir = cdUp then
3694      AddCommand(emcNone,              False, mbXLeft,   ccAny,    cdDown, [], []);
3695  end;
3696
3697  with FGutterActionsOverViewMarks do begin
3698    R := R - [crLastDownPosSameLine];
3699    if R <> [] then
3700      R := R + [crAllowFallback];
3701    AddCommand(emcOverViewGutterGotoMark, True, mbXLeft, ccAny,  CDir, R, [], [ssShift, ssCtrl, ssAlt]);
3702  end;
3703  with FGutterActionsOverView do begin
3704    if R <> [] then
3705      R := R + [crLastDownPosSearchAll];
3706    AddCommand(emcOverViewGutterScrollTo, True, mbXLeft, ccAny,  CDir, R, [], [ssShift, ssCtrl, ssAlt]);
3707  end;
3708
3709end;
3710
3711procedure TEditorMouseOptions.ResetTextToDefault;
3712
3713  procedure AddBtnClick(AnAction: TMouseOptButtonAction; const AButton: TSynMouseButton;
3714    AShift, AShiftMask: TShiftState; AddLinkDummy: Boolean = False;
3715    ASelContShift: TShiftState = []; AClickCount: TSynMAClickCount = ccSingle;
3716    AMoveCaret: Boolean = True; ADir: TSynMAClickDir = cdUp);
3717
3718      procedure AddSelCommand(const ACmd: TSynEditorMouseCommand);
3719      begin
3720        AShiftMask := AShiftMask + ASelContShift;
3721        FTextActions.AddCommand(  ACmd, True, AButton, AClickCount, cdDown, AShift,              AShiftMask, emcoSelectionStart);
3722        if ASelContShift <> [] then
3723          FTextActions.AddCommand(ACmd, True, AButton, AClickCount, cdDown, AShift+ASelContShift, AShiftMask, emcoSelectionContinue);
3724      end;
3725
3726  begin
3727    with FTextActions do begin
3728      case AnAction of
3729        mbaNone: {nothing};
3730        mbaSelect:       AddSelCommand(emcStartSelections);
3731        mbaSelectColumn: AddSelCommand(emcStartColumnSelections);
3732        mbaSelectLine:   AddSelCommand(emcStartLineSelections);
3733        //mbaSelectTokens: AddSelCommand(emcStartSelectTokens);
3734        //mbaSelectWords:  AddSelCommand(emcStartSelectWords);
3735        //mbaSelectLines:  AddSelCommand(emcStartSelectLines);
3736        //mbaSelectTokens: AddCommand(emcStartSelectTokens, True, AButton, AClickCount, cdDown, AShift, AShiftMask, emcoSelectionStart);
3737        mbaSelectWords:  AddCommand(emcStartSelectWords,  True, AButton, AClickCount, cdDown, AShift, AShiftMask, emcoSelectionStart);
3738        //mbaSelectLines:  AddCommand(emcStartSelectLines,  True, AButton, AClickCount, cdDown, AShift, AShiftMask, emcoSelectionStart);
3739        mbaSelectSetWord:
3740            AddCommand(emcSelectWord,       True,  AButton, AClickCount, ADir, AShift, AShiftMask);
3741        mbaSelectSetLineSmart:
3742            AddCommand(emcSelectLine,       True,  AButton, AClickCount, ADir, AShift, AShiftMask, emcoSelectLineSmart);
3743        mbaSelectSetLineFull:
3744            AddCommand(emcSelectLine,       True,  AButton, AClickCount, ADir, AShift, AShiftMask, emcoSelectLineFull);
3745        mbaSelectSetPara:
3746            AddCommand(emcSelectPara,       True,  AButton, AClickCount, ADir, AShift, AShiftMask);
3747        mbaPaste:            // TODOS act on up? but needs to prevent selection on down
3748            AddCommand(emcPasteSelection,   True,  AButton, AClickCount, cdDown,  AShift, AShiftMask, 0, 0, 0, True);
3749        mbaDeclarationJump,
3750        mbaDeclarationOrBlockJump: begin
3751            if AddLinkDummy then
3752              AddCommand(emcMouseLink,      False, AButton, AClickCount, ADir,    [SYNEDIT_LINK_MODIFIER], [SYNEDIT_LINK_MODIFIER], emcoMouseLinkShow, 999);
3753            AddCommand(emcMouseLink,        False, AButton, AClickCount, ADir,    AShift, AShiftMask);
3754            if AnAction = mbaDeclarationOrBlockJump then
3755              AddCommand(emcSynEditCommand, True,  AButton, AClickCount, ADir,    AShift, AShiftMask, ecFindBlockOtherEnd, 1);
3756          end;
3757        mbaAddHistoryPoint:
3758          AddCommand(emcSynEditCommand,     True,  AButton, AClickCount, ADir, AShift, AShiftMask, ecAddJumpPoint);
3759        mbaHistoryBack:
3760          AddCommand(emcSynEditCommand,     False, AButton, AClickCount, ADir, AShift, AShiftMask, ecJumpBack);
3761        mbaHistoryForw:
3762          AddCommand(emcSynEditCommand,     False, AButton, AClickCount, ADir, AShift, AShiftMask, ecJumpForward);
3763        mbaSetFreeBookmark:
3764          AddCommand(emcSynEditCommand,     True,  AButton, AClickCount, ADir, AShift, AShiftMask, ecSetFreeBookmark);
3765        mbaZoomReset: begin
3766            AddCommand(emcWheelZoomNorm,    False, AButton, AClickCount, ADir, AShift, AShiftMask);
3767            FMainActions.AddCommand(emcWheelZoomNorm,    False,  AButton, AClickCount, ADir, AShift, AShiftMask);
3768          end;
3769        mbaContextMenu:
3770            AddCommand(emcContextMenu, AMoveCaret, AButton, AClickCount, ADir, AShift, AShiftMask, emcoSelectionCaretMoveNever);
3771        mbaContextMenuDebug:
3772            AddCommand(emcContextMenu, True,       AButton, AClickCount, ADir, AShift, AShiftMask, emcoSelectionCaretMoveOutside, 0, 1);
3773        mbaContextMenuTab:
3774            AddCommand(emcContextMenu, True,       AButton, AClickCount, ADir, AShift, AShiftMask, emcoSelectionCaretMoveOutside, 0, 2);
3775        mbaMultiCaretToggle:
3776          begin
3777            AddCommand(emcPluginMultiCaretToggleCaret, False, AButton, AClickCount, ADir, AShift, AShiftMask);
3778            FSelActions.AddCommand(emcPluginMultiCaretSelectionToCarets, False, AButton, AClickCount, ADir, AShift, AShiftMask);
3779          end;
3780      end;
3781    end;
3782  end;
3783
3784  procedure AddWheelAct(AnAction: TMouseOptWheelAction; const AShift, AShiftMask: TShiftState; AnHorizontal: Boolean = False);
3785  var
3786    opt: TSynEditorMouseCommandOpt;
3787    opt2: integer;
3788    mbU, mbD: TSynMouseButton;
3789  begin
3790    if AnHorizontal then begin
3791      mbD := mbXWheelLeft;
3792      mbU := mbXWheelRight;
3793    end
3794    else begin
3795      mbD := mbXWheelDown;
3796      mbU := mbXWheelUp;
3797    end;
3798    opt2 := 0;
3799    with FMainActions do begin
3800      case AnAction of
3801        mwaNone: {nothing};
3802        mwaScroll:                 opt := emcoWheelScrollSystem;
3803        mwaScrollSingleLine:       opt := emcoWheelScrollLines;
3804        mwaScrollPage:             opt := emcoWheelScrollPages;
3805        mwaScrollPageLessOne:      opt := emcoWheelScrollPagesLessOne;
3806        mwaScrollHalfPage: begin
3807                                   opt := emcoWheelScrollPages;
3808                                   opt2 := 50;
3809          end;
3810        mwaScrollHoriz:            opt := emcoWheelScrollSystem;
3811        mwaScrollHorizSingleLine:  opt := emcoWheelScrollLines;
3812        mwaScrollHorizPage:        opt := emcoWheelScrollPages;
3813        mwaScrollHorizPageLessOne: opt := emcoWheelScrollPagesLessOne;
3814        mwaScrollHorizHalfPage: begin
3815                                   opt := emcoWheelScrollPages;
3816                                   opt2 := 50;
3817          end;
3818        mwaZoom: begin
3819            AddCommand(emcWheelZoomOut, False,  mbD, ccAny, cdDown, AShift, AShiftMask);
3820            AddCommand(emcWheelZoomIn,  False,  mbU,   ccAny, cdDown, AShift, AShiftMask);
3821          end;
3822      end;
3823
3824      if AnAction in [mwaScroll, mwaScrollSingleLine, mwaScrollPage, mwaScrollPageLessOne, mwaScrollHalfPage] then begin
3825        AddCommand(emcWheelVertScrollDown,       False,  mbD, ccAny, cdDown, AShift, AShiftMask, opt, 0, opt2);
3826        AddCommand(emcWheelVertScrollUp,         False,  mbU,   ccAny, cdDown, AShift, AShiftMask, opt, 0, opt2);
3827      end;
3828      if AnAction in [mwaScrollHoriz, mwaScrollHorizSingleLine, mwaScrollHorizPage, mwaScrollHorizPageLessOne, mwaScrollHorizHalfPage] then begin
3829        AddCommand(emcWheelHorizScrollDown,       False,  mbD, ccAny, cdDown, AShift, AShiftMask, opt, 0, opt2);
3830        AddCommand(emcWheelHorizScrollUp,         False,  mbU,   ccAny, cdDown, AShift, AShiftMask, opt, 0, opt2);
3831      end;
3832
3833    end;
3834  end;
3835
3836var
3837  ModKeys, SelKey: TShiftState;
3838begin
3839  FMainActions.Clear;
3840  FSelActions.Clear;
3841  FTextActions.Clear;
3842
3843  // Left Btn
3844  ModKeys := [ssShift];
3845  if FTextAltLeftClick     <> mbaNone then ModKeys := ModKeys + [ssAlt];
3846  if FTextCtrlLeftClick    <> mbaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3847  if FTextAltCtrlLeftClick <> mbaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3848  if FTextShiftAltLeftClick     <> mbaNone then ModKeys := ModKeys + [ssAlt];
3849  if FTextShiftCtrlLeftClick    <> mbaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3850  if FTextShiftAltCtrlLeftClick <> mbaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3851  if FTextAltDoubleLeftClick     <> mbaNone then ModKeys := ModKeys + [ssAlt];
3852  if FTextCtrlDoubleLeftClick    <> mbaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3853
3854  if FTextShiftLeftClick = mbaNone
3855  then SelKey := [ssShift]
3856  else SelKey := [];
3857  AddBtnClick(mbaSelect,                  mbXLeft,   [],                      ModKeys, False, SelKey);
3858  AddBtnClick(FTextShiftLeftClick,        mbXLeft,   [ssShift],               ModKeys, False, SelKey);
3859
3860  if FTextShiftCtrlLeftClick = mbaNone
3861  then SelKey := [ssShift]
3862  else SelKey := [];
3863  AddBtnClick(FTextCtrlLeftClick,         mbXLeft,   [SYNEDIT_LINK_MODIFIER],          ModKeys, False, SelKey);
3864  AddBtnClick(FTextShiftCtrlLeftClick,    mbXLeft,   [ssShift, SYNEDIT_LINK_MODIFIER], ModKeys, False, SelKey);
3865
3866  if FTextShiftAltLeftClick = mbaNone
3867  then SelKey := [ssShift]
3868  else SelKey := [];
3869  AddBtnClick(FTextAltLeftClick,          mbXLeft,   [ssAlt],                 ModKeys, False, SelKey);
3870  AddBtnClick(FTextShiftAltLeftClick,     mbXLeft,   [ssShift, ssAlt],               ModKeys, False, SelKey);
3871
3872  if FTextShiftAltCtrlLeftClick = mbaNone
3873  then SelKey := [ssShift]
3874  else SelKey := [];
3875  AddBtnClick(FTextAltCtrlLeftClick,      mbXLeft, [ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, SelKey);
3876  AddBtnClick(FTextShiftAltCtrlLeftClick, mbXLeft, [ssShift, ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, SelKey);
3877
3878  SelKey := [];
3879  AddBtnClick(FTextDoubleLeftClick,        mbXLeft,   [], ModKeys, False, SelKey, ccDouble);
3880  AddBtnClick(FTextTripleLeftClick,        mbXLeft,   [], ModKeys, False, SelKey, ccTriple);
3881  AddBtnClick(FTextQuadLeftClick,          mbXLeft,   [], ModKeys, False, SelKey, ccQuad);
3882  AddBtnClick(FTextShiftDoubleLeftClick,   mbXLeft,   [ssShift],               ModKeys, False, SelKey, ccDouble);
3883  AddBtnClick(FTextCtrlDoubleLeftClick,    mbXLeft,   [SYNEDIT_LINK_MODIFIER], ModKeys, False, SelKey, ccDouble);
3884  AddBtnClick(FTextAltDoubleLeftClick,     mbXLeft,   [ssAlt],                 ModKeys, False, SelKey, ccDouble);
3885
3886
3887  SelKey := [];
3888  ModKeys := [];
3889  if FTextShiftMiddleClick         <> mbaNone then ModKeys := ModKeys + [ssShift];
3890  if FTextCtrlMiddleClick          <> mbaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3891  if FTextAltMiddleClick           <> mbaNone then ModKeys := ModKeys + [ssAlt];
3892  if FTextAltCtrlMiddleClick       <> mbaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3893  if FTextShiftCtrlMiddleClick     <> mbaNone then ModKeys := ModKeys + [ssShift] + [SYNEDIT_LINK_MODIFIER];
3894  if FTextShiftAltMiddleClick      <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt];
3895  if FTextShiftAltCtrlMiddleClick  <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt] + [SYNEDIT_LINK_MODIFIER];
3896  AddBtnClick(FTextMiddleClick,     mbXMiddle, [], ModKeys, FTextCtrlMiddleClick = mbaNone);
3897  AddBtnClick(FTextShiftMiddleClick,mbXMiddle, [ssShift], ModKeys);
3898  AddBtnClick(FTextAltMiddleClick,  mbXMiddle, [ssAlt], ModKeys);
3899  AddBtnClick(FTextCtrlMiddleClick, mbXMiddle, [SYNEDIT_LINK_MODIFIER], ModKeys);
3900  AddBtnClick(FTextAltCtrlMiddleClick,      mbXMiddle, [ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys);
3901  AddBtnClick(FTextShiftCtrlMiddleClick,    mbXMiddle, [ssShift, SYNEDIT_LINK_MODIFIER], ModKeys);
3902  AddBtnClick(FTextShiftAltMiddleClick,     mbXMiddle, [ssShift, ssAlt], ModKeys);
3903  AddBtnClick(FTextShiftAltCtrlMiddleClick, mbXMiddle, [ssShift, ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys);
3904
3905  SelKey := [];
3906  ModKeys := [];
3907  if FTextShiftRightClick         <> mbaNone then ModKeys := ModKeys + [ssShift];
3908  if FTextCtrlRightClick          <> mbaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3909  if FTextAltRightClick           <> mbaNone then ModKeys := ModKeys + [ssAlt];
3910  if FTextAltCtrlRightClick       <> mbaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3911  if FTextShiftCtrlRightClick     <> mbaNone then ModKeys := ModKeys + [ssShift] + [SYNEDIT_LINK_MODIFIER];
3912  if FTextShiftAltRightClick      <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt];
3913  if FTextShiftAltCtrlRightClick  <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt] + [SYNEDIT_LINK_MODIFIER];
3914  AddBtnClick(FTextRightClick,     mbXRight, [], ModKeys, FTextCtrlRightClick = mbaNone, [], ccSingle, FTextRightMoveCaret);
3915  AddBtnClick(FTextShiftRightClick,mbXRight, [ssShift], ModKeys, False, [], ccSingle, FTextRightMoveCaret);
3916  AddBtnClick(FTextAltRightClick,  mbXRight, [ssAlt], ModKeys, False, [], ccSingle, FTextRightMoveCaret);
3917  AddBtnClick(FTextCtrlRightClick, mbXRight, [SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, FTextRightMoveCaret);
3918  AddBtnClick(FTextAltCtrlRightClick,      mbXRight, [ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, FTextRightMoveCaret);
3919  AddBtnClick(FTextShiftCtrlRightClick,    mbXRight, [ssShift, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, FTextRightMoveCaret);
3920  AddBtnClick(FTextShiftAltRightClick,     mbXRight, [ssShift, ssAlt], ModKeys, False, [], ccSingle, FTextRightMoveCaret);
3921  AddBtnClick(FTextShiftAltCtrlRightClick, mbXRight, [ssShift, ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, FTextRightMoveCaret);
3922
3923  SelKey := [];
3924  ModKeys := [];
3925  if FTextShiftExtra1Click         <> mbaNone then ModKeys := ModKeys + [ssShift];
3926  if FTextCtrlExtra1Click          <> mbaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3927  if FTextAltExtra1Click           <> mbaNone then ModKeys := ModKeys + [ssAlt];
3928  if FTextAltCtrlExtra1Click       <> mbaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3929  if FTextShiftCtrlExtra1Click     <> mbaNone then ModKeys := ModKeys + [ssShift] + [SYNEDIT_LINK_MODIFIER];
3930  if FTextShiftAltExtra1Click      <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt];
3931  if FTextShiftAltCtrlExtra1Click  <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt] + [SYNEDIT_LINK_MODIFIER];
3932  AddBtnClick(FTextExtra1Click,     mbXExtra1, [], ModKeys, FTextCtrlExtra1Click = mbaNone, [], ccSingle, True, cdDown);
3933  AddBtnClick(FTextShiftExtra1Click,mbXExtra1, [ssShift], ModKeys, False, [], ccSingle, True, cdDown);
3934  AddBtnClick(FTextAltExtra1Click,  mbXExtra1, [ssAlt], ModKeys, False, [], ccSingle, True, cdDown);
3935  AddBtnClick(FTextCtrlExtra1Click, mbXExtra1, [SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3936  AddBtnClick(FTextAltCtrlExtra1Click,      mbXExtra1, [ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3937  AddBtnClick(FTextShiftCtrlExtra1Click,    mbXExtra1, [ssShift, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3938  AddBtnClick(FTextShiftAltExtra1Click,     mbXExtra1, [ssShift, ssAlt], ModKeys, False, [], ccSingle, True, cdDown);
3939  AddBtnClick(FTextShiftAltCtrlExtra1Click, mbXExtra1, [ssShift, ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3940
3941  // TODO: on w32 extra btn do not call mouse up
3942  SelKey := [];
3943  ModKeys := [];
3944  if FTextShiftExtra2Click         <> mbaNone then ModKeys := ModKeys + [ssShift];
3945  if FTextCtrlExtra2Click          <> mbaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3946  if FTextAltExtra2Click           <> mbaNone then ModKeys := ModKeys + [ssAlt];
3947  if FTextAltCtrlExtra2Click       <> mbaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3948  if FTextShiftCtrlExtra2Click     <> mbaNone then ModKeys := ModKeys + [ssShift] + [SYNEDIT_LINK_MODIFIER];
3949  if FTextShiftAltExtra2Click      <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt];
3950  if FTextShiftAltCtrlExtra2Click  <> mbaNone then ModKeys := ModKeys + [ssShift, ssAlt] + [SYNEDIT_LINK_MODIFIER];
3951  AddBtnClick(FTextExtra2Click,     mbXExtra2, [], ModKeys, FTextCtrlExtra2Click = mbaNone, [], ccSingle, True, cdDown);
3952  AddBtnClick(FTextShiftExtra2Click,mbXExtra2, [ssShift], ModKeys, False, [], ccSingle, True, cdDown);
3953  AddBtnClick(FTextAltExtra2Click,  mbXExtra2, [ssAlt], ModKeys, False, [], ccSingle, True, cdDown);
3954  AddBtnClick(FTextCtrlExtra2Click, mbXExtra2, [SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3955  AddBtnClick(FTextAltCtrlExtra2Click,      mbXExtra2, [ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3956  AddBtnClick(FTextShiftCtrlExtra2Click,    mbXExtra2, [ssShift, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3957  AddBtnClick(FTextShiftAltExtra2Click,     mbXExtra2, [ssShift, ssAlt], ModKeys, False, [], ccSingle, True, cdDown);
3958  AddBtnClick(FTextShiftAltCtrlExtra2Click, mbXExtra2, [ssShift, ssAlt, SYNEDIT_LINK_MODIFIER], ModKeys, False, [], ccSingle, True, cdDown);
3959
3960  ModKeys := [];
3961  if FShiftWheel         <> mwaNone then ModKeys := ModKeys + [ssShift];
3962  if FCtrlWheel          <> mwaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3963  if FAltWheel           <> mwaNone then ModKeys := ModKeys + [ssAlt];
3964  if FAltCtrlWheel       <> mwaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3965  if FShiftCtrlWheel     <> mwaNone then ModKeys := ModKeys + [ssShift] + [SYNEDIT_LINK_MODIFIER];
3966  if FShiftAltWheel      <> mwaNone then ModKeys := ModKeys + [ssShift, ssAlt];
3967  if FShiftAltCtrlWheel  <> mwaNone then ModKeys := ModKeys + [ssShift, ssAlt] + [SYNEDIT_LINK_MODIFIER];
3968  AddWheelAct(FWheel, [], []);
3969  AddWheelAct(FCtrlWheel,  [ssCtrl],  ModKeys);
3970  AddWheelAct(FAltWheel,   [ssAlt],   ModKeys);
3971  AddWheelAct(FShiftWheel, [ssShift], ModKeys);
3972  AddWheelAct(FAltCtrlWheel,      [ssAlt, ssCtrl], ModKeys);
3973  AddWheelAct(FShiftCtrlWheel,    [ssShift, ssCtrl], ModKeys);
3974  AddWheelAct(FShiftAltWheel,     [ssShift, ssAlt], ModKeys);
3975  AddWheelAct(FShiftAltCtrlWheel, [ssShift, ssAlt, ssCtrl], ModKeys);
3976
3977  ModKeys := [];
3978  if FShiftHorizWheel         <> mwaNone then ModKeys := ModKeys + [ssShift];
3979  if FCtrlHorizWheel          <> mwaNone then ModKeys := ModKeys + [SYNEDIT_LINK_MODIFIER];
3980  if FAltHorizWheel           <> mwaNone then ModKeys := ModKeys + [ssAlt];
3981  if FAltCtrlHorizWheel       <> mwaNone then ModKeys := ModKeys + [ssAlt] + [SYNEDIT_LINK_MODIFIER];
3982  if FShiftCtrlHorizWheel     <> mwaNone then ModKeys := ModKeys + [ssShift] + [SYNEDIT_LINK_MODIFIER];
3983  if FShiftAltHorizWheel      <> mwaNone then ModKeys := ModKeys + [ssShift, ssAlt];
3984  if FShiftAltCtrlHorizWheel  <> mwaNone then ModKeys := ModKeys + [ssShift, ssAlt] + [SYNEDIT_LINK_MODIFIER];
3985  AddWheelAct(FHorizWheel, [], [], True);
3986  AddWheelAct(FCtrlHorizWheel,  [ssCtrl],  ModKeys, True);
3987  AddWheelAct(FAltHorizWheel,   [ssAlt],   ModKeys, True);
3988  AddWheelAct(FShiftHorizWheel, [ssShift], ModKeys, True);
3989  AddWheelAct(FAltCtrlHorizWheel,      [ssAlt, ssCtrl], ModKeys, True);
3990  AddWheelAct(FShiftCtrlHorizWheel,    [ssShift, ssCtrl], ModKeys, True);
3991  AddWheelAct(FShiftAltHorizWheel,     [ssShift, ssAlt], ModKeys, True);
3992  AddWheelAct(FShiftAltCtrlHorizWheel, [ssShift, ssAlt, ssCtrl], ModKeys, True);
3993
3994  if FTextDrag then
3995    FSelActions.AddCommand(emcStartDragMove, False, mbXLeft, ccSingle, cdDown,
3996                           [], [ssShift], emcoNotDragedNoCaretOnUp);
3997  FTextActions.AddCommand(emcNone, True, mbXLeft, ccSingle, cdUp, [], [], 0, 99);
3998end;
3999
4000procedure TEditorMouseOptions.ResetToUserScheme;
4001var
4002  i: LongInt;
4003begin
4004  i := SelectedUserSchemeIndex;
4005  if i < 0 then exit;
4006  AssignActions(UserSchemesAtPos[i]);
4007end;
4008
4009procedure TEditorMouseOptions.AssignActions(Src: TEditorMouseOptions);
4010begin
4011  FMainActions.Assign         (Src.MainActions);
4012  FSelActions.Assign          (Src.SelActions);
4013  FTextActions.Assign         (Src.TextActions);
4014  FGutterActions.Assign       (Src.GutterActions);
4015  FGutterActionsFold.Assign   (Src.GutterActionsFold);
4016  FGutterActionsFoldExp.Assign(Src.GutterActionsFoldExp);
4017  FGutterActionsFoldCol.Assign(Src.GutterActionsFoldCol);
4018  FGutterActionsLines.Assign  (Src.GutterActionsLines);
4019  FGutterActionsChanges.Assign(Src.GutterActionsChanges);
4020  FGutterActionsOverView.Assign(Src.GutterActionsOverView);
4021  FGutterActionsOverViewMarks.Assign(Src.GutterActionsOverViewMarks);
4022end;
4023
4024procedure TEditorMouseOptions.SetTextCtrlLeftClick(AValue: TMouseOptButtonActionOld);
4025begin
4026  // upgrade old values
4027  if AValue in [low(MouseOptButtonActionOld)..high(MouseOptButtonActionOld)] then
4028    AValue := MouseOptButtonActionOld[AValue];
4029  if FTextCtrlLeftClick = AValue then Exit;
4030  FTextCtrlLeftClick := AValue;
4031end;
4032
4033procedure TEditorMouseOptions.SetTextMiddleClick(AValue: TMouseOptButtonActionOld);
4034begin
4035  // upgrade old values
4036  if AValue in [low(MouseOptButtonActionOld)..high(MouseOptButtonActionOld)] then
4037    AValue := MouseOptButtonActionOld[AValue];
4038  if FTextMiddleClick = AValue then Exit;
4039  FTextMiddleClick := AValue;
4040end;
4041
4042procedure TEditorMouseOptions.AssignEx(Src: TEditorMouseOptions; WithUserSchemes: Boolean);
4043var
4044  i: Integer;
4045  Opt: TEditorMouseOptions;
4046begin
4047  FName                 := Src.FName;
4048  FGutterLeft           := Src.GutterLeft;
4049  FSelectOnLineNumbers  := Src.SelectOnLineNumbers;
4050  FTextDrag             := Src.TextDrag;
4051  FTextRightMoveCaret   := Src.TextRightMoveCaret;
4052  FSelectedUserScheme   := Src.FSelectedUserScheme;
4053
4054    // left multi click
4055  FTextDoubleLeftClick       := Src.TextDoubleLeftClick;
4056  FTextTripleLeftClick       := Src.TextTripleLeftClick;
4057  FTextQuadLeftClick         := Src.TextQuadLeftClick;
4058  FTextShiftDoubleLeftClick  := Src.TextShiftDoubleLeftClick;
4059  FTextAltDoubleLeftClick    := Src.TextAltDoubleLeftClick;
4060  FTextCtrlDoubleLeftClick   := Src.TextCtrlDoubleLeftClick;
4061    // left + modifier click
4062  FTextAltLeftClick          := Src.TextAltLeftClick;
4063  FTextCtrlLeftClick         := Src.TextCtrlLeftClick;
4064  FTextAltCtrlLeftClick      := Src.TextAltCtrlLeftClick;
4065  FTextShiftLeftClick        := Src.TextShiftLeftClick;
4066  FTextShiftAltLeftClick     := Src.TextShiftAltLeftClick;
4067  FTextShiftCtrlLeftClick    := Src.TextShiftCtrlLeftClick;
4068  FTextShiftAltCtrlLeftClick := Src.TextShiftAltCtrlLeftClick;
4069    // middle click
4070  FTextMiddleClick           := Src.TextMiddleClick;
4071  FTextAltMiddleClick        := Src.TextAltMiddleClick;
4072  FTextCtrlMiddleClick       := Src.TextCtrlMiddleClick;
4073  FTextShiftMiddleClick      := Src.TextShiftMiddleClick;
4074  FTextAltCtrlMiddleClick      := Src.TextAltCtrlMiddleClick;
4075  FTextShiftAltMiddleClick     := Src.TextShiftAltMiddleClick;
4076  FTextShiftCtrlMiddleClick    := Src.TextShiftCtrlMiddleClick;
4077  FTextShiftAltCtrlMiddleClick := Src.TextShiftAltCtrlMiddleClick;
4078  // wheel
4079  FWheel                := Src.Wheel;
4080  FCtrlWheel            := Src.CtrlWheel;
4081  FAltWheel             := Src.AltWheel;
4082  FShiftWheel           := Src.ShiftWheel;
4083  FAltCtrlWheel         := Src.AltCtrlWheel;
4084  FShiftCtrlWheel       := Src.ShiftCtrlWheel;
4085  FShiftAltWheel        := Src.ShiftAltWheel;
4086  FShiftAltCtrlWheel    := Src.ShiftAltCtrlWheel;
4087  // wheel
4088  FHorizWheel                := Src.HorizWheel;
4089  FCtrlHorizWheel            := Src.CtrlHorizWheel;
4090  FAltHorizWheel             := Src.AltHorizWheel;
4091  FShiftHorizWheel           := Src.ShiftHorizWheel;
4092  FAltCtrlHorizWheel         := Src.AltCtrlHorizWheel;
4093  FShiftCtrlHorizWheel       := Src.ShiftCtrlHorizWheel;
4094  FShiftAltHorizWheel        := Src.ShiftAltHorizWheel;
4095  FShiftAltCtrlHorizWheel    := Src.ShiftAltCtrlHorizWheel;
4096  // right
4097  FTextAltCtrlRightClick := Src.TextAltCtrlRightClick;
4098  FTextAltRightClick := Src.TextAltRightClick;
4099  FTextCtrlRightClick := Src.TextCtrlRightClick;
4100  FTextRightClick := Src.TextRightClick;
4101  FTextShiftAltCtrlRightClick := Src.TextShiftAltCtrlRightClick;
4102  FTextShiftAltRightClick := Src.TextShiftAltRightClick;
4103  FTextShiftCtrlRightClick := Src.TextShiftCtrlRightClick;
4104  FTextShiftRightClick := Src.TextShiftRightClick;
4105  // extra-1 click
4106  FTextAltCtrlExtra1Click := Src.TextAltCtrlExtra1Click;
4107  FTextAltExtra1Click := Src.TextAltExtra1Click;
4108  FTextCtrlExtra1Click := Src.TextCtrlExtra1Click;
4109  FTextExtra1Click := Src.TextExtra1Click;
4110  FTextShiftAltCtrlExtra1Click := Src.TextShiftAltCtrlExtra1Click;
4111  FTextShiftAltExtra1Click := Src.TextShiftAltExtra1Click;
4112  FTextShiftCtrlExtra1Click := Src.TextShiftCtrlExtra1Click;
4113  FTextShiftExtra1Click := Src.TextShiftExtra1Click;
4114  // extra-2 click
4115  FTextAltCtrlExtra2Click := Src.TextAltCtrlExtra2Click;
4116  FTextAltExtra2Click := Src.TextAltExtra2Click;
4117  FTextCtrlExtra2Click := Src.TextCtrlExtra2Click;
4118  FTextExtra2Click := Src.TextExtra2Click;
4119  FTextShiftAltCtrlExtra2Click := Src.TextShiftAltCtrlExtra2Click;
4120  FTextShiftAltExtra2Click := Src.TextShiftAltExtra2Click;
4121  FTextShiftCtrlExtra2Click := Src.TextShiftCtrlExtra2Click;
4122  FTextShiftExtra2Click := Src.TextShiftExtra2Click;
4123
4124  AssignActions(Src);
4125
4126  if WithUserSchemes then begin
4127    ClearUserSchemes;
4128    for i := 0 to Src.FUserSchemes.Count - 1 do begin
4129      Opt := TEditorMouseOptions.Create;
4130      Opt.Assign(TEditorMouseOptions(Src.FUserSchemes.Objects[i]));
4131      FUserSchemes.AddObject(Src.FUserSchemes[i], Opt);
4132    end;
4133  end;
4134end;
4135
4136procedure TEditorMouseOptions.Assign(Src: TEditorMouseOptions);
4137begin
4138  AssignEx(Src, True);
4139end;
4140
4141function TEditorMouseOptions.IsPresetEqualToMouseActions: Boolean;
4142var
4143  Temp: TEditorMouseOptions;
4144  i: Integer;
4145begin
4146  i := SelectedUserSchemeIndex;
4147  Temp := TEditorMouseOptions.Create;
4148  Temp.AssignEx(self, i >= 0);
4149  if i >= 0 then begin
4150    Temp.ResetToUserScheme;
4151  end else begin
4152    Temp.ResetTextToDefault;
4153    Temp.ResetGutterToDefault;
4154  end;
4155  Result :=
4156    Temp.MainActions.Equals(self.MainActions) and
4157    Temp.SelActions.Equals (self.SelActions) and
4158    Temp.TextActions.Equals (self.TextActions) and
4159    Temp.GutterActions.Equals       (self.GutterActions) and
4160    Temp.GutterActionsFold.Equals   (self.GutterActionsFold) and
4161    Temp.GutterActionsFoldCol.Equals(self.GutterActionsFoldCol) and
4162    Temp.GutterActionsFoldExp.Equals(self.GutterActionsFoldExp) and
4163    Temp.GutterActionsLines.Equals  (self.GutterActionsLines) and
4164    Temp.GutterActionsChanges.Equals(Self.GutterActionsChanges) and
4165    Temp.GutterActionsOverView.Equals(Self.GutterActionsOverView) and
4166    Temp.GutterActionsOverViewMarks.Equals(Self.GutterActionsOverViewMarks);
4167  Temp.Free;
4168end;
4169
4170function TEditorMouseOptions.CalcCustomSavedActions: Boolean;
4171begin
4172  Result := not IsPresetEqualToMouseActions;
4173  FCustomSavedActions := Result;
4174end;
4175
4176procedure TEditorMouseOptions.LoadFromXml(aXMLConfig: TRttiXMLConfig; aPath: String;
4177  aOldPath: String; FileVersion: Integer);
4178
4179  Procedure LoadMouseAct(Path: String; MActions: TSynEditMouseActions);
4180  var
4181    c, i: Integer;
4182    MAct: TSynEditMouseActionKeyCmdHelper;
4183    //ErrShown: Boolean;
4184  begin
4185    //ErrShown := False;
4186    MActions.Clear;
4187    MAct := TSynEditMouseActionKeyCmdHelper.Create(nil);
4188
4189    c := aXMLConfig.GetValue(Path + 'Count', 0);
4190    for i := 0 to c - 1 do begin
4191      try
4192        MActions.IncAssertLock;
4193        try
4194          // If the object would ever be extended, old configs will not have all properties.
4195          Mact.Clear;
4196          aXMLConfig.ReadObject(Path + 'M' + IntToStr(i) + '/', MAct);
4197          MActions.Add.Assign(MAct);
4198        finally
4199          MActions.DecAssertLock;
4200        end;
4201        MActions.AssertNoConflict(MAct);
4202      except
4203        MActions.Delete(MActions.Count-1);
4204        //if not ErrShown then
4205        //  IDEMessageDialog(dlgMouseOptErrorDup, dlgMouseOptErrorDupText, mtError, [mbOk]);
4206        //ErrShown := True;
4207      end;
4208    end;
4209    MAct.Free;
4210  end;
4211
4212var
4213  AltColumnMode: Boolean;
4214  TextDoubleSelLine: Boolean;
4215begin
4216  Reset;
4217  if FileVersion < 11 then
4218    FGutterLeft := moGLDownClick;
4219  AltColumnMode := False;
4220  TextDoubleSelLine := False;
4221  if aOldPath <> '' then begin
4222    // Read deprecated value
4223    // It is on by default, so only if a user switched it off, actions is required
4224    if not aXMLConfig.GetValue(aOldPath + 'DragDropEditing', True) then
4225      TextDrag := False;
4226    aXMLConfig.DeleteValue(aOldPath + 'DragDropEditing');
4227
4228    if aXMLConfig.GetValue(aOldPath + 'AltSetsColumnMode', False) then
4229      AltColumnMode := True;
4230    aXMLConfig.DeleteValue(aOldPath + 'AltSetsColumnMode');
4231
4232    if not aXMLConfig.GetValue(aOldPath + 'CtrlMouseLinks', True) then
4233      TextCtrlLeftClick := mbaNone;
4234    aXMLConfig.DeleteValue(aOldPath + 'CtrlMouseLinks');
4235
4236    if aXMLConfig.GetValue(aOldPath + 'DoubleClickSelectsLine', False) then
4237      TextDoubleSelLine := True;
4238    aXMLConfig.DeleteValue(aOldPath + 'DoubleClickSelectsLine');
4239  end;
4240
4241  //AltColumnMode, before TextAltLeftClick
4242  if (not AltColumnMode) then
4243    AltColumnMode := aXMLConfig.GetValue(aPath + 'Default/AltColumnMode', True);
4244  aXMLConfig.DeleteValue(aPath + 'Default/AltColumnMode');
4245
4246  if (not AltColumnMode) then
4247    TextAltLeftClick := mbaNone;
4248
4249  if aXMLConfig.GetValue(aPath + 'Default/TextDoubleSelLine', TextDoubleSelLine) then begin
4250    FTextDoubleLeftClick       := mbaSelectSetLineSmart;
4251    FTextTripleLeftClick       := mbaSelectSetLineFull;
4252  end;
4253  aXMLConfig.DeleteValue(aPath + 'Default/TextDoubleSelLine');
4254
4255  CustomSavedActions := False;
4256  aXMLConfig.ReadObject(aPath + 'Default/', Self);
4257
4258  if (FSelectedUserScheme <> '') and (UserSchemes[FSelectedUserScheme] = nil) then
4259    FSelectedUserScheme := '';
4260
4261  if CustomSavedActions then begin
4262    // Load
4263    LoadMouseAct(aPath + 'Main/',          MainActions);
4264    LoadMouseAct(aPath + 'MainText/',      TextActions);
4265    LoadMouseAct(aPath + 'MainSelection/', SelActions);
4266    LoadMouseAct(aPath + 'Gutter/',        GutterActions);
4267    LoadMouseAct(aPath + 'GutterFold/',    GutterActionsFold);
4268    LoadMouseAct(aPath + 'GutterFoldExp/', GutterActionsFoldExp);
4269    LoadMouseAct(aPath + 'GutterFoldCol/', GutterActionsFoldCol);
4270    LoadMouseAct(aPath + 'GutterLineNum/', GutterActionsLines);
4271    LoadMouseAct(aPath + 'GutterLineChange/', GutterActionsChanges);
4272    LoadMouseAct(aPath + 'GutterOverView/',   GutterActionsOverView);
4273    LoadMouseAct(aPath + 'GutterOverViewMarks/',   GutterActionsOverViewMarks);
4274
4275    if Version < 1 then begin
4276      try
4277        FMainActions.AddCommand(emcWheelVertScrollDown,       False,  mbXWheelDown, ccAny, cdDown, [], []);
4278        FMainActions.AddCommand(emcWheelVertScrollUp,         False,  mbXWheelUp,   ccAny, cdDown, [], []);
4279        FMainActions.AddCommand(emcWheelHorizScrollDown,      False,  mbXWheelLeft, ccAny, cdDown, [], []);
4280        FMainActions.AddCommand(emcWheelHorizScrollUp,        False,  mbXWheelRight,ccAny, cdDown, [], []);
4281      except
4282      end;
4283    end;
4284  end
4285  else
4286  if (FSelectedUserScheme <> '') then begin
4287    ResetToUserScheme;
4288  end else begin
4289    ResetTextToDefault;
4290    ResetGutterToDefault;
4291  end;
4292end;
4293
4294procedure TEditorMouseOptions.SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String);
4295
4296  Procedure SaveMouseAct(Path: String; MActions: TSynEditMouseActions);
4297  var
4298    i, OldCnt: Integer;
4299    MAct: TSynEditMouseActionKeyCmdHelper;
4300  begin
4301    MAct := TSynEditMouseActionKeyCmdHelper.Create(nil);
4302    OldCnt := aXMLConfig.GetValue(Path + 'Count', 0);
4303    for i := 0 to MActions.Count - 1 do begin
4304      if MActions[i].Command = emcSynEditCommand then begin
4305        MAct.Assign(MActions[i]);
4306        aXMLConfig.WriteObject(Path + 'M' + IntToStr(i) + '/', MAct);
4307      end else
4308        aXMLConfig.WriteObject(Path + 'M' + IntToStr(i) + '/', MActions[i]);
4309    end;
4310    aXMLConfig.SetDeleteValue(Path + 'Count', MActions.Count,0);
4311    for i := MActions.Count to OldCnt do
4312      aXMLConfig.DeletePath(Path + 'M' + IntToStr(i));
4313    MAct.Free;
4314  end;
4315
4316var
4317  DefMouseSettings: TEditorMouseOptions;
4318begin
4319  FVersion := EditorMouseOptsFormatVersion;
4320  DefMouseSettings := TEditorMouseOptions.Create;
4321  CalcCustomSavedActions;
4322  aXMLConfig.WriteObject(aPath + 'Default/', Self, DefMouseSettings);
4323  DefMouseSettings.Free;
4324  if CustomSavedActions then begin
4325    // Save full settings / based on empty
4326    SaveMouseAct(aPath + 'Main/',          MainActions);
4327    SaveMouseAct(aPath + 'MainText/',      TextActions);
4328    SaveMouseAct(aPath + 'MainSelection/', SelActions);
4329    SaveMouseAct(aPath + 'Gutter/',        GutterActions);
4330    SaveMouseAct(aPath + 'GutterFold/',    GutterActionsFold);
4331    SaveMouseAct(aPath + 'GutterFoldExp/', GutterActionsFoldExp);
4332    SaveMouseAct(aPath + 'GutterFoldCol/', GutterActionsFoldCol);
4333    SaveMouseAct(aPath + 'GutterLineNum/', GutterActionsLines);
4334    SaveMouseAct(aPath + 'GutterLineChange/', GutterActionsChanges);
4335    SaveMouseAct(aPath + 'GutterOverView/',   GutterActionsOverView);
4336    SaveMouseAct(aPath + 'GutterOverViewMarks/',GutterActionsOverViewMarks);
4337  end else begin
4338    // clear unused entries
4339    aXMLConfig.DeletePath(aPath + 'Main');
4340    aXMLConfig.DeletePath(aPath + 'MainSelection');
4341    aXMLConfig.DeletePath(aPath + 'Gutter');
4342    aXMLConfig.DeletePath(aPath + 'GutterFold');
4343    aXMLConfig.DeletePath(aPath + 'GutterFoldExp');
4344    aXMLConfig.DeletePath(aPath + 'GutterFoldCol');
4345    aXMLConfig.DeletePath(aPath + 'GutterLineNum');
4346  end;
4347end;
4348
4349procedure TEditorMouseOptions.ImportFromXml(aXMLConfig: TRttiXMLConfig; aPath: String);
4350
4351  Procedure LoadMouseAct(Path: String; MActions: TSynEditMouseActions);
4352  var
4353    i, c: Integer;
4354    MAct: TSynEditMouseActionKeyCmdHelper;
4355  begin
4356    MActions.Clear;
4357    MAct := TSynEditMouseActionKeyCmdHelper.Create(nil);
4358    c := aXMLConfig.GetValue(Path + 'Count', 0);
4359    for i := 0 to c - 1 do begin
4360      try
4361        MActions.IncAssertLock;
4362        try
4363          Mact.Clear;
4364          aXMLConfig.ReadObject(Path + 'M' + IntToStr(i) + '/', MAct);
4365          MActions.Add.Assign(MAct);
4366        finally
4367          MActions.DecAssertLock;
4368        end;
4369        MActions.AssertNoConflict(MAct);
4370      except
4371        MActions.Delete(MActions.Count-1);
4372        IDEMessageDialog(dlgMouseOptErrorDup, dlgMouseOptErrorDupText + LineEnding
4373                   + Path + 'M' + IntToStr(i) + LineEnding + MAct.DisplayName,
4374                   mtError, [mbOk]);
4375      end;
4376    end;
4377    Mact.Free;
4378  end;
4379
4380begin
4381  LoadMouseAct(aPath + 'Main/',          MainActions);
4382  LoadMouseAct(aPath + 'MainText/',      TextActions);
4383  LoadMouseAct(aPath + 'MainSel/',       SelActions);
4384  LoadMouseAct(aPath + 'Gutter/',        GutterActions);
4385  LoadMouseAct(aPath + 'GutterFold/',    GutterActionsFold);
4386  LoadMouseAct(aPath + 'GutterFoldExp/', GutterActionsFoldExp);
4387  LoadMouseAct(aPath + 'GutterFoldCol/', GutterActionsFoldCol);
4388  LoadMouseAct(aPath + 'GutterLineNum/', GutterActionsLines);
4389  LoadMouseAct(aPath + 'GutterLineChange/', GutterActionsChanges);
4390  LoadMouseAct(aPath + 'GutterOverView/',   GutterActionsOverView);
4391  LoadMouseAct(aPath + 'GutterOverViewMarks/',GutterActionsOverViewMarks);
4392end;
4393
4394procedure TEditorMouseOptions.ExportToXml(aXMLConfig: TRttiXMLConfig; aPath: String);
4395var
4396  MAct: TSynEditMouseActionKeyCmdHelper;
4397
4398  Procedure SaveMouseAct(Path: String; MActions: TSynEditMouseActions);
4399  var
4400    i: Integer;
4401  begin
4402    for i := 0 to MActions.Count - 1 do
4403      if MActions[i].Command = emcSynEditCommand then begin
4404        MAct.Assign(MActions[i]);
4405        aXMLConfig.WriteObject(Path + 'M' + IntToStr(i) + '/', MAct);
4406      end
4407      else
4408        aXMLConfig.WriteObject(Path + 'M' + IntToStr(i) + '/', MActions[i]);
4409    aXMLConfig.SetDeleteValue(Path + 'Count', MActions.Count,0);
4410  end;
4411
4412begin
4413  MAct := TSynEditMouseActionKeyCmdHelper.Create(nil);
4414  SaveMouseAct(aPath + 'Main/',          MainActions);
4415  SaveMouseAct(aPath + 'MainText/',      TextActions);
4416  SaveMouseAct(aPath + 'MainSel/',       SelActions);
4417  SaveMouseAct(aPath + 'Gutter/',        GutterActions);
4418  SaveMouseAct(aPath + 'GutterFold/',    GutterActionsFold);
4419  SaveMouseAct(aPath + 'GutterFoldExp/', GutterActionsFoldExp);
4420  SaveMouseAct(aPath + 'GutterFoldCol/', GutterActionsFoldCol);
4421  SaveMouseAct(aPath + 'GutterLineNum/', GutterActionsLines);
4422  SaveMouseAct(aPath + 'GutterLineChange/', GutterActionsChanges);
4423  SaveMouseAct(aPath + 'GutterOverView/',   GutterActionsOverView);
4424  SaveMouseAct(aPath + 'GutterOverViewMarks/',GutterActionsOverViewMarks);
4425  MAct.Free;
4426end;
4427
4428procedure TEditorMouseOptions.LoadUserSchemes;
4429var
4430  i, j, c: Integer;
4431  FileList: TStringList;
4432  XMLConfig: TRttiXMLConfig;
4433  n: String;
4434  mo: TEditorMouseOptions;
4435begin
4436  ClearUserSchemes;
4437  if DirectoryExistsUTF8(UserSchemeDirectory(False)) then begin
4438    FileList := FindAllFiles(UserSchemeDirectory(False), '*.xml', False);
4439    for i := 0 to FileList.Count - 1 do begin
4440      XMLConfig := nil;
4441      try
4442        XMLConfig := TRttiXMLConfig.Create(FileList[i]);
4443        c := XMLConfig.GetValue('Lazarus/MouseSchemes/Names/Count', 0);
4444        for j := 1 to c do begin
4445          n := XMLConfig.GetValue('Lazarus/MouseSchemes/Names/Item'+IntToStr(j)+'/Value', '');
4446          if n <> '' then begin
4447            mo := TEditorMouseOptions.Create;
4448            mo.FName := n;
4449            mo.ImportFromXml(XMLConfig, 'Lazarus/MouseSchemes/Scheme' + n + '/');
4450            FUserSchemes.AddObject(n, mo);
4451          end;
4452        end;
4453      except
4454        ShowMessage(Format(dlgUserSchemeError, [FileList[i]]));
4455      end;
4456      XMLConfig.Free;
4457    end;
4458    FileList.Free;
4459  end;
4460end;
4461
4462function TEditorMouseOptions.UserSchemeCount: Integer;
4463begin
4464  Result := FUserSchemes.Count;
4465end;
4466
4467function TEditorMouseOptions.IndexOfUserScheme(SchemeName: String): Integer;
4468begin
4469  Result := FUserSchemes.IndexOf(SchemeName);
4470end;
4471
4472function TEditorMouseOptions.GetSelectedUserSchemeIndex: Integer;
4473begin
4474  if FSelectedUserScheme = '' then
4475    Result := -1
4476  else
4477    Result := IndexOfUserScheme(FSelectedUserScheme);
4478end;
4479
4480procedure TEditorMouseOptions.SetSelectedUserScheme(const AValue: String);
4481begin
4482  if FSelectedUserScheme = AValue then exit;
4483  FSelectedUserScheme := AValue;
4484  ResetToUserScheme;
4485end;
4486
4487procedure TEditorMouseOptions.SetSelectedUserSchemeIndex(const AValue: Integer);
4488begin
4489  if AValue < 0 then
4490    SelectedUserScheme := ''
4491  else
4492    SelectedUserScheme := TEditorMouseOptions(FUserSchemes.Objects[AValue]).Name;
4493end;
4494
4495{ TEditorMouseOptionPresets }
4496
4497constructor TEditorMouseOptionPresets.Create;
4498var
4499  FileList: TStringList;
4500  XMLConfig: TRttiXMLConfig;
4501  i, j, c: Integer;
4502  n: String;
4503begin
4504  if DirectoryExistsUTF8(UserSchemeDirectory(False)) then begin
4505    FileList := FindAllFiles(UserSchemeDirectory(False), '*.xml', False);
4506    for i := 0 to FileList.Count - 1 do begin
4507      XMLConfig := nil;
4508      try
4509        XMLConfig := TRttiXMLConfig.Create(FileList[i]);
4510        c := XMLConfig.GetValue('Lazarus/MouseSchemes/Names/Count', 0);
4511        for j := 1 to c do begin
4512          n := XMLConfig.GetValue('Lazarus/MouseSchemes/Names/Item'+IntToStr(j)+'/Value', '');
4513          if n <> '' then begin
4514            //NewMouse := TEditorMouseOptions.Create;
4515            //Singleton.RegisterScheme(XMLConfig, n, 'Lazarus/MouseSchemes/');
4516          end;
4517        end;
4518      except
4519        ShowMessage(Format(dlgUserSchemeError, [FileList[i]]));
4520      end;
4521      XMLConfig.Free;
4522    end;
4523    FileList.Free;
4524  end;
4525end;
4526
4527{ TEditorOptionsEditAccessOrderList }
4528
4529function TEditorOptionsEditAccessOrderList.GetItems(Index: Integer): TEditorOptionsEditAccessOrderEntry;
4530begin
4531  Result := TEditorOptionsEditAccessOrderEntry(FList[Index]);
4532end;
4533
4534constructor TEditorOptionsEditAccessOrderList.Create;
4535begin
4536  Flist := TFPList.Create;
4537  FSearchOrder := eoeaOrderByEditFocus;
4538end;
4539
4540destructor TEditorOptionsEditAccessOrderList.Destroy;
4541begin
4542  Clear;
4543  FreeAndNil(FList);
4544  inherited Destroy;
4545end;
4546
4547procedure TEditorOptionsEditAccessOrderList.Clear;
4548var
4549  i: Integer;
4550begin
4551  for i := 0 to Count - 1 do
4552    Items[i].Free;
4553  FList.Clear;
4554end;
4555
4556procedure TEditorOptionsEditAccessOrderList.InitDefaults;
4557var
4558  i: Integer;
4559  Entry: TEditorOptionsEditAccessOrderEntry;
4560begin
4561  for i := 0 to high(EditorOptionsEditAccessDefaults) do begin
4562    Entry := TEditorOptionsEditAccessOrderEntry.Create(Self);
4563    Entry.InitFrom(EditorOptionsEditAccessDefaults[i]);
4564    FList.Add(Entry);
4565  end;
4566  Entry.FIsFallback := True;
4567end;
4568
4569procedure TEditorOptionsEditAccessOrderList.Assign(Src: TEditorOptionsEditAccessOrderList);
4570var
4571  i: Integer;
4572  Entry: TEditorOptionsEditAccessOrderEntry;
4573begin
4574  Clear;
4575  FSearchOrder := Src.FSearchOrder;
4576  for i := 0 to Src.Count - 1 do begin
4577    Entry := TEditorOptionsEditAccessOrderEntry.Create(Self);
4578    Entry.Assign(Src[i]);
4579    FList.Add(Entry);
4580  end;
4581end;
4582
4583procedure TEditorOptionsEditAccessOrderList.LoadFromXMLConfig(XMLConfig: TRttiXMLConfig;
4584  Path: String);
4585var
4586  i: Integer;
4587  def: TEditorOptionsEditAccessOrderList;
4588begin
4589  def := TEditorOptionsEditAccessOrderList.Create;
4590  XMLConfig.ReadObject(Path + 'Main/', self, def);
4591  def.Free;
4592  Path := Path + 'Entry/';
4593  for i := 0 to Count - 1 do
4594    XMLConfig.ReadObject(Path + Items[i].ID + '/', Items[i], Items[i].FDefaults);
4595end;
4596
4597procedure TEditorOptionsEditAccessOrderList.SaveToXMLConfig(XMLConfig: TRttiXMLConfig;
4598  Path: String);
4599var
4600  i: Integer;
4601  def: TEditorOptionsEditAccessOrderList;
4602begin
4603  def := TEditorOptionsEditAccessOrderList.Create;
4604  XMLConfig.WriteObject(Path + 'Main/', Self, def);
4605  def.Free;
4606  Path := Path + 'Entry/';
4607  for i := 0 to Count - 1 do
4608    XMLConfig.WriteObject(Path + Items[i].ID + '/', Items[i], Items[i].FDefaults);
4609end;
4610
4611function TEditorOptionsEditAccessOrderList.Count: Integer;
4612begin
4613  Result := FList.Count;
4614end;
4615
4616{ TEditorOptionsEditAccessOrderEntry }
4617
4618procedure TEditorOptionsEditAccessOrderEntry.AssignFrom(AValue: TEditorOptionsEditAccessDefaultEntry);
4619begin
4620  FId      := AValue.ID;
4621  FCaption := AValue.Caption;
4622  FDesc    := AValue.Desc;
4623  FEnabled := AValue.Enabled;
4624  FSearchInView  := AValue.SearchInView;
4625  FSearchLocked  := AValue.SearchLocked;
4626  FSearchOpenNew := AValue.SearchOpenNew;
4627  FSearchOrder   := AValue.SearchOrder;
4628end;
4629
4630procedure TEditorOptionsEditAccessOrderEntry.SetEnabled(const AValue: Boolean);
4631begin
4632  FEnabled := AValue or FIsFallback;
4633end;
4634
4635constructor TEditorOptionsEditAccessOrderEntry.Create(AList: TEditorOptionsEditAccessOrderList);
4636begin
4637  inherited Create;
4638  FList := AList;
4639end;
4640
4641destructor TEditorOptionsEditAccessOrderEntry.Destroy;
4642begin
4643  FreeAndNil(FDefaults);
4644  inherited Destroy;
4645end;
4646
4647procedure TEditorOptionsEditAccessOrderEntry.Assign(Src: TEditorOptionsEditAccessOrderEntry);
4648begin
4649  FId      := Src.FID;
4650  FCaption := Src.FCaption;
4651  FDesc    := Src.FDesc;
4652  FEnabled := Src.FEnabled;
4653  FIsFallback := Src.FIsFallback;
4654  FSearchInView  := Src.FSearchInView;
4655  FSearchLocked  := Src.FSearchLocked;
4656  FSearchOpenNew := Src.FSearchOpenNew;
4657  FSearchOrder   := Src.FSearchOrder;
4658  FreeAndNil(FDefaults);
4659  if Src.FDefaults <> nil then begin
4660    FDefaults := TEditorOptionsEditAccessOrderEntry.Create(nil);
4661    FDefaults.Assign(Src.FDefaults);
4662  end;
4663end;
4664
4665procedure TEditorOptionsEditAccessOrderEntry.InitFrom(AValue: TEditorOptionsEditAccessDefaultEntry);
4666begin
4667  AssignFrom(AValue);
4668  FDefaults := TEditorOptionsEditAccessOrderEntry.Create(nil);
4669  FDefaults.AssignFrom(AValue);
4670end;
4671
4672function TEditorOptionsEditAccessOrderEntry.RealSearchOrder: TEditorOptionsEditAccessOrder;
4673begin
4674  Result := SearchOrder;
4675  if Result = eoeaOrderByListPref then begin
4676    if FList = nil then Result := eoeaOrderByEditFocus;
4677    Result := FList.SearchOrder;
4678    if Result = eoeaOrderByListPref then Result := eoeaOrderByEditFocus;
4679  end;
4680end;
4681
4682{ TEditorOptionsBase }
4683
4684constructor TEditorOptionsBase.Create;
4685begin
4686  inherited Create;
4687  FScrollOnEditLeftOptions := TSynScrollOnEditLeftOptions.Create;
4688  FScrollOnEditRightOptions := TSynScrollOnEditRightOptions.Create;
4689end;
4690
4691destructor TEditorOptionsBase.Destroy;
4692begin
4693  FreeAndNil(FScrollOnEditLeftOptions);
4694  FreeAndNil(FScrollOnEditRightOptions);
4695  inherited Destroy;
4696end;
4697
4698procedure TEditorOptionsBase.InitForRttiXmlConf;
4699begin
4700  // General options
4701  fMultiLineTab := False;
4702  fTabPosition := tpTop;
4703  fMultiCaretOnColumnSelect := True;
4704  fMultiCaretDefaultMode := mcmMoveAllCarets;
4705  fMultiCaretDefaultColumnSelectMode := mcmCancelOnCaretMove;
4706  fMultiCaretDeleteSkipLineBreak := False;
4707  // Display options
4708  fShowOverviewGutter := True;
4709  fTopInfoView := True;
4710  // hints
4711  fDbgHintAutoTypeCastClass := True;
4712  // Code Tools options
4713  fCompletionLongLineHintType := DefaultCompletionLongLineHintType;
4714  // Code folding
4715  fReverseFoldPopUpOrder := True;
4716  // pas highlighter
4717  fPasExtendedKeywordsMode := False;
4718  fPasStringKeywordMode := spsmDefault;
4719  // Multi window
4720  fCtrlMiddleTabClickClosesOthers := True;
4721  fMiddleTabClickClosesOthersModifier := [ssCtrl];
4722  fMiddleTabClickClosesToRightModifier := [];
4723  fShowFileNameInCaption := False;
4724  // Comment
4725  FAnsiCommentContinueEnabled := False;
4726  FAnsiCommentMatch := '^\s?(\*)';
4727  FAnsiCommentMatchMode := scmMatchAtAsterisk;
4728  FAnsiCommentPrefix := '$1';
4729  FAnsiIndentMode := [sciAddTokenLen, sciAddPastTokenIndent,
4730                      sciAlignOnlyTokenLen, sciAlignOnlyPastTokenIndent,
4731                      sciMatchOnlyPastTokenIndent
4732                     ];
4733  FAnsiIndentAlignMax := 40;
4734
4735  FCurlyCommentContinueEnabled := False;
4736  FCurlyCommentMatch := '^\s?(\*)';
4737  FCurlyCommentMatchMode := scmMatchAfterOpening;
4738  FCurlyCommentPrefix := '$1';
4739  FCurlyIndentMode := [sciAddTokenLen, sciAddPastTokenIndent,
4740                      sciAlignOnlyTokenLen, sciAlignOnlyPastTokenIndent,
4741                      sciMatchOnlyPastTokenIndent
4742                     ];
4743  FCurlyIndentAlignMax := 40;
4744
4745  FSlashCommentContinueEnabled := False;
4746  FSlashCommentMatch := '^\s?(\*)';
4747  FSlashCommentMatchMode := scmMatchAfterOpening;
4748  FSlashCommentPrefix := '$1';
4749  FSlashIndentMode := [sciAddTokenLen, sciAddPastTokenIndent,
4750                      sciAlignOnlyTokenLen, sciAlignOnlyPastTokenIndent,
4751                      sciMatchOnlyPastTokenIndent
4752                     ];
4753  FSlashCommentExtend := sceMatching;
4754  FSlashIndentAlignMax := 40;
4755
4756  FStringBreakEnabled := False;
4757  FStringBreakAppend  := ' +';
4758  FStringBreakPrefix  := '';
4759end;
4760
4761function TEditorOptionsBase.GetTabPosition: TTabPosition;
4762begin
4763  Result := fTabPosition;
4764end;
4765
4766{ TEditorOptionsDefaults }
4767
4768constructor TEditorOptionsDefaults.Create;
4769begin
4770  inherited Create;
4771  InitForRttiXmlConf;
4772end;
4773
4774{ TEditorOptions }
4775
4776class function TEditorOptions.GetGroupCaption: string;
4777begin
4778  Result := dlgGroupEditor;
4779end;
4780
4781class function TEditorOptions.GetInstance: TAbstractIDEOptions;
4782begin
4783  Result := EditorOpts;
4784end;
4785
4786procedure TEditorOptions.DoAfterWrite(Restore: boolean);
4787begin
4788  if not Restore then
4789    Save;
4790  inherited;
4791end;
4792
4793constructor TEditorOptions.Create;
4794var
4795  ConfFileName: String;
4796begin
4797  inherited Create;
4798  InitLocale;
4799  ConfFileName := AppendPathDelim(GetPrimaryConfigPath) + EditOptsConfFileName;
4800  CopySecondaryConfigFile(EditOptsConfFileName);
4801  try
4802    if not FileExistsUTF8(ConfFileName) then
4803    begin
4804      DebugLn('NOTE: editor options config file not found - using defaults');
4805      XMLConfig := TRttiXMLConfig.CreateClean(ConfFileName);
4806    end
4807    else
4808      XMLConfig := TRttiXMLConfig.Create(ConfFileName);
4809  except
4810    on E: Exception do
4811    begin
4812      DebugLn('WARNING: unable to read ', ConfFileName, ' ', E.Message);
4813      XMLConfig := Nil;
4814    end;
4815  end;
4816  // set defaults
4817  InitForRttiXmlConf;
4818  Init;
4819  // code templates (dci file)
4820  fCodeTemplateFileNameRaw :=
4821    TrimFilename(AppendPathDelim(GetPrimaryConfigPath)+DefaultCodeTemplatesFilename);
4822  CopySecondaryConfigFile(DefaultCodeTemplatesFilename);
4823  FMultiWinEditAccessOrder := TEditorOptionsEditAccessOrderList.Create;
4824  FMultiWinEditAccessOrder.InitDefaults;
4825  // Default values for RttiXmlConfig
4826  FDefaultValues := TEditorOptionsDefaults.Create;
4827end;
4828
4829destructor TEditorOptions.Destroy;
4830begin
4831  FreeAndNil(FDefaultValues);
4832  FreeAndNil(fMultiWinEditAccessOrder);
4833  FreeAndNil(fUserDefinedColors);
4834  FreeAndNil(fUserColorSchemeGroup);
4835  fUserMouseSettings.Free;
4836  fTempMouseSettings.Free;
4837  fKeyMap.Free;
4838  XMLConfig.Free;
4839  inherited Destroy;
4840end;
4841
4842procedure TEditorOptions.Init;
4843begin
4844  // General options
4845  fSynEditOptions := SynEditDefaultOptions;
4846  fSynEditOptions2 := SynEditDefaultOptions2;
4847  fShowTabCloseButtons := True;
4848  fHideSingleTabInWindow := False;
4849  fCopyWordAtCursorOnCopyNone := True;
4850  fShowGutterHints := True;
4851  fBlockIndent := 2;
4852  FBlockTabIndent := 0;
4853  fBlockIndentType := sbitSpace;
4854  fTrimSpaceType := settEditLine;
4855  fUndoLimit := 32767;
4856  fTabWidth := 8;
4857  fBracketHighlightStyle := sbhsBoth;
4858  // Display options
4859  fGutterSeparatorIndex := 3;
4860  fEditorFont := SynDefaultFontName;
4861  fEditorFontSize := SynDefaultFontSize;
4862  fDisableAntialiasing := DefaultEditorDisableAntiAliasing;
4863  // Key Mappings
4864  fKeyMappingScheme := KeyMapSchemeNames[kmsLazarus];
4865  fKeyMap := TKeyCommandRelationList.Create;
4866  // Mouse Mappings
4867  fUserMouseSettings := TEditorMouseOptions.Create;
4868  fTempMouseSettings := TEditorMouseOptions.Create;
4869  fUserMouseSettings.LoadUserSchemes;
4870  // Color options
4871  fHighlighterList := HighlighterListSingleton;
4872  FUserColorSchemeGroup := TColorSchemeFactory.Create;
4873  FUserColorSchemeGroup.Assign(ColorSchemeFactory); // Copy from global singleton.
4874  fUserDefinedColors := TEditorUserDefinedWordsList.Create;
4875  fUserDefinedColors.UseGlobalIDECommandList := True;
4876  // Markup Current Word
4877  fMarkupCurWordTime := 1500;
4878  fMarkupCurWordFullLen := 3;
4879  fMarkupCurWordNoKeyword := True;
4880  fMarkupCurWordTrim := True;
4881  fMarkupCurWordNoTimer := False;
4882  // Code Tools
4883  fAutoDisplayFuncPrototypes := True;
4884end;
4885
4886function TEditorOptions.GetCodeTemplateFileNameExpand: String;
4887begin
4888  Result := fCodeTemplateFileNameRaw;
4889  IDEMacros.SubstituteMacros(result);
4890end;
4891
4892procedure TEditorOptions.Load;
4893// load options from XML file
4894var
4895  SynEditOpt: TSynEditorOption;
4896  SynEditOptName: String;
4897  i: Integer;
4898  SynEditOpt2: TSynEditorOption2;
4899  FileVersion: LongInt;
4900  DefOpts: TSynEditorOptions;
4901begin
4902  try
4903    FileVersion:=XMLConfig.GetValue('EditorOptions/Version', EditorOptsFormatVersion);
4904
4905    XMLConfig.ReadObject('EditorOptions/Misc/', Self, FDefaultValues);
4906
4907    // general options
4908    DefOpts := SynEditDefaultOptions;
4909    if (FileVersion < 10) then DefOpts := DefOpts - [eoTabIndent];
4910    for SynEditOpt := Low(TSynEditorOption) to High(TSynEditorOption) do
4911    begin
4912      SynEditOptName := GetSynEditOptionName(SynEditOpt);
4913      if SynEditOptName <> '' then
4914        if XMLConfig.GetValue('EditorOptions/General/Editor/'+SynEditOptName,SynEditOpt in DefOpts) then
4915          Include(fSynEditOptions, SynEditOpt)
4916        else
4917          Exclude(fSynEditOptions, SynEditOpt);
4918    end;
4919    for SynEditOpt2 := Low(TSynEditorOption2) to High(TSynEditorOption2) do
4920    begin
4921      case SynEditOpt2 of
4922        eoCaretSkipsSelection:
4923          SynEditOptName := 'CaretSkipsSelection';
4924        eoCaretSkipTab:
4925          SynEditOptName := 'CaretSkipTab';
4926        eoAlwaysVisibleCaret:
4927          SynEditOptName := 'AlwaysVisibleCaret';
4928        eoEnhanceEndKey:
4929          SynEditOptName := 'EnhanceEndKey';
4930        eoFoldedCopyPaste:
4931          SynEditOptName := 'FoldedCopyPaste';
4932        eoPersistentBlock:
4933          SynEditOptName := 'PersistentBlock';
4934        eoOverwriteBlock:
4935          SynEditOptName := 'OverwriteBlock';
4936        eoAutoHideCursor:
4937          SynEditOptName := 'AutoHideCursor';
4938        eoCaretMoveEndsSelection, eoPersistentCaretStopBlink, eoNoScrollOnSelectRange:
4939          WriteStr(SynEditOptName, SynEditOpt2);
4940        else
4941          SynEditOptName := '';
4942      end;
4943      if SynEditOptName <> '' then
4944        if XMLConfig.GetValue('EditorOptions/General/Editor/' + SynEditOptName,
4945          SynEditOpt2 in SynEditDefaultOptions2) then
4946          Include(fSynEditOptions2, SynEditOpt2)
4947        else
4948          Exclude(fSynEditOptions2, SynEditOpt2);
4949    end;
4950
4951    fShowTabCloseButtons :=
4952      XMLConfig.GetValue('EditorOptions/General/Editor/ShowTabCloseButtons', True);
4953    FHideSingleTabInWindow :=
4954      XMLConfig.GetValue('EditorOptions/General/Editor/HideSingleTabInWindow', False);
4955    fShowTabNumbers :=
4956      XMLConfig.GetValue('EditorOptions/General/Editor/ShowTabNumbers', False);
4957    FCopyWordAtCursorOnCopyNone :=
4958      XMLConfig.GetValue('EditorOptions/General/Editor/CopyWordAtCursorOnCopyNone', True);
4959    FShowGutterHints :=
4960      XMLConfig.GetValue('EditorOptions/General/Editor/ShowGutterHints', True);
4961    fUndoAfterSave :=
4962      XMLConfig.GetValue('EditorOptions/General/Editor/UndoAfterSave', True);
4963    fFindTextAtCursor :=
4964      XMLConfig.GetValue('EditorOptions/General/Editor/FindTextAtCursor', True);
4965    fUseSyntaxHighlight :=
4966      XMLConfig.GetValue('EditorOptions/General/Editor/UseSyntaxHighlight', True);
4967    fBlockIndent :=
4968      XMLConfig.GetValue('EditorOptions/General/Editor/BlockIndent', 2);
4969    FBlockTabIndent :=
4970      XMLConfig.GetValue('EditorOptions/General/Editor/BlockTabIndent', 0);
4971    fBlockIndentType := GetSynBeautifierIndentType
4972      (XMLConfig.GetValue('EditorOptions/General/Editor/BlockIndentType',
4973                          'SpaceIndent'));
4974    FTrimSpaceType := GetTrimSpaceType
4975      (XMLConfig.GetValue('EditorOptions/General/Editor/SpaceTrimType',
4976                          'EditLine'));
4977    fUndoLimit :=
4978      XMLConfig.GetValue('EditorOptions/General/Editor/UndoLimit', 32767);
4979    fTabWidth :=
4980      XMLConfig.GetValue('EditorOptions/General/Editor/TabWidth', 8);
4981    FBracketHighlightStyle :=
4982      TSynEditBracketHighlightStyle(XMLConfig.GetValue('EditorOptions/General/Editor/BracketHighlightStyle', 2));
4983
4984    // Display options
4985    fVisibleRightMargin :=
4986      XMLConfig.GetValue('EditorOptions/Display/VisibleRightMargin', True);
4987    fVisibleGutter :=
4988      XMLConfig.GetValue('EditorOptions/Display/VisibleGutter', True);
4989    if FileVersion<4 then begin
4990      fShowLineNumbers :=
4991        XMLConfig.GetValue('EditorOptions/Display/ShowLineNumbers', False);
4992      fShowOnlyLineNumbersMultiplesOf :=
4993        XMLConfig.GetValue('EditorOptions/Display/ShowOnlyLineNumbersMultiplesOf', 1);
4994    end else begin
4995      fShowLineNumbers :=
4996        XMLConfig.GetValue('EditorOptions/Display/ShowLineNumbers', True);
4997      fShowOnlyLineNumbersMultiplesOf :=
4998        XMLConfig.GetValue('EditorOptions/Display/ShowOnlyLineNumbersMultiplesOf', 5);
4999    end;
5000    fGutterWidth :=
5001      XMLConfig.GetValue('EditorOptions/Display/GutterWidth', 30);
5002    FGutterSeparatorIndex :=
5003      XMLConfig.GetValue('EditorOptions/Display/GutterSeparatorIndex', 3);
5004    fRightMargin :=
5005      XMLConfig.GetValue('EditorOptions/Display/RightMargin', 80);
5006    fEditorFont  :=
5007      XMLConfig.GetValue('EditorOptions/Display/EditorFont', SynDefaultFontName);
5008    if FileVersion < 8 then begin
5009      fEditorFontSize :=
5010        XMLConfig.GetValue('EditorOptions/Display/EditorFontHeight', SynDefaultFontHeight);
5011      fEditorFontSize := FontHeightToSize(fEditorFontSize);
5012    end else begin
5013      fEditorFontSize :=
5014        XMLConfig.GetValue('EditorOptions/Display/EditorFontSize', SynDefaultFontSize);
5015    end;
5016    RepairEditorFontSize(fEditorFontSize);
5017    fExtraCharSpacing :=
5018      XMLConfig.GetValue('EditorOptions/Display/ExtraCharSpacing', 0);
5019    fExtraLineSpacing :=
5020      XMLConfig.GetValue('EditorOptions/Display/ExtraLineSpacing', 1);
5021    fDisableAntialiasing :=
5022      XMLConfig.GetValue('EditorOptions/Display/DisableAntialiasing', FileVersion<7);
5023    FDoNotWarnForFont :=
5024      XMLConfig.GetValue('EditorOptions/Display/DoNotWarnForFont', '');
5025
5026    // Key Mappings options
5027    fKeyMappingScheme :=
5028      XMLConfig.GetValue('EditorOptions/KeyMapping/Scheme', KeyMapSchemeNames[kmsLazarus]);
5029    fKeyMap.LoadFromXMLConfig(XMLConfig
5030      , 'EditorOptions/KeyMapping/' + fKeyMappingScheme + '/');
5031
5032    // Color options
5033    for i := 0 to HighlighterList.Count - 1 do
5034      HighlighterList[i].FileExtensions :=
5035        XMLConfig.GetValue('EditorOptions/Color/Lang' +
5036        StrToValidXMLName(HighlighterList[i].SynClass.GetLanguageName) +
5037        '/FileExtensions/Value', HighlighterList[i].DefaultFileExtensions)
5038      // color attributes are stored in the highlighters
5039    ;
5040
5041    FUserDefinedColors.LoadFromXMLConfig(xmlconfig, 'EditorOptions/UserDefinedColors');
5042
5043    FMarkupCurWordTime :=
5044      XMLConfig.GetValue('EditorOptions/Display/MarkupCurrentWord/Time', 1500);
5045    FMarkupCurWordFullLen :=
5046      XMLConfig.GetValue('EditorOptions/Display/MarkupCurrentWord/FullLen', 3);
5047    // check deprecated value
5048    if not XMLConfig.GetValue('EditorOptions/Display/MarkupCurrentWord/FullWord', True) then
5049      FMarkupCurWordFullLen := 0;
5050    XMLConfig.DeleteValue('EditorOptions/Display/MarkupCurrentWord/FullWord');
5051    FMarkupCurWordNoKeyword :=
5052      XMLConfig.GetValue('EditorOptions/Display/MarkupCurrentWord/NoKeyword', True);
5053    FMarkupCurWordTrim :=
5054      XMLConfig.GetValue('EditorOptions/Display/MarkupCurrentWord/Trim', True);
5055    FMarkupCurWordNoTimer :=
5056      XMLConfig.GetValue('EditorOptions/Display/MarkupCurrentWord/NoTimer', False);
5057    FShowFileNameInCaption :=
5058      XMLConfig.GetValue('EditorOptions/Display/ShowFileNameInCaption', False);
5059
5060    // Code Tools options
5061    fAutoBlockCompletion :=
5062      XMLConfig.GetValue('EditorOptions/CodeTools/AutoBlockCompletion', True);
5063    fAutoDisplayFuncPrototypes :=
5064      XMLConfig.GetValue('EditorOptions/CodeTools/AutoDisplayFuncPrototypes', True);
5065    fAutoCodeParameters :=
5066      XMLConfig.GetValue('EditorOptions/CodeTools/AutoCodeParameters', True);
5067    fAutoToolTipExprEval :=
5068      XMLConfig.GetValue('EditorOptions/CodeTools/AutoToolTipExprEval', True);
5069    fAutoToolTipSymbTools :=
5070      XMLConfig.GetValue('EditorOptions/CodeTools/AutoToolTipSymbTools', True);
5071    fAutoDelayInMSec    :=
5072      XMLConfig.GetValue('EditorOptions/CodeTools/AutoDelayInMSec', 1000);
5073    fAutoHintDelayInMSec    :=
5074      XMLConfig.GetValue('EditorOptions/CodeTools/AutoDelayHintInMSec', 1000);
5075    fCodeTemplateFileNameRaw :=
5076      XMLConfig.GetValue('EditorOptions/CodeTools/CodeTemplateFileName'
5077      , TrimFilename(AppendPathDelim(GetPrimaryConfigPath) + DefaultCodeTemplatesFilename));
5078    fCTemplIndentToTokenStart :=
5079      XMLConfig.GetValue('EditorOptions/CodeTools/CodeTemplateIndentToTokenStart/Value', False);
5080    fAutoRemoveEmptyMethods :=
5081      XMLConfig.GetValue('EditorOptions/CodeTools/AutoRemoveEmptyMethods', False);
5082    FCompletionLongLineHintInMSec :=
5083      XMLConfig.GetValue('EditorOptions/CodeTools/CompletionLongLineHintInMSec', 0);
5084    FCompletionLongLineHintType := DefaultCompletionLongLineHintType;
5085    XMLConfig.ReadObject('EditorOptions/CodeTools/CompletionLongLineHintType',
5086                         Self, Self, 'CompletionLongLineHintType');
5087
5088    // Code Folding
5089    FUseCodeFolding :=
5090      XMLConfig.GetValue('EditorOptions/CodeFolding/UseCodeFolding', True);
5091    FUseMarkupWordBracket :=
5092      XMLConfig.GetValue('EditorOptions/CodeFolding/UseMarkupWordBracket', True);
5093    FUseMarkupOutline :=
5094      XMLConfig.GetValue('EditorOptions/CodeFolding/UseMarkupOutline', False);
5095
5096    FUserMouseSettings.LoadFromXml(XMLConfig, 'EditorOptions/Mouse/',
5097                                  'EditorOptions/General/Editor/', FileVersion);
5098
5099    FMultiWinEditAccessOrder.LoadFromXMLConfig(XMLConfig, 'EditorOptions/MultiWin/');
5100    UserColorSchemeGroup.LoadFromXml(XMLConfig, 'EditorOptions/Color/',
5101      ColorSchemeFactory, 'EditorOptions/Display/');
5102
5103  except
5104    on E: Exception do
5105      DebugLn('[TEditorOptions.Load] ERROR: ', e.Message);
5106  end;
5107  if FileVersion < 13 then
5108    if not CtrlMiddleTabClickClosesOthers then // user set option to false
5109      MiddleTabClickClosesOthersModifier := [];
5110end;
5111
5112procedure TEditorOptions.Save;
5113// save options to XML file
5114var
5115  SynEditOpt: TSynEditorOption;
5116  SynEditOptName: String;
5117  i: Integer;
5118  SynEditOpt2: TSynEditorOption2;
5119
5120begin
5121  try
5122    XMLConfig.SetValue('EditorOptions/Version', EditorOptsFormatVersion);
5123
5124    XMLConfig.WriteObject('EditorOptions/Misc/', Self, FDefaultValues);
5125
5126    // general options
5127    for SynEditOpt := Low(TSynEditorOption) to High(TSynEditorOption) do
5128    begin
5129      SynEditOptName := GetSynEditOptionName(SynEditOpt);
5130      if SynEditOptName <> '' then
5131        XMLConfig.SetDeleteValue('EditorOptions/General/Editor/' + SynEditOptName,
5132          SynEditOpt in fSynEditOptions, SynEditOpt in SynEditDefaultOptions);
5133    end;
5134    // general options
5135    for SynEditOpt2 := Low(TSynEditorOption2) to High(TSynEditorOption2) do
5136    begin
5137      case SynEditOpt2 of
5138        eoCaretSkipsSelection:
5139          SynEditOptName := 'CaretSkipsSelection';
5140        eoCaretSkipTab:
5141          SynEditOptName := 'CaretSkipTab';
5142        eoAlwaysVisibleCaret:
5143          SynEditOptName := 'AlwaysVisibleCaret';
5144        eoEnhanceEndKey:
5145          SynEditOptName := 'EnhanceEndKey';
5146        eoFoldedCopyPaste:
5147          SynEditOptName := 'FoldedCopyPaste';
5148        eoPersistentBlock:
5149          SynEditOptName := 'PersistentBlock';
5150        eoOverwriteBlock:
5151          SynEditOptName := 'OverwriteBlock';
5152        eoAutoHideCursor:
5153          SynEditOptName := 'AutoHideCursor';
5154        eoCaretMoveEndsSelection, eoPersistentCaretStopBlink, eoNoScrollOnSelectRange:
5155          WriteStr(SynEditOptName, SynEditOpt2);
5156        else
5157          SynEditOptName := '';
5158      end;
5159      if SynEditOptName <> '' then
5160        XMLConfig.SetDeleteValue('EditorOptions/General/Editor/' + SynEditOptName,
5161          SynEditOpt2 in fSynEditOptions2, SynEditOpt2 in SynEditDefaultOptions2);
5162    end;
5163
5164    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/ShowTabCloseButtons'
5165      , fShowTabCloseButtons, True);
5166    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/HideSingleTabInWindow'
5167      , FHideSingleTabInWindow, False);
5168    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/ShowTabNumbers'
5169      , fShowTabNumbers, False);
5170    XMLConfig.SetDeleteValue(
5171      'EditorOptions/General/Editor/CopyWordAtCursorOnCopyNone',
5172      FCopyWordAtCursorOnCopyNone, True);
5173    XMLConfig.SetDeleteValue(
5174      'EditorOptions/General/Editor/ShowGutterHints',
5175      FShowGutterHints, True);
5176    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/UndoAfterSave'
5177      , fUndoAfterSave, True);
5178    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/FindTextAtCursor'
5179      , fFindTextAtCursor, True);
5180    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/UseSyntaxHighlight'
5181      , fUseSyntaxHighlight, True);
5182    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/BlockIndent'
5183      , fBlockIndent, 2);
5184    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/BlockTabIndent'
5185      , FBlockTabIndent, 0);
5186    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/BlockIndentType'
5187      , GetSynBeautifierIndentName(fBlockIndentType), 'SpaceIndent');
5188    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/SpaceTrimType'
5189      , GetTrimSpaceName(FTrimSpaceType), 'EditLine');
5190    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/UndoLimit'
5191      , fUndoLimit, 32767);
5192    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/TabWidth'
5193      , fTabWidth, 8);
5194    XMLConfig.SetDeleteValue('EditorOptions/General/Editor/BracketHighlightStyle'
5195      , Ord(FBracketHighlightStyle), 2);
5196
5197    // Display options
5198    XMLConfig.SetDeleteValue('EditorOptions/Display/VisibleRightMargin'
5199      , fVisibleRightMargin, True);
5200    XMLConfig.SetDeleteValue('EditorOptions/Display/VisibleGutter',
5201      fVisibleGutter, True);
5202    XMLConfig.SetDeleteValue('EditorOptions/Display/ShowLineNumbers',
5203      fShowLineNumbers, True);
5204    XMLConfig.SetDeleteValue('EditorOptions/Display/ShowOnlyLineNumbersMultiplesOf',
5205      fShowOnlyLineNumbersMultiplesOf, 5);
5206    XMLConfig.SetDeleteValue('EditorOptions/Display/GutterWidth',
5207      fGutterWidth, 30);
5208    XMLConfig.SetDeleteValue('EditorOptions/Display/GutterSeparatorIndex',
5209      fGutterSeparatorIndex, 3);
5210    XMLConfig.SetDeleteValue('EditorOptions/Display/RightMargin',
5211      fRightMargin, 80);
5212    XMLConfig.SetDeleteValue('EditorOptions/Display/EditorFont',
5213      fEditorFont, SynDefaultFontName);
5214    XMLConfig.DeleteValue('EditorOptions/Display/EditorFontHeight'); // unused old value
5215    XMLConfig.SetDeleteValue('EditorOptions/Display/EditorFontSize'
5216      ,fEditorFontSize, SynDefaultFontSize);
5217    XMLConfig.SetDeleteValue('EditorOptions/Display/ExtraCharSpacing'
5218      ,fExtraCharSpacing, 0);
5219    XMLConfig.SetDeleteValue('EditorOptions/Display/ExtraLineSpacing'
5220      ,fExtraLineSpacing, 1);
5221    XMLConfig.SetDeleteValue('EditorOptions/Display/DisableAntialiasing'
5222      ,fDisableAntialiasing, DefaultEditorDisableAntiAliasing);
5223    XMLConfig.SetDeleteValue('EditorOptions/Display/DoNotWarnForFont'
5224      ,FDoNotWarnForFont, '');
5225
5226    // Key Mappings options
5227    XMLConfig.SetDeleteValue('EditorOptions/KeyMapping/Scheme', fKeyMappingScheme,
5228       KeyMapSchemeNames[kmsLazarus]);
5229    fKeyMap.SaveToXMLConfig(
5230              XMLConfig, 'EditorOptions/KeyMapping/' + fKeyMappingScheme + '/');
5231
5232    // Color options
5233    for i := 0 to HighlighterList.Count - 1 do
5234      XMLConfig.SetDeleteValue('EditorOptions/Color/Lang' +
5235        StrToValidXMLName(HighlighterList[i].SynClass.GetLanguageName) +
5236        '/FileExtensions/Value', HighlighterList[i].FileExtensions,
5237        HighlighterList[i].DefaultFileExtensions)
5238      // color attributes are stored in the highlighters
5239    ;
5240
5241    FUserDefinedColors.SaveToXMLConfig(xmlconfig, 'EditorOptions/UserDefinedColors');
5242
5243    XMLConfig.SetDeleteValue('EditorOptions/Display/MarkupCurrentWord/Time',
5244      FMarkupCurWordTime, 1500);
5245    XMLConfig.SetDeleteValue('EditorOptions/Display/MarkupCurrentWord/FullLen',
5246      FMarkupCurWordFullLen, 3);
5247    XMLConfig.SetDeleteValue('EditorOptions/Display/MarkupCurrentWord/NoKeyword',
5248      FMarkupCurWordNoKeyword, True);
5249    XMLConfig.SetDeleteValue('EditorOptions/Display/MarkupCurrentWord/Trim',
5250      FMarkupCurWordTrim, True);
5251    XMLConfig.SetDeleteValue('EditorOptions/Display/MarkupCurrentWord/NoTimer',
5252      FMarkupCurWordNoTimer, False);
5253    XMLConfig.SetDeleteValue('EditorOptions/Display/ShowFileNameInCaption',
5254        FShowFileNameInCaption, False);
5255
5256    // Code Tools options
5257    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoBlockCompletion'
5258      , fAutoBlockCompletion, True);
5259    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoDisplayFuncPrototypes'
5260      , fAutoDisplayFuncPrototypes, True);
5261    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoCodeParameters'
5262      , fAutoCodeParameters, True);
5263    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoToolTipExprEval'
5264      , fAutoToolTipExprEval, True);
5265    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoToolTipSymbTools'
5266      , fAutoToolTipSymbTools, True);
5267    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoDelayInMSec'
5268      , fAutoDelayInMSec, 1000);
5269    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoDelayHintInMSec'
5270      , fAutoHintDelayInMSec, 1000);
5271    XMLConfig.SetDeleteValue('EditorOptions/CodeTools/CodeTemplateFileName'
5272      , fCodeTemplateFileNameRaw, '');
5273    XMLConfig.SetDeleteValue(
5274      'EditorOptions/CodeTools/CodeTemplateIndentToTokenStart/Value'
5275      , fCTemplIndentToTokenStart, False);
5276    XMLConfig.SetDeleteValue(
5277      'EditorOptions/CodeTools/AutoRemoveEmptyMethods'
5278      , fAutoRemoveEmptyMethods, False);
5279    XMLConfig.SetDeleteValue(
5280      'EditorOptions/CodeTools/CompletionLongLineHintInMSec',
5281      FCompletionLongLineHintInMSec, 0);
5282    XMLConfig.WriteObject('EditorOptions/CodeTools/CompletionLongLineHintType',
5283                         Self, nil, 'CompletionLongLineHintType');
5284
5285    // Code Folding
5286    XMLConfig.SetDeleteValue('EditorOptions/CodeFolding/UseCodeFolding',
5287        FUseCodeFolding, True);
5288    XMLConfig.SetDeleteValue('EditorOptions/CodeFolding/UseMarkupWordBracket',
5289        FUseMarkupWordBracket, True);
5290    XMLConfig.SetDeleteValue('EditorOptions/CodeFolding/UseMarkupOutline',
5291        FUseMarkupOutline, False);
5292
5293    FUserMouseSettings.SaveToXml(XMLConfig, 'EditorOptions/Mouse/');
5294
5295    FMultiWinEditAccessOrder.SaveToXMLConfig(XMLConfig, 'EditorOptions/MultiWin/');
5296    UserColorSchemeGroup.SaveToXml(XMLConfig, 'EditorOptions/Color/', ColorSchemeFactory);
5297
5298    InvalidateFileStateCache;
5299    XMLConfig.Flush;
5300  except
5301    on E: Exception do
5302      DebugLn('[TEditorOptions.Save] ERROR: ', e.Message);
5303  end;
5304end;
5305
5306function TEditorOptions.LoadCodeTemplates(AnAutoComplete: TSynEditAutoComplete
5307  ): TModalResult;
5308
5309  function ResourceDCIAsText: String;
5310  var
5311    data: TResourceStream;
5312    i: Int64;
5313  begin
5314    data := TResourceStream.Create(HInstance, PChar('lazarus_dci_file'), PChar(RT_RCDATA));
5315    i := data.Size;
5316    SetLength(Result, i);
5317    if i > 0 then
5318      data.Read(Result[1], i);
5319    data.Free;
5320  end;
5321
5322var
5323  s: String;
5324  FileVersion, i, j, v: Integer;
5325  NewAutoComplete: TSynEditAutoComplete;
5326  Attr, ExAtr: TStrings;
5327  Added: Boolean;
5328begin
5329  s := CodeTemplateFileNameExpand;
5330  Result := mrAbort;
5331  if FileExistsUTF8(s) then begin
5332    try
5333      AnAutoComplete.AutoCompleteList.LoadFromFile(s);
5334      Result := mrOK;
5335    except
5336      Result := mrAbort;
5337    end;
5338    if Result = mrAbort then
5339      exit;
5340
5341    FileVersion := AnAutoComplete.Completions.Count;
5342    if (FileVersion > 0) then begin
5343      ExAtr := AnAutoComplete.CompletionAttributes[0];
5344      FileVersion := ExAtr.IndexOfName(DciFileVersionName);
5345      if (FileVersion >= 0) then
5346        FileVersion := StrToIntDef(ExAtr.ValueFromIndex[FileVersion], 0);
5347    end;
5348    if FileVersion < DciFileVersion then begin
5349      // Merge new entries
5350      NewAutoComplete := TSynEditAutoComplete.Create(nil);
5351      NewAutoComplete.AutoCompleteList.Text := ResourceDCIAsText;
5352      Added := False;
5353      for i := 0 to NewAutoComplete.Completions.Count - 1 do begin
5354        ExAtr := NewAutoComplete.CompletionAttributes[i];
5355        j := ExAtr.IndexOfName(DciVersionName);
5356        if j < 0 then
5357          continue;
5358        v := StrToIntDef(ExAtr.ValueFromIndex[j], 0);
5359        if v <= FileVersion then
5360          continue;
5361        if AnAutoComplete.Completions.IndexOf(NewAutoComplete.Completions[i]) >= 0 then
5362          continue;
5363        Attr := TStringListUTF8Fast.Create;
5364        Attr.Assign(ExAtr); // will be owned by AnAutoComplete;
5365        AnAutoComplete.AddCompletion(
5366          NewAutoComplete.Completions[i],
5367          NewAutoComplete.CompletionValues[i],
5368          NewAutoComplete.CompletionComments[i],
5369          Attr);
5370        Added := True;
5371      end;
5372      NewAutoComplete.Free;
5373      if Added then
5374        if BuildBorlandDCIFile(AnAutoComplete) then
5375          SaveCodeTemplates(AnAutoComplete);
5376    end;
5377  end
5378  else begin
5379    AnAutoComplete.AutoCompleteList.Text := ResourceDCIAsText;
5380  end;
5381end;
5382
5383function TEditorOptions.SaveCodeTemplates(AnAutoComplete: TSynEditAutoComplete
5384  ): TModalResult;
5385begin
5386  try
5387    AnAutoComplete.AutoCompleteList.SaveToFile(CodeTemplateFileNameExpand);
5388    Result := mrOK;
5389  except
5390    Result := mrAbort;
5391  end;
5392end;
5393
5394procedure TEditorOptions.AssignKeyMapTo(ASynEdit: TSynEdit; SimilarEdit: TSynEdit);
5395var
5396  c, i: Integer;
5397begin
5398  if SimilarEdit<>nil then
5399    ASynEdit.KeyStrokes.Assign(SimilarEdit.Keystrokes)
5400  else
5401    KeyMap.AssignTo(ASynEdit.KeyStrokes, TSourceEditorWindowInterface);
5402
5403  c := ASynEdit.PluginCount - 1;
5404  while (c >= 0) do begin
5405    if SimilarEdit<>nil then begin
5406      i := SimilarEdit.PluginCount - 1;
5407      while (i >= 0) and not (SimilarEdit.Plugin[i].ClassType = ASynEdit.Plugin[c].ClassType) do
5408        dec(i);
5409    end
5410    else
5411      i:= -1;
5412
5413    if (ASynEdit.Plugin[c] is TSynPluginTemplateEdit) then begin
5414      TSynPluginTemplateEdit(ASynEdit.Plugin[c]).Keystrokes.Clear;
5415      TSynPluginTemplateEdit(ASynEdit.Plugin[c]).KeystrokesOffCell.Clear;
5416      if i >= 0 then begin
5417        TSynPluginTemplateEdit(ASynEdit.Plugin[c]).Keystrokes.Assign(
5418                               TSynPluginTemplateEdit(SimilarEdit.Plugin[i]).KeyStrokes);
5419        TSynPluginTemplateEdit(ASynEdit.Plugin[c]).KeystrokesOffCell.Assign(
5420                               TSynPluginTemplateEdit(SimilarEdit.Plugin[i]).KeystrokesOffCell);
5421      end else begin
5422        KeyMap.AssignTo(TSynPluginTemplateEdit(ASynEdit.Plugin[c]).Keystrokes,
5423                        TLazSynPluginTemplateEditForm, ecIdePTmplOffset);
5424        KeyMap.AssignTo(TSynPluginTemplateEdit(ASynEdit.Plugin[c]).KeystrokesOffCell,
5425                        TLazSynPluginTemplateEditFormOff, ecIdePTmplOutOffset);
5426      end;
5427    end;
5428
5429    if (ASynEdit.Plugin[c] is TSynPluginSyncroEdit) then begin
5430      TSynPluginSyncroEdit(ASynEdit.Plugin[c]).KeystrokesSelecting.Clear;
5431      TSynPluginSyncroEdit(ASynEdit.Plugin[c]).Keystrokes.Clear;
5432      TSynPluginSyncroEdit(ASynEdit.Plugin[c]).KeystrokesOffCell.Clear;
5433      if i >= 0 then begin
5434        TSynPluginSyncroEdit(ASynEdit.Plugin[c]).KeystrokesSelecting.Assign(
5435                             TSynPluginSyncroEdit(SimilarEdit.Plugin[i]).KeystrokesSelecting);
5436        TSynPluginSyncroEdit(ASynEdit.Plugin[c]).Keystrokes.Assign(
5437                             TSynPluginSyncroEdit(SimilarEdit.Plugin[i]).KeyStrokes);
5438        TSynPluginSyncroEdit(ASynEdit.Plugin[c]).KeystrokesOffCell.Assign(
5439                             TSynPluginSyncroEdit(SimilarEdit.Plugin[i]).KeystrokesOffCell);
5440      end else begin
5441        KeyMap.AssignTo(TSynPluginSyncroEdit(ASynEdit.Plugin[c]).KeystrokesSelecting,
5442                        TLazSynPluginSyncroEditFormSel, ecIdePSyncroSelOffset);
5443        KeyMap.AssignTo(TSynPluginSyncroEdit(ASynEdit.Plugin[c]).Keystrokes,
5444                        TLazSynPluginSyncroEditForm, ecIdePSyncroOffset);
5445        KeyMap.AssignTo(TSynPluginSyncroEdit(ASynEdit.Plugin[c]).KeystrokesOffCell,
5446                        TLazSynPluginSyncroEditFormOff, ecIdePSyncroOutOffset);
5447      end;
5448    end;
5449
5450    if (ASynEdit.Plugin[c] is TSynPluginMultiCaret) then begin
5451      // Only ecPluginMultiCaretClearAll
5452      // the others are handled in SynEdit.Keystrokes
5453      TSynPluginMultiCaret(ASynEdit.Plugin[c]).Keystrokes.Clear;
5454      if i >= 0 then begin
5455        TSynPluginMultiCaret(ASynEdit.Plugin[c]).Keystrokes.Assign(
5456                               TSynPluginMultiCaret(SimilarEdit.Plugin[i]).KeyStrokes);
5457      end else begin
5458        KeyMap.AssignTo(TSynPluginMultiCaret(ASynEdit.Plugin[c]).Keystrokes,
5459                        TLazSynPluginTemplateMultiCaret, 0); //ecIdePTmplOffset);
5460      end;
5461    end;
5462
5463    dec(c);
5464  end;
5465end;
5466
5467function TEditorOptions.GetColorSchemeLanguage(aHighLighter: TSynCustomHighlighter;
5468  SynColorSchemeName: String): TColorSchemeLanguage;
5469var
5470  Scheme: TColorScheme;
5471begin
5472  Result := nil;
5473  // initialize with defaults
5474  if SynColorSchemeName = '' then
5475    SynColorSchemeName := ReadColorScheme(aHighLighter.LanguageName);
5476  if (SynColorSchemeName = '') then
5477    exit;
5478  Scheme := UserColorSchemeGroup.ColorSchemeGroup[SynColorSchemeName];
5479  if Scheme = nil then
5480    exit;
5481  Result := Scheme.ColorSchemeBySynClass[aHighLighter.ClassType];
5482end;
5483
5484function TEditorOptions.ReadColorScheme(const LanguageName: String): String;
5485(* The name of the currently chosen color-scheme for that language *)
5486begin
5487  if LanguageName = '' then
5488    Exit(ColorSchemeFactory.ColorSchemeGroupAtPos[0].Name);
5489  if LanguageName <> TPreviewPasSyn.GetLanguageName then
5490    Result := XMLConfig.GetValue(
5491      'EditorOptions/Color/Lang' + StrToValidXMLName(LanguageName) + '/ColorScheme/Value', '')
5492  else
5493    Result := '';
5494  if ColorSchemeFactory.ColorSchemeGroup[Result] = nil then
5495    Result := '';
5496  if Result = '' then
5497    Result := ReadPascalColorScheme;
5498end;
5499
5500function TEditorOptions.ReadPascalColorScheme: String;
5501(* The name of the currently chosen color-scheme for pascal code *)
5502var
5503  FormatVersion: Integer;
5504begin
5505  FormatVersion := XMLConfig.GetValue('EditorOptions/Color/Version', EditorOptsFormatVersion);
5506  if FormatVersion > 1 then
5507    Result := XMLConfig.GetValue('EditorOptions/Color/Lang' +
5508      StrToValidXMLName(TPreviewPasSyn.GetLanguageName) + '/ColorScheme/Value', '')
5509  else
5510    Result := XMLConfig.GetValue('EditorOptions/Color/ColorScheme', '');
5511  if ColorSchemeFactory.ColorSchemeGroup[Result] = nil then
5512    Result := '';
5513  if (Result = '') then begin
5514    if DefaultColorSchemeName <> '' then
5515      Result := DefaultColorSchemeName
5516    else
5517      Result := ColorSchemeFactory.ColorSchemeGroupAtPos[0].Name;
5518  end;
5519end;
5520
5521procedure TEditorOptions.WriteColorScheme(const LanguageName, SynColorScheme: String);
5522begin
5523  if (LanguageName = '') or (SynColorScheme = '') then
5524    exit;
5525  XMLConfig.SetValue('EditorOptions/Color/Lang' + StrToValidXMLName(LanguageName) +
5526                     '/ColorScheme/Value', SynColorScheme);
5527  XMLConfig.SetValue('EditorOptions/Color/Version', EditorOptsFormatVersion);
5528end;
5529
5530procedure TEditorOptions.ReadHighlighterSettings(Syn: TSrcIDEHighlighter;
5531  SynColorScheme: String);
5532// if SynColorScheme='' then default ColorScheme will be used
5533var
5534  LangScheme: TColorSchemeLanguage;
5535begin
5536  LangScheme := GetColorSchemeLanguage(Syn, SynColorScheme);
5537  if LangScheme = nil then
5538    exit;
5539  LangScheme.ApplyTo(Syn);
5540end;
5541
5542procedure TEditorOptions.ReadHighlighterFoldSettings(Syn: TSrcIDEHighlighter;
5543  ReadForOptions: Boolean);
5544var
5545  Path, ValidLang: String;
5546  i, h, idx: Integer;
5547  FoldRec: TEditorOptionsFoldRecord;
5548  FoldInf: TEditorOptionsFoldInfo;
5549  DefHl, FoldHl: TSynCustomFoldHighlighter;
5550begin
5551  h := HighlighterList.FindByHighlighter(Syn);
5552  if h < 0 then
5553    h := HighlighterList.FindByName(Syn.LanguageName);
5554  if h < 0 then exit;
5555
5556  if Syn is TSynCustomFoldHighlighter then begin
5557    FoldHl := TSynCustomFoldHighlighter(Syn);
5558    DefHl := TSynCustomFoldHighlighter(TCustomSynClass(Syn.ClassType).Create(nil));
5559    try
5560      ReadDefaultsForHighlighterFoldSettings(DefHl);
5561      ValidLang := StrToValidXMLName(Syn.LanguageName);
5562      FoldRec := EditorOptionsFoldDefaults[HighlighterList[h].TheType];
5563      for i := 0 to FoldRec.Count - 1 do begin
5564        FoldInf := FoldRec.Info^[i];
5565        idx := FoldInf.Index;
5566        Path := 'EditorOptions/FoldConfig/Lang' + ValidLang + '/Type' + FoldInf.Xml + '/' ;
5567        // try reading the old config first
5568        FoldHl.FoldConfig[idx].Enabled :=
5569          XMLConfig.GetValue(Path + 'Enabled/Value', FoldHl.FoldConfig[idx].Enabled);
5570        XMLConfig.ReadObject(Path + 'Settings/', FoldHl.FoldConfig[idx], DefHl.FoldConfig[idx]);
5571
5572        (* if ReadForOptions=True then Enabled appies only to fmFold,fmHide.
5573           This allows to store what selection was previously active *)
5574        if not ReadForOptions then begin
5575          if (not FoldHl.FoldConfig[idx].Enabled) or (not FUseCodeFolding) then
5576            FoldHl.FoldConfig[idx].Modes := FoldHl.FoldConfig[idx].Modes - [fmFold, fmHide];
5577          if (not FUseMarkupWordBracket) then
5578            FoldHl.FoldConfig[idx].Modes := FoldHl.FoldConfig[idx].Modes - [fmMarkup];
5579          if (not FUseMarkupOutline) then
5580            FoldHl.FoldConfig[idx].Modes := FoldHl.FoldConfig[idx].Modes - [fmOutline];
5581
5582          FoldHl.FoldConfig[idx].Enabled := FoldHl.FoldConfig[idx].Modes <> [];
5583        end;
5584
5585        if (FoldHl is TSynPasSyn) and (idx = ord(cfbtIfThen)) then begin
5586          FoldHl.FoldConfig[ord(cfbtIfElse)].Modes := FoldHl.FoldConfig[idx].Modes * [fmOutline];
5587          FoldHl.FoldConfig[ord(cfbtIfElse)].Enabled := FoldHl.FoldConfig[idx].Enabled and (FoldHl.FoldConfig[ord(cfbtIfElse)].Modes <> []);
5588        end;
5589
5590      end;
5591    finally
5592      DefHl.Free;
5593    end;
5594  end;
5595end;
5596
5597procedure TEditorOptions.ReadDefaultsForHighlighterFoldSettings(Syn: TSrcIDEHighlighter);
5598var
5599  i, h: Integer;
5600  TheFoldInfo: TEditorOptionsFoldRecord;
5601begin
5602  h := HighlighterList.FindByHighlighter(Syn);
5603  if h < 0 then
5604    h := HighlighterList.FindByName(Syn.LanguageName);
5605  if h < 0 then exit;
5606  if (syn is TSynCustomFoldHighlighter) then begin
5607    TheFoldInfo := EditorOptionsFoldDefaults[HighlighterList[h].TheType];
5608    for i := 0 to TheFoldInfo.Count - 1 do
5609      with TSynCustomFoldHighlighter(Syn).FoldConfig[TheFoldInfo.Info^[i].Index] do
5610        Enabled := TheFoldInfo.Info^[i].Enabled;
5611  end;
5612end;
5613
5614procedure TEditorOptions.WriteHighlighterFoldSettings(Syn: TSrcIDEHighlighter);
5615var
5616  DefSyn: TSrcIDEHighlighter;
5617  i, h:   Integer;
5618  Path:   String;
5619  ConfName: String;
5620  TheFoldInfo: TEditorOptionsFoldRecord;
5621begin
5622  h := HighlighterList.FindByHighlighter(Syn);
5623  if h < 0 then
5624    h := HighlighterList.FindByName(Syn.LanguageName);
5625  if h < 0 then exit;
5626
5627  DefSyn := TCustomSynClass(Syn.ClassType).Create(Nil);
5628  try
5629    ReadDefaultsForHighlighterFoldSettings(DefSyn);
5630
5631    if (syn is TSynCustomFoldHighlighter) then begin
5632      TheFoldInfo := EditorOptionsFoldDefaults[HighlighterList[h].TheType];
5633      for i := 0 to TheFoldInfo.Count - 1 do begin
5634        ConfName := TheFoldInfo.Info^[i].Xml;
5635        Path := 'EditorOptions/FoldConfig/Lang' +
5636          StrToValidXMLName(Syn.LanguageName) + '/Type' + ConfName + '/' ;
5637        XMLConfig.DeletePath(Path + 'Enabled/');
5638        XMLConfig.WriteObject(Path + 'Settings/',
5639          TSynCustomFoldHighlighter(Syn).FoldConfig[TheFoldInfo.Info^[i].Index],
5640          TSynCustomFoldHighlighter(DefSyn).FoldConfig[TheFoldInfo.Info^[i].Index]);
5641      end;
5642    end;
5643
5644  finally
5645    DefSyn.Free;
5646  end;
5647end;
5648
5649procedure TEditorOptions.ReadHighlighterDivDrawSettings(Syn: TSrcIDEHighlighter);
5650var
5651  TheInfo: TEditorOptionsDividerRecord;
5652  Conf: TSynDividerDrawConfig;
5653  ConfName: String;
5654  Path: String;
5655  i, h: Integer;
5656begin
5657  h := HighlighterList.FindByHighlighter(Syn);
5658  if h < 0 then
5659    h := HighlighterList.FindByName(Syn.LanguageName);
5660  if h < 0 then exit;
5661  TheInfo := EditorOptionsDividerDefaults[HighlighterList[h].TheType];
5662
5663  ReadDefaultsForHighlighterDivDrawSettings(Syn);
5664
5665  // read settings, that are different from the defaults
5666  for i := 0 to TheInfo.Count - 1 do begin
5667    Conf := Syn.DividerDrawConfig[i];
5668    ConfName := TheInfo.Info^[i].Xml;
5669    Path := 'EditorOptions/DividerDraw/Lang' + Syn.LanguageName + '/Type' + ConfName + '/' ;
5670    Conf.MaxDrawDepth := XMLConfig.GetValue(Path + 'MaxDepth/Value', Conf.MaxDrawDepth);
5671    Conf.TopColor := XMLConfig.GetValue(Path + 'TopColor/Value', Conf.TopColor);
5672    Conf.NestColor := XMLConfig.GetValue(Path + 'NestColor/Value', Conf.NestColor);
5673  end;
5674end;
5675
5676procedure TEditorOptions.ReadDefaultsForHighlighterDivDrawSettings(Syn: TSrcIDEHighlighter);
5677var
5678  TheInfo: TEditorOptionsDividerRecord;
5679  i, h: Integer;
5680begin
5681  h := HighlighterList.FindByHighlighter(Syn);
5682  if h < 0 then
5683    h := HighlighterList.FindByName(Syn.LanguageName);
5684  if h < 0 then exit;
5685  TheInfo := EditorOptionsDividerDefaults[HighlighterList[h].TheType];
5686  for i := 0 to TheInfo.Count - 1 do begin
5687    Syn.DividerDrawConfig[i].MaxDrawDepth := TheInfo.Info^[i].MaxLeveL;
5688    Syn.DividerDrawConfig[i].TopColor := clDefault;
5689    Syn.DividerDrawConfig[i].NestColor := clDefault;
5690  end;
5691end;
5692
5693procedure TEditorOptions.WriteHighlighterDivDrawSettings(Syn: TSrcIDEHighlighter);
5694var
5695  DefSyn: TSrcIDEHighlighter;
5696  i, h:   Integer;
5697  Path:   String;
5698  Conf, DefConf: TSynDividerDrawConfig;
5699  TheInfo: TEditorOptionsDividerRecord;
5700  ConfName: String;
5701begin
5702  h := HighlighterList.FindByHighlighter(Syn);
5703  if h < 0 then
5704    h := HighlighterList.FindByName(Syn.LanguageName);
5705  if h < 0 then exit;
5706  TheInfo := EditorOptionsDividerDefaults[HighlighterList[h].TheType];
5707
5708  DefSyn := TCustomSynClass(Syn.ClassType).Create(Nil);
5709  try
5710    ReadDefaultsForHighlighterDivDrawSettings(DefSyn);
5711    for i := 0 to TheInfo.Count - 1 do begin
5712      Conf := Syn.DividerDrawConfig[i];
5713      DefConf := DefSyn.DividerDrawConfig[i]; // default value
5714      ConfName := TheInfo.Info^[i].Xml;
5715      Path := 'EditorOptions/DividerDraw/Lang' +
5716        StrToValidXMLName(Syn.LanguageName) + '/Type' + ConfName + '/' ;
5717      XMLConfig.SetDeleteValue(Path + 'MaxDepth/Value', Conf.MaxDrawDepth,
5718                               DefConf.MaxDrawDepth);
5719      XMLConfig.SetDeleteValue(Path + 'TopColor/Value', Conf.TopColor,
5720                               DefConf.TopColor);
5721      XMLConfig.SetDeleteValue(Path + 'NestColor/Value', Conf.NestColor,
5722                               DefConf.NestColor);
5723    end;
5724
5725  finally
5726    DefSyn.Free;
5727  end;
5728end;
5729
5730procedure TEditorOptions.GetHighlighterSettings(Syn: TSrcIDEHighlighter);
5731// read highlight settings from config file
5732begin
5733  ReadHighlighterSettings(Syn, '');
5734  ReadHighlighterFoldSettings(Syn);
5735  ReadHighlighterDivDrawSettings(Syn);
5736  if Syn is TSynPasSyn then begin
5737    TSynPasSyn(Syn).ExtendedKeywordsMode := PasExtendedKeywordsMode;
5738    TSynPasSyn(Syn).StringKeywordMode := PasStringKeywordMode;
5739  end;;
5740end;
5741
5742procedure TEditorOptions.SetMarkupColor(Syn : TSrcIDEHighlighter;
5743  AddHilightAttr : TAdditionalHilightAttribute; aMarkup : TSynSelectedColor);
5744var
5745  SchemeGrp: TColorScheme;
5746  Scheme: TColorSchemeLanguage;
5747  Attrib: TColorSchemeAttribute;
5748begin
5749  if assigned(Syn) then begin
5750    Scheme := GetColorSchemeLanguage(Syn);
5751  end else begin
5752    SchemeGrp := UserColorSchemeGroup.ColorSchemeGroup[DefaultColorSchemeName];
5753    if SchemeGrp = nil then
5754      exit;
5755    Scheme := SchemeGrp.DefaultColors;
5756  end;
5757
5758  Attrib := Scheme.AttributeByEnum[AddHilightAttr];
5759  if Attrib <> nil then begin
5760    Attrib.ApplyTo(aMarkup);
5761    exit;
5762  end;
5763
5764  // set default
5765  aMarkup.Foreground := clNone;
5766  aMarkup.Background := clNone;
5767  aMarkup.FrameColor := clNone;
5768  aMarkup.FrameEdges := sfeAround;
5769  aMarkup.FrameStyle := slsSolid;
5770  aMarkup.Style := [];
5771  aMarkup.StyleMask := [];
5772end;
5773
5774procedure TEditorOptions.SetMarkupColors(aSynEd: TSynEdit);
5775var
5776  Scheme: TColorSchemeLanguage;
5777begin
5778  // Find current color scheme for default colors
5779  if (aSynEd.Highlighter = nil) then begin
5780    aSynEd.Color := clWhite;
5781    aSynEd.Font.Color := clBlack;
5782    exit;
5783  end;
5784  // get current colorscheme:
5785  Scheme := GetColorSchemeLanguage(aSynEd.Highlighter);
5786  if Assigned(Scheme) then Scheme.ApplyTo(aSynEd);
5787end;
5788
5789procedure TEditorOptions.ApplyFontSettingsTo(ASynEdit: TSynEdit);
5790begin
5791  ASynEdit.Font.Size := fEditorFontSize;// set size before name for XLFD !
5792  ASynEdit.Font.Name := fEditorFont;
5793  if fDisableAntialiasing then
5794    ASynEdit.Font.Quality := fqNonAntialiased
5795  else
5796    ASynEdit.Font.Quality := fqDefault;
5797end;
5798
5799function TEditorOptions.ExtensionToLazSyntaxHighlighter(Ext: String): TLazSyntaxHighlighter;
5800var
5801  s, CurExt: String;
5802  LangID, StartPos, EndPos: Integer;
5803begin
5804  Result := lshNone;
5805  if (Ext = '') or (Ext = '.') or (HighlighterList = Nil) then
5806    exit;
5807  if Ext[1] = '.' then
5808    Delete(Ext, 1, 1);
5809  LangID := 0;
5810  while LangID < HighlighterList.Count do
5811  begin
5812    s := HighlighterList[LangID].FileExtensions;
5813    StartPos := 1;
5814    while StartPos <= length(s) do
5815    begin
5816      Endpos := StartPos;
5817      while (EndPos <= length(s)) and (s[EndPos] <> ';') do
5818        inc(EndPos);
5819      CurExt := copy(s, Startpos, EndPos - StartPos);
5820      if (CurExt <> '') and (CurExt[1] = '.') then
5821        Delete(CurExt, 1, 1);
5822      if CompareText(CurExt, Ext) = 0 then
5823        exit(HighlighterList[LangID].TheType);
5824      Startpos := EndPos + 1;
5825    end;
5826    inc(LangID);
5827  end;
5828end;
5829
5830procedure TEditorOptions.GetSynEditSettings(ASynEdit: TSynEdit; SimilarEdit: TSynEdit);
5831// read synedit settings from config file
5832// if SimilarEdit is given it is used for speed up
5833var
5834  MarkCaret: TSynEditMarkupHighlightAllCaret;
5835  b: TSynBeautifierPascal;
5836  i: Integer;
5837  mw: TSourceSynEditMarkupHighlightAllMulti;
5838  TermsConf: TEditorUserDefinedWords;
5839  Markup: TSynEditMarkup;
5840begin
5841  // general options
5842  ASynEdit.BeginUpdate(False);
5843  try
5844    ASynEdit.Options := fSynEditOptions;
5845    ASynEdit.Options2 := fSynEditOptions2;
5846    ASynEdit.BlockIndent := fBlockIndent;
5847    ASynEdit.BlockTabIndent := FBlockTabIndent;
5848    (ASynEdit.Beautifier as TSynBeautifier).IndentType := fBlockIndentType;
5849    if ASynEdit.Beautifier is TSynBeautifierPascal then begin
5850      b := ASynEdit.Beautifier as TSynBeautifierPascal;
5851
5852      if FAnsiCommentContinueEnabled then begin
5853        b.AnsiCommentMode := sccPrefixMatch;
5854        b.AnsiIndentMode := FAnsiIndentMode;
5855        b.AnsiMatch := FAnsiCommentMatch;
5856        b.AnsiPrefix := FAnsiCommentPrefix;
5857        b.AnsiMatchLine := sclMatchPrev;
5858        b.AnsiMatchMode := AnsiCommentMatchMode;
5859        b.AnsiCommentIndent := sbitCopySpaceTab;
5860        b.AnsiIndentFirstLineMax := AnsiIndentAlignMax;
5861      end
5862      else begin
5863        b.AnsiCommentMode := sccNoPrefix;
5864        b.AnsiIndentMode := [];
5865      end;
5866
5867      if FCurlyCommentContinueEnabled then begin
5868        b.BorCommentMode := sccPrefixMatch;
5869        b.BorIndentMode := FCurlyIndentMode;
5870        b.BorMatch := FCurlyCommentMatch;
5871        b.BorPrefix := FCurlyCommentPrefix;
5872        b.BorMatchLine := sclMatchPrev;
5873        b.BorMatchMode := CurlyCommentMatchMode;
5874        b.BorCommentIndent := sbitCopySpaceTab;
5875        b.BorIndentFirstLineMax := CurlyIndentAlignMax;
5876      end
5877      else begin
5878        b.BorCommentMode := sccNoPrefix;
5879        b.BorIndentMode := [];
5880      end;
5881
5882      if FSlashCommentContinueEnabled then begin
5883        b.SlashCommentMode := sccPrefixMatch;
5884        b.SlashIndentMode := FSlashIndentMode;
5885        b.SlashMatch := FSlashCommentMatch;
5886        b.SlashPrefix := FSlashCommentPrefix;
5887        b.SlashMatchLine := sclMatchPrev;
5888        b.SlashMatchMode := SlashCommentMatchMode;
5889        b.SlashCommentIndent := sbitCopySpaceTab;
5890        b.ExtendSlashCommentMode := FSlashCommentExtend;
5891        b.SlashIndentFirstLineMax := SlashIndentAlignMax;
5892      end
5893      else begin
5894        b.SlashCommentMode := sccNoPrefix;
5895        b.SlashIndentMode := [];
5896      end;
5897
5898      b.StringBreakEnabled := FStringBreakEnabled;
5899      b.StringBreakAppend  := FStringBreakAppend;
5900      b.StringBreakPrefix  := FStringBreakPrefix;
5901
5902    end;
5903
5904    ASynEdit.TrimSpaceType := FTrimSpaceType;
5905    ASynEdit.TabWidth := fTabWidth;
5906    ASynEdit.BracketHighlightStyle := FBracketHighlightStyle;
5907    {$IFDEF WinIME}
5908    if ASynEdit is TIDESynEditor then begin
5909      if UseMinimumIme
5910      then TIDESynEditor(ASynEdit).CreateMinimumIme
5911      else TIDESynEditor(ASynEdit).CreateFullIme;
5912    end;
5913    {$ENDIF}
5914
5915    if ASynEdit is TIDESynEditor then begin
5916      TIDESynEditor(ASynEdit).HighlightUserWordCount := UserDefinedColors.Count;
5917      for i := 0 to UserDefinedColors.Count - 1 do begin
5918        TermsConf := UserDefinedColors.Lists[i];
5919        mw := TIDESynEditor(ASynEdit).HighlightUserWords[i];
5920        if TermsConf.GlobalList or (not TermsConf.HasKeyAssigned)
5921        then begin
5922          if TermsConf.GlobalTermsCache = nil then
5923            TermsConf.GlobalTermsCache := mw.Terms
5924          else
5925            mw.Terms := TermsConf.GlobalTermsCache;
5926        end
5927        else begin
5928          if mw.Terms = TermsConf.GlobalTermsCache then
5929            mw.Terms := nil;
5930          if TermsConf.GlobalTermsCache <> nil then
5931            TermsConf.GlobalTermsCache.Clear;
5932        end;
5933
5934        mw.MarkupInfo.Assign(TermsConf.ColorAttr);
5935        mw.Clear;
5936        mw.Terms.Assign(TermsConf);
5937        mw.RestoreLocalChanges;
5938        if TermsConf.AddTermCmd <> nil then
5939          mw.AddTermCmd := TermsConf.AddTermCmd.Command;
5940        if TermsConf.RemoveTermCmd <> nil then
5941          mw.RemoveTermCmd := TermsConf.RemoveTermCmd.Command;
5942        if TermsConf.ToggleTermCmd <> nil then
5943          mw.ToggleTermCmd := TermsConf.ToggleTermCmd.Command;
5944        mw.KeyAddTermBounds        := TermsConf.KeyAddTermBounds;
5945        mw.KeyAddCase              := TermsConf.KeyAddCase;
5946        mw.KeyAddWordBoundMaxLen   := TermsConf.KeyAddWordBoundMaxLen;
5947        mw.KeyAddSelectBoundMaxLen := TermsConf.KeyAddSelectBoundMaxLen;
5948        mw.KeyAddSelectSmart       := TermsConf.KeyAddSelectSmart;
5949      end;
5950    end;
5951
5952    {$IFnDEF WithoutSynMultiCaret}
5953    if ASynEdit is TIDESynEditor then begin
5954      TIDESynEditor(ASynEdit).MultiCaret.EnableWithColumnSelection := MultiCaretOnColumnSelect;
5955      TIDESynEditor(ASynEdit).MultiCaret.DefaultMode := FMultiCaretDefaultMode;
5956      TIDESynEditor(ASynEdit).MultiCaret.DefaultColumnSelectMode := FMultiCaretDefaultColumnSelectMode;
5957      if FMultiCaretDeleteSkipLineBreak
5958      then TIDESynEditor(ASynEdit).MultiCaret.Options := TIDESynEditor(ASynEdit).MultiCaret.Options + [smcoDeleteSkipLineBreak]
5959      else TIDESynEditor(ASynEdit).MultiCaret.Options := TIDESynEditor(ASynEdit).MultiCaret.Options - [smcoDeleteSkipLineBreak];
5960    end;
5961    {$ENDIF}
5962
5963    // Display options
5964    ASynEdit.Gutter.Visible := fVisibleGutter;
5965    ASynEdit.Gutter.AutoSize := true;
5966    ASynEdit.Gutter.LineNumberPart.Visible := fShowLineNumbers;
5967    ASynEdit.Gutter.LineNumberPart(0).ShowOnlyLineNumbersMultiplesOf :=
5968      fShowOnlyLineNumbersMultiplesOf;
5969    ASynEdit.RightGutter.Visible := ShowOverviewGutter;
5970    if ASynEdit is TIDESynEditor then
5971      TIDESynEditor(ASynEdit).ShowTopInfo := TopInfoView;
5972
5973    ASynEdit.Gutter.CodeFoldPart.Visible := FUseCodeFolding;
5974    if not FUseCodeFolding then
5975      ASynEdit.UnfoldAll;
5976    ASynEdit.Gutter.CodeFoldPart.ReversePopMenuOrder := ReverseFoldPopUpOrder;
5977
5978    ASynEdit.Gutter.Width := fGutterWidth;
5979    ASynEdit.Gutter.SeparatorPart.Visible := FGutterSeparatorIndex <> -1;
5980    if FGutterSeparatorIndex <> -1 then
5981    ASynEdit.Gutter.SeparatorPart(0).Index := FGutterSeparatorIndex;
5982
5983    ASynEdit.RightEdge := fRightMargin;
5984    if fVisibleRightMargin then
5985      ASynEdit.Options := ASynEdit.Options - [eoHideRightMargin]
5986    else
5987      ASynEdit.Options := ASynEdit.Options + [eoHideRightMargin];
5988
5989    ApplyFontSettingsTo(ASynEdit);
5990    //debugln(['TEditorOptions.GetSynEditSettings ',ASynEdit.font.height]);
5991
5992    ASynEdit.ExtraCharSpacing := fExtraCharSpacing;
5993    ASynEdit.ExtraLineSpacing := fExtraLineSpacing;
5994    ASynEdit.MaxUndo := fUndoLimit;
5995    // The Highlighter on the SynEdit will have been initialized with the configured
5996    // values already (including all the additional-attributes.
5997    // Just copy the colors from the SynEdit's highlighter to the SynEdit's Markup and co
5998    SetMarkupColors(ASynEdit);
5999
6000    MarkCaret := TSynEditMarkupHighlightAllCaret(ASynEdit.MarkupByClass[TSynEditMarkupHighlightAllCaret]);
6001    if assigned(MarkCaret) then begin
6002      if FMarkupCurWordNoTimer then
6003        MarkCaret.WaitTime := 0
6004      else
6005        MarkCaret.WaitTime := FMarkupCurWordTime;
6006      MarkCaret.FullWord := FMarkupCurWordFullLen > 0;
6007      MarkCaret.FullWordMaxLen := FMarkupCurWordFullLen;
6008      MarkCaret.IgnoreKeywords := FMarkupCurWordNoKeyword;
6009      MarkCaret.Trim := FMarkupCurWordTrim;
6010    end;
6011
6012    Markup := ASynEdit.MarkupByClass[TSynEditMarkupFoldColors];
6013    if (Markup <> nil) then
6014      Markup.Enabled := FUseMarkupOutline;
6015
6016    AssignKeyMapTo(ASynEdit, SimilarEdit);
6017
6018    ASynEdit.MouseOptions := [emUseMouseActions];
6019    ASynEdit.MouseActions.Assign(FUserMouseSettings.MainActions);
6020    ASynEdit.MouseSelActions.Assign(FUserMouseSettings.SelActions);
6021    ASynEdit.MouseTextActions.Assign(FUserMouseSettings.TextActions);
6022    ASynEdit.Gutter.MouseActions.Assign(FUserMouseSettings.GutterActions);
6023    if ASynEdit.Gutter.CodeFoldPart <> nil then begin
6024      ASynEdit.Gutter.CodeFoldPart.MouseActions.Assign(FUserMouseSettings.GutterActionsFold);
6025      ASynEdit.Gutter.CodeFoldPart.MouseActionsCollapsed.Assign(FUserMouseSettings.GutterActionsFoldCol);
6026      ASynEdit.Gutter.CodeFoldPart.MouseActionsExpanded.Assign(FUserMouseSettings.GutterActionsFoldExp);
6027    end;
6028    if ASynEdit.Gutter.LineNumberPart <> nil then begin
6029      ASynEdit.Gutter.LineNumberPart.MouseActions.Assign(FUserMouseSettings.GutterActionsLines);
6030    end;
6031    if ASynEdit.Gutter.ChangesPart<> nil then
6032      ASynEdit.Gutter.ChangesPart.MouseActions.Assign(FUserMouseSettings.GutterActionsChanges);
6033
6034    if (ASynEdit.Gutter.SeparatorPart <> nil) and (GutterSeparatorIndex = 2) and ShowLineNumbers then
6035      ASynEdit.Gutter.SeparatorPart.MouseActions.Assign(FUserMouseSettings.GutterActionsLines)
6036    else
6037    if (ASynEdit.Gutter.SeparatorPart <> nil) and (GutterSeparatorIndex >= 2) then
6038      ASynEdit.Gutter.SeparatorPart.MouseActions.Assign(FUserMouseSettings.GutterActionsChanges);
6039    if ASynEdit.RightGutter.LineOverviewPart <> nil then begin
6040      ASynEdit.RightGutter.LineOverviewPart.MouseActions.Assign(FUserMouseSettings.GutterActionsOverView);
6041      ASynEdit.RightGutter.LineOverviewPart.MouseActionsForMarks.Assign(FUserMouseSettings.GutterActionsOverViewMarks);
6042    end;
6043
6044    ASynEdit.ScrollOnEditLeftOptions.Assign(ScrollOnEditLeftOptions);
6045    ASynEdit.ScrollOnEditRightOptions.Assign(ScrollOnEditRightOptions);
6046  finally
6047    ASynEdit.EndUpdate;
6048  end;
6049end;
6050
6051function TEditorOptions.CreateSyn(LazSynHilighter: TLazSyntaxHighlighter): TSrcIDEHighlighter;
6052begin
6053  if LazSyntaxHighlighterClasses[LazSynHilighter] <> Nil then
6054  begin
6055    Result := LazSyntaxHighlighterClasses[LazSynHilighter].Create(Nil);
6056    GetHighlighterSettings(Result);
6057  end
6058  else
6059    Result := Nil;
6060end;
6061
6062function TEditorOptions.CreateSynHighlighter(
6063  LazSynHilighter: TLazSyntaxHighlighter): TObject;
6064begin
6065  Result := CreateSyn(LazSynHilighter);
6066end;
6067
6068procedure TEditorOptions.GetSynEditPreviewSettings(APreviewEditor: TObject);
6069// read synedit setings from config file
6070var
6071  ASynEdit: TSynEdit;
6072begin
6073  if not (APreviewEditor is TSynEdit) then
6074    exit;
6075  ASynEdit := TSynEdit(APreviewEditor);
6076
6077  // Get real settings
6078  GetSynEditSettings(ASynEdit);
6079
6080  // Change to preview settings
6081  ASynEdit.Options := ASynEdit.Options
6082    - SynEditPreviewExcludeOptions + SynEditPreviewIncludeOptions;
6083  ASynEdit.Options2 := ASynEdit.Options2 - SynEditPreviewExcludeOptions2;
6084  ASynEdit.ReadOnly := True;
6085end;
6086
6087{ TColorSchemeAttribute }
6088
6089procedure TColorSchemeAttribute.SetMarkupFoldLineAlpha(AValue: Byte);
6090begin
6091  if FMarkupFoldLineAlpha = AValue then Exit;
6092  FMarkupFoldLineAlpha := AValue;
6093  Changed;
6094end;
6095
6096procedure TColorSchemeAttribute.SetMarkupFoldLineColor(AValue: TColor);
6097begin
6098  if FMarkupFoldLineColor = AValue then Exit;
6099  FMarkupFoldLineColor := AValue;
6100  Changed;
6101end;
6102
6103procedure TColorSchemeAttribute.SetMarkupFoldLineStyle(AValue: TSynLineStyle);
6104begin
6105  if FMarkupFoldLineStyle = AValue then Exit;
6106  FMarkupFoldLineStyle := AValue;
6107  Changed;
6108end;
6109
6110procedure TColorSchemeAttribute.Init;
6111begin
6112  inherited Init;
6113  FFeatures := [hafBackColor, hafForeColor, hafFrameColor, hafStyle, hafFrameStyle, hafFrameEdges, hafPrior];
6114  FMarkupFoldLineColor := clNone;
6115  FMarkupFoldLineStyle := slsSolid;
6116  FMarkupFoldLineAlpha := 0;
6117end;
6118
6119function TColorSchemeAttribute.GetIsUsingSchemeGlobals: Boolean;
6120begin
6121  Result := FUseSchemeGlobals and (GetSchemeGlobal <> nil);
6122end;
6123
6124function TColorSchemeAttribute.GetSchemeGlobal: TColorSchemeAttribute;
6125begin
6126  if FAlreadyGotSchemeGlobal then
6127    Result := FSchemeGlobalCache
6128  else begin
6129    Result := nil;
6130    if (FOwner <> nil) and (FOwner.FOwner <> nil) and
6131       (FOwner.FOwner.FDefaultColors <> nil)
6132    then
6133      Result := FOwner.FOwner.FDefaultColors.Attribute[StoredName];
6134    if Result = Self then
6135      Result := nil;
6136    FSchemeGlobalCache := Result;
6137    FAlreadyGotSchemeGlobal := True;
6138  end;
6139end;
6140
6141constructor TColorSchemeAttribute.Create(ASchemeLang: TColorSchemeLanguage;
6142  attribName: PString; const aStoredName: String);
6143begin
6144  inherited Create(attribName, aStoredName);
6145  FOwner := ASchemeLang;
6146  FUseSchemeGlobals := True;
6147end;
6148
6149function TColorSchemeAttribute.IsEnabled: boolean;
6150begin
6151  Result := (inherited IsEnabled) or (FMarkupFoldLineColor <> clNone);
6152end;
6153
6154procedure TColorSchemeAttribute.ApplyTo(aDest: TSynHighlighterAttributes;
6155  aDefault: TColorSchemeAttribute);
6156// aDefault (if supplied) is usually the Schemes agnDefault / DefaultAttribute
6157var
6158  Src: TColorSchemeAttribute;
6159begin
6160  Src := Self;
6161  if IsUsingSchemeGlobals then
6162    Src := GetSchemeGlobal;
6163  aDest.BeginUpdate;
6164  try
6165    aDest.Background := Src.Background;
6166    aDest.Foreground := Src.Foreground;
6167    aDest.FrameColor := Src.FrameColor;
6168    aDest.FrameEdges := Src.FrameEdges;
6169    aDest.FrameStyle := Src.FrameStyle;
6170    aDest.Style      := Src.Style;
6171    if hafStyleMask in Src.Features then
6172      aDest.StyleMask  := Src.StyleMask
6173    else
6174      aDest.StyleMask  := [low(TFontStyle)..high(TFontStyle)];
6175
6176    if aDest is TSynHighlighterAttributesModifier then begin
6177      TSynHighlighterAttributesModifier(aDest).ForeAlpha := Src.ForeAlpha;
6178      TSynHighlighterAttributesModifier(aDest).BackAlpha := Src.BackAlpha;
6179      TSynHighlighterAttributesModifier(aDest).FrameAlpha := Src.FrameAlpha;
6180    end;
6181
6182    if hafPrior in Src.Features then begin
6183      aDest.ForePriority      := Src.ForePriority;
6184      aDest.BackPriority      := Src.BackPriority;
6185      aDest.FramePriority     := Src.FramePriority;
6186      aDest.BoldPriority      := Src.BoldPriority;
6187      aDest.ItalicPriority    := Src.ItalicPriority;
6188      aDest.UnderlinePriority := Src.UnderlinePriority;
6189    end;
6190
6191    if not (aDest is TSynSelectedColor) then begin
6192      if aDefault <> nil then begin
6193        if aDefault.IsUsingSchemeGlobals then
6194          aDefault := aDefault.GetSchemeGlobal;
6195        if Background = clDefault then
6196          aDest.Background := aDefault.Background;
6197        if Foreground = clDefault then
6198          aDest.Foreground := aDefault.Foreground;
6199        if FrameColor = clDefault then begin
6200          aDest.FrameColor := aDefault.FrameColor;
6201          aDest.FrameEdges := aDefault.FrameEdges;
6202          aDest.FrameStyle := aDefault.FrameStyle;
6203        end;
6204      end;
6205
6206      if aDest is TColorSchemeAttribute then
6207        TColorSchemeAttribute(aDest).Group := Src.Group;
6208    end;
6209  finally
6210    aDest.EndUpdate;
6211  end;
6212end;
6213
6214procedure TColorSchemeAttribute.Assign(Src: TPersistent);
6215var
6216  SrcAttr: TColorSchemeAttribute;
6217begin
6218  inherited Assign(Src);
6219  FFeatures := [hafBackColor, hafForeColor, hafFrameColor,
6220                hafStyle, hafFrameStyle, hafFrameEdges, hafPrior];
6221  if Src is TSynHighlighterAttributesModifier then
6222    FFeatures := FFeatures + [hafAlpha, hafStyleMask];
6223
6224  if Src is TColorSchemeAttribute then begin
6225    SrcAttr := TColorSchemeAttribute(Src);
6226    FGroup               := SrcAttr.FGroup;
6227    FUseSchemeGlobals    := SrcAttr.FUseSchemeGlobals;
6228    FFeatures            := SrcAttr.FFeatures;
6229    FMarkupFoldLineColor := SrcAttr.FMarkupFoldLineColor;
6230    FMarkupFoldLineStyle := SrcAttr.FMarkupFoldLineStyle;
6231    FMarkupFoldLineAlpha := SrcAttr.FMarkupFoldLineAlpha;
6232  end;
6233end;
6234
6235function TColorSchemeAttribute.Equals(Other: TColorSchemeAttribute): Boolean;
6236begin
6237  Result := (FGroup      = Other.FGroup) and
6238            (FUseSchemeGlobals = Other.FUseSchemeGlobals) and
6239            // ignore resourcestring Name and Caption
6240            (StoredName  = Other.StoredName) and
6241            (Background  = Other.Background) and
6242            (Foreground  = Other.Foreground) and
6243            (FrameColor  = Other.FrameColor) and
6244            ( (FrameColor = clNone) or
6245              ( (FrameStyle = Other.FrameStyle) and
6246                (FrameEdges = Other.FrameEdges)
6247              )
6248            ) and
6249            (Style       = Other.Style) and
6250            (StyleMask   = Other.StyleMask) and
6251            (Features   = Other.Features);
6252end;
6253
6254function TColorSchemeAttribute.GetStoredValuesForAttrib: TColorSchemeAttribute;
6255var
6256  csl: TColorSchemeLanguage;
6257begin
6258  Result := nil;
6259  if FOwner <> nil then begin
6260    csl := FOwner.GetStoredValuesForLanguage;
6261    if csl <> nil then
6262      Result := csl.Attribute[StoredName];
6263  end;
6264end;
6265
6266procedure TColorSchemeAttribute.LoadFromXml(aXMLConfig: TRttiXMLConfig; aPath: String;
6267  Defaults: TColorSchemeAttribute; Version: Integer);
6268var
6269  Path: String;
6270begin
6271  // FormatVersion >= 5
6272  (* Note: This is currently always called with a default, so the nil handling isn't needed*)
6273  Assert(Version > 4, 'TColorSchemeAttribute.LoadFromXml: Version ('+IntToStr(Version)+' < 5.');
6274  if StoredName = '' then exit;
6275  Path := aPath + StrToValidXMLName(StoredName) + '/';
6276  if aXMLConfig.HasPath(Path, False) then
6277    aXMLConfig.ReadObject(Path, Self, Defaults)
6278  else begin
6279    if (Defaults <> Self) and (Defaults <> nil) then begin
6280      // do not copy (Stored)Name or Features ...
6281      Background := Defaults.Background;
6282      Foreground := Defaults.Foreground;
6283      FrameColor := Defaults.FrameColor;
6284      FrameEdges := Defaults.FrameEdges;
6285      FrameStyle := Defaults.FrameStyle;
6286      Style      := Defaults.Style;
6287      StyleMask  := Defaults.StyleMask;
6288      UseSchemeGlobals  := Defaults.UseSchemeGlobals;
6289      ForePriority      := Defaults.ForePriority;
6290      BackPriority      := Defaults.BackPriority;
6291      FramePriority     := Defaults.FramePriority;
6292      BoldPriority      := Defaults.BoldPriority;
6293      ItalicPriority    := Defaults.ItalicPriority;
6294      UnderlinePriority := Defaults.UnderlinePriority;
6295    end;
6296  end;
6297end;
6298
6299procedure TColorSchemeAttribute.SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String;
6300  Defaults: TColorSchemeAttribute);
6301var
6302  AttriName: String;
6303begin
6304  if StoredName = '' then
6305    exit;
6306  // Delete Version <= 4
6307  AttriName := OldAdditionalAttributeName(StoredName);
6308  if AttriName <> '' then
6309    aXMLConfig.DeletePath(aPath + StrToValidXMLName(AttriName));
6310
6311  aXMLConfig.WriteObject(aPath + StrToValidXMLName(StoredName) + '/', Self, Defaults);
6312end;
6313
6314{ TColorSchemeLanguage }
6315
6316function TColorSchemeLanguage.GetAttribute(Index: String): TColorSchemeAttribute;
6317var
6318  Idx: Integer;
6319begin
6320  Idx := FAttributes.IndexOf(Index);
6321  if Idx = -1 then
6322    Result := nil
6323  else
6324    Result := TColorSchemeAttribute(FAttributes.Objects[Idx]);
6325end;
6326
6327function TColorSchemeLanguage.GetAttributeAtPos(Index: Integer): TColorSchemeAttribute;
6328begin
6329  Result := TColorSchemeAttribute(FAttributes.Objects[Index]);
6330end;
6331
6332function TColorSchemeLanguage.GetAttributeByEnum(Index: TAdditionalHilightAttribute): TColorSchemeAttribute;
6333begin
6334  Result := Attribute[GetAddiHilightAttrName(Index)];
6335end;
6336
6337function TColorSchemeLanguage.GetName: String;
6338begin
6339  Result := FOwner.Name;
6340end;
6341
6342function TColorSchemeLanguage.GetStoredValuesForLanguage: TColorSchemeLanguage;
6343var
6344  cs: TColorScheme;
6345begin
6346  Result := nil;
6347  if FOwner <> nil then begin
6348    cs := FOwner.GetStoredValuesForScheme;
6349    if cs <> nil then
6350      Result := cs.ColorScheme[FLanguage];
6351  end;
6352end;
6353
6354constructor TColorSchemeLanguage.Create(AGroup: TColorScheme;
6355  ALang: TLazSyntaxHighlighter; IsSchemeDefault: Boolean);
6356begin
6357  inherited Create;
6358  FIsSchemeDefault := IsSchemeDefault;
6359  FAttributes := TQuickStringlist.Create;
6360  FOwner := AGroup;
6361  FHighlighter := nil;
6362  FLanguage := ALang;
6363  if LazSyntaxHighlighterClasses[ALang] <> nil then begin
6364    FHighlighter := LazSyntaxHighlighterClasses[ALang].Create(nil);
6365    FLanguageName := FHighlighter.LanguageName;
6366  end;
6367end;
6368
6369constructor TColorSchemeLanguage.CreateWithDefColor(AGroup: TColorScheme;
6370  ALang: TLazSyntaxHighlighter; IsSchemeDefault: Boolean);
6371begin
6372  Create(AGroup, ALang, IsSchemeDefault);
6373  FDefaultAttribute := TColorSchemeAttribute.Create(Self, @dlgAddHiAttrDefault, 'ahaDefault');
6374  FDefaultAttribute.Features := [hafBackColor, hafForeColor];
6375  FDefaultAttribute.Group := agnDefault;
6376  FAttributes.AddObject(FDefaultAttribute.StoredName, FDefaultAttribute);
6377end;
6378
6379constructor TColorSchemeLanguage.CreateFromXml(AGroup: TColorScheme;
6380  ALang: TLazSyntaxHighlighter; aXMLConfig: TRttiXMLConfig;
6381  const aPath: String; IsSchemeDefault: Boolean);
6382var
6383  hla: TSynHighlighterAttributes;
6384  csa: TColorSchemeAttribute;
6385  aha: TAdditionalHilightAttribute;
6386  FormatVersion, i: Integer;
6387begin
6388  CreateWithDefColor(AGroup, ALang, IsSchemeDefault); // don't call inherited Create
6389
6390  FAttributes.Sorted := False;
6391  if FHighlighter <> nil then begin
6392    for i := 0 to FHighlighter.AttrCount - 1 do begin
6393      hla := FHighlighter.Attribute[i];
6394      csa := TColorSchemeAttribute.Create(Self, hla.Caption, hla.StoredName);
6395      csa.Assign(hla);
6396      csa.Group := agnLanguage;
6397      FAttributes.AddObject(csa.StoredName, csa);
6398    end;
6399  end;
6400
6401  for aha := Low(TAdditionalHilightAttribute) to High(TAdditionalHilightAttribute) do begin
6402    if aha = ahaNone then continue;
6403    csa := TColorSchemeAttribute.Create(Self, @AdditionalHighlightAttributes[aha],
6404                                        GetAddiHilightAttrName(aha) );
6405    csa.Features := ahaSupportedFeatures[aha];
6406    csa.Group    := ahaGroupMap[aha];
6407    FAttributes.AddObject(csa.StoredName, csa);
6408  end;
6409  FAttributes.Sorted := true;
6410  FormatVersion := aXMLConfig.GetValue(aPath + 'Version', 0);
6411  LoadFromXml(aXMLConfig, aPath, nil, FormatVersion);
6412end;
6413
6414destructor TColorSchemeLanguage.Destroy;
6415begin
6416  Clear;
6417  FreeAndNil(FHighlighter);
6418  FreeAndNil(FAttributes);
6419  // FreeAndNil(FDefaultAttribute); // part of the list
6420end;
6421
6422procedure TColorSchemeLanguage.Clear;
6423var
6424  i: Integer;
6425begin
6426  if Assigned(FAttributes) then
6427    for i := 0 to FAttributes.Count - 1 do
6428      TColorSchemeAttribute(FAttributes.Objects[i]).Free;
6429  FAttributes.Clear;
6430end;
6431
6432procedure TColorSchemeLanguage.Assign(Src: TColorSchemeLanguage);
6433var
6434  i: Integer;
6435  Attr, SrcAttr: TColorSchemeAttribute;
6436begin
6437  Clear;
6438  FAttributes.Sorted := false;
6439  FLanguage := Src.FLanguage;
6440  FLanguageName := Src.FLanguageName;
6441  FDefaultAttribute := nil;
6442  for i := 0 to Src.AttributeCount - 1 do begin
6443    SrcAttr := Src.AttributeAtPos[i];
6444    Attr := TColorSchemeAttribute.Create(Self, SrcAttr.Caption, SrcAttr.StoredName);
6445    Attr.Assign(SrcAttr);
6446    FAttributes.AddObject(Attr.StoredName, Attr);
6447    if SrcAttr = Src.DefaultAttribute then
6448      FDefaultAttribute := Attr;
6449  end;
6450  FAttributes.Sorted := true;
6451end;
6452
6453function TColorSchemeLanguage.Equals(Other: TColorSchemeLanguage): Boolean;
6454var
6455  i: Integer;
6456  csa, othercsa: TColorSchemeAttribute;
6457begin
6458  Result := //FDefaultAttribute.Equals(Other.FDefaultAttribute) and
6459            (FLanguage = Other.FLanguage) and
6460            (FAttributes.Count = Other.FAttributes.Count);
6461  i := FAttributes.Count - 1;
6462  while Result and (i >= 0) do begin
6463    csa := AttributeAtPos[i];
6464    othercsa := Other.Attribute[csa.StoredName];
6465    Result := Result and (othercsa <> nil) and csa.Equals(othercsa);
6466    dec(i);
6467  end;
6468end;
6469
6470function TColorSchemeLanguage.IndexOfAttr(AnAttr: TColorSchemeAttribute): Integer;
6471begin
6472  Result := FAttributes.IndexOfObject(AnAttr);
6473end;
6474
6475procedure TColorSchemeLanguage.LoadFromXml(aXMLConfig: TRttiXMLConfig;
6476  const aPath: String; Defaults: TColorSchemeLanguage; ColorVersion: Integer;
6477  const aOldPath: String);
6478var
6479  Def, EmptyDef, CurAttr: TColorSchemeAttribute;
6480  FormatVersion: longint;
6481  TmpPath: String;
6482  i: Integer;
6483begin
6484//  Path := 'EditorOptions/Color/'
6485  if not FIsSchemeDefault then
6486    TmpPath := aPath + 'Lang' + StrToValidXMLName(FLanguageName) + '/'
6487  else
6488    TmpPath := aPath;
6489  if aXMLConfig.HasChildPaths(TmpPath) then begin
6490    FormatVersion := aXMLConfig.GetValue(TmpPath + 'Version', 0);
6491    if FormatVersion > ColorVersion then
6492      FormatVersion := ColorVersion;
6493    if FIsSchemeDefault and (FormatVersion < 6) then
6494      FormatVersion := 6;
6495  end
6496  else
6497    FormatVersion := 6;
6498  FFormatVersion := FormatVersion;
6499  TmpPath := TmpPath + 'Scheme' + StrToValidXMLName(Name) + '/';
6500
6501  if (aOldPath <> '') and (FormatVersion > 1) then begin
6502    // convert some old data (loading user settings only):
6503    // aOldPath should be 'EditorOptions/Display/'
6504    if aXMLConfig.GetValue(aOldPath + 'RightMarginColor', '') <> '' then
6505      aXMLConfig.SetValue(TmpPath + 'ahaRightMargin/ForegroundColor/Value',
6506                          aXMLConfig.GetValue(aOldPath + 'RightMarginColor', 0)
6507                         );
6508    if aXMLConfig.GetValue(aOldPath + 'GutterColor', '') <> '' then
6509      aXMLConfig.SetValue(TmpPath + 'ahaGutter/BackgroundColor/Value',
6510                          aXMLConfig.GetValue(aOldPath + 'GutterColor', 0)
6511                         );
6512  end;
6513
6514  // Defaults <> nil => saving diff between Scheme(=Defaults) and userSettings
6515  // Defaults = nil
6516  //   Attribute has SchemeDefault => Save diff to SchemeDefault
6517  //     SchemeDefault_Attri.UseSchemeGlobals must be TRUE => so it serves as default
6518  //   Attribute hasn't SchemeDefault => Save diff to empty
6519  if Defaults = nil then
6520    // default all colors = clNone
6521    EmptyDef := TColorSchemeAttribute.Create(Self, nil, '')
6522  else
6523    EmptyDef := nil;
6524
6525  for i := 0 to AttributeCount - 1 do begin
6526    CurAttr := AttributeAtPos[i];
6527    if Defaults <> nil then
6528      Def := Defaults.Attribute[CurAttr.StoredName]
6529    else begin
6530      Def := CurAttr.GetSchemeGlobal;
6531      if Def = nil then
6532        Def := EmptyDef;
6533    end;
6534    CurAttr.LoadFromXml(aXMLConfig, TmpPath, Def, FormatVersion);
6535    if (ColorVersion < 9)
6536    and (CurAttr.StoredName = GetAddiHilightAttrName(ahaMouseLink)) then
6537    begin
6538      // upgrade ahaMouseLink
6539      CurAttr.FrameColor := CurAttr.Foreground;
6540      CurAttr.Background := clNone;
6541      CurAttr.Style := [];
6542      CurAttr.StyleMask := [];
6543      CurAttr.FrameStyle := slsSolid;
6544      CurAttr.FrameEdges := sfeBottom;
6545    end;
6546
6547    if (ColorVersion < 12) and (CurAttr.Group = agnOutlineColors) then
6548      CurAttr.MarkupFoldLineColor := CurAttr.Foreground;
6549  end;
6550  FreeAndNil(EmptyDef);
6551
6552  // Version 5 and before stored the global background on the Whitespace attribute.
6553  // If a whitespace Attribute was loaded (UseSchemeGlobals=false) then copy it
6554  if (FormatVersion <= 5) and (DefaultAttribute <> nil)
6555  and (FHighlighter <> nil) and (FHighlighter.WhitespaceAttribute <> nil) then
6556  begin
6557    CurAttr := Attribute[Highlighter.WhitespaceAttribute.StoredName];
6558    if (CurAttr <> nil) and not CurAttr.UseSchemeGlobals then
6559      DefaultAttribute.Background := CurAttr.Background;
6560  end;
6561end;
6562
6563procedure TColorSchemeLanguage.SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String;
6564  Defaults: TColorSchemeLanguage);
6565var
6566  Def, EmptyDef, CurAttr: TColorSchemeAttribute;
6567  i: Integer;
6568begin
6569  if (FLanguageName = '') and (not FIsSchemeDefault) then
6570    exit;
6571  if not FIsSchemeDefault then
6572    aPath := aPath + 'Lang' + StrToValidXMLName(FLanguageName) + '/';
6573  if (Defaults <> nil) and Self.Equals(Defaults) then begin
6574    aXMLConfig.DeletePath(aPath + 'Scheme' + StrToValidXMLName(Name));
6575    if not (FIsSchemeDefault or aXMLConfig.HasChildPaths(aPath)) then
6576      aXMLConfig.DeletePath(aPath);
6577    exit;
6578  end;
6579  aXMLConfig.SetValue(aPath + 'Version', EditorOptsFormatVersion);
6580  aPath := aPath + 'Scheme' + StrToValidXMLName(Name) + '/';
6581
6582  if (Defaults = nil) then
6583    // default all colors = clNone
6584    EmptyDef := TColorSchemeAttribute.Create(Self, nil, '')
6585  else
6586    EmptyDef := nil;
6587
6588  for i := 0 to AttributeCount - 1 do begin
6589    CurAttr := AttributeAtPos[i];
6590    if Defaults <> nil then
6591      Def := Defaults.Attribute[CurAttr.StoredName]
6592    else begin
6593      Def := CurAttr.GetSchemeGlobal;
6594      if Def = nil then
6595        Def := EmptyDef;
6596    end;
6597    CurAttr.SaveToXml(aXMLConfig, aPath, Def);
6598  end;
6599  FreeAndNil(EmptyDef);
6600end;
6601
6602procedure TColorSchemeLanguage.ApplyTo(ASynEdit: TSynEdit);
6603  procedure SetMarkupColor(aha: TAdditionalHilightAttribute; aMarkup : TSynSelectedColor);
6604  var Attrib: TColorSchemeAttribute;
6605  begin
6606    Attrib := AttributeByEnum[aha];
6607    if Attrib <> nil then
6608      Attrib.ApplyTo(aMarkup)
6609    else
6610      DefaultAttribute.ApplyTo(aMarkup);
6611  end;
6612  procedure SetMarkupColorByClass(aha: TAdditionalHilightAttribute; aClass: TSynEditMarkupClass);
6613  begin
6614    if assigned(ASynEdit.MarkupByClass[aClass]) then
6615      SetMarkupColor(aha, ASynEdit.MarkupByClass[aClass].MarkupInfo);
6616  end;
6617  procedure SetGutterColorByClass(aha: TAdditionalHilightAttribute;
6618                                  aClass: TSynGutterPartBaseClass);
6619  begin
6620    if assigned(ASynEdit.Gutter.Parts.ByClass[aClass, 0]) then
6621      SetMarkupColor(aha, ASynEdit.Gutter.Parts.ByClass[aClass, 0].MarkupInfo);
6622  end;
6623  function GetUsedAttr(aha: TAdditionalHilightAttribute): TColorSchemeAttribute;
6624  begin
6625    Result := AttributeByEnum[aha];
6626    if Assigned(Result) and Result.IsUsingSchemeGlobals then
6627      Result := Result.GetSchemeGlobal;
6628  end;
6629var
6630  Attri: TColorSchemeAttribute;
6631  i, c, j: Integer;
6632  IDESynEdit: TIDESynEditor;
6633  aha: TAdditionalHilightAttribute;
6634  col: TColor;
6635  OGutter: TSynGutterLineOverview;
6636  OGutterProv: TSynGutterLineOverviewProvider;
6637begin
6638  ASynEdit.BeginUpdate;
6639  try
6640    try
6641      Attri := DefaultAttribute;
6642      if Attri.IsUsingSchemeGlobals then
6643        Attri := Attri.GetSchemeGlobal;
6644      if (Attri.Background = clNone) or (Attri.Background = clDefault)
6645        then aSynEdit.Color := clWhite
6646        else aSynEdit.Color := Attri.Background;
6647      if (Attri.Foreground = clNone) or (Attri.Foreground = clDefault)
6648        then aSynEdit.Font.Color := clBlack
6649        else aSynEdit.Font.Color := Attri.Foreground;
6650    except
6651      aSynEdit.Color := clWhite;
6652      aSynEdit.Font.Color := clBlack;
6653    end;
6654
6655    Attri := GetUsedAttr(ahaGutter);
6656    if Attri <> nil then
6657      aSynEdit.Gutter.Color := Attri.Background;
6658
6659    Attri := GetUsedAttr(ahaRightMargin);
6660    if Attri <> nil then
6661      aSynEdit.RightEdgeColor := Attri.Foreground;
6662
6663    SetMarkupColor(ahaTextBlock,         aSynEdit.SelectedColor);
6664    SetMarkupColor(ahaIncrementalSearch, aSynEdit.IncrementColor);
6665    SetMarkupColor(ahaHighlightAll,      aSynEdit.HighlightAllColor);
6666    SetMarkupColor(ahaBracketMatch,      aSynEdit.BracketMatchColor);
6667    SetMarkupColor(ahaMouseLink,         aSynEdit.MouseLinkColor);
6668    SetMarkupColor(ahaFoldedCode,        aSynEdit.FoldedCodeColor);
6669    SetMarkupColor(ahaFoldedCodeLine,    aSynEdit.FoldedCodeLineColor);
6670    SetMarkupColor(ahaHiddenCodeLine,    aSynEdit.HiddenCodeLineColor);
6671    SetMarkupColor(ahaLineHighlight,     aSynEdit.LineHighlightColor);
6672    if ASynEdit is TIDESynEditor then begin
6673      SetMarkupColor(ahaTopInfoHint,  TIDESynEditor(aSynEdit).TopInfoMarkup);
6674      Attri := GetUsedAttr(ahaCaretColor);
6675      if Attri <> nil then begin
6676        TIDESynEditor(aSynEdit).CaretColor := Attri.Foreground;
6677
6678        col := Attri.Background;
6679        if (col = clNone) or (col = clDefault) then
6680          col := $606060;
6681        TIDESynEditor(aSynEdit).MultiCaret.Color := col;
6682      end;
6683    end;
6684    SetMarkupColorByClass(ahaHighlightWord, TSynEditMarkupHighlightAllCaret);
6685    SetMarkupColorByClass(ahaWordGroup,     TSynEditMarkupWordGroup);
6686    SetMarkupColorByClass(ahaSpecialVisibleChars, TSynEditMarkupSpecialChar);
6687    if ASynEdit is TIDESynEditor then begin
6688      with TIDESynEditor(ASynEdit) do begin
6689        Attri := AttributeByEnum[ahaIfDefBlockInactive];
6690        if Attri <> nil
6691          then Attri.ApplyTo(MarkupIfDef.MarkupInfoDisabled )
6692          else MarkupIfDef.MarkupInfoDisabled.Clear;
6693        Attri := AttributeByEnum[ahaIfDefBlockActive];
6694        if Attri <> nil
6695          then Attri.ApplyTo(MarkupIfDef.MarkupInfoEnabled )
6696          else MarkupIfDef.MarkupInfoEnabled.Clear;
6697        Attri := AttributeByEnum[ahaIfDefBlockTmpActive];
6698        if Attri <> nil
6699          then Attri.ApplyTo(MarkupIfDef.MarkupInfoTempEnabled )
6700          else MarkupIfDef.MarkupInfoTempEnabled.Clear;
6701        Attri := AttributeByEnum[ahaIfDefNodeInactive];
6702        if Attri <> nil
6703          then Attri.ApplyTo(MarkupIfDef.MarkupInfoNodeDisabled )
6704          else MarkupIfDef.MarkupInfoNodeDisabled.Clear;
6705        Attri := AttributeByEnum[ahaIfDefNodeActive];
6706        if Attri <> nil
6707          then Attri.ApplyTo(MarkupIfDef.MarkupInfoNodeEnabled )
6708          else MarkupIfDef.MarkupInfoNodeEnabled.Clear;
6709        Attri := AttributeByEnum[ahaIfDefNodeTmpActive];
6710        if Attri <> nil
6711          then Attri.ApplyTo(MarkupIfDef.MarkupInfoTempNodeEnabled )
6712          else MarkupIfDef.MarkupInfoTempNodeEnabled.Clear;
6713      end;
6714    end;
6715    SetGutterColorByClass(ahaLineNumber,      TSynGutterLineNumber);
6716    SetGutterColorByClass(ahaModifiedLine,    TSynGutterChanges);
6717    SetGutterColorByClass(ahaCodeFoldingTree, TSynGutterCodeFolding);
6718    SetGutterColorByClass(ahaGutterSeparator, TSynGutterSeparator);
6719
6720    OGutter := TSynGutterLineOverview(ASynEdit.RightGutter.Parts.ByClass[TSynGutterLineOverview, 0]);
6721    if OGutter <> nil then begin
6722      for i := 0 to OGutter.Providers.Count - 1 do begin
6723        OGutterProv := OGutter.Providers[i];
6724        if OGutterProv is TSynGutterLOvProviderModifiedLines then begin
6725          Attri := GetUsedAttr(ahaModifiedLine);
6726          if Attri <> nil then begin
6727            OGutterProv.Color := Attri.FrameColor;
6728            TSynGutterLOvProviderModifiedLines(OGutterProv).ColorSaved := Attri.Foreground;
6729          end;
6730        end
6731        else
6732        if OGutterProv is TSynGutterLOvProviderCurrentPage then begin
6733          Attri := GetUsedAttr(ahaOverviewGutter);
6734          if Attri <> nil then begin
6735            OGutterProv.Color := Attri.FrameColor;
6736          end;
6737        end
6738        else
6739        if OGutterProv is TIDESynGutterLOvProviderPascal then begin
6740          Attri := GetUsedAttr(ahaOverviewGutter);
6741          if Attri <> nil then begin
6742            OGutterProv.Color := Attri.Foreground;
6743            TIDESynGutterLOvProviderPascal(OGutterProv).Color2 := Attri.Background;
6744          end;
6745        end;
6746      end;
6747    end;
6748
6749    if ASynEdit is TIDESynEditor then
6750    begin
6751      IDESynEdit := TIDESynEditor(ASynEdit);
6752
6753      Attri := GetUsedAttr(ahaIdentComplWindow);
6754      if Attri<>nil then
6755      begin
6756        IDESynEdit.MarkupIdentComplWindow.TextColor := Attri.Foreground;
6757        IDESynEdit.MarkupIdentComplWindow.WindowColor:= Attri.Background;
6758      end else
6759      begin
6760        IDESynEdit.MarkupIdentComplWindow.TextColor := clNone;
6761        IDESynEdit.MarkupIdentComplWindow.WindowColor:= clNone;
6762      end;
6763
6764      Attri := GetUsedAttr(ahaIdentComplWindowBorder);
6765      if Attri<>nil then
6766        IDESynEdit.MarkupIdentComplWindow.BorderColor:= Attri.Foreground
6767      else
6768        IDESynEdit.MarkupIdentComplWindow.BorderColor:= clNone;
6769
6770      Attri := GetUsedAttr(ahaIdentComplWindowHighlight);
6771      if Attri<>nil then
6772        IDESynEdit.MarkupIdentComplWindow.HighlightColor:= Attri.Foreground
6773      else
6774        IDESynEdit.MarkupIdentComplWindow.HighlightColor:= clNone;
6775
6776      Attri := GetUsedAttr(ahaIdentComplWindowSelection);
6777      if Attri<>nil then
6778      begin
6779        IDESynEdit.MarkupIdentComplWindow.TextSelectedColor:= Attri.Foreground;
6780        IDESynEdit.MarkupIdentComplWindow.BackgroundSelectedColor:= Attri.Background;
6781      end else
6782      begin
6783        IDESynEdit.MarkupIdentComplWindow.TextSelectedColor := clNone;
6784        IDESynEdit.MarkupIdentComplWindow.BackgroundSelectedColor:= clNone;
6785      end;
6786    end;
6787
6788    i := aSynEdit.PluginCount - 1;
6789    while (i >= 0) and not(aSynEdit.Plugin[i] is TSynPluginTemplateEdit) do
6790      dec(i);
6791    if i >= 0 then begin
6792      SetMarkupColor(ahaTemplateEditOther,TSynPluginTemplateEdit(aSynEdit.Plugin[i]).MarkupInfo);
6793      SetMarkupColor(ahaTemplateEditCur,  TSynPluginTemplateEdit(aSynEdit.Plugin[i]).MarkupInfoCurrent);
6794      SetMarkupColor(ahaTemplateEditSync, TSynPluginTemplateEdit(aSynEdit.Plugin[i]).MarkupInfoSync);
6795    end;
6796    i := aSynEdit.PluginCount - 1;
6797    while (i >= 0) and not(aSynEdit.Plugin[i] is TSynPluginSyncroEdit) do
6798      dec(i);
6799    if i >= 0 then begin
6800      SetMarkupColor(ahaSyncroEditOther, TSynPluginSyncroEdit(aSynEdit.Plugin[i]).MarkupInfo);
6801      SetMarkupColor(ahaSyncroEditCur,   TSynPluginSyncroEdit(aSynEdit.Plugin[i]).MarkupInfoCurrent);
6802      SetMarkupColor(ahaSyncroEditSync,  TSynPluginSyncroEdit(aSynEdit.Plugin[i]).MarkupInfoSync);
6803      SetMarkupColor(ahaSyncroEditArea,  TSynPluginSyncroEdit(aSynEdit.Plugin[i]).MarkupInfoArea);
6804    end;
6805    i := aSynEdit.MarkupCount - 1;
6806    while (i >= 0) and not(aSynEdit.Markup[i] is TSynEditMarkupFoldColors) do
6807      dec(i);
6808    if i >= 0 then begin
6809      TSynEditMarkupFoldColors(aSynEdit.Markup[i]).ColorCount := 10;
6810      j := 0;
6811      c := 0;
6812      for aha := ahaOutlineLevel1Color to ahaOutlineLevel10Color do begin
6813        Attri := GetUsedAttr(aha);
6814        if Attri = nil then Continue;
6815        if (Attri.IsEnabled) or
6816           (FFormatVersion >= 12)
6817        then begin
6818          SetMarkupColor(aha, TSynEditMarkupFoldColors(aSynEdit.Markup[i]).Color[j]);
6819
6820          TSynEditMarkupFoldColors(aSynEdit.Markup[i]).LineColor[j].Color := Attri.MarkupFoldLineColor;
6821          TSynEditMarkupFoldColors(aSynEdit.Markup[i]).LineColor[j].Style := Attri.MarkupFoldLineStyle;
6822          TSynEditMarkupFoldColors(aSynEdit.Markup[i]).LineColor[j].Alpha := Attri.MarkupFoldLineAlpha;
6823          TSynEditMarkupFoldColors(aSynEdit.Markup[i]).LineColor[j].Priority := Attri.FramePriority;
6824          inc(j);
6825          if Attri.IsEnabled then
6826            c := j;
6827        end;
6828      end;
6829      TSynEditMarkupFoldColors(aSynEdit.Markup[i]).ColorCount := c; // discard unused colors at the end
6830    end;
6831  finally
6832    ASynEdit.EndUpdate;
6833  end;
6834end;
6835
6836procedure TColorSchemeLanguage.ApplyTo(AHLighter: TSynCustomHighlighter);
6837var
6838  i: Integer;
6839  Attr: TColorSchemeAttribute;
6840  hlattrs: TSynHighlighterAttributes;
6841begin
6842  AHLighter.BeginUpdate;
6843  try
6844    for i := 0 to AHLighter.AttrCount - 1 do begin
6845      hlattrs := AHLighter.Attribute[i];
6846      Attr := Attribute[hlattrs.StoredName];
6847      if Attr <> nil then
6848        Attr.ApplyTo(hlattrs, DefaultAttribute);
6849    end;
6850  finally
6851    AHLighter.EndUpdate;
6852  end;
6853end;
6854
6855function TColorSchemeLanguage.AttributeCount: Integer;
6856begin
6857  Result := FAttributes.Count;
6858end;
6859
6860{ TColorScheme }
6861
6862function TColorScheme.GetColorScheme(Index: TLazSyntaxHighlighter): TColorSchemeLanguage;
6863begin
6864  Result := FColorSchemes[CompatibleLazSyntaxHilighter[Index]];
6865end;
6866
6867function TColorScheme.GetColorSchemeBySynClass(Index: TClass): TColorSchemeLanguage;
6868var
6869  i: TLazSyntaxHighlighter;
6870begin
6871  for i := low(TLazSyntaxHighlighter) to high(TLazSyntaxHighlighter) do
6872    if LazSyntaxHighlighterClasses[i] = Index then
6873      exit(FColorSchemes[CompatibleLazSyntaxHilighter[i]]);
6874  Result := nil;
6875end;
6876
6877function TColorScheme.GetStoredValuesForScheme: TColorScheme;
6878begin
6879  Result:=ColorSchemeFactory.ColorSchemeGroup[Name];
6880end;
6881
6882constructor TColorScheme.Create(const AName: String);
6883begin
6884  inherited Create;
6885  FName := AName;
6886end;
6887
6888constructor TColorScheme.CreateFromXml(aXMLConfig: TRttiXMLConfig; const AName, aPath: String);
6889var
6890  i: TLazSyntaxHighlighter;
6891begin
6892  Create(AName);
6893  FDefaultColors := TColorSchemeLanguage.CreateFromXml(Self, lshNone, aXMLConfig,
6894                                                       aPath + 'Globals/', True);
6895  for i := low(TLazSyntaxHighlighter) to high(TLazSyntaxHighlighter) do
6896    // do not create duplicates
6897    if CompatibleLazSyntaxHilighter[i] = i then
6898      FColorSchemes[i] := TColorSchemeLanguage.CreateFromXml(Self, i, aXMLConfig,
6899                                                             aPath, False)
6900    else
6901      FColorSchemes[i] := nil;
6902end;
6903
6904destructor TColorScheme.Destroy;
6905var
6906  i: TLazSyntaxHighlighter;
6907begin
6908  inherited Destroy;
6909  FreeAndNil(FDefaultColors);
6910  for i := low(TLazSyntaxHighlighter) to high(TLazSyntaxHighlighter) do
6911    FreeAndNil(FColorSchemes[i]);
6912end;
6913
6914procedure TColorScheme.Assign(Src: TColorScheme);
6915var
6916  i: TLazSyntaxHighlighter;
6917begin
6918  if Src.FDefaultColors = nil then
6919    FreeAndNil(FDefaultColors)
6920  else if FDefaultColors = nil then
6921    FDefaultColors := TColorSchemeLanguage.Create(Self, lshNone, True);
6922  if FDefaultColors <> nil then
6923    FDefaultColors.Assign(Src.FDefaultColors);
6924  for i := low(FColorSchemes) to high(FColorSchemes) do begin
6925    if Src.FColorSchemes[i] = nil then begin
6926      FreeAndNil(FColorSchemes[i]);
6927    end else begin
6928      if FColorSchemes[i] = nil then
6929        FColorSchemes[i] := TColorSchemeLanguage.Create(Self, i, False);
6930      FColorSchemes[i].Assign(Src.FColorSchemes[i]);
6931    end;
6932  end;
6933end;
6934
6935procedure TColorScheme.LoadFromXml(aXMLConfig: TRttiXMLConfig; aPath: String;
6936  Defaults: TColorScheme; aOldPath: String);
6937var
6938  i: TLazSyntaxHighlighter;
6939  Def: TColorSchemeLanguage;
6940  FormatVersion: longint;
6941begin
6942  FormatVersion := aXMLConfig.GetValue(aPath + 'Version', 0);
6943  if Defaults <> nil then
6944    Def := Defaults.DefaultColors
6945  else
6946    Def := nil;
6947  FDefaultColors.LoadFromXml(aXMLConfig, aPath + 'Globals/', Def, FormatVersion);
6948  for i := low(TLazSyntaxHighlighter) to high(TLazSyntaxHighlighter) do
6949    if ColorScheme[i] <> nil then begin
6950      if Defaults <> nil then
6951        Def := Defaults.ColorScheme[i]
6952      else
6953        Def := nil;
6954      ColorScheme[i].LoadFromXml(aXMLConfig, aPath, Def, FormatVersion, aOldPath);
6955    end;
6956end;
6957
6958procedure TColorScheme.SaveToXml(aXMLConfig: TRttiXMLConfig; aPath: String;
6959  Defaults: TColorScheme);
6960var
6961  i: TLazSyntaxHighlighter;
6962  Def: TColorSchemeLanguage;
6963begin
6964  if Defaults <> nil then
6965    Def := Defaults.DefaultColors
6966  else
6967    Def := nil;
6968  FDefaultColors.SaveToXml(aXMLConfig, aPath + 'Globals/', Def);
6969  if not aXMLConfig.HasChildPaths(aPath + 'Globals') then
6970    aXMLConfig.DeletePath(aPath + 'Globals');
6971  for i := low(TLazSyntaxHighlighter) to high(TLazSyntaxHighlighter) do
6972    if ColorScheme[i] <> nil then begin
6973      if Defaults <> nil then
6974        Def := Defaults.ColorScheme[i]
6975      else
6976        Def := nil;
6977      ColorScheme[i].SaveToXml(aXMLConfig, aPath, Def);
6978    end;
6979  aXMLConfig.SetValue(aPath + 'Version', EditorOptsFormatVersion);
6980end;
6981
6982{ TColorSchemeFactory }
6983
6984function TColorSchemeFactory.GetColorSchemeGroup(Index: String): TColorScheme;
6985var
6986  Idx: integer;
6987begin
6988  Idx := FMappings.IndexOf(Index);
6989  if Idx = -1 then
6990    Result := nil
6991  else
6992    Result := TColorScheme(FMappings.Objects[Idx]);
6993end;
6994
6995function TColorSchemeFactory.GetColorSchemeGroupAtPos(Index: Integer): TColorScheme;
6996begin
6997  Result := TColorScheme(FMappings.Objects[Index]);
6998end;
6999
7000constructor TColorSchemeFactory.Create;
7001begin
7002  inherited Create;
7003  FMappings := TQuickStringlist.Create;
7004  FMappings.Sorted := true;
7005end;
7006
7007destructor TColorSchemeFactory.Destroy;
7008begin
7009  Clear;
7010  FreeAndNil(FMappings);
7011  inherited Destroy;
7012end;
7013
7014procedure TColorSchemeFactory.Clear;
7015var
7016  i: Integer;
7017begin
7018  if Assigned(FMappings) then
7019  begin
7020    for i := 0 to FMappings.Count - 1 do
7021      TColorScheme(FMappings.Objects[i]).Free;
7022    FMappings.Clear;
7023  end;
7024end;
7025
7026procedure TColorSchemeFactory.Assign(Src: TColorSchemeFactory);
7027var
7028  lMapping: TColorScheme;
7029  i: Integer;
7030begin
7031  FMappings.Sorted := False;
7032  Clear;
7033  for i := 0 to Src.FMappings.Count - 1 do begin
7034    lMapping := TColorScheme.Create(Src.ColorSchemeGroupAtPos[i].Name);
7035    lMapping.Assign(Src.ColorSchemeGroupAtPos[i]);
7036    FMappings.AddObject(lMapping.Name, lMapping);
7037  end;
7038  FMappings.Sorted := true;
7039end;
7040
7041procedure TColorSchemeFactory.LoadFromXml(aXMLConfig: TRttiXMLConfig;
7042  const aPath: String; Defaults: TColorSchemeFactory; const aOldPath: String);
7043var
7044  i: Integer;
7045  Def: TColorScheme;
7046begin
7047  for i := 0 to FMappings.Count - 1 do begin
7048    if Defaults <> nil then
7049      Def := Defaults.ColorSchemeGroupAtPos[i]
7050    else
7051      Def := nil;
7052    ColorSchemeGroupAtPos[i].LoadFromXml(aXMLConfig, aPath, Def, aOldPath);
7053  end;
7054  // all Schemes have read (and relocated) the old values
7055  if aOldPath <> '' then begin
7056    aXMLConfig.DeletePath(aOldPath + 'RightMarginColor');
7057    aXMLConfig.DeletePath(aOldPath + 'GutterColor');
7058  end;
7059end;
7060
7061procedure TColorSchemeFactory.SaveToXml(aXMLConfig: TRttiXMLConfig;
7062  const aPath: String; Defaults: TColorSchemeFactory);
7063var
7064  i: Integer;
7065  Def: TColorScheme;
7066begin
7067  for i := 0 to FMappings.Count - 1 do begin
7068    if Defaults <> nil then
7069      Def := Defaults.ColorSchemeGroupAtPos[i]
7070    else
7071      Def := nil;
7072    ColorSchemeGroupAtPos[i].SaveToXml(aXMLConfig, aPath, Def);
7073  end
7074end;
7075
7076procedure TColorSchemeFactory.RegisterScheme(aXMLConfig: TRttiXMLConfig; AName, aPath: String);
7077var
7078  lMapping: TColorScheme;
7079  i, j: integer;
7080begin
7081  i := FMappings.IndexOf(AName);
7082  if i <> -1 then begin
7083    j := 0;
7084    repeat
7085      inc(j);
7086      i := FMappings.IndexOf(AName+'_'+IntToStr(j));
7087    until i = -1;
7088    AName := AName+'_'+IntToStr(j);
7089    DebugLn(['TColorSchemeFactory.RegisterScheme: Adjusting AName to ', AName]);
7090  end;
7091  lMapping := TColorScheme.CreateFromXml(aXMLConfig, AName, aPath);
7092  FMappings.AddObject(AName, lMapping);
7093end;
7094
7095procedure TColorSchemeFactory.GetRegisteredSchemes(AList: TStrings);
7096var
7097  i: integer;
7098begin
7099  AList.BeginUpdate;
7100  try
7101    AList.Clear;
7102    for i := 0 to FMappings.Count - 1 do
7103      AList.Add(TColorScheme(FMappings.Objects[i]).Name);
7104  finally
7105    AList.EndUpdate;
7106  end;
7107end;
7108
7109{ TQuickStringlist }
7110
7111function TQuickStringlist.DoCompareText(const s1, s2: string): PtrInt;
7112begin
7113  Result := CompareText(s1, s2);
7114end;
7115
7116
7117initialization
7118  RegisterIDEOptionsGroup(GroupEditor, TEditorOptions);
7119
7120finalization
7121  ColorSchemeFactory.Free;
7122  HighlighterListSingleton.Free;
7123
7124end.
7125