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: SynHighlighterDfm.pas, released 2000-04-14.
12 The Original Code is based on the dmDfmSyn.pas file from the
13 mwEdit component suite by Martin Waldenburg and other developers, the Initial
14 Author of this file is David H. Muir.
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$
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 a Delphi Form Source highlighter for SynEdit)
39 @author(David Muir <david@loanhead45.freeserve.co.uk>)
40 @created(April 13, 2000)
41 @lastmod(2000-06-23)
42 The SynHighlighterLFM unit provides SynEdit with a Delphi Form Source (.LFM) highlighter.
43 The highlighter formats form source code similar to when forms are viewed as text in the Delphi editor.
44 }
45 unit SynHighlighterLFM;
46 
47 {$I SynEdit.inc}
48 
49 interface
50 
51 uses
52   SysUtils, Classes, FileUtil, Graphics,
53   SynEditTypes, SynEditHighlighter, SynEditHighlighterFoldBase, SynEditStrConst;
54 
55 type
56   TtkTokenKind = (tkComment, tkIdentifier, tkKey, tkNull, tkNumber, tkSpace,
57     tkString, tkSymbol, tkUnknown);
58 
59   TRangeState = (rsANil, rsComment, rsUnKnown);
60 
61   TLfmCodeFoldBlockType = (
62     cfbtLfmObject,      // object, inherited, inline
63     cfbtLfmList,        // <>
64     cfbtLfmItem,         // Item
65     // internal type / no config
66     cfbtLfmNone
67     );
68   TLfmCodeFoldBlockTypes = set of TLfmCodeFoldBlockType;
69 
70   TProcTableProc = procedure of object;
71 
72 const
73   CountLfmCodeFoldBlockOffset: Pointer =
74     Pointer(PtrInt(Integer(high(TLfmCodeFoldBlockType))+1));
75 
76 type
77 
78   { TSynLFMSyn }
79 
80   TSynLFMSyn = class(TSynCustomFoldHighlighter)
81   private
82     fRange: TRangeState;
83     fLine: PChar;
84     fLineNumber: Integer;
85     fProcTable: array[#0..#255] of TProcTableProc;
86     Run: integer;
87     fTokenPos: Integer;
88     FTokenID: TtkTokenKind;
89     fCommentAttri: TSynHighlighterAttributes;
90     fIdentifierAttri: TSynHighlighterAttributes;
91     fKeyAttri: TSynHighlighterAttributes;
92     fNumberAttri: TSynHighlighterAttributes;
93     fSpaceAttri: TSynHighlighterAttributes;
94     fStringAttri: TSynHighlighterAttributes;
95     fSymbolAttri: TSynHighlighterAttributes;
96     procedure AltProc;
97     procedure AsciiCharProc;
98     procedure BraceCloseProc;
99     procedure BraceOpenProc;
100     procedure CommentProc;
101     procedure CRProc;
102     procedure EndProc;
103     procedure IntegerProc;
104     procedure LFProc;
105     procedure NullProc;
106     procedure NumberProc;
107     procedure ObjectProc;
108     procedure InheritedInlineProc;
109     procedure SpaceProc;
110     procedure StringProc;
111     procedure SymbolProc;
112     procedure UnknownProc;
113     procedure MakeMethodTables;
114   protected
GetIdentCharsnull115     function GetIdentChars: TSynIdentChars; override;
GetSampleSourcenull116     function GetSampleSource: string; override;
117   protected
118     // folding
119     procedure CreateRootCodeFoldBlock; override;
120 
StartLfmCodeFoldBlocknull121     function StartLfmCodeFoldBlock
122              (ABlockType: TLfmCodeFoldBlockType): TSynCustomCodeFoldBlock;
123     procedure EndLfmCodeFoldBlock;
TopLfmCodeFoldBlockTypenull124     function TopLfmCodeFoldBlockType(DownIndex: Integer = 0): TLfmCodeFoldBlockType;
125   protected
GetFoldConfigInstancenull126     function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
GetFoldConfigCountnull127     function GetFoldConfigCount: Integer; override;
GetFoldConfigInternalCountnull128     function GetFoldConfigInternalCount: Integer; override;
129   public
GetLanguageNamenull130     class function GetLanguageName: string; override;
131   public
132     constructor Create(AOwner: TComponent); override;
133     destructor Destroy; override;
GetDefaultAttributenull134     function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
135       override;
GetEolnull136     function GetEol: Boolean; override;
GetRangenull137     function GetRange: Pointer; override;
GetTokenIDnull138     function GetTokenID: TtkTokenKind;
139     procedure SetLine(const NewValue: String;
140       LineNumber: Integer); override;
GetTokennull141     function GetToken: String; override;
142     procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override;
GetTokenAttributenull143     function GetTokenAttribute: TSynHighlighterAttributes; override;
GetTokenKindnull144     function GetTokenKind: integer; override;
GetTokenPosnull145     function GetTokenPos: Integer; override;
146     procedure Next; override;
147     procedure SetRange(Value: Pointer); override;
148     procedure ResetRange; override;
149     property IdentChars;
150   published
151     property CommentAttri: TSynHighlighterAttributes read fCommentAttri
152       write fCommentAttri;
153     property IdentifierAttri: TSynHighlighterAttributes read fIdentifierAttri
154       write fIdentifierAttri;
155     property KeyAttri: TSynHighlighterAttributes read fKeyAttri write fKeyAttri;
156     property NumberAttri: TSynHighlighterAttributes read fNumberAttri
157       write fNumberAttri;
158     property SpaceAttri: TSynHighlighterAttributes read fSpaceAttri
159       write fSpaceAttri;
160     property StringAttri: TSynHighlighterAttributes read fStringAttri
161       write fStringAttri;
162   end;
163 
LoadLFMFile2Stringsnull164 function LoadLFMFile2Strings(const AFile: string; AStrings: TStrings;
165   var WasText: boolean): integer;
SaveStrings2LFMFilenull166 function SaveStrings2LFMFile(AStrings: TStrings; const AFile: string): integer;
167 
168 implementation
169 
170 { A couple of useful Lazarus Form functions }
171 
LoadLFMFile2Stringsnull172 function LoadLFMFile2Strings(const AFile: string; AStrings: TStrings;
173   var WasText: boolean): integer;
174 var
175   Src, Dest: TStream;
176 begin
177   Result := 0;
178   WasText := FALSE;
179   AStrings.Clear;
180   try
181     Src := TFileStream.Create(AFile, fmOpenRead or fmShareDenyWrite);
182     try
183       Dest := TMemoryStream.Create;
184       try
185         ObjectResourceToText(Src, Dest);
186         Dest.Seek(0, soFromBeginning);
187         AStrings.LoadFromStream(Dest);
188       finally
189         Dest.Free;
190       end;
191     finally
192       Src.Free;
193     end;
194   except
195     on E: EInOutError do Result := -E.ErrorCode;
196     else Result := -1;
197   end;
198 end;
199 
SaveStrings2LFMFilenull200 function SaveStrings2LFMFile(AStrings: TStrings; const AFile: string): integer;
201 var
202   Src, Dest: TStream;
203 begin
204   Result := 0;
205   try
206     Src := TMemoryStream.Create;
207     try
208       AStrings.SaveToStream(Src);
209       Src.Seek(0, soFromBeginning);
210       Dest := TFileStream.Create(AFile, fmCreate);
211       try
212         ObjectTextToResource(Src, Dest);
213       finally
214         Dest.Free;
215       end;
216     finally
217       Src.Free;
218     end;
219   except
220     on E: EInOutError do Result := -E.ErrorCode;
221     else Result := -1;
222   end;
223 end;
224 
225 { TSynLFMSyn }
226 
227 procedure TSynLFMSyn.MakeMethodTables;
228 var
229   I: Char;
230 begin
231   for I := #0 to #255 do
232     case I of
233       '#': fProcTable[I] := @AsciiCharProc;
234       '}': fProcTable[I] := @BraceCloseProc;
235       '{': fProcTable[I] := @BraceOpenProc;
236       #13: fProcTable[I] := @CRProc;
237       'A'..'Z', 'a'..'z', '_':
238         if I in ['e', 'E'] then
239           fProcTable[I] := @EndProc
240         else if I in ['o', 'O'] then
241           fProcTable[I] := @ObjectProc
242         else if I in ['i', 'I'] then
243           fProcTable[I] := @InheritedInlineProc
244         else
245           fProcTable[I] := @AltProc;
246       '$': fProcTable[I] := @IntegerProc;
247       #10: fProcTable[I] := @LFProc;
248       #0: fProcTable[I] := @NullProc;
249       '0'..'9': fProcTable[I] := @NumberProc;
250       '(', ')', '/', '=', '<', '>', '.', ',', '[', ']', ':':
251         fProcTable[I] := @SymbolProc;
252       #1..#9, #11, #12, #14..#32: fProcTable[I] := @SpaceProc;
253       #39: fProcTable[I] := @StringProc;
254     else fProcTable[I] := @UnknownProc;
255     end;
256 end;
257 
GetFoldConfigInstancenull258 function TSynLFMSyn.GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig;
259 begin
260   Result := inherited GetFoldConfigInstance(Index);
261   Result.Enabled := True;
262   if TLfmCodeFoldBlockType(Index) in [cfbtLfmObject, cfbtLfmList, cfbtLfmItem] then begin
263     Result.SupportedModes := Result.SupportedModes + [fmMarkup];
264     Result.Modes := Result.Modes + [fmMarkup];
265   end;
266 end;
267 
268 constructor TSynLFMSyn.Create(AOwner: TComponent);
269 begin
270   inherited Create(AOwner);
271   fCommentAttri := TSynHighlighterAttributes.Create(@SYNS_AttrComment, SYNS_XML_AttrComment);
272   fCommentAttri.Style := [fsItalic];
273   AddAttribute(fCommentAttri);
274   fIdentifierAttri := TSynHighlighterAttributes.Create(@SYNS_AttrIdentifier, SYNS_XML_AttrIdentifier);
275   AddAttribute(fIdentifierAttri);
276   fKeyAttri := TSynHighlighterAttributes.Create(@SYNS_AttrKey, SYNS_XML_AttrKey);
277   fKeyAttri.Style := [fsBold];
278   AddAttribute(fKeyAttri);
279   fNumberAttri := TSynHighlighterAttributes.Create(@SYNS_AttrNumber, SYNS_XML_AttrNumber);
280   AddAttribute(fNumberAttri);
281   fSpaceAttri := TSynHighlighterAttributes.Create(@SYNS_AttrSpace, SYNS_XML_AttrSpace);
282   AddAttribute(fSpaceAttri);
283   fStringAttri := TSynHighlighterAttributes.Create(@SYNS_AttrString, SYNS_XML_AttrString);
284   AddAttribute(fStringAttri);
285   fSymbolAttri := TSynHighlighterAttributes.Create(@SYNS_AttrSymbol, SYNS_XML_AttrSymbol);
286   AddAttribute(fSymbolAttri);
287   SetAttributesOnChange(@DefHighlightChange);
288   MakeMethodTables;
289   fDefaultFilter := SYNS_FilterLFM;
290   fRange := rsUnknown;
291 end;
292 
293 destructor TSynLFMSyn.Destroy;
294 begin
295   inherited Destroy;
296 end;
297 
298 procedure TSynLFMSyn.SetLine(const NewValue: String;
299   LineNumber: Integer);
300 begin
301   inherited;
302   fLine := PChar(NewValue);
303   Run := 0;
304   fLineNumber := LineNumber;
305   Next;
306 end;
307 
308 procedure TSynLFMSyn.AltProc;
309 begin
310   fTokenID := tkIdentifier;
311   repeat
312     Inc(Run);
313   until not (fLine[Run] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']);
314 end;
315 
316 procedure TSynLFMSyn.AsciiCharProc;
317 begin
318   fTokenID := tkString;
319   repeat
320     Inc(Run);
321   until not (fLine[Run] in ['0'..'9']);
322 end;
323 
324 procedure TSynLFMSyn.BraceCloseProc;
325 begin
326   inc(Run);
327   fRange := rsUnknown;
328   fTokenId := tkIdentifier;
329 end;
330 
331 procedure TSynLFMSyn.BraceOpenProc;
332 begin
333   fRange := rsComment;
334   CommentProc;
335 end;
336 
337 procedure TSynLFMSyn.CommentProc;
338 begin
339   fTokenID := tkComment;
340   repeat
341     inc(Run);
342     if fLine[Run] = '}' then begin
343       Inc(Run);
344       fRange := rsUnknown;
345       break;
346     end;
347   until fLine[Run] in [#0, #10, #13];
348 end;
349 
350 procedure TSynLFMSyn.CRProc;
351 begin
352   fTokenID := tkSpace;
353   Inc(Run);
354   if (fLine[Run] = #10) then Inc(Run);
355 end;
356 
357 procedure TSynLFMSyn.EndProc;
358 begin
359   if (fLine[Run + 1] in ['n', 'N']) and
360      (fLine[Run + 2] in ['d', 'D']) and
361      not (fLine[Run + 3] in ['_', '0'..'9', 'a'..'z', 'A'..'Z'])
362   then begin
363     fTokenID := tkKey;
364     Inc(Run, 3);
365     if (TopLfmCodeFoldBlockType in [cfbtLfmObject, cfbtLfmItem]) then
366       EndLfmCodeFoldBlock;
367   end else
368     AltProc;
369 end;
370 
371 procedure TSynLFMSyn.IntegerProc;
372 begin
373   fTokenID := tkNumber;
374   repeat
375     inc(Run);
376   until not (fLine[Run] in ['0'..'9', 'A'..'F', 'a'..'f']);
377 end;
378 
379 procedure TSynLFMSyn.LFProc;
380 begin
381   fTokenID := tkSpace;
382   inc(Run);
383 end;
384 
385 procedure TSynLFMSyn.NullProc;
386 begin
387   fTokenID := tkNull;
388 end;
389 
390 procedure TSynLFMSyn.NumberProc;
391 begin
392   fTokenID := tkNumber;
393   repeat
394     Inc(Run);
395     if fLine[Run] = '.' then begin
396       if fLine[Run + 1] <> '.' then Inc(Run);
397       break;
398     end;
399   until not (fLine[Run] in ['0'..'9', 'e', 'E']);
400 end;
401 
402 procedure TSynLFMSyn.ObjectProc;
403 begin
404   if (fLine[Run + 1] in ['b', 'B']) and
405      (fLine[Run + 2] in ['j', 'J']) and
406      (fLine[Run + 3] in ['e', 'E']) and
407      (fLine[Run + 4] in ['c', 'C']) and
408      (fLine[Run + 5] in ['t', 'T']) and
409      not (fLine[Run + 6] in ['_', '0'..'9', 'a'..'z', 'A'..'Z'])
410   then
411   begin
412     fTokenID := tkKey;
413     Inc(Run, 6);
414     StartLfmCodeFoldBlock(cfbtLfmObject);
415   end
416   else
417     AltProc;
418 end;
419 
420 procedure TSynLFMSyn.InheritedInlineProc;
421 begin
422   if ((fLine[Run + 1] in ['n', 'N']) and
423      (fLine[Run + 2] in ['h', 'H']) and
424      (fLine[Run + 3] in ['e', 'E']) and
425      (fLine[Run + 4] in ['r', 'R']) and
426      (fLine[Run + 5] in ['i', 'I']) and
427      (fLine[Run + 6] in ['t', 'T']) and
428      (fLine[Run + 7] in ['e', 'E']) and
429      (fLine[Run + 8] in ['d', 'D']) and
430      not (fLine[Run + 9] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']))
431   then
432   begin
433     fTokenID := tkKey;
434     Inc(Run, 9);
435     StartLfmCodeFoldBlock(cfbtLfmObject);
436   end
437   else if ((fLine[Run + 1] in ['n', 'N']) and
438            (fLine[Run + 2] in ['l', 'L']) and
439            (fLine[Run + 3] in ['i', 'I']) and
440            (fLine[Run + 4] in ['n', 'N']) and
441            (fLine[Run + 5] in ['e', 'E']) and
442            not (fLine[Run + 6] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']))
443   then
444   begin
445     fTokenID := tkKey;
446     Inc(Run, 6);
447     StartLfmCodeFoldBlock(cfbtLfmObject);
448   end
449   else if ((fLine[Run + 1] in ['t', 'T']) and
450            (fLine[Run + 2] in ['e', 'E']) and
451            (fLine[Run + 3] in ['m', 'M']) and
452            not (fLine[Run + 4] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']))
453   then
454   begin
455     fTokenID := tkIdentifier;
456     Inc(Run, 4);
457     StartLfmCodeFoldBlock(cfbtLfmItem);
458   end
459   else
460     AltProc;
461 end;
462 
463 procedure TSynLFMSyn.SpaceProc;
464 begin
465   fTokenID := tkSpace;
466   repeat
467     Inc(Run);
468   until (fLine[Run] > #32) or (fLine[Run] in [#0, #10, #13]);
469 end;
470 
471 procedure TSynLFMSyn.StringProc;
472 begin
473   fTokenID := tkString;
474   repeat
475     Inc(Run);
476     if fLine[Run] = '''' then begin
477       Inc(Run);
478       if fLine[Run] <> '''' then break
479     end;
480   until fLine[Run] in [#0, #10, #13];
481 end;
482 
483 procedure TSynLFMSyn.SymbolProc;
484 begin
485 
486   inc(Run);
487   fTokenID := tkSymbol;
488   if fLine[Run-1] = '<' then
489   begin
490     StartLfmCodeFoldBlock(cfbtLfmList)
491   end
492   else
493   if (fLine[Run-1] = '>') and (TopLfmCodeFoldBlockType = cfbtLfmList) then
494     EndLfmCodeFoldBlock;
495 end;
496 
497 procedure TSynLFMSyn.UnknownProc;
498 begin
499 {$IFDEF SYN_MBCSSUPPORT}
500   if FLine[Run] in LeadBytes then
501     Inc(Run,2)
502   else
503 {$ENDIF}
504   inc(Run);
505   while (fLine[Run] in [#128..#191]) OR // continued utf8 subcode
506    ((fLine[Run]<>#0) and (fProcTable[fLine[Run]] = @UnknownProc)) do inc(Run);
507   fTokenID := tkUnknown;
508 end;
509 
510 procedure TSynLFMSyn.Next;
511 begin
512   fTokenPos := Run;
513   if fRange = rsComment then begin
514     if fLine[Run] = #0 then NullProc
515                        else CommentProc;
516   end else
517     fProcTable[fLine[Run]]();
518 end;
519 
GetDefaultAttributenull520 function TSynLFMSyn.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
521 begin
522   case Index of
523     SYN_ATTR_COMMENT: Result := fCommentAttri;
524     SYN_ATTR_IDENTIFIER: Result := fIdentifierAttri;
525     SYN_ATTR_KEYWORD: Result := fKeyAttri;
526     SYN_ATTR_STRING: Result := fStringAttri;
527     SYN_ATTR_WHITESPACE: Result := fSpaceAttri;
528     SYN_ATTR_SYMBOL: Result := fSymbolAttri;
529     SYN_ATTR_NUMBER: Result := fNumberAttri;
530   else
531     Result := nil;
532   end;
533 end;
534 
TSynLFMSyn.GetEolnull535 function TSynLFMSyn.GetEol: Boolean;
536 begin
537   Result := fTokenId = tkNull;
538 end;
539 
TSynLFMSyn.GetRangenull540 function TSynLFMSyn.GetRange: Pointer;
541 begin
542   CodeFoldRange.RangeType:=Pointer(PtrUInt(Integer(fRange)));
543   Result := inherited;
544 end;
545 
GetTokenIDnull546 function TSynLFMSyn.GetTokenID: TtkTokenKind;
547 begin
548   Result := fTokenId;
549 end;
550 
GetTokennull551 function TSynLFMSyn.GetToken: String;
552 var
553   Len: LongInt;
554 begin
555   Result := '';
556   Len := Run - fTokenPos;
557   SetString(Result, (FLine + fTokenPos), Len);
558 end;
559 
560 procedure TSynLFMSyn.GetTokenEx(out TokenStart: PChar;
561   out TokenLength: integer);
562 begin
563   TokenLength:=Run-fTokenPos;
564   TokenStart:=FLine + fTokenPos;
565 end;
566 
GetTokenAttributenull567 function TSynLFMSyn.GetTokenAttribute: TSynHighlighterAttributes;
568 begin
569   case fTokenID of
570     tkComment: Result := fCommentAttri;
571     tkIdentifier: Result := fIdentifierAttri;
572     tkKey: Result := fKeyAttri;
573     tkNumber: Result := fNumberAttri;
574     tkSpace: Result := fSpaceAttri;
575     tkString: Result := fStringAttri;
576     tkSymbol: Result := fSymbolAttri;
577     tkUnknown: Result := fIdentifierAttri;
578     else Result := nil;
579   end;
580 end;
581 
GetTokenKindnull582 function TSynLFMSyn.GetTokenKind: integer;
583 begin
584   Result := Ord(fTokenID);
585 end;
586 
GetTokenPosnull587 function TSynLFMSyn.GetTokenPos: Integer;
588 begin
589   Result := fTokenPos;
590 end;
591 
592 procedure TSynLFMSyn.ResetRange;
593 begin
594   inherited;
595   fRange := rsUnknown;
596 end;
597 
598 procedure TSynLFMSyn.SetRange(Value: Pointer);
599 begin
600   inherited;
601   fRange := TRangeState(Integer(PtrUInt(CodeFoldRange.RangeType)));
602 end;
603 
GetIdentCharsnull604 function TSynLFMSyn.GetIdentChars: TSynIdentChars;
605 begin
606   Result := TSynValidStringChars;
607 end;
608 
TSynLFMSyn.GetLanguageNamenull609 class function TSynLFMSyn.GetLanguageName: string;
610 begin
611   Result := SYNS_LangLFM;
612 end;
613 
TSynLFMSyn.GetSampleSourcenull614 function TSynLFMSyn.GetSampleSource: string;
615 begin
616   Result := '{ Delphi/C++ Builder Form Definitions }'#13#10 +
617             'object TestForm: TTestForm'#13#10 +
618             '  Left = 273'#13#10 +
619             '  Top = 103'#13#10 +
620             '  Caption = ''SynEdit sample source'''#13#10 +
621             'end';
622 end; { GetSampleSource }
623 
624 procedure TSynLFMSyn.CreateRootCodeFoldBlock;
625 begin
626   inherited CreateRootCodeFoldBlock;
627   RootCodeFoldBlock.InitRootBlockType(Pointer(PtrInt(cfbtLfmNone)));
628 end;
629 
TSynLFMSyn.StartLfmCodeFoldBlocknull630 function TSynLFMSyn.StartLfmCodeFoldBlock(ABlockType: TLfmCodeFoldBlockType): TSynCustomCodeFoldBlock;
631 var
632   FoldBlock: Boolean;
633   p: PtrInt;
634 begin
635   FoldBlock :=  FFoldConfig[ord(ABlockType)].Enabled;
636   p := 0;
637   if not FoldBlock then
638     p := PtrInt(CountLfmCodeFoldBlockOffset);
639   Result := StartCodeFoldBlock(p + Pointer(PtrInt(ABlockType)), FoldBlock);
640 end;
641 
642 procedure TSynLFMSyn.EndLfmCodeFoldBlock;
643 var
644   DecreaseLevel: Boolean;
645 begin
646   DecreaseLevel := TopCodeFoldBlockType < CountLfmCodeFoldBlockOffset;
647   EndCodeFoldBlock(DecreaseLevel);
648 end;
649 
TSynLFMSyn.TopLfmCodeFoldBlockTypenull650 function TSynLFMSyn.TopLfmCodeFoldBlockType(DownIndex: Integer): TLfmCodeFoldBlockType;
651 var
652   p: Pointer;
653 begin
654   p := TopCodeFoldBlockType(DownIndex);
655   if p >= CountLfmCodeFoldBlockOffset then
656     p := p - PtrUInt(CountLfmCodeFoldBlockOffset);
657   Result := TLfmCodeFoldBlockType(PtrUInt(p));
658 end;
659 
TSynLFMSyn.GetFoldConfigCountnull660 function TSynLFMSyn.GetFoldConfigCount: Integer;
661 begin
662   // excluded cfbtLfmNone
663   Result := ord(high(TLfmCodeFoldBlockType)) - ord(low(TLfmCodeFoldBlockType));
664 end;
665 
TSynLFMSyn.GetFoldConfigInternalCountnull666 function TSynLFMSyn.GetFoldConfigInternalCount: Integer;
667 begin
668   // include cfbtLfmNone
669   Result := ord(high(TLfmCodeFoldBlockType)) - ord(low(TLfmCodeFoldBlockType)) + 1;
670 end;
671 
672 initialization
673   RegisterPlaceableHighlighter(TSynLFMSyn);
674 
675 end.
676