1{-------------------------------------------------------------------------------
2The contents of this file are subject to the Mozilla Public License
3Version 1.1 (the "License"); you may not use this file except in compliance
4with the License. You may obtain a copy of the License at
5http://www.mozilla.org/MPL/
6
7Software distributed under the License is distributed on an "AS IS" basis,
8WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9the specific language governing rights and limitations under the License.
10
11The Original Code is: SynHighlighterCpp.pas, released 2000-04-10.
12The Original Code is based on the dcjCppSyn.pas file from the
13mwEdit component suite by Martin Waldenburg and other developers, the Initial
14Author of this file is Michael Trier.
15All Rights Reserved.
16
17Contributors to the SynEdit and mwEdit projects are listed in the
18Contributors.txt file.
19
20Alternatively, the contents of this file may be used under the terms of the
21GNU General Public License Version 2 or later (the "GPL"), in which case
22the provisions of the GPL are applicable instead of those above.
23If you wish to allow use of your version of this file only under the terms
24of the GPL and not to allow others to use your version of this file
25under the MPL, indicate your decision by deleting the provisions above and
26replace them with the notice and other provisions required by the GPL.
27If you do not delete the provisions above, a recipient may use your version
28of this file under either the MPL or the GPL.
29
30$Id$
31
32You may retrieve the latest version of this file at the SynEdit home page,
33located at http://SynEdit.SourceForge.net
34
35Known Issues:
36  - strings on multiple lines are not supported
37-------------------------------------------------------------------------------}
38{
39@abstract(Provides a C++ syntax highlighter for SynEdit)
40@author(Michael Trier)
41@created(1998)
42@lastmod(2000-05-05)
43The SynHighlighterCpp unit provides SynEdit with a C++ syntax highlighter.
44Thanks to Martin Waldenburg.
45}
46unit SynHighlighterCpp;
47
48{$I synedit.inc}
49
50interface
51
52uses
53  SysUtils,
54  LCLIntf,
55  Classes, Registry, Controls, Graphics,
56  SynEditTypes, SynEditHighlighter, SynEditStrConst;
57
58type
59  TtkTokenKind = (tkAsm, tkComment, tkDirective, tkIdentifier, tkKey, tkNull,
60    tkNumber, tkSpace, tkString, tkSymbol, tkUnknown);
61
62  TxtkTokenKind = (
63    xtkAdd, xtkAddAssign, xtkAnd, xtkAndAssign, xtkArrow, xtkAssign,
64    xtkBitComplement, xtkBraceClose, xtkBraceOpen, xtkColon, xtkComma,
65    xtkDecrement, xtkDivide, xtkDivideAssign, xtkEllipse, xtkGreaterThan,
66    xtkGreaterThanEqual, xtkIncOr, xtkIncOrAssign, xtkIncrement, xtkLessThan,
67    xtkLessThanEqual, xtkLogAnd, xtkLogComplement, xtkLogEqual, xtkLogOr,
68    xtkMod, xtkModAssign, xtkMultiplyAssign, xtkNotEqual, xtkPoint, xtkQuestion,
69    xtkRoundClose, xtkRoundOpen, xtkScopeResolution, xtkSemiColon, xtkShiftLeft,
70    xtkShiftLeftAssign, xtkShiftRight, xtkShiftRightAssign, xtkSquareClose,
71    xtkSquareOpen, xtkStar, xtkSubtract, xtkSubtractAssign, xtkXor,
72    xtkXorAssign);
73
74  TRangeState = (rsUnknown, rsAnsiC, rsAnsiCAsm, rsAnsiCAsmBlock, rsAsm,
75                 rsAsmBlock, rsDirective, rsDirectiveComment, {rsString34, rsString39,}
76                 rsAsmBlockString, rsAsmString, rsDirectiveString, rsString
77                );
78
79const
80  // map the range into a stringtype range (comments are never mapped into string)
81  // keep the range, if it already is a string-range
82  SynCppRangeToStringRange: Array [TRangeState] of TRangeState
83              = (rsString, rsString, rsString, rsString, rsAsmString,
84                 rsAsmBlockString, rsDirectiveString, rsString,
85                 rsAsmBlockString, rsAsmString, rsDirectiveString, rsString
86                );
87  // map the string-range back into the correct range
88  // non string ranges are kept as they were
89  SynCppStringRangeToRange: Array [TRangeState] of TRangeState
90              = (rsUnknown, rsAnsiC, rsAnsiCAsm, rsAnsiCAsmBlock, rsAsm,
91                 rsAsmBlock, rsDirective, rsDirectiveComment,
92                 rsAsmBlock, rsAsm, rsDirective, rsUnknown
93                );
94
95type
96
97  TProcTableProc = procedure of object;
98
99  PIdentFuncTableFunc = ^TIdentFuncTableFunc;
100  TIdentFuncTableFunc = function: TtkTokenKind of object;
101
102  TSynCppSyn = class(TSynCustomHighlighter)
103  private
104    fAsmStart: Boolean;
105    fRange: TRangeState;
106    fLine: PChar;
107    fProcTable: array[#0..#255] of TProcTableProc;
108    Run: LongInt;
109    fStringLen: Integer;
110    fToIdent: PChar;
111    fTokenPos: Integer;
112    FTokenID: TtkTokenKind;
113    FExtTokenID: TxtkTokenKind;
114    fLineNumber: Integer;
115    fIdentFuncTable: array[0..206] of TIdentFuncTableFunc;
116    fAsmAttri: TSynHighlighterAttributes;
117    fCommentAttri: TSynHighlighterAttributes;
118    fDirecAttri: TSynHighlighterAttributes;
119    fIdentifierAttri: TSynHighlighterAttributes;
120    fInvalidAttri: TSynHighlighterAttributes;
121    fKeyAttri: TSynHighlighterAttributes;
122    fNumberAttri: TSynHighlighterAttributes;
123    fSpaceAttri: TSynHighlighterAttributes;
124    fStringAttri: TSynHighlighterAttributes;
125    fSymbolAttri: TSynHighlighterAttributes;
126    function KeyHash(ToHash: PChar): Integer;
127    function KeyComp(const aKey: String): Boolean;
128    function Func17: TtkTokenKind;
129    function Func21: TtkTokenKind;
130    function Func32: TtkTokenKind;
131    function Func34: TtkTokenKind;
132    function Func36: TtkTokenKind;
133    function Func40: TtkTokenKind;
134    function Func42: TtkTokenKind;
135    function Func45: TtkTokenKind;
136    function Func46: TtkTokenKind;
137    function Func48: TtkTokenKind;
138    function Func52: TtkTokenKind;
139    function Func54: TtkTokenKind;
140    function Func57: TtkTokenKind;
141    function Func58: TtkTokenKind;
142    function Func59: TtkTokenKind;
143    function Func60: TtkTokenKind;
144    function Func61: TtkTokenKind;
145    function Func62: TtkTokenKind;
146    function Func64: TtkTokenKind;
147    function Func65: TtkTokenKind;
148    function Func66: TtkTokenKind;
149    function Func67: TtkTokenKind;
150    function Func68: TtkTokenKind;
151    function Func69: TtkTokenKind;
152    function Func71: TtkTokenKind;
153    function Func74: TtkTokenKind;
154    function Func75: TtkTokenKind;
155    function Func76: TtkTokenKind;
156    function Func78: TtkTokenKind;
157    function Func79: TtkTokenKind;
158    function Func81: TtkTokenKind;
159    function Func82: TtkTokenKind;
160    function Func85: TtkTokenKind;
161    function Func86: TtkTokenKind;
162    function Func88: TtkTokenKind;
163    function Func89: TtkTokenKind;
164    function Func92: TtkTokenKind;
165    function Func97: TtkTokenKind;
166    function Func98: TtkTokenKind;
167    function Func100: TtkTokenKind;
168    function Func101: TtkTokenKind;
169    function Func102: TtkTokenKind;
170    function Func104: TtkTokenKind;
171    function Func105: TtkTokenKind;
172    function Func106: TtkTokenKind;
173    function Func107: TtkTokenKind;
174    function Func109: TtkTokenKind;
175    function Func110: TtkTokenKind;
176    function Func115: TtkTokenKind;
177    function Func116: TtkTokenKind;
178    function Func121: TtkTokenKind;
179    function Func123: TtkTokenKind;
180    function Func125: TtkTokenKind;
181    function Func141: TtkTokenKind;
182    function Func206: TtkTokenKind;
183    procedure AnsiCProc;
184    procedure AndSymbolProc;
185    procedure AsciiCharProc;
186    procedure AtSymbolProc;
187    procedure BraceCloseProc;
188    procedure BraceOpenProc;
189    procedure CRProc;
190    procedure ColonProc;
191    procedure CommaProc;
192    procedure DirectiveProc;
193    procedure EqualProc;
194    procedure GreaterProc;
195    procedure IdentProc;
196    procedure LFProc;
197    procedure LowerProc;
198    procedure MinusProc;
199    procedure ModSymbolProc;
200    procedure NotSymbolProc;
201    procedure NullProc;
202    procedure NumberProc;
203    procedure OrSymbolProc;
204    procedure PlusProc;
205    procedure PointProc;
206    procedure QuestionProc;
207    procedure RoundCloseProc;
208    procedure RoundOpenProc;
209    procedure SemiColonProc;
210    procedure SlashProc;
211    procedure SpaceProc;
212    procedure SquareCloseProc;
213    procedure SquareOpenProc;
214    procedure StarProc;
215    procedure StringProc;
216    procedure TildeProc;
217    procedure XOrSymbolProc;
218    procedure UnknownProc;
219    function AltFunc: TtkTokenKind;
220    procedure InitIdent;
221    function IdentKind(MayBe: PChar): TtkTokenKind;
222    procedure MakeMethodTables;
223  protected
224    function GetIdentChars: TSynIdentChars; override;
225    function GetExtTokenID: TxtkTokenKind;
226  public
227    class function GetCapabilities: TSynHighlighterCapabilities; override;
228    class function GetLanguageName: string; override;
229  public
230    constructor Create(AOwner: TComponent); override;
231    function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
232      override;
233    function GetEol: Boolean; override;
234    function GetRange: Pointer; override;
235    function GetTokenID: TtkTokenKind;
236    procedure SetLine(const NewValue: String; LineNumber:Integer); override;
237    function GetToken: String; override;
238    procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override;
239    function GetTokenAttribute: TSynHighlighterAttributes; override;
240    function GetTokenKind: integer; override;
241    function GetTokenPos: Integer; override;
242    procedure Next; override;
243    procedure SetRange(Value: Pointer); override;
244    procedure ResetRange; override;
245    function UseUserSettings(settingIndex: integer): boolean; override;
246    procedure EnumUserSettings(settings: TStrings); override;
247    property ExtTokenID: TxtkTokenKind read GetExtTokenID;
248  published
249    property AsmAttri: TSynHighlighterAttributes read fAsmAttri write fAsmAttri;
250    property CommentAttri: TSynHighlighterAttributes read fCommentAttri
251      write fCommentAttri;
252    property DirecAttri: TSynHighlighterAttributes read fDirecAttri
253      write fDirecAttri;
254    property IdentifierAttri: TSynHighlighterAttributes read fIdentifierAttri
255      write fIdentifierAttri;
256    property InvalidAttri: TSynHighlighterAttributes read fInvalidAttri
257      write fInvalidAttri;
258    property KeyAttri: TSynHighlighterAttributes read fKeyAttri write fKeyAttri;
259    property NumberAttri: TSynHighlighterAttributes read fNumberAttri
260      write fNumberAttri;
261    property SpaceAttri: TSynHighlighterAttributes read fSpaceAttri
262      write fSpaceAttri;
263    property StringAttri: TSynHighlighterAttributes read fStringAttri
264      write fStringAttri;
265    property SymbolAttri: TSynHighlighterAttributes read fSymbolAttri
266      write fSymbolAttri;
267  end;
268
269implementation
270
271var
272  Identifiers: array[#0..#255] of ByteBool;
273  mHashTable: array[#0..#255] of Integer;
274
275procedure MakeIdentTable;
276var
277  I: Char;
278begin
279  for I := #0 to #255 do
280  begin
281    Case I of
282      '_', '0'..'9', 'a'..'z', 'A'..'Z': Identifiers[I] := True;
283    else Identifiers[I] := False;
284    end;
285    Case I in['a'..'z', 'A'..'Z'] of { Bug fix: mHashTable['_'] was uninitialised. [Kit] }
286      True:
287        begin
288          if (I > #64) and (I < #91) then mHashTable[I] := Ord(I) - 64 else
289            mHashTable[I] := Ord(I) - 95;
290        end;
291    else mHashTable[I] := 0;
292    end;
293  end;
294end;
295
296procedure TSynCppSyn.InitIdent;
297var
298  I: Integer;
299  pF: PIdentFuncTableFunc;
300begin
301  pF := PIdentFuncTableFunc(@fIdentFuncTable);
302  for I := Low(fIdentFuncTable) to High(fIdentFuncTable) do begin
303    pF^ := @AltFunc;
304    Inc(pF);
305  end;
306  fIdentFuncTable[17] := @Func17;
307  fIdentFuncTable[21] := @Func21;
308  fIdentFuncTable[32] := @Func32;
309  fIdentFuncTable[34] := @Func34;
310  fIdentFuncTable[36] := @Func36;
311  fIdentFuncTable[40] := @Func40;
312  fIdentFuncTable[42] := @Func42;
313  fIdentFuncTable[45] := @Func45;
314  fIdentFuncTable[46] := @Func46;
315  fIdentFuncTable[48] := @Func48;
316  fIdentFuncTable[52] := @Func52;
317  fIdentFuncTable[54] := @Func54;
318  fIdentFuncTable[57] := @Func57;
319  fIdentFuncTable[58] := @Func58;
320  fIdentFuncTable[59] := @Func59;
321  fIdentFuncTable[60] := @Func60;
322  fIdentFuncTable[61] := @Func61;
323  fIdentFuncTable[62] := @Func62;
324  fIdentFuncTable[64] := @Func64;
325  fIdentFuncTable[65] := @Func65;
326  fIdentFuncTable[66] := @Func66;
327  fIdentFuncTable[67] := @Func67;
328  fIdentFuncTable[68] := @Func68;
329  fIdentFuncTable[69] := @Func69;
330  fIdentFuncTable[71] := @Func71;
331  fIdentFuncTable[74] := @Func74;
332  fIdentFuncTable[75] := @Func75;
333  fIdentFuncTable[76] := @Func76;
334  fIdentFuncTable[78] := @Func78;
335  fIdentFuncTable[79] := @Func79;
336  fIdentFuncTable[81] := @Func81;
337  fIdentFuncTable[82] := @Func82;
338  fIdentFuncTable[85] := @Func85;
339  fIdentFuncTable[86] := @Func86;
340  fIdentFuncTable[88] := @Func88;
341  fIdentFuncTable[89] := @Func89;
342  fIdentFuncTable[92] := @Func92;
343  fIdentFuncTable[97] := @Func97;
344  fIdentFuncTable[98] := @Func98;
345  fIdentFuncTable[100] := @Func100;
346  fIdentFuncTable[101] := @Func101;
347  fIdentFuncTable[102] := @Func102;
348  fIdentFuncTable[104] := @Func104;
349  fIdentFuncTable[105] := @Func105;
350  fIdentFuncTable[106] := @Func106;
351  fIdentFuncTable[107] := @Func107;
352  fIdentFuncTable[109] := @Func109;
353  fIdentFuncTable[110] := @Func110;
354  fIdentFuncTable[115] := @Func115;
355  fIdentFuncTable[116] := @Func116;
356  fIdentFuncTable[121] := @Func121;
357  fIdentFuncTable[123] := @Func123;
358  fIdentFuncTable[125] := @Func125;
359  fIdentFuncTable[141] := @Func141;
360  fIdentFuncTable[206] := @Func206;
361end;
362
363function TSynCppSyn.KeyHash(ToHash: PChar): Integer;
364begin
365  Result := 0;
366  while ToHash^ in ['_', '0'..'9', 'a'..'z', 'A'..'Z'] do
367  begin
368    inc(Result, mHashTable[ToHash^]);
369    inc(ToHash);
370  end;
371  fStringLen := ToHash - fToIdent;
372end; { KeyHash }
373
374function TSynCppSyn.KeyComp(const aKey: String): Boolean;
375var
376  I: Integer;
377  Temp: PChar;
378begin
379  Temp := fToIdent;
380  if Length(aKey) = fStringLen then
381  begin
382    Result := True;
383    for i := 1 to fStringLen do
384    begin
385      if Temp^ <> aKey[i] then
386      begin
387        Result := False;
388        break;
389      end;
390      inc(Temp);
391    end;
392  end else Result := False;
393end; { KeyComp }
394
395function TSynCppSyn.Func17: TtkTokenKind;
396begin
397  if KeyComp('if') then Result := tkKey else Result := tkIdentifier;
398end;
399
400function TSynCppSyn.Func21: TtkTokenKind;
401begin
402  if KeyComp('do') then Result := tkKey else Result := tkIdentifier;
403end;
404
405function TSynCppSyn.Func32: TtkTokenKind;
406begin
407  if KeyComp('cdecl') then Result := tkKey else
408    if KeyComp('case') then Result := tkKey else
409      if KeyComp('_cdecl') then Result := tkKey else
410        if KeyComp('__cdecl') then Result := tkKey else Result := tkIdentifier;
411end;
412
413function TSynCppSyn.Func34: TtkTokenKind;
414begin
415  if KeyComp('char') then Result := tkKey else Result := tkIdentifier;
416end;
417
418function TSynCppSyn.Func36: TtkTokenKind;
419begin
420  if KeyComp('asm') or KeyComp('_asm') or KeyComp('__asm') then
421  begin
422    Result := tkKey;
423    fRange := rsAsm;
424    fAsmStart := True;
425  end else
426    Result := tkIdentifier;
427end;
428
429function TSynCppSyn.Func40: TtkTokenKind;
430begin
431  if KeyComp('catch') then Result := tkKey else Result := tkIdentifier;
432end;
433
434function TSynCppSyn.Func42: TtkTokenKind;
435begin
436  if KeyComp('for') then Result := tkKey else
437    if KeyComp('break') then Result := tkKey else Result := tkIdentifier;
438end;
439
440function TSynCppSyn.Func45: TtkTokenKind;
441begin
442  if KeyComp('else') then Result := tkKey else
443    if KeyComp('new') then Result := tkKey else Result := tkIdentifier;
444end;
445
446function TSynCppSyn.Func46: TtkTokenKind;
447begin
448  if KeyComp('__int8') then Result := tkKey else
449    if KeyComp('__int16') then Result := tkKey else
450      if KeyComp('int') then Result := tkKey else
451        if KeyComp('__int32') then Result := tkKey else
452          if KeyComp('__int64') then Result := tkKey else Result := tkIdentifier;
453end;
454
455function TSynCppSyn.Func48: TtkTokenKind;
456begin
457  if KeyComp('false') then Result := tkKey else
458    if KeyComp('bool') then Result := tkKey else Result := tkIdentifier;
459end;
460
461function TSynCppSyn.Func52: TtkTokenKind;
462begin
463  if KeyComp('long') then Result := tkKey else Result := tkIdentifier;
464end;
465
466function TSynCppSyn.Func54: TtkTokenKind;
467begin
468  if KeyComp('void') then Result := tkKey else Result := tkIdentifier;
469end;
470
471function TSynCppSyn.Func57: TtkTokenKind;
472begin
473  if KeyComp('enum') then Result := tkKey else
474    if KeyComp('delete') then Result := tkKey else Result := tkIdentifier;
475end;
476
477function TSynCppSyn.Func58: TtkTokenKind;
478begin
479  if KeyComp('_pascal') then Result := tkKey else
480    if KeyComp('__pascal') then Result := tkKey else
481      if KeyComp('pascal') then Result := tkKey else Result := tkIdentifier;
482end;
483
484function TSynCppSyn.Func59: TtkTokenKind;
485begin
486  if KeyComp('class') then Result := tkKey else
487    if KeyComp('float') then Result := tkKey else Result := tkIdentifier;
488end;
489
490function TSynCppSyn.Func60: TtkTokenKind;
491begin
492  if KeyComp('this') then Result := tkKey else Result := tkIdentifier;
493end;
494
495function TSynCppSyn.Func61: TtkTokenKind;
496begin
497  if KeyComp('goto') then Result := tkKey else
498    if KeyComp('auto') then Result := tkKey else Result := tkIdentifier;
499end;
500
501function TSynCppSyn.Func62: TtkTokenKind;
502begin
503  if KeyComp('__thread') then Result := tkKey else
504    if KeyComp('while') then Result := tkKey else
505      if KeyComp('friend') then Result := tkKey else Result := tkIdentifier;
506end;
507
508function TSynCppSyn.Func64: TtkTokenKind;
509begin
510  if KeyComp('signed') then Result := tkKey else Result := tkIdentifier;
511end;
512
513function TSynCppSyn.Func65: TtkTokenKind;
514begin
515  if KeyComp('double') then Result := tkKey else Result := tkIdentifier;
516end;
517
518function TSynCppSyn.Func66: TtkTokenKind;
519begin
520  if KeyComp('__try') then Result := tkKey else
521    if KeyComp('try') then Result := tkKey else Result := tkIdentifier;
522end;
523
524function TSynCppSyn.Func67: TtkTokenKind;
525begin
526  if KeyComp('__dispid') then Result := tkKey else Result := tkIdentifier;
527end;
528
529function TSynCppSyn.Func68: TtkTokenKind;
530begin
531  if KeyComp('true') then Result := tkKey else Result := tkIdentifier;
532end;
533
534function TSynCppSyn.Func69: TtkTokenKind;
535begin
536  if KeyComp('public') then Result := tkKey else
537    if KeyComp('inline') then Result := tkKey else Result := tkIdentifier;
538end;
539
540function TSynCppSyn.Func71: TtkTokenKind;
541begin
542  if KeyComp('__rtti') then Result := tkKey else Result := tkIdentifier;
543end;
544
545function TSynCppSyn.Func74: TtkTokenKind;
546begin
547  if KeyComp('__classid') then Result := tkKey else Result := tkIdentifier;
548end;
549
550function TSynCppSyn.Func75: TtkTokenKind;
551begin
552  if KeyComp('__declspec') then Result := tkKey else
553    if KeyComp('using') then Result := tkKey else Result := tkIdentifier;
554end;
555
556function TSynCppSyn.Func76: TtkTokenKind;
557begin
558  if KeyComp('const') then Result := tkKey else
559    if KeyComp('default') then Result := tkKey else Result := tkIdentifier;
560end;
561
562function TSynCppSyn.Func78: TtkTokenKind;
563begin
564  if KeyComp('_stdcall') then Result := tkKey else
565    if KeyComp('union') then Result := tkKey else
566      if KeyComp('__stdcall') then Result := tkKey else
567        if KeyComp('static') then Result := tkKey else Result := tkIdentifier;
568end;
569
570function TSynCppSyn.Func79: TtkTokenKind;
571begin
572  if KeyComp('__except') then Result := tkKey else
573    if KeyComp('wchar_t') then Result := tkKey else Result := tkIdentifier;
574end;
575
576function TSynCppSyn.Func81: TtkTokenKind;
577begin
578  if KeyComp('mutable') then Result := tkKey else Result := tkIdentifier;
579end;
580
581function TSynCppSyn.Func82: TtkTokenKind;
582begin
583  if KeyComp('_fastcall') then Result := tkKey else
584    if KeyComp('__fastcall') then Result := tkKey else Result := tkIdentifier;
585end;
586
587function TSynCppSyn.Func85: TtkTokenKind;
588begin
589  if KeyComp('short') then Result := tkKey else
590    if KeyComp('typeid') then Result := tkKey else Result := tkIdentifier;
591end;
592
593function TSynCppSyn.Func86: TtkTokenKind;
594begin
595  if KeyComp('sizeof') then Result := tkKey else
596    if KeyComp('__finally') then Result := tkKey else
597      if KeyComp('namespace') then Result := tkKey else Result := tkIdentifier;
598end;
599
600function TSynCppSyn.Func88: TtkTokenKind;
601begin
602  if KeyComp('switch') then Result := tkKey else
603    if KeyComp('typedef') then Result := tkKey else Result := tkIdentifier;
604end;
605
606function TSynCppSyn.Func89: TtkTokenKind;
607begin
608  if KeyComp('throw') then Result := tkKey else Result := tkIdentifier;
609end;
610
611function TSynCppSyn.Func92: TtkTokenKind;
612begin
613  if KeyComp('extern') then Result := tkKey else Result := tkIdentifier;
614end;
615
616function TSynCppSyn.Func97: TtkTokenKind;
617begin
618  if KeyComp('__import') then Result := tkKey else
619    if KeyComp('_import') then Result := tkKey else Result := tkIdentifier;
620end;
621
622function TSynCppSyn.Func98: TtkTokenKind;
623begin
624  if KeyComp('private') then Result := tkKey else Result := tkIdentifier;
625end;
626
627function TSynCppSyn.Func100: TtkTokenKind;
628begin
629  if KeyComp('template') then Result := tkKey else
630    if KeyComp('__closure') then Result := tkKey else Result := tkIdentifier;
631end;
632
633function TSynCppSyn.Func101: TtkTokenKind;
634begin
635  if KeyComp('unsigned') then Result := tkKey else Result := tkIdentifier;
636end;
637
638function TSynCppSyn.Func102: TtkTokenKind;
639begin
640  if KeyComp('return') then Result := tkKey else Result := tkIdentifier;
641end;
642
643function TSynCppSyn.Func104: TtkTokenKind;
644begin
645  if KeyComp('volatile') then Result := tkKey else
646    if KeyComp('_export') then Result := tkKey else
647      if KeyComp('__export') then Result := tkKey else Result := tkIdentifier;
648end;
649
650function TSynCppSyn.Func105: TtkTokenKind;
651begin
652  if KeyComp('__published') then Result := tkKey else Result := tkIdentifier;
653end;
654
655function TSynCppSyn.Func106: TtkTokenKind;
656begin
657  if KeyComp('explicit') then Result := tkKey else Result := tkIdentifier;
658end;
659
660function TSynCppSyn.Func107: TtkTokenKind;
661begin
662  if KeyComp('typename') then Result := tkKey else
663    if KeyComp('struct') then Result := tkKey else Result := tkIdentifier;
664end;
665
666function TSynCppSyn.Func109: TtkTokenKind;
667begin
668  if KeyComp('register') then Result := tkKey else
669    if KeyComp('continue') then Result := tkKey else
670      if KeyComp('__automated') then Result := tkKey else Result := tkIdentifier;
671end;
672
673function TSynCppSyn.Func110: TtkTokenKind;
674begin
675  if KeyComp('virtual') then Result := tkKey else Result := tkIdentifier;
676end;
677
678function TSynCppSyn.Func115: TtkTokenKind;
679begin
680  if KeyComp('protected') then Result := tkKey else Result := tkIdentifier;
681end;
682
683function TSynCppSyn.Func116: TtkTokenKind;
684begin
685  if KeyComp('operator') then Result := tkKey else Result := tkIdentifier;
686end;
687
688function TSynCppSyn.Func121: TtkTokenKind;
689begin
690  if KeyComp('_vectorcall') then Result := tkKey else
691    if KeyComp('__vectorcall') then Result := tkKey else
692      Result := tkIdentifier;
693end;
694
695function TSynCppSyn.Func123: TtkTokenKind;
696begin
697  if KeyComp('dynamic_cast') then Result := tkKey else
698    if KeyComp('const_cast') then Result := tkKey else Result := tkIdentifier;
699end;
700
701function TSynCppSyn.Func125: TtkTokenKind;
702begin
703  if KeyComp('static_cast') then Result := tkKey else Result := tkIdentifier;
704end;
705
706function TSynCppSyn.Func141: TtkTokenKind;
707begin
708  if KeyComp('__property') then Result := tkKey else Result := tkIdentifier;
709end;
710
711function TSynCppSyn.Func206: TtkTokenKind;
712begin
713  if KeyComp('reinterpret_cast') then Result := tkKey else Result := tkIdentifier;
714end;
715
716function TSynCppSyn.AltFunc: TtkTokenKind;
717begin
718  Result := tkIdentifier;
719end;
720
721function TSynCppSyn.IdentKind(MayBe: PChar): TtkTokenKind;
722var
723  HashKey: Integer;
724begin
725  fToIdent := MayBe;
726  HashKey := KeyHash(MayBe);
727  if HashKey < 207 then
728    Result := fIdentFuncTable[HashKey]()
729  else
730    Result := tkIdentifier;
731end;
732
733procedure TSynCppSyn.MakeMethodTables;
734var
735  I: Char;
736begin
737  for I := #0 to #255 do
738    case I of
739      '&': fProcTable[I] := @AndSymbolProc;
740      #39: fProcTable[I] := @AsciiCharProc;
741      '@': fProcTable[I] := @AtSymbolProc;
742      '}': fProcTable[I] := @BraceCloseProc;
743      '{': fProcTable[I] := @BraceOpenProc;
744      #13: fProcTable[I] := @CRProc;
745      ':': fProcTable[I] := @ColonProc;
746      ',': fProcTable[I] := @CommaProc;
747      '#': fProcTable[I] := @DirectiveProc;
748      '=': fProcTable[I] := @EqualProc;
749      '>': fProcTable[I] := @GreaterProc;
750      '?': fProcTable[I] := @QuestionProc;
751      'A'..'Z', 'a'..'z', '_': fProcTable[I] := @IdentProc;
752      #10: fProcTable[I] := @LFProc;
753      '<': fProcTable[I] := @LowerProc;
754      '-': fProcTable[I] := @MinusProc;
755      '%': fProcTable[I] := @ModSymbolProc;
756      '!': fProcTable[I] := @NotSymbolProc;
757      #0: fProcTable[I] := @NullProc;
758      '0'..'9': fProcTable[I] := @NumberProc;
759      '|': fProcTable[I] := @OrSymbolProc;
760      '+': fProcTable[I] := @PlusProc;
761      '.': fProcTable[I] := @PointProc;
762      ')': fProcTable[I] := @RoundCloseProc;
763      '(': fProcTable[I] := @RoundOpenProc;
764      ';': fProcTable[I] := @SemiColonProc;
765      '/': fProcTable[I] := @SlashProc;
766      #1..#9, #11, #12, #14..#32: fProcTable[I] := @SpaceProc;
767      ']': fProcTable[I] := @SquareCloseProc;
768      '[': fProcTable[I] := @SquareOpenProc;
769      '*': fProcTable[I] := @StarProc;
770      #34: fProcTable[I] := @StringProc;
771      '~': fProcTable[I] := @TildeProc;
772      '^': fProcTable[I] := @XOrSymbolProc;
773      else fProcTable[I] := @UnknownProc;
774    end;
775end;
776
777constructor TSynCppSyn.Create(AOwner: TComponent);
778begin
779  inherited Create(AOwner);
780  fAsmAttri := TSynHighlighterAttributes.Create(@SYNS_AttrAssembler, SYNS_XML_AttrAssembler);
781  AddAttribute(fAsmAttri);
782  fCommentAttri := TSynHighlighterAttributes.Create(@SYNS_AttrComment, SYNS_XML_AttrComment);
783  fCommentAttri.Style:= [fsItalic];
784  AddAttribute(fCommentAttri);
785  fIdentifierAttri := TSynHighlighterAttributes.Create(@SYNS_AttrIdentifier, SYNS_XML_AttrIdentifier);
786  AddAttribute(fIdentifierAttri);
787  fInvalidAttri := TSynHighlighterAttributes.Create(@SYNS_AttrIllegalChar, SYNS_XML_AttrIllegalChar);
788  AddAttribute(fInvalidAttri);
789  fKeyAttri := TSynHighlighterAttributes.Create(@SYNS_AttrReservedWord, SYNS_XML_AttrReservedWord);
790  fKeyAttri.Style:= [fsBold];
791  AddAttribute(fKeyAttri);
792  fNumberAttri := TSynHighlighterAttributes.Create(@SYNS_AttrNumber, SYNS_XML_AttrNumber);
793  AddAttribute(fNumberAttri);
794  fSpaceAttri := TSynHighlighterAttributes.Create(@SYNS_AttrSpace, SYNS_XML_AttrSpace);
795  fSpaceAttri.Foreground := clWindow;
796  AddAttribute(fSpaceAttri);
797  fStringAttri := TSynHighlighterAttributes.Create(@SYNS_AttrString, SYNS_XML_AttrString);
798  AddAttribute(fStringAttri);
799  fSymbolAttri := TSynHighlighterAttributes.Create(@SYNS_AttrSymbol, SYNS_XML_AttrSymbol);
800  AddAttribute(fSymbolAttri);
801  fDirecAttri := TSynHighlighterAttributes.Create(@SYNS_AttrPreprocessor, SYNS_XML_AttrPreprocessor);
802  AddAttribute(fDirecAttri);
803  SetAttributesOnChange(@DefHighlightChange);
804  InitIdent;
805  MakeMethodTables;
806  fRange := rsUnknown;
807  fAsmStart := False;
808  fDefaultFilter := SYNS_FilterCPP;
809end; { Create }
810
811procedure TSynCppSyn.SetLine(const NewValue: String; LineNumber:Integer);
812begin
813  inherited;
814  fLine := PChar(NewValue);
815  Run := 0;
816  fLineNumber := LineNumber;
817  Next;
818end; { SetLine }
819
820procedure TSynCppSyn.AnsiCProc;
821begin
822  fTokenID := tkComment;
823  case FLine[Run] of
824    #0:
825      begin
826        NullProc;
827        exit;
828      end;
829    #10:
830      begin
831        LFProc;
832        exit;
833      end;
834    #13:
835      begin
836        CRProc;
837        exit;
838      end;
839  end;
840
841  while FLine[Run] <> #0 do
842    case FLine[Run] of
843      '*':
844        if fLine[Run + 1] = '/' then
845        begin
846          inc(Run, 2);
847          if fRange = rsAnsiCAsm then
848            fRange := rsAsm
849          else if fRange = rsAnsiCAsmBlock then
850            fRange := rsAsmBlock
851          else if fRange = rsDirectiveComment then
852            fRange := rsDirective
853          else
854            fRange := rsUnKnown;
855          break;
856        end else
857          inc(Run);
858      #10: break;
859      #13: break;
860    else inc(Run);
861    end;
862end;
863
864procedure TSynCppSyn.AndSymbolProc;
865begin
866  fTokenID := tkSymbol;
867  case FLine[Run + 1] of
868    '=':                               {and assign}
869      begin
870        inc(Run, 2);
871        FExtTokenID := xtkAndAssign;
872      end;
873    '&':                               {logical and}
874      begin
875        inc(Run, 2);
876        FExtTokenID := xtkLogAnd;
877      end;
878  else                                 {and}
879    begin
880      inc(Run);
881      FExtTokenID := xtkAnd;
882    end;
883  end;
884end;
885
886procedure TSynCppSyn.AsciiCharProc;
887begin
888  fTokenID := tkString;
889  repeat
890    if fLine[Run] = '\' then begin
891      if fLine[Run + 1] in [#39, '\'] then                                      //ek 2000-04-26
892        inc(Run);
893    end;
894    inc(Run);
895  until fLine[Run] in [#0, #10, #13, #39];
896  if fLine[Run] = #39 then
897    inc(Run);
898end;
899
900procedure TSynCppSyn.AtSymbolProc;
901begin
902  fTokenID := tkUnknown;
903  inc(Run);
904end;
905
906procedure TSynCppSyn.BraceCloseProc;
907begin
908  inc(Run);
909  fTokenId := tkSymbol;
910  FExtTokenID := xtkBraceClose;
911  if fRange = rsAsmBlock then fRange := rsUnknown;
912end;
913
914procedure TSynCppSyn.BraceOpenProc;
915begin
916  inc(Run);
917  fTokenId := tkSymbol;
918  FExtTokenID := xtkBraceOpen;
919  if fRange = rsAsm then
920  begin
921    fRange := rsAsmBlock;
922    fAsmStart := True;
923  end;
924end;
925
926procedure TSynCppSyn.CRProc;
927begin
928  fTokenID := tkSpace;
929  Inc(Run);
930  if fLine[Run + 1] = #10 then Inc(Run);
931end;
932
933procedure TSynCppSyn.ColonProc;
934begin
935  fTokenID := tkSymbol;
936  Case FLine[Run + 1] of
937    ':':                               {scope resolution operator}
938      begin
939        inc(Run, 2);
940        FExtTokenID := xtkScopeResolution;
941      end;
942  else                                 {colon}
943    begin
944      inc(Run);
945      FExtTokenID := xtkColon;
946    end;
947  end;
948end;
949
950procedure TSynCppSyn.CommaProc;
951begin
952  inc(Run);
953  fTokenID := tkSymbol;
954  FExtTokenID := xtkComma;
955end;
956
957procedure TSynCppSyn.DirectiveProc;
958begin
959  if fLine[Run] in [#0, #10, #13] then begin
960    if (Run <= 0) or (fLine[Run - 1] <> '\') then
961      fRange := rsUnknown;
962    fProcTable[fLine[Run]];
963  end else begin
964    fTokenID := tkDirective;
965    while TRUE do
966      case fLine[Run] of
967        '/': // comment?
968          begin
969            if fLine[Run + 1] = '/' then begin // is end of directive as well
970              fRange := rsUnknown;                                              //ek 2000-04-25
971              break;
972            end else if fLine[Run + 1] = '*' then begin // might be embedded only
973              fRange := rsDirectiveComment;
974              break;
975            end else
976              Inc(Run);
977          end;
978        '\': // directive continued on next line?
979          begin
980            Inc(Run);
981            if fLine[Run] in [#0, #10, #13] then begin
982              fRange := rsDirective;
983              break;
984            end;
985          end;
986        #0, #10, #13:
987          begin
988            fRange := rsUnknown;
989            break;
990          end;
991        else Inc(Run);
992      end;
993  end;
994end;
995
996procedure TSynCppSyn.EqualProc;
997begin
998  fTokenID := tkSymbol;
999  case FLine[Run + 1] of
1000    '=':                               {logical equal}
1001      begin
1002        inc(Run, 2);
1003        FExtTokenID := xtkLogEqual;
1004      end;
1005  else                                 {assign}
1006    begin
1007      inc(Run);
1008      FExtTokenID := xtkAssign;
1009    end;
1010  end;
1011end;
1012
1013procedure TSynCppSyn.GreaterProc;
1014begin
1015  fTokenID := tkSymbol;
1016  Case FLine[Run + 1] of
1017    '=':                               {greater than or equal to}
1018      begin
1019        inc(Run, 2);
1020        FExtTokenID := xtkGreaterThanEqual;
1021      end;
1022    '>':
1023      begin
1024        if FLine[Run + 2] = '=' then   {shift right assign}
1025        begin
1026          inc(Run, 3);
1027          FExtTokenID := xtkShiftRightAssign;
1028        end
1029        else                           {shift right}
1030        begin
1031          inc(Run, 2);
1032          FExtTokenID := xtkShiftRight;
1033        end;
1034      end;
1035  else                                 {greater than}
1036    begin
1037      inc(Run);
1038      FExtTokenID := xtkGreaterThan;
1039    end;
1040  end;
1041end;
1042
1043procedure TSynCppSyn.QuestionProc;
1044begin
1045  fTokenID := tkSymbol;                {conditional}
1046  FExtTokenID := xtkQuestion;
1047  inc(Run);
1048end;
1049
1050procedure TSynCppSyn.IdentProc;
1051begin
1052  fTokenID := IdentKind((fLine + Run));
1053  inc(Run, fStringLen);
1054  while Identifiers[fLine[Run]] do inc(Run);
1055end;
1056
1057procedure TSynCppSyn.LFProc;
1058begin
1059  fTokenID := tkSpace;
1060  inc(Run);
1061end;
1062
1063procedure TSynCppSyn.LowerProc;
1064begin
1065  fTokenID := tkSymbol;
1066  case FLine[Run + 1] of
1067    '=':                               {less than or equal to}
1068      begin
1069        inc(Run, 2);
1070        FExtTokenID := xtkLessThanEqual;
1071      end;
1072    '<':
1073      begin
1074        if FLine[Run + 2] = '=' then   {shift left assign}
1075        begin
1076          inc(Run, 3);
1077          FExtTokenID := xtkShiftLeftAssign;
1078        end
1079        else                           {shift left}
1080        begin
1081          inc(Run, 2);
1082          FExtTokenID := xtkShiftLeft;
1083        end;
1084      end;
1085  else                                 {less than}
1086    begin
1087      inc(Run);
1088      FExtTokenID := xtkLessThan;
1089    end;
1090  end;
1091end;
1092
1093procedure TSynCppSyn.MinusProc;
1094begin
1095  fTokenID := tkSymbol;
1096  case FLine[Run + 1] of
1097    '=':                               {subtract assign}
1098      begin
1099        inc(Run, 2);
1100        FExtTokenID := xtkSubtractAssign;
1101      end;
1102    '-':                               {decrement}
1103      begin
1104        inc(Run, 2);
1105        FExtTokenID := xtkDecrement;
1106      end;
1107    '>':                               {arrow}
1108      begin
1109        inc(Run, 2);
1110        FExtTokenID := xtkArrow;
1111      end;
1112  else                                 {subtract}
1113    begin
1114      inc(Run);
1115      FExtTokenID := xtkSubtract;
1116    end;
1117  end;
1118end;
1119
1120procedure TSynCppSyn.ModSymbolProc;
1121begin
1122  fTokenID := tkSymbol;
1123  case FLine[Run + 1] of
1124    '=':                               {mod assign}
1125      begin
1126        inc(Run, 2);
1127        FExtTokenID := xtkModAssign;
1128      end;
1129  else                                 {mod}
1130    begin
1131      inc(Run);
1132      FExtTokenID := xtkMod;
1133    end;
1134  end;
1135end;
1136
1137procedure TSynCppSyn.NotSymbolProc;
1138begin
1139  fTokenID := tkSymbol;
1140  case FLine[Run + 1] of
1141    '=':                               {not equal}
1142      begin
1143        inc(Run, 2);
1144        FExtTokenID := xtkNotEqual;
1145      end;
1146  else                                 {not}
1147    begin
1148      inc(Run);
1149      FExtTokenID := xtkLogComplement;
1150    end;
1151  end;
1152end;
1153
1154procedure TSynCppSyn.NullProc;
1155begin
1156  fTokenID := tkNull;
1157end;
1158
1159procedure TSynCppSyn.NumberProc;
1160begin
1161  fTokenID := tkNumber;
1162
1163  if (FLine[Run] = '0') and (FLine[Run+1] in ['x', 'X'])then
1164  begin
1165    inc(Run, 2);
1166    while FLine[Run] in ['0'..'9', 'A'..'F', 'a'..'f'] do inc(Run);
1167    if FLine[Run] in ['u', 'U', 'l', 'L'] then inc(Run);
1168    exit;
1169  end;
1170
1171  inc(Run);
1172  while FLine[Run] in ['0'..'9'] do inc(Run);
1173  if (FLine[Run]='.') and not(fLine[Run+1]='.')  then begin
1174    inc(Run);
1175    while FLine[Run] in ['0'..'9'] do inc(Run);
1176  end;
1177  if (FLine[Run]='e') or (fLine[Run]='E')  then begin
1178    inc(Run);
1179    if (FLine[Run]='+') or (fLine[Run]='-')  then inc(Run);
1180    while FLine[Run] in ['0'..'9'] do inc(Run);
1181  end;
1182  if FLine[Run] in ['u', 'U', 'l', 'L'] then inc(Run);
1183end;
1184
1185procedure TSynCppSyn.OrSymbolProc;
1186begin
1187  fTokenID := tkSymbol;
1188  case FLine[Run + 1] of
1189    '=':                               {or assign}
1190      begin
1191        inc(Run, 2);
1192        FExtTokenID := xtkIncOrAssign;
1193      end;
1194    '|':                               {logical or}
1195      begin
1196        inc(Run, 2);
1197        FExtTokenID := xtkLogOr;
1198      end;
1199  else                                 {or}
1200    begin
1201      inc(Run);
1202      FExtTokenID := xtkIncOr;
1203    end;
1204  end;
1205end;
1206
1207procedure TSynCppSyn.PlusProc;
1208begin
1209  fTokenID := tkSymbol;
1210  case FLine[Run + 1] of
1211    '=':                               {add assign}
1212      begin
1213        inc(Run, 2);
1214        FExtTokenID := xtkAddAssign;
1215      end;
1216    '+':                               {increment}
1217      begin
1218        inc(Run, 2);
1219        FExtTokenID := xtkIncrement;
1220      end;
1221  else                                 {add}
1222    begin
1223      inc(Run);
1224      FExtTokenID := xtkAdd;
1225    end;
1226  end;
1227end;
1228
1229procedure TSynCppSyn.PointProc;
1230begin
1231  fTokenID := tkSymbol;
1232  if (FLine[Run + 1] = '.') and (FLine[Run + 2] = '.') then
1233    begin                              {ellipse}
1234      inc(Run, 3);
1235      FExtTokenID := xtkEllipse;
1236    end
1237  else                                 {point}
1238    begin
1239      inc(Run);
1240      FExtTokenID := xtkPoint;
1241    end;
1242end;
1243
1244procedure TSynCppSyn.RoundCloseProc;
1245begin
1246  inc(Run);
1247  fTokenID := tkSymbol;
1248  FExtTokenID := xtkRoundClose;
1249end;
1250
1251procedure TSynCppSyn.RoundOpenProc;
1252begin
1253  inc(Run);
1254  FTokenID := tkSymbol;
1255  FExtTokenID := xtkRoundOpen;
1256end;
1257
1258procedure TSynCppSyn.SemiColonProc;
1259begin
1260  inc(Run);
1261  fTokenID := tkSymbol;
1262  FExtTokenID := xtkSemiColon;
1263  if fRange = rsAsm then fRange := rsUnknown;
1264end;
1265
1266procedure TSynCppSyn.SlashProc;
1267begin
1268  case FLine[Run + 1] of
1269    '/':                               {c++ style comments}
1270      begin
1271        fTokenID := tkComment;
1272        inc(Run, 2);
1273        while not (fLine[Run] in [#0, #10, #13]) do Inc(Run);
1274      end;
1275    '*':                               {c style comments}
1276      begin
1277        fTokenID := tkComment;
1278        if fRange = rsAsm then
1279          fRange := rsAnsiCAsm
1280        else if fRange = rsAsmBlock then
1281          fRange := rsAnsiCAsmBlock
1282        else if fRange <> rsDirectiveComment then
1283          fRange := rsAnsiC;
1284        inc(Run, 2);
1285        while fLine[Run] <> #0 do
1286          case fLine[Run] of
1287            '*':
1288              if fLine[Run + 1] = '/' then
1289              begin
1290                inc(Run, 2);
1291                if fRange = rsDirectiveComment then
1292                  fRange := rsDirective
1293                else if fRange = rsAnsiCAsm then
1294                  fRange := rsAsm
1295                else
1296                  begin
1297                  if fRange = rsAnsiCAsmBlock then
1298                    fRange := rsAsmBlock
1299                  else
1300                    fRange := rsUnKnown;
1301                  end;
1302                break;
1303              end else inc(Run);
1304            #10, #13:
1305              begin
1306                if fRange = rsDirectiveComment then
1307                  fRange := rsAnsiC;
1308                break;
1309              end;
1310          else inc(Run);
1311          end;
1312      end;
1313    '=':                               {divide assign}
1314      begin
1315        inc(Run, 2);
1316        fTokenID := tkSymbol;
1317        FExtTokenID := xtkDivideAssign;
1318      end;
1319  else                                 {divide}
1320    begin
1321      inc(Run);
1322      fTokenID := tkSymbol;
1323      FExtTokenID := xtkDivide;
1324    end;
1325  end;
1326end;
1327
1328procedure TSynCppSyn.SpaceProc;
1329begin
1330  inc(Run);
1331  fTokenID := tkSpace;
1332  while FLine[Run] in [#1..#9, #11, #12, #14..#32] do inc(Run);
1333end;
1334
1335procedure TSynCppSyn.SquareCloseProc;
1336begin
1337  inc(Run);
1338  fTokenID := tkSymbol;
1339  FExtTokenID := xtkSquareClose;
1340end;
1341
1342procedure TSynCppSyn.SquareOpenProc;
1343begin
1344  inc(Run);
1345  fTokenID := tkSymbol;
1346  FExtTokenID := xtkSquareOpen;
1347end;
1348
1349procedure TSynCppSyn.StarProc;
1350begin
1351  fTokenID := tkSymbol;
1352  case FLine[Run + 1] of
1353    '=':                               {multiply assign}
1354      begin
1355        inc(Run, 2);
1356        FExtTokenID := xtkMultiplyAssign;
1357      end;
1358  else                                 {star}
1359    begin
1360      inc(Run);
1361      FExtTokenID := xtkStar;
1362    end;
1363  end;
1364end;
1365
1366procedure TSynCppSyn.StringProc;
1367begin
1368  case FLine[Run] of
1369    #0:
1370      begin
1371        NullProc;
1372        exit;
1373      end;
1374    #10:
1375      begin
1376        LFProc;
1377        exit;
1378      end;
1379    #13:
1380      begin
1381        CRProc;
1382        exit;
1383      end;
1384  end;
1385  fTokenID := tkString;
1386  if not((fRange in [rsAsmBlockString,rsAsmString,rsDirectiveString,rsString])
1387         and (Run = 0) and (FLine[Run] = #34 ))
1388  then
1389    repeat
1390      if fLine[Run] = '\' then begin
1391        if fLine[Run + 1] in [#34, '\'] then                                      //ek 2000-04-26
1392          Inc(Run);
1393      end;
1394      inc(Run);
1395    until fLine[Run] in [#0, #10, #13, #34];
1396  if FLine[Run] = #34 then begin
1397    inc(Run);
1398    fRange := SynCppStringRangeToRange[fRange];
1399  end else begin
1400    // string continues in next line
1401    fRange := SynCppRangeToStringRange[fRange];
1402  end;
1403end;
1404
1405procedure TSynCppSyn.TildeProc;
1406begin
1407  inc(Run);                            {bitwise complement}
1408  fTokenId := tkSymbol;
1409  FExtTokenID := xtkBitComplement;
1410end;
1411
1412procedure TSynCppSyn.XOrSymbolProc;
1413begin
1414  fTokenID := tkSymbol;
1415  Case FLine[Run + 1] of
1416  	'=':                               {xor assign}
1417      begin
1418        inc(Run, 2);
1419        FExtTokenID := xtkXorAssign;
1420      end;
1421  else                                 {xor}
1422    begin
1423      inc(Run);
1424      FExtTokenID := xtkXor;
1425    end;
1426  end;
1427end;
1428
1429procedure TSynCppSyn.UnknownProc;
1430begin
1431  inc(Run);
1432  while (fLine[Run] in [#128..#191]) OR // continued utf8 subcode
1433   ((fLine[Run]<>#0) and (fProcTable[fLine[Run]] = @UnknownProc)) do inc(Run);
1434  fTokenID := tkUnknown;
1435end;
1436
1437procedure TSynCppSyn.Next;
1438begin
1439  fAsmStart := False;
1440  fTokenPos := Run;
1441  case fRange of
1442    rsAnsiC, rsAnsiCAsm, rsAnsiCAsmBlock, rsDirectiveComment:
1443      AnsiCProc;
1444    rsAsmBlockString,rsAsmString,rsDirectiveString,rsString:
1445      StringProc;
1446    rsDirective:
1447      DirectiveProc;
1448  else
1449    begin
1450      fRange := rsUnknown;
1451      fProcTable[fLine[Run]];
1452    end;
1453  end;
1454end;
1455
1456function TSynCppSyn.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
1457begin
1458  case Index of
1459    SYN_ATTR_COMMENT: Result := fCommentAttri;
1460    SYN_ATTR_IDENTIFIER: Result := fIdentifierAttri;
1461    SYN_ATTR_KEYWORD: Result := fKeyAttri;
1462    SYN_ATTR_STRING: Result := fStringAttri;
1463    SYN_ATTR_WHITESPACE: Result := fSpaceAttri;
1464    SYN_ATTR_NUMBER: Result := fNumberAttri;
1465    SYN_ATTR_DIRECTIVE: Result := fDirecAttri;
1466    SYN_ATTR_ASM: Result := fAsmAttri;
1467    else Result := nil;
1468  end;
1469end;
1470
1471function TSynCppSyn.GetEol: Boolean;
1472begin
1473  Result := fTokenID = tkNull;
1474end;
1475
1476function TSynCppSyn.GetRange: Pointer;
1477begin
1478  Result := Pointer(PtrInt(fRange));
1479end;
1480
1481function TSynCppSyn.GetToken: String;
1482var
1483  Len: LongInt;
1484begin
1485  Result := '';
1486  Len := Run - fTokenPos;
1487  SetString(Result, (FLine + fTokenPos), Len);
1488end;
1489
1490procedure TSynCppSyn.GetTokenEx(out TokenStart: PChar;
1491  out TokenLength: integer);
1492begin
1493  TokenLength:=Run-fTokenPos;
1494  TokenStart:=FLine + fTokenPos;
1495end;
1496
1497function TSynCppSyn.GetTokenID: TtkTokenKind;
1498begin
1499  Result := fTokenId;
1500  if ((fRange = rsAsm) or (fRange = rsAsmBlock)) and not fAsmStart
1501    and not (fTokenId in [tkComment, tkSpace, tkNull])
1502  then
1503    Result := tkAsm;
1504end;
1505
1506function TSynCppSyn.GetExtTokenID: TxtkTokenKind;
1507begin
1508  Result := FExtTokenID;
1509end;
1510
1511function TSynCppSyn.GetTokenAttribute: TSynHighlighterAttributes;
1512begin
1513  case fTokenID of
1514    tkAsm: Result := fAsmAttri;
1515    tkComment: Result := fCommentAttri;
1516    tkDirective: Result := fDirecAttri;
1517    tkIdentifier: Result := fIdentifierAttri;
1518    tkKey: Result := fKeyAttri;
1519    tkNumber: Result := fNumberAttri;
1520    tkSpace: Result := fSpaceAttri;
1521    tkString: Result := fStringAttri;
1522    tkSymbol: Result := fSymbolAttri;
1523    tkUnknown: Result := fInvalidAttri;
1524    else Result := nil;
1525  end;
1526end;
1527
1528function TSynCppSyn.GetTokenKind: integer;
1529begin
1530  Result := Ord(GetTokenID);
1531end;
1532
1533function TSynCppSyn.GetTokenPos: Integer;
1534begin
1535  Result := fTokenPos;
1536end;
1537
1538procedure TSynCppSyn.ReSetRange;
1539begin
1540  fRange:= rsUnknown;
1541end;
1542
1543procedure TSynCppSyn.SetRange(Value: Pointer);
1544begin
1545  fRange := TRangeState(PtrUInt(Value));
1546end;
1547
1548procedure TSynCppSyn.EnumUserSettings(settings: TStrings);
1549begin
1550  { returns the user settings that exist in the registry }
1551  with TRegistry.Create do
1552  begin
1553    try
1554      RootKey := HKEY_LOCAL_MACHINE;
1555      {$IFNDEF SYN_LAZARUS}
1556      if OpenKeyReadOnly('\SOFTWARE\Borland\C++Builder') then
1557      begin
1558        try
1559          GetKeyNames(settings);
1560        finally
1561          CloseKey;
1562        end;
1563      end;
1564      {$ENDIF}
1565    finally
1566      Free;
1567    end;
1568  end;
1569end;
1570
1571function TSynCppSyn.UseUserSettings(settingIndex: integer): boolean;
1572// Possible parameter values:
1573//   index into TStrings returned by EnumUserSettings
1574// Possible return values:
1575//   true : settings were read and used
1576//   false: problem reading settings or invalid version specified - old settings
1577//          were preserved
1578
1579  function ReadCPPBSettings(settingIndex: integer): boolean;
1580
1581    function ReadCPPBSetting(settingTag: string; attri: TSynHighlighterAttributes; key: string): boolean;
1582
1583      function ReadCPPB1(settingTag: string; attri: TSynHighlighterAttributes; name: string): boolean;
1584      var
1585        i: integer;
1586      begin
1587        for i := 1 to Length(name) do
1588          if name[i] = ' ' then name[i] := '_';
1589        Result := attri.LoadFromBorlandRegistry(HKEY_CURRENT_USER,
1590             '\SOFTWARE\Borland\C++Builder\'+settingTag+'\Highlight',name,true);
1591      end; { ReadCPPB1 }
1592
1593      function ReadCPPB3OrMore(settingTag: string; attri: TSynHighlighterAttributes; key: string): boolean;
1594      begin
1595        Result := attri.LoadFromBorlandRegistry(HKEY_CURRENT_USER,
1596                 '\Software\Borland\C++Builder\'+settingTag+'\Editor\Highlight',
1597                 key,false);
1598      end; { ReadCPPB3OrMore }
1599
1600    begin { ReadCPPBSetting }
1601      try
1602        if (settingTag[1] = '1')
1603          then Result := ReadCPPB1(settingTag,attri,key)
1604          else Result := ReadCPPB3OrMore(settingTag,attri,key);
1605      except Result := false; end;
1606    end; { ReadCPPBSetting }
1607
1608  var
1609    tmpStringAttri    : TSynHighlighterAttributes;
1610    tmpNumberAttri    : TSynHighlighterAttributes;
1611    tmpKeyAttri       : TSynHighlighterAttributes;
1612    tmpSymbolAttri    : TSynHighlighterAttributes;
1613    tmpAsmAttri       : TSynHighlighterAttributes;
1614    tmpCommentAttri   : TSynHighlighterAttributes;
1615    tmpIdentifierAttri: TSynHighlighterAttributes;
1616    tmpInvalidAttri   : TSynHighlighterAttributes;
1617    tmpSpaceAttri     : TSynHighlighterAttributes;
1618    tmpDirecAttri     : TSynHighlighterAttributes;
1619    s                 : TStringList;
1620
1621  begin { ReadCPPBSettings }
1622    s := TStringList.Create;
1623    try
1624      EnumUserSettings(s);
1625      if settingIndex >= s.Count then Result := false
1626      else begin
1627        tmpStringAttri    := TSynHighlighterAttributes.Create(nil);
1628        tmpNumberAttri    := TSynHighlighterAttributes.Create(nil);
1629        tmpKeyAttri       := TSynHighlighterAttributes.Create(nil);
1630        tmpSymbolAttri    := TSynHighlighterAttributes.Create(nil);
1631        tmpAsmAttri       := TSynHighlighterAttributes.Create(nil);
1632        tmpCommentAttri   := TSynHighlighterAttributes.Create(nil);
1633        tmpIdentifierAttri:= TSynHighlighterAttributes.Create(nil);
1634        tmpInvalidAttri   := TSynHighlighterAttributes.Create(nil);
1635        tmpSpaceAttri     := TSynHighlighterAttributes.Create(nil);
1636        tmpDirecAttri     := TSynHighlighterAttributes.Create(nil);
1637        tmpStringAttri    .Assign(fStringAttri);
1638        tmpNumberAttri    .Assign(fNumberAttri);
1639        tmpKeyAttri       .Assign(fKeyAttri);
1640        tmpSymbolAttri    .Assign(fSymbolAttri);
1641        tmpAsmAttri       .Assign(fAsmAttri);
1642        tmpCommentAttri   .Assign(fCommentAttri);
1643        tmpIdentifierAttri.Assign(fIdentifierAttri);
1644        tmpInvalidAttri   .Assign(fInvalidAttri);
1645        tmpSpaceAttri     .Assign(fSpaceAttri);
1646        tmpDirecAttri     .Assign(fDirecAttri);
1647        if s[settingIndex][1] = '1'
1648          then Result := ReadCPPBSetting(s[settingIndex],fAsmAttri,'Plain text')
1649          else Result := ReadCPPBSetting(s[settingIndex],fAsmAttri,'Assembler');
1650        Result := Result                                                         and
1651                  ReadCPPBSetting(s[settingIndex],fCommentAttri,'Comment')       and
1652                  ReadCPPBSetting(s[settingIndex],fIdentifierAttri,'Identifier') and
1653                  ReadCPPBSetting(s[settingIndex],fInvalidAttri,'Illegal Char')  and
1654                  ReadCPPBSetting(s[settingIndex],fKeyAttri,'Reserved word')     and
1655                  ReadCPPBSetting(s[settingIndex],fNumberAttri,'Integer')        and
1656                  ReadCPPBSetting(s[settingIndex],fSpaceAttri,'Whitespace')      and
1657                  ReadCPPBSetting(s[settingIndex],fStringAttri,'String')         and
1658                  ReadCPPBSetting(s[settingIndex],fSymbolAttri,'Symbol')         and
1659                  ReadCPPBSetting(s[settingIndex],fDirecAttri,'Preprocessor');
1660        if not Result then begin
1661          fStringAttri    .Assign(tmpStringAttri);
1662          fNumberAttri    .Assign(tmpNumberAttri);
1663          fKeyAttri       .Assign(tmpKeyAttri);
1664          fSymbolAttri    .Assign(tmpSymbolAttri);
1665          fAsmAttri       .Assign(tmpAsmAttri);
1666          fCommentAttri   .Assign(tmpCommentAttri);
1667          fIdentifierAttri.Assign(tmpIdentifierAttri);
1668          fInvalidAttri.Assign(tmpInvalidAttri);
1669          fSpaceAttri     .Assign(tmpSpaceAttri);
1670          fDirecAttri     .Assign(tmpDirecAttri);
1671        end;
1672        tmpStringAttri    .Free;
1673        tmpNumberAttri    .Free;
1674        tmpKeyAttri       .Free;
1675        tmpSymbolAttri    .Free;
1676        tmpAsmAttri       .Free;
1677        tmpCommentAttri   .Free;
1678        tmpIdentifierAttri.Free;
1679        tmpInvalidAttri   .Free;
1680        tmpSpaceAttri     .Free;
1681        tmpDirecAttri     .Free;
1682      end;
1683    finally s.Free; end;
1684  end; { ReadCPPBSettings }
1685
1686begin
1687  Result := ReadCPPBSettings(settingIndex);
1688end; { TSynCppSyn.UseUserSettings }
1689
1690function TSynCppSyn.GetIdentChars: TSynIdentChars;
1691begin
1692  Result := ['_', '0'..'9', 'a'..'z', 'A'..'Z'];
1693end;
1694
1695class function TSynCppSyn.GetLanguageName: string;
1696begin
1697  Result := SYNS_LangCPP;
1698end;
1699
1700class function TSynCppSyn.GetCapabilities: TSynHighlighterCapabilities;
1701begin
1702  Result := inherited GetCapabilities + [hcUserSettings];
1703end;
1704
1705initialization
1706  MakeIdentTable;
1707  RegisterPlaceableHighlighter(TSynCppSyn);
1708
1709end.
1710
1711