***Code folding support*** **Introduction** This pull request adds code folding support for SynEdit. It blends well with the Synedit highligting infrastructure and provides fast and efficient code folding that can cope with files with tens of thousands of lines without lags. **Converting existing highlighters** To support code folding a Highlighter must inherit from TSynCustomCodeFoldingHighlighter and implement one abstact procedure ``` ScanForFoldRanges(FoldRanges: TSynFoldRanges; LinesToScan: TStrings; FromLine: Integer; ToLine: Integer); ``` For each line, ScanForFoldRanges needs to call one of the following: ``` FoldRanges.StartFoldRange FoldRanges.StopFoldRange FoldRanges.NoFoldInfo ``` ScanForFoldRanges is called after the standard highlighter scanning has taken place so one can use the Range information stored inside LinesToScan, which is a TSynEditStringList, to avoid duplicating effort. Initally two hightlighters have been converted SynHighlighterJScript and SynHighlighterPython, to serve as examples of adding code folding support to brace-based and indentation-based languagges. Alternatively, code folding support can be provided just by implementing the SynEdit OnScanForFoldRangesEvent event. **Demo of Coding Folding** A Folding demo has been added that demonstrates the use of the JScript and Python highlighters as well as the use of the OnScanForFoldRangesEvent event to support code folding in C++ files. **Synedit Commants and Shortcuts** The following commands have been added: ecFoldAll, ecUnfoldAll, ecFoldNearest, ecUnfoldNearest, ecFoldLevel1, ecFoldLevel2, ecFoldLevel3,, ecUnfoldLevel1, ecUnfoldLevel2, ecUnfoldLevel3, ecFoldRegions, ecUnfoldRegions. The default customisable shortcuts are: ``` AddKey(ecFoldAll, VK_OEM_MINUS, [ssCtrl, ssShift]); //- _ AddKey(ecUnfoldAll, VK_OEM_PLUS, [ssCtrl, ssShift]); //= + AddKey(ecFoldNearest, VK_OEM_2, [ssCtrl]); // Divide //'/' AddKey(ecUnfoldNearest, VK_OEM_2, [ssCtrl, ssShift]); AddKey(ecFoldLevel1, ord('K'), [ssCtrl], Ord('1'), [ssCtrl]); AddKey(ecFoldLevel2, ord('K'), [ssCtrl], Ord('2'), [ssCtrl]); AddKey(ecFoldLevel3, ord('K'), [ssCtrl], Ord('3'), [ssCtrl]); AddKey(ecUnfoldLevel1, ord('K'), [ssCtrl, ssShift], Ord('1'), [ssCtrl, ssShift]); AddKey(ecUnfoldLevel2, ord('K'), [ssCtrl, ssShift], Ord('2'), [ssCtrl, ssShift]); AddKey(ecUnfoldLevel3, ord('K'), [ssCtrl, ssShift], Ord('3'), [ssCtrl, ssShift]); ``` **Limitations** - Code folding can not be used simultaneously with Wordwrap. Synedit takes care of that. - The code uses generic collections, so it cannot be used with Delphi versions prior to Delphi 2009. **Improvements** Although the code folding infrastructure is fairly complete, improvements can be made in providing the user with more painting options (folding hints etc.) **Technical details** The main code folding structure is TSynFoldRanges in SynEditCodefolding.pas. It contains a public `TList` (sorted by starting line numbers). This list is used by Synedit to paint the gutter and lines, fold and unfold ranges etc. Internally, TSynFoldRange maintains a `TList` that is modified during scanning. The `TList` is reconstructed from the `TList` only when it is necessary.