1 {-------------------------------------------------------------------------------
2 The contents of this file are subject to the Mozilla Public License
3 Version 1.1 (the "License"); you may not use this file except in compliance
4 with the License. You may obtain a copy of the License at
5 http://www.mozilla.org/MPL/
6 
7 Software distributed under the License is distributed on an "AS IS" basis,
8 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9 the specific language governing rights and limitations under the License.
10 
11 The Original Code is: SynHighlighterIni.pas, released 2000-04-21.
12 The Original Code is based on the izIniSyn.pas file from the
13 mwEdit component suite by Martin Waldenburg and other developers, the Initial
14 Author of this file is Igor P. Zenkov.
15 All Rights Reserved.
16 
17 Contributors to the SynEdit and mwEdit projects are listed in the
18 Contributors.txt file.
19 
20 Alternatively, the contents of this file may be used under the terms of the
21 GNU General Public License Version 2 or later (the "GPL"), in which case
22 the provisions of the GPL are applicable instead of those above.
23 If you wish to allow use of your version of this file only under the terms
24 of the GPL and not to allow others to use your version of this file
25 under the MPL, indicate your decision by deleting the provisions above and
26 replace them with the notice and other provisions required by the GPL.
27 If you do not delete the provisions above, a recipient may use your version
28 of this file under either the MPL or the GPL.
29 
30 $Id: SynHighlighterIni.pas,v 1.7 2001/11/09 07:46:17 plpolak Exp $
31 
32 You may retrieve the latest version of this file at the SynEdit home page,
33 located at http://SynEdit.SourceForge.net
34 
35 Known Issues:
36 -------------------------------------------------------------------------------}
37 {
38 @abstract(Provides an Ini-files highlighter for SynEdit)
39 @author(Igor P. Zenkov, converted to SynEdit by Bruno Mikkelsen <btm@scientist.com>)
40 @created(1999-11-02, converted to SynEdit 2000-04-21)
41 @lastmod(2000-04-21)
42 The SynHighlighterIni unit provides SynEdit with an Ini-files highlighter.
43 Thanks to Primoz Gabrijelcic, Martin Waldenburg and Michael Hieke.
44 }
45 unit SynHighlighterIni;
46 
47 {$I SynEdit.inc}
48 
49 interface
50 
51 uses
52   Classes,
53   Graphics,
54   SynEditTypes, SynEditHighlighter;
55 
56 type
57   TtkTokenKind = (tkComment, tkText, tkSection, tkKey, tkNull, tkNumber,
58     tkSpace, tkString, tkSymbol, tkUnknown);
59 
60   TProcTableProc = procedure of object;
61 
62 type
63 
64   { TSynIniSyn }
65 
66   TSynIniSyn = class(TSynCustomHighlighter)
67   private
68     fLine: PChar;
69     fLineNumber: Integer;
70     fProcTable: array[#0..#255] of TProcTableProc;
71     Run: LongInt;
72     fTokenPos: Integer;
73     FTokenID: TtkTokenKind;
74     fCommentAttri: TSynHighlighterAttributes;
75     fTextAttri: TSynHighlighterAttributes;
76     fSectionAttri: TSynHighlighterAttributes;
77     fKeyAttri: TSynHighlighterAttributes;
78     fNumberAttri: TSynHighlighterAttributes;
79     fSpaceAttri: TSynHighlighterAttributes;
80     fStringAttri: TSynHighlighterAttributes;
81     fSymbolAttri: TSynHighlighterAttributes;
82     procedure SectionOpenProc;
83     procedure KeyProc;
84     procedure CRProc;
85     procedure EqualProc;
86     procedure TextProc;
87     procedure LFProc;
88     procedure NullProc;
89     procedure NumberProc;
90     procedure SemiColonProc;
91     procedure SpaceProc;
92     procedure StringProc;  // ""
93     procedure StringProc1; // ''
94     procedure MakeMethodTables;
95   protected
96     {General Stuff}
GetIdentCharsnull97     function GetIdentChars: TSynIdentChars; override;
GetSampleSourcenull98     function GetSampleSource: String; override;
99   public
GetLanguageNamenull100     class function GetLanguageName: string; override;
101   public
102     constructor Create(AOwner: TComponent); override;
GetDefaultAttributenull103     function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
104       override;
GetEolnull105     function GetEol: Boolean; override;
GetTokenIDnull106     function GetTokenID: TtkTokenKind;
107     procedure SetLine(const NewValue: String; LineNumber:Integer); override;
GetTokennull108     function GetToken: String; override;
109     procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override;
GetTokenAttributenull110     function GetTokenAttribute: TSynHighlighterAttributes; override;
GetTokenKindnull111     function GetTokenKind: integer; override;
GetTokenPosnull112     function GetTokenPos: Integer; override;
113     procedure Next; override;
114   published
115     property CommentAttri: TSynHighlighterAttributes read fCommentAttri
116       write fCommentAttri;
117     property TextAttri   : TSynHighlighterAttributes read fTextAttri
118       write fTextAttri;
119     property SectionAttri: TSynHighlighterAttributes read fSectionAttri
120       write fSectionAttri;
121     property KeyAttri    : TSynHighlighterAttributes read fKeyAttri
122       write fKeyAttri;
123     property NumberAttri : TSynHighlighterAttributes read fNumberAttri
124       write fNumberAttri;
125     property SpaceAttri  : TSynHighlighterAttributes read fSpaceAttri
126       write fSpaceAttri;
127     property StringAttri : TSynHighlighterAttributes read fStringAttri
128       write fStringAttri;
129     property SymbolAttri : TSynHighlighterAttributes read fSymbolAttri
130       write fSymbolAttri;
131   end;
132 
133 implementation
134 
135 uses
136   SynEditStrConst;
137 
138 procedure TSynIniSyn.MakeMethodTables;
139 var
140   i: Char;
141 begin
142   for i := #0 to #255 do
143     case i of
144       #0      : fProcTable[i] := @NullProc;
145       #10 {LF}: fProcTable[i] := @LFProc;
146       #13 {CR}: fProcTable[i] := @CRProc;
147       #34 {"} : fProcTable[i] := @StringProc;
148       #39 {'} : fProcTable[i] := @StringProc1;
149       '0'..'9': fProcTable[i] := @NumberProc;
150       #59 {;} : fProcTable[i] := @SemiColonProc;
151       #61 {=} : fProcTable[i] := @EqualProc;
152       #91 {[} : fProcTable[i] := @SectionOpenProc;
153       #1..#9, #11, #12, #14..#32: fProcTable[i] := @SpaceProc;
154     else
155       fProcTable[i] := @TextProc;
156     end;
157 end;
158 
159 constructor TSynIniSyn.Create(AOwner: TComponent);
160 begin
161   inherited Create(AOwner);
162   fCommentAttri            := TSynHighlighterAttributes.Create(@SYNS_AttrComment);
163   fCommentAttri.Style      := [fsItalic];
164   fCommentAttri.Foreground := clGreen;
165   AddAttribute(fCommentAttri);
166   fTextAttri               := TSynHighlighterAttributes.Create(@SYNS_AttrText);
167   AddAttribute(fTextAttri);
168   fSectionAttri            := TSynHighlighterAttributes.Create(@SYNS_AttrSection);
169   fSectionAttri.Style      := [fsBold];
170   AddAttribute(fSectionAttri);
171   fKeyAttri                := TSynHighlighterAttributes.Create(@SYNS_AttrKey);
172   fKeyAttri.Foreground     := clBlue;
173   AddAttribute(fKeyAttri);
174   fNumberAttri             := TSynHighlighterAttributes.Create(@SYNS_AttrNumber);
175   AddAttribute(fNumberAttri);
176   fSpaceAttri              := TSynHighlighterAttributes.Create(@SYNS_AttrSpace);
177   AddAttribute(fSpaceAttri);
178   fStringAttri             := TSynHighlighterAttributes.Create(@SYNS_AttrString);
179   AddAttribute(fStringAttri);
180   fSymbolAttri             := TSynHighlighterAttributes.Create(@SYNS_AttrSymbol);
181   fSymbolAttri.Foreground := clRed;
182   AddAttribute(fSymbolAttri);
183   SetAttributesOnChange(@DefHighlightChange);
184 
185   fDefaultFilter      := SYNS_FilterINI;
186   MakeMethodTables;
187 end; { Create }
188 
189 procedure TSynIniSyn.SetLine(const NewValue: String; LineNumber:Integer);
190 begin
191   inherited;
192   fLine := PChar(NewValue);
193   Run := 0;
194   fLineNumber := LineNumber;
195   Next;
196 end; { SetLine }
197 
198 procedure TSynIniSyn.SectionOpenProc;
199 begin
200   // if it is not column 0 mark as tkText and get out of here
201   if Run > 0 then
202   begin
203     fTokenID := tkText;
204     inc(Run);
205     Exit;
206   end;
207 
208   // this is column 0 ok it is a Section
209   fTokenID := tkSection;
210   inc(Run);
211   while FLine[Run] <> #0 do
212     case FLine[Run] of
213       ']': begin inc(Run); break end;
214       #10: break;
215       #13: break;
216     else inc(Run);
217     end;
218 end;
219 
220 procedure TSynIniSyn.CRProc;
221 begin
222   fTokenID := tkSpace;
223   Case FLine[Run + 1] of
224     #10: inc(Run, 2);
225   else inc(Run);
226   end;
227 end;
228 
229 procedure TSynIniSyn.EqualProc;
230 begin
231   inc(Run);
232   fTokenID := tkSymbol;
233 end;
234 
235 procedure TSynIniSyn.KeyProc;
236 begin
237   fTokenID := tkKey;
238   inc(Run);
239   while FLine[Run] <> #0 do
240     case FLine[Run] of
241       '=': break;
242       #10: break;
243       #13: break;
244     else inc(Run);
245     end;
246 end;
247 
248 procedure TSynIniSyn.TextProc;
249 begin
250   if Run = 0 then
251     KeyProc
252   else begin
253     inc(Run);
254     while (fLine[Run] in [#128..#191]) OR // continued utf8 subcode
255      ((fLine[Run]<>#0) and (fProcTable[fLine[Run]] = @TextProc)) do inc(Run);
256     fTokenID := tkText;
257     //fTokenID := tkText;
258     //inc(Run);
259   end;
260 end;
261 
262 procedure TSynIniSyn.LFProc;
263 begin
264   fTokenID := tkSpace;
265   inc(Run);
266 end;
267 
268 procedure TSynIniSyn.NullProc;
269 begin
270   fTokenID := tkNull;
271 end;
272 
273 procedure TSynIniSyn.NumberProc;
274 begin
275   if Run = 0 then
276     KeyProc
277   else begin
278     inc(Run);
279     fTokenID := tkNumber;
280     while FLine[Run] in ['0'..'9', '.', 'e', 'E'] do inc(Run);
281     if FLine[Run] in ['a'..'z','A'..'Z'] then TextProc;
282   end;
283 end;
284 
285 // ;
286 procedure TSynIniSyn.SemiColonProc;
287 begin
288   // if it is not column 0 mark as tkText and get out of here
289   if Run > 0 then
290   begin
291     fTokenID := tkText;
292     inc(Run);
293     Exit;
294   end;
295 
296   // this is column 0 ok it is a comment
297   fTokenID := tkComment;
298   inc(Run);
299   while FLine[Run] <> #0 do
300     case FLine[Run] of
301       #10: break;
302       #13: break;
303     else inc(Run);
304     end;
305 end;
306 
307 procedure TSynIniSyn.SpaceProc;
308 begin
309   inc(Run);
310   fTokenID := tkSpace;
311   while FLine[Run] in [#1..#9, #11, #12, #14..#32] do inc(Run);
312 end;
313 
314 // ""
315 procedure TSynIniSyn.StringProc;
316 begin
317   fTokenID := tkString;
318   if (FLine[Run + 1] = #34) and (FLine[Run + 2] = #34) then inc(Run, 2);
319   repeat
320     case FLine[Run] of
321       #0, #10, #13: break;
322     end;
323     inc(Run);
324   until FLine[Run] = #34;
325   if FLine[Run] <> #0 then inc(Run);
326 end;
327 
328 // ''
329 procedure TSynIniSyn.StringProc1;
330 begin
331   fTokenID := tkString;
332   if (FLine[Run + 1] = #39) and (FLine[Run + 2] = #39) then inc(Run, 2);
333   repeat
334     case FLine[Run] of
335       #0, #10, #13: break;
336     end;
337     inc(Run);
338   until FLine[Run] = #39;
339   if FLine[Run] <> #0 then inc(Run);
340 end;
341 
342 procedure TSynIniSyn.Next;
343 begin
344   fTokenPos := Run;
345   fProcTable[fLine[Run]];
346 end;
347 
TSynIniSyn.GetDefaultAttributenull348 function TSynIniSyn.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
349 begin
350   case Index of
351     SYN_ATTR_COMMENT: Result := fCommentAttri;
352     SYN_ATTR_KEYWORD: Result := fKeyAttri;
353     SYN_ATTR_STRING: Result := fStringAttri;
354     SYN_ATTR_WHITESPACE: Result := fSpaceAttri;
355     SYN_ATTR_SYMBOL: Result := fSymbolAttri;
356     SYN_ATTR_NUMBER: Result := fNumberAttri;
357   else
358     Result := nil;
359   end;
360 end;
361 
GetEolnull362 function TSynIniSyn.GetEol: Boolean;
363 begin
364   Result := fTokenId = tkNull;
365 end;
366 
TSynIniSyn.GetTokennull367 function TSynIniSyn.GetToken: String;
368 var
369   Len: LongInt;
370 begin
371   Len := Run - fTokenPos;
372   SetString(Result, (FLine + fTokenPos), Len);
373 end;
374 
375 procedure TSynIniSyn.GetTokenEx(out TokenStart: PChar; out TokenLength: integer);
376 begin
377   TokenLength := Run - fTokenPos;
378   TokenStart := FLine + fTokenPos;
379 end;
380 
GetTokenIDnull381 function TSynIniSyn.GetTokenID: TtkTokenKind;
382 begin
383   Result := fTokenId;
384 end;
385 
GetTokenAttributenull386 function TSynIniSyn.GetTokenAttribute: TSynHighlighterAttributes;
387 begin
388   case fTokenID of
389     tkComment: Result := fCommentAttri;
390     tkText   : Result := fTextAttri;
391     tkSection: Result := fSectionAttri;
392     tkKey    : Result := fKeyAttri;
393     tkNumber : Result := fNumberAttri;
394     tkSpace  : Result := fSpaceAttri;
395     tkString : Result := fStringAttri;
396     tkSymbol : Result := fSymbolAttri;
397     tkUnknown: Result := fTextAttri;
398     else Result := nil;
399   end;
400 end;
401 
GetTokenKindnull402 function TSynIniSyn.GetTokenKind: integer;
403 begin
404   Result := Ord(fTokenId);
405 end;
406 
GetTokenPosnull407 function TSynIniSyn.GetTokenPos: Integer;
408 begin
409  Result := fTokenPos;
410 end;
411 
GetIdentCharsnull412 function TSynIniSyn.GetIdentChars: TSynIdentChars;
413 begin
414   Result := TSynValidStringChars;
415 end;
416 
TSynIniSyn.GetLanguageNamenull417 class function TSynIniSyn.GetLanguageName: string;
418 begin
419   Result := SYNS_LangINI;
420 end;
421 
GetSampleSourcenull422 function TSynIniSyn.GetSampleSource: String;
423 begin
424   Result := '; Syntax highlighting'#13#10+
425             '[Section]'#13#10+
426             'Key=value'#13#10+
427             'String="Arial"'#13#10+
428             'Number=123456';
429 end;
430 
431 initialization
432   RegisterPlaceableHighlighter(TSynIniSyn);
433 
434 end.
435