SynEdit: Refactored fold-highlighters: unify methods to get fold-nest info

git-svn-id: trunk@35115 -
This commit is contained in:
martin 2012-02-03 16:50:04 +00:00
parent e10dc0f7ea
commit 7a03599f16
13 changed files with 1022 additions and 631 deletions

2
.gitattributes vendored
View File

@ -2438,6 +2438,8 @@ components/synedit/test/testbasicsynedit.pas svneol=native#text/pascal
components/synedit/test/testblockindent.pas svneol=native#text/pascal components/synedit/test/testblockindent.pas svneol=native#text/pascal
components/synedit/test/testbookmarks.pas svneol=native#text/pascal components/synedit/test/testbookmarks.pas svneol=native#text/pascal
components/synedit/test/testfoldedview.pas svneol=native#text/pascal components/synedit/test/testfoldedview.pas svneol=native#text/pascal
components/synedit/test/testhighlighterlfm.pas svneol=native#text/pascal
components/synedit/test/testhighlightfoldbase.pas svneol=native#text/pascal
components/synedit/test/testhighlightmulti.pas svneol=native#text/pascal components/synedit/test/testhighlightmulti.pas svneol=native#text/pascal
components/synedit/test/testhighlightpas.pas svneol=native#text/pascal components/synedit/test/testhighlightpas.pas svneol=native#text/pascal
components/synedit/test/testhighlightxml.pas svneol=native#text/pascal components/synedit/test/testhighlightxml.pas svneol=native#text/pascal

View File

@ -284,6 +284,50 @@ type
end; end;
TSynEditFoldProviderNodeInfoList = array of TSynEditFoldProviderNodeInfo; TSynEditFoldProviderNodeInfoList = array of TSynEditFoldProviderNodeInfo;
TSynEditFoldProvider = class;
(* TLazSynEditNestedFoldsList
Provides Info on all foldable-blocks containing a given line (0 based index).
That are:
- All foldable blocks opening on a previous line, that are still open
at the start of the line. (May end on this line or later)
- Foldable blocks opening on that line. (OpeningOnLineCount)
The data is NOT automatically invalidated.
*)
TLazSynEditNestedFoldsListEntry = record
HNode: TSynFoldNodeInfo; // Highlighter Node
//FNode: TSynTextFoldAVLNode; // AvlFoldNode
//Text, Keyword: String;
LineIdx: TLineIdx;
//ColIndex: Integer;
//OpenCount: Integer;
end;
TLazSynEditNestedFoldsList = class
private
FFoldProvider: TSynEditFoldProvider;
FFoldGroup: Integer;
FLine: TLineIdx;
procedure SetFoldGroup(AValue: Integer);
procedure SetLines(AValue: TLineIdx);
private
FGroupCount: Integer;
FGroupEndLevels, FGroupEndLevelsAtEval: Array of integer;
FCount, FOpeningOnLineCount: Integer;
FNestInfo: Array of TLazSynEditNestedFoldsListEntry;
FEvaluationIndex: Integer;
procedure InitSubGroupEndLevels;
procedure InitNestInfoForIndex(AnIndex: Integer);
public
constructor Create(aFoldProvider: TSynEditFoldProvider);
procedure Clear;
function Count: Integer;
function OpeningOnLineCount: Integer;
property Line: TLineIdx read FLine write SetLines;
property FoldGroup: Integer read FFoldGroup write SetFoldGroup;
end;
TSynEditFoldProvider = class TSynEditFoldProvider = class
private private
@ -292,17 +336,21 @@ type
FSelection: TSynEditSelection; FSelection: TSynEditSelection;
FFoldTree : TSynTextFoldAVLTree; FFoldTree : TSynTextFoldAVLTree;
function GetFoldsAvailable: Boolean; function GetFoldsAvailable: Boolean;
function GetHighLighterWithLines: TSynCustomFoldHighlighter;
function GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities; function GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
function GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications; function GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
procedure SetHighLighter(const AValue: TSynCustomFoldHighlighter); procedure SetHighLighter(const AValue: TSynCustomFoldHighlighter);
protected
property HighLighterWithLines: TSynCustomFoldHighlighter read GetHighLighterWithLines;
public public
constructor Create(aTextView : TSynEditStrings; AFoldTree : TSynTextFoldAVLTree); constructor Create(aTextView : TSynEditStrings; AFoldTree : TSynTextFoldAVLTree);
function FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
function FoldOpenInfo(ALineIdx, AFoldIdx: Integer; AType: Integer = 0): TSynFoldNodeInfo; // Info about Folds opening on ALineIdx
function FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
function FoldOpenInfo(ALineIdx, AFoldIdx: Integer; AType: Integer = 0): TSynFoldNodeInfo;
//property FoldOpenInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldOpenInfo; //property FoldOpenInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldOpenInfo;
//property FoldInfoCount[ALineIdx: Integer]: Integer read GetFoldInfoCount;
//property FoldInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldInfo; function FoldLineLength(ALine, AFoldIndex: Integer): integer;
function FoldLineLength(ALine, AFoldIndex: Integer): integer;
function InfoForFoldAtTextIndex(ALine, AFoldIndex : Integer; function InfoForFoldAtTextIndex(ALine, AFoldIndex : Integer;
HideLen: Boolean = False; HideLen: Boolean = False;
NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo; NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo;
@ -2724,6 +2772,131 @@ begin
fNestedNodesTree := nil; fNestedNodesTree := nil;
end; end;
{ TLazSynEditNestedFoldsList }
procedure TLazSynEditNestedFoldsList.SetLines(AValue: TLineIdx);
begin
if FLine = AValue then Exit;
FLine := AValue;
// Todo: might be able to re-use old data
Clear;
end;
procedure TLazSynEditNestedFoldsList.Clear;
begin
FGroupCount := -1;
FCount := -1;
FOpeningOnLineCount := -1;
FEvaluationIndex := -1;
SetLength(FNestInfo, 0);
end;
procedure TLazSynEditNestedFoldsList.InitSubGroupEndLevels;
var
hl: TSynCustomFoldHighlighter;
i: integer;
begin
if FGroupCount > 0 then
exit;
hl := FFoldProvider.HighLighterWithLines;
if hl = nil then exit;
if FFoldGroup = 0 then begin
// special, join other groups (or some other...)
FGroupCount := hl.FoldTypeCount;
// start at 1, so FoldGroup can be used as index
SetLength(FGroupEndLevels, FGroupCount + 1);
SetLength(FGroupEndLevelsAtEval, FGroupCount + 1);
for i := 1 to FGroupCount do
FGroupEndLevels[i] := hl.FoldBlockEndLevel(FLine - 1, i) + OpeningOnLineCount;
FGroupEndLevelsAtEval[i] := FGroupEndLevels[i];
end
else begin
FGroupCount := 1;
SetLength(FGroupEndLevels, 1);
SetLength(FGroupEndLevelsAtEval, 1);
FGroupEndLevels[0] := Count;
FGroupEndLevelsAtEval[0] := FGroupEndLevels[0];
end;
end;
procedure TLazSynEditNestedFoldsList.InitNestInfoForIndex(AnIndex: Integer);
var
CurLine: TLineIdx;
hl: TSynCustomFoldHighlighter;
i: Integer;
begin
if (AnIndex >= Count) or (AnIndex >= FEvaluationIndex) then exit;
hl := FFoldProvider.HighLighterWithLines;
if hl = nil then exit;
InitSubGroupEndLevels;
if FEvaluationIndex = Count then
CurLine := Line
else
CurLine := FNestInfo[FEvaluationIndex].LineIdx;
// need index/column...
inc(CurLine);
while CurLine > 0 do begin
dec(CurLine);
if FFoldGroup = 0 then begin
i := FGroupCount;
while (i > 0) do begin
// hl.MinimumFoldLevel(CurLine, i) // minimumPas
dec(i);
end;
if i < 0 then continue;
end
else begin
//if ... continue
end;
end;
end;
procedure TLazSynEditNestedFoldsList.SetFoldGroup(AValue: Integer);
begin
if FFoldGroup = AValue then Exit;
FFoldGroup := AValue;
Clear;
end;
constructor TLazSynEditNestedFoldsList.Create(aFoldProvider: TSynEditFoldProvider);
begin
FFoldProvider := aFoldProvider;
end;
function TLazSynEditNestedFoldsList.Count: Integer;
var
hl: TSynCustomFoldHighlighter;
begin
Result := FCount;
if Result >= 0 then exit;
hl := FFoldProvider.HighLighterWithLines;
if hl = nil then exit(-1);
FCount := hl.FoldBlockEndLevel(FLine - 1, FFoldGroup) + OpeningOnLineCount;
FEvaluationIndex := FCount;
SetLength(FNestInfo, FCount);
Result := FCount;
end;
function TLazSynEditNestedFoldsList.OpeningOnLineCount: Integer;
begin
Result := FOpeningOnLineCount;
if Result >= 0 then exit;
FOpeningOnLineCount := FFoldProvider.FoldOpenCount(FLine);
Result := FOpeningOnLineCount;
end;
{ TSynEditFoldProvider } { TSynEditFoldProvider }
function TSynEditFoldProvider.GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities; function TSynEditFoldProvider.GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
@ -2744,8 +2917,8 @@ begin
exit; exit;
FHighlighter.CurrentLines := FLines; FHighlighter.CurrentLines := FLines;
if FHighlighter.FoldNestCount(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody]; if FHighlighter.FoldBlockEndLevel(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
if FHighlighter.FoldCloseCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody]; if FHighlighter.FoldBlockClosingCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([]); c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([]);
if c > 0 then begin if c > 0 then begin
@ -2761,7 +2934,7 @@ begin
Result := Result + [cfHideStart, cfSingleLineHide]; Result := Result + [cfHideStart, cfSingleLineHide];
end end
else else
if FHighlighter.FoldOpenCount(ALineIdx) > 0 then include(Result, cfFoldStart); if FHighlighter.FoldBlockOpeningCount(ALineIdx) > 0 then include(Result, cfFoldStart);
end; end;
function TSynEditFoldProvider.GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications; function TSynEditFoldProvider.GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
@ -2777,6 +2950,14 @@ begin
((FSelection <> nil) and FSelection.SelAvail); ((FSelection <> nil) and FSelection.SelAvail);
end; end;
function TSynEditFoldProvider.GetHighLighterWithLines: TSynCustomFoldHighlighter;
begin
Result := FHighlighter;
if (Result = nil) then
exit;
Result.CurrentLines := FLines;
end;
procedure TSynEditFoldProvider.SetHighLighter(const AValue: TSynCustomFoldHighlighter); procedure TSynEditFoldProvider.SetHighLighter(const AValue: TSynCustomFoldHighlighter);
begin begin
if FHighlighter = AValue then exit; if FHighlighter = AValue then exit;
@ -2790,30 +2971,18 @@ begin
end; end;
function TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer; function TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
var
i: Integer;
begin begin
if (FHighlighter = nil) or (ALineIdx < 0) then begin if (FHighlighter = nil) or (ALineIdx < 0) then begin
if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then exit(1); if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then exit(1);
exit(0); exit(0);
end; end;
// Need to check alll nodes with FoldNodeInfoCount
// Hide-able nodes can open and close on the same line "(* cmment *)"
FHighlighter.CurrentLines := FLines; FHighlighter.CurrentLines := FLines;
Result := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold]); Result := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold], AType);
if (result > 0) and (AType > 0) then begin // fallback for HL without GetFoldNodeInfoCountEx
i := Result ;
Result := 0;
while i > 0 do begin
dec(i);
if FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(i, [sfaOpen, sfaFold]).FoldGroup = AType then
inc(Result);
end;
end
//Result := Result + FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFoldHide]];
//Result := Result + FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOneLineOpen, sfaFoldHide]];
else
if Result < 0 then if Result < 0 then
Result := FHighlighter.FoldOpenCount(ALineIdx, AType); Result := FHighlighter.FoldBlockOpeningCount(ALineIdx, AType);
if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then
inc(Result); inc(Result);
end; end;
@ -2837,8 +3006,6 @@ function TSynEditFoldProvider.FoldOpenInfo(ALineIdx, AFoldIdx: Integer;
Result.FoldGroup := -1; Result.FoldGroup := -1;
end; end;
var
i, x: Integer;
begin begin
Result.FoldAction := [sfaInvalid]; Result.FoldAction := [sfaInvalid];
if (FHighlighter = nil) or (ALineIdx < 0) then begin if (FHighlighter = nil) or (ALineIdx < 0) then begin
@ -2848,27 +3015,13 @@ begin
end; end;
FHighlighter.CurrentLines := FLines; FHighlighter.CurrentLines := FLines;
if AType = 0 then if (AType = 0) and (FSelection <> nil) and FSelection.SelAvail and
if (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) and (FSelection.FirstLineBytePos.Y=ALineIdx+1) and
(AFoldIdx = FoldOpenCount(ALineIdx, 0)-1) (AFoldIdx = FoldOpenCount(ALineIdx, AType)-1)
then then
Result := BlockSelInfo(AFoldIdx-1) Result := BlockSelInfo(AFoldIdx)
else else
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(AFoldIdx, [sfaOpen, sfaFold]) Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(AFoldIdx, [sfaOpen, sfaFold], AType);
else begin
x := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold]);
i := 0;
while i < x do begin
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(i, [sfaOpen, sfaFold]);
if (Result.FoldGroup = AType) then begin
if AFoldIdx = 0 then
exit;
dec(AFoldIdx);
end;
inc(i);
end;
Result.FoldAction := [sfaInvalid];
end;
end; end;
function TSynEditFoldProvider.FoldLineLength(ALine, AFoldIndex: Integer): integer; function TSynEditFoldProvider.FoldLineLength(ALine, AFoldIndex: Integer): integer;
@ -3369,7 +3522,7 @@ begin
while i < fLines.Count do begin while i < fLines.Count do begin
// Todo: Highlighter should return a list of types that can return default folded // Todo: Highlighter should return a list of types that can return default folded
// Currently PascalHl Type 2 = Region // Currently PascalHl Type 2 = Region
c := hl.FoldOpenCount(i, 2); c := hl.FoldBlockOpeningCount(i, 2);
if c > 0 then begin if c > 0 then begin
c := hl.FoldNodeInfo[i].CountEx([sfaOpen, sfaFold]); c := hl.FoldNodeInfo[i].CountEx([sfaOpen, sfaFold]);
j := 0; j := 0;
@ -3855,9 +4008,9 @@ begin
fFoldTree.Clear; fFoldTree.Clear;
i := 0; i := 0;
while i < fLines.Count do begin while i < fLines.Count do begin
if (hl.FoldOpenCount(i, t) > 0) if (hl.FoldBlockOpeningCount(i, t) > 0)
and (hl.FoldNestCount(i, t) > StartLevel) then begin and (hl.FoldBlockEndLevel(i, t) > StartLevel) then begin
c := hl.FoldOpenCount(i) -1; c := hl.FoldBlockOpeningCount(i) -1;
fldinf := FoldProvider.InfoForFoldAtTextIndex(i, c); fldinf := FoldProvider.InfoForFoldAtTextIndex(i, c);
// i is 0-based // i is 0-based
// FoldTree is 1-based AND first line remains visble // FoldTree is 1-based AND first line remains visble
@ -4111,7 +4264,7 @@ begin
hl := TSynCustomFoldHighlighter(HighLighter); hl := TSynCustomFoldHighlighter(HighLighter);
if not assigned(hl) then if not assigned(hl) then
exit(-1); exit(-1);
Result := hl.FoldNestCount(AStartIndex-1, AType) + FoldProvider.FoldOpenCount(AStartIndex); Result := hl.FoldBlockEndLevel(AStartIndex-1, AType) + FoldProvider.FoldOpenCount(AStartIndex);
end; end;
function TSynEditFoldedView.OpenFoldInfo(aStartIndex, ColIndex: Integer; AType: Integer = 0): TFoldViewNodeInfo; function TSynEditFoldedView.OpenFoldInfo(aStartIndex, ColIndex: Integer; AType: Integer = 0): TFoldViewNodeInfo;
@ -4126,13 +4279,13 @@ var
begin begin
if AType = 0 then begin; if AType = 0 then begin;
for i := 1 to TypeCnt do begin for i := 1 to TypeCnt do begin
EndLvl[i] := hl.FoldNestCount(l-1, i); EndLvl[i] := hl.FoldBlockEndLevel(l-1, i);
EndLvl[i] := EndLvl[i] + FoldProvider.FoldOpenCount(l, i); EndLvl[i] := EndLvl[i] + FoldProvider.FoldOpenCount(l, i);
CurLvl[i] := EndLvl[i]; CurLvl[i] := EndLvl[i];
end; end;
end end
else begin else begin
EndLvl[0] := hl.FoldNestCount(l-1, AType); EndLvl[0] := hl.FoldBlockEndLevel(l-1, AType);
EndLvl[0] := EndLvl[0] + FoldProvider.FoldOpenCount(l, AType); EndLvl[0] := EndLvl[0] + FoldProvider.FoldOpenCount(l, AType);
CurLvl[0] := EndLvl[0]; CurLvl[0] := EndLvl[0];
end; end;
@ -4146,7 +4299,7 @@ begin
TypeCnt := 1 TypeCnt := 1
else else
TypeCnt := hl.FoldTypeCount; TypeCnt := hl.FoldTypeCount;
Lvl := hl.FoldNestCount(AStartIndex-1, AType); Lvl := hl.FoldBlockEndLevel(AStartIndex-1, AType);
if ColIndex >= Lvl then begin if ColIndex >= Lvl then begin
n := ColIndex - Lvl; n := ColIndex - Lvl;
if AType = 0 then begin if AType = 0 then begin
@ -4165,8 +4318,8 @@ begin
aStartIndex := aStartIndex; aStartIndex := aStartIndex;
while (ColIndex < Lvl) and (aStartIndex > 0) do begin while (ColIndex < Lvl) and (aStartIndex > 0) do begin
dec(aStartIndex); dec(aStartIndex);
o := hl.FoldOpenCount(AStartIndex, AType); o := hl.FoldBlockOpeningCount(AStartIndex, AType);
if (o > 0) or (hl.FoldCloseCount(aStartIndex, AType) > 0) then begin if (o > 0) or (hl.FoldBlockClosingCount(aStartIndex, AType) > 0) then begin
n := o; n := o;
c := hl.FoldNodeInfo[aStartIndex].CountEx([], AType) - 1; c := hl.FoldNodeInfo[aStartIndex].CountEx([], AType) - 1;
for i := c downto 0 do begin for i := c downto 0 do begin
@ -4194,7 +4347,7 @@ begin
end; end;
end end
else else
if hl.FoldNestCount(AStartIndex-1, AType) = 0 then break; if hl.FoldBlockEndLevel(AStartIndex-1, AType) = 0 then break;
end; end;
end; end;
Result.HNode := nd; Result.HNode := nd;
@ -4220,7 +4373,7 @@ begin
exit; exit;
i := ALine; i := ALine;
l := hl.FoldOpenCount(i - 1); l := hl.FoldBlockOpeningCount(i - 1);
if l > 0 then begin if l > 0 then begin
node := fFoldTree.FindFoldForLine(ALine, true); node := fFoldTree.FindFoldForLine(ALine, true);
if node.IsInFold and (node.StartLine = ALine +1) then begin if node.IsInFold and (node.StartLine = ALine +1) then begin
@ -4234,19 +4387,19 @@ begin
else else
exit(ALine); exit(ALine);
end end
else if hl.FoldCloseCount(i - 1) > 0 then else if hl.FoldBlockClosingCount(i - 1) > 0 then
dec(i); dec(i);
if (i < 0) or (hl.FoldNestCount(i-1) = 0) then if (i < 0) or (hl.FoldBlockEndLevel(i-1) = 0) then
exit; exit;
l := 0; l := 0;
while (i > 0) and (l >= 0) do begin // (FoldMinLevel[i] >= l) do while (i > 0) and (l >= 0) do begin // (FoldMinLevel[i] >= l) do
dec(i); dec(i);
l := l - hl.FoldOpenCount(i); l := l - hl.FoldBlockOpeningCount(i);
if l >= 0 then if l >= 0 then
l := l + hl.FoldCloseCount(i); l := l + hl.FoldBlockClosingCount(i);
end; end;
if (hl.FoldNestCount(i) > 0) then // TODO, check for collapsed at index = 0 if (hl.FoldBlockEndLevel(i) > 0) then // TODO, check for collapsed at index = 0
Result := i + 1; Result := i + 1;
end; end;

View File

@ -22,9 +22,25 @@ $Id: synedithighlighter.pp 19051 2009-03-21 00:47:33Z martin $
You may retrieve the latest version of this file at the SynEdit home page, You may retrieve the latest version of this file at the SynEdit home page,
located at http://SynEdit.SourceForge.net located at http://SynEdit.SourceForge.net
Known Issues:
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
(* Naming Conventions:
- FoldBlock:
A continuous range of lines, that can (optional) be folded.
Which Foldblocks can be folded is decided by the Highlighter. It may be
configurable.
A Foldblock can contain other Foldbloccks (nested), but two Foldblocks can
not overlap.
- FoldBlockLevel (FoldBlockNestLevel):
The amount of FoldBlocks in which a line (or a point of text) is.
- FoldGroup:
An independent set of FoldBlocks. FoldBlocks in different Groups may overlap.
(e.g. IFDEF/REGION in the SynPasSyn allow for overlaps, rather than strict nesting)
Some older code use "FoldType" instead
- FoldNode
Start or End of a FoldBlock
*)
unit SynEditHighlighterFoldBase; unit SynEditHighlighterFoldBase;
{$I synedit.inc} {$I synedit.inc}
@ -54,6 +70,42 @@ type
); );
TSynFoldActions = set of TSynFoldAction; TSynFoldActions = set of TSynFoldAction;
(* TSynFoldBlockFilter
used to specify which folds to include for:
- FoldOpenCount, FoldCloseCount, FoldNestCount
- maybe in future TLazSynFoldNodeInfoList
TLazSynFoldNodeInfoList has additional filters
TLazSynFoldNodeInfoList always uses the full set (sfbIncludeDisabled)
A Highlighter is not required to implement this, or can choose to implement
a subset only. For any field/value a Highlighter may simple assume default.
- Highlighter that have only one "FoldGroup" do not require this.
- Highlighter that do not store foldblocks that are unavailable (e.g. off by
config) always return the same set
Using a record, as argument is the virtual methods, allows to add further
fields/values, without breaking inheritance.
New fields values are expected to be ignored (handled as default) by existing
highlighter.
Callers of the method can:
- use InitFoldBlockFilter to make sure all fields are set to default
- use (none virtual) wrapper methods
*)
TSynFoldBlockFilterFlag = (
sfbIncludeDisabled // Foldable by config = off
);
TSynFoldBlockFilterFlags = set of TSynFoldBlockFilterFlag;
TSynFoldBlockFilter = record
FoldGroup: integer;
Flags: TSynFoldBlockFilterFlags;
end;
procedure InitFoldBlockFilter(out AFilter: TSynFoldBlockFilter;
AFoldGroup: Integer = 0; AFlag: TSynFoldBlockFilterFlags = []);
type
TSynFoldNodeInfo = record TSynFoldNodeInfo = record
LineIndex: Integer; LineIndex: Integer;
NodeIndex: Integer; // Indicates the position within the list of info nodes (depends on search-Filter) NodeIndex: Integer; // Indicates the position within the list of info nodes (depends on search-Filter)
@ -204,7 +256,7 @@ type
TSynCustomFoldHighlighter = class(TSynCustomHighlighter) TSynCustomFoldHighlighter = class(TSynCustomHighlighter)
protected protected
// Config // Fold Config
FFoldConfig: Array of TSynCustomFoldConfig; FFoldConfig: Array of TSynCustomFoldConfig;
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; virtual; function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; virtual;
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); virtual; procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); virtual;
@ -220,36 +272,55 @@ type
FRootCodeFoldBlock: TSynCustomCodeFoldBlock; FRootCodeFoldBlock: TSynCustomCodeFoldBlock;
FFoldNodeInfoList: TLazSynFoldNodeInfoList; FFoldNodeInfoList: TLazSynFoldNodeInfoList;
protected protected
function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; virtual; // "Range"
function GetFoldNodeInfo(Line: TLineIdx): TLazSynFoldNodeInfoList;
procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); virtual;
protected
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
function GetRangeClass: TSynCustomHighlighterRangeClass; virtual; function GetRangeClass: TSynCustomHighlighterRangeClass; virtual;
procedure CreateRootCodeFoldBlock; virtual; // set RootCodeFoldBlock
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
function TopCodeFoldBlockType(DownIndex: Integer = 0): Pointer; function TopCodeFoldBlockType(DownIndex: Integer = 0): Pointer;
property RootCodeFoldBlock: TSynCustomCodeFoldBlock read FRootCodeFoldBlock
write FRootCodeFoldBlock;
// Open/Close Folds
function StartCodeFoldBlock(ABlockType: Pointer; function StartCodeFoldBlock(ABlockType: Pointer;
IncreaseLevel: Boolean = true): TSynCustomCodeFoldBlock; virtual; IncreaseLevel: Boolean = true): TSynCustomCodeFoldBlock; virtual;
procedure EndCodeFoldBlock(DecreaseLevel: Boolean = True); virtual; procedure EndCodeFoldBlock(DecreaseLevel: Boolean = True); virtual;
procedure CreateRootCodeFoldBlock; virtual;
property RootCodeFoldBlock: TSynCustomCodeFoldBlock read FRootCodeFoldBlock // Info about Folds
write FRootCodeFoldBlock; function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; virtual;
function GetFoldNodeInfo(Line: TLineIdx): TLazSynFoldNodeInfoList;
procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); virtual;
// Info about Folds, on currently set line/range (simply forwarding to range
function MinimumCodeFoldBlockLevel: integer; virtual;
function CurrentCodeFoldBlockLevel: integer; virtual;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
function GetRange: Pointer; override; function GetRange: Pointer; override;
function MinimumCodeFoldBlockLevel: integer; virtual; // Info about Folds
function CurrentCodeFoldBlockLevel: integer; virtual; function FoldBlockOpeningCount(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
function FoldBlockClosingCount(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
function FoldBlockEndLevel(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
function FoldBlockMinLevel(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer; virtual; overload;
// requires CurrentLines; function FoldBlockOpeningCount(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
function MinimumFoldLevel(Index: Integer): integer; virtual; abstract; // TODO: Move to Fold* AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
function EndFoldLevel(Index: Integer): integer; virtual; abstract; // TODO: Replace with FoldNestCount function FoldBlockClosingCount(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
function FoldBlockEndLevel(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
function FoldBlockMinLevel(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; deprecated;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; deprecated;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; deprecated;
// fold-nodes that can be collapsed
// Highlighter can join several fold structures Or leave out some
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; virtual;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; virtual;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; virtual;
function FoldTypeCount: integer; virtual; function FoldTypeCount: integer; virtual;
function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer; function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer;
UseCloseNodes: boolean = false): integer; virtual; // TODO: could be deprecated ./ only child-classes UseCloseNodes: boolean = false): integer; virtual; // TODO: could be deprecated ./ only child-classes
@ -296,6 +367,13 @@ function AllocateHighlighterRanges(
implementation implementation
procedure InitFoldBlockFilter(out AFilter: TSynFoldBlockFilter; AFoldGroup: Integer;
AFlag: TSynFoldBlockFilterFlags = []);
begin
AFilter.FoldGroup := AFoldGroup;
AFilter.Flags := AFlag;
end;
function CompareSynHighlighterRanges(Data1, Data2: Pointer): integer; function CompareSynHighlighterRanges(Data1, Data2: Pointer): integer;
var var
Range1: TSynCustomHighlighterRange; Range1: TSynCustomHighlighterRange;
@ -597,6 +675,92 @@ begin
Result:=fRanges.GetEqual(FCodeFoldRange); Result:=fRanges.GetEqual(FCodeFoldRange);
end; end;
function TSynCustomFoldHighlighter.FoldBlockOpeningCount(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
Result := FoldBlockEndLevel(ALineIndex, AFilter) - FoldBlockMinLevel(ALineIndex, AFilter);
end;
function TSynCustomFoldHighlighter.FoldBlockClosingCount(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
Result := FoldBlockEndLevel(ALineIndex - 1, AFilter) - FoldBlockMinLevel(ALineIndex, AFilter);
end;
function TSynCustomFoldHighlighter.FoldBlockEndLevel(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer;
var
r: Pointer;
begin
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockEndLevel requires CurrentRanges');
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := CurrentRanges[ALineIndex];
if (r <> nil) and (r <> NullRange) then
Result := TSynCustomHighlighterRange(r).CodeFoldStackSize
else
Result:=0;
end;
function TSynCustomFoldHighlighter.FoldBlockMinLevel(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer;
var
r: Pointer;
begin
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockMinLevelrequires CurrentRanges');
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := CurrentRanges[ALineIndex];
if (r <> nil) and (r <> NullRange) then
Result := TSynCustomHighlighterRange(r).MinimumCodeFoldBlockLevel
else
Result:=0;
end;
function TSynCustomFoldHighlighter.FoldBlockOpeningCount(ALineIndex: TLineIdx;
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
var
Filter: TSynFoldBlockFilter;
begin
Filter.FoldGroup := AFoldGroup;
Filter.Flags := AFlags;
Result := FoldBlockOpeningCount(ALineIndex, Filter);
end;
function TSynCustomFoldHighlighter.FoldBlockClosingCount(ALineIndex: TLineIdx;
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
var
Filter: TSynFoldBlockFilter;
begin
Filter.FoldGroup := AFoldGroup;
Filter.Flags := AFlags;
Result := FoldBlockClosingCount(ALineIndex, Filter);
end;
function TSynCustomFoldHighlighter.FoldBlockEndLevel(ALineIndex: TLineIdx;
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
var
Filter: TSynFoldBlockFilter;
begin
Filter.FoldGroup := AFoldGroup;
Filter.Flags := AFlags;
Result := FoldBlockEndLevel(ALineIndex, Filter);
end;
function TSynCustomFoldHighlighter.FoldBlockMinLevel(ALineIndex: TLineIdx;
AFoldGroup: integer; AFlags: TSynFoldBlockFilterFlags): integer;
var
Filter: TSynFoldBlockFilter;
begin
Filter.FoldGroup := AFoldGroup;
Filter.Flags := AFlags;
Result := FoldBlockMinLevel(ALineIndex, Filter);
end;
procedure TSynCustomFoldHighlighter.ResetRange; procedure TSynCustomFoldHighlighter.ResetRange;
begin begin
FCodeFoldRange.Clear; FCodeFoldRange.Clear;
@ -605,6 +769,7 @@ end;
function TSynCustomFoldHighlighter.MinimumCodeFoldBlockLevel: integer; function TSynCustomFoldHighlighter.MinimumCodeFoldBlockLevel: integer;
begin begin
assert(FCodeFoldRange <> nil, 'MinimumCodeFoldBlockLevel requires FCodeFoldRange');
Result := FCodeFoldRange.MinimumCodeFoldBlockLevel; Result := FCodeFoldRange.MinimumCodeFoldBlockLevel;
end; end;
@ -625,25 +790,23 @@ end;
function TSynCustomFoldHighlighter.CurrentCodeFoldBlockLevel: integer; function TSynCustomFoldHighlighter.CurrentCodeFoldBlockLevel: integer;
begin begin
if CodeFoldRange<>nil then assert(FCodeFoldRange <> nil, 'MinimumCodeFoldBlockLevel requires FCodeFoldRange');
Result:=CodeFoldRange.CodeFoldStackSize Result := FCodeFoldRange.CodeFoldStackSize;
else
Result:=0;
end; end;
function TSynCustomFoldHighlighter.FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; function TSynCustomFoldHighlighter.FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer;
begin begin
result := 0; result := FoldBlockOpeningCount(ALineIndex, AType);
end; end;
function TSynCustomFoldHighlighter.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; function TSynCustomFoldHighlighter.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer;
begin begin
result := 0; result := FoldBlockClosingCount(ALineIndex, AType);
end; end;
function TSynCustomFoldHighlighter.FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; function TSynCustomFoldHighlighter.FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer;
begin begin
Result := 0; Result := FoldBlockEndLevel(ALineIndex, AType);
end; end;
function TSynCustomFoldHighlighter.FoldTypeCount: integer; function TSynCustomFoldHighlighter.FoldTypeCount: integer;
@ -661,7 +824,7 @@ function TSynCustomFoldHighlighter.FoldLineLength(ALineIndex, FoldIndex: Integer
begin begin
Result := FoldEndLine(ALineIndex, FoldIndex); Result := FoldEndLine(ALineIndex, FoldIndex);
// check if fold last line of block (not mixed "end begin") // check if fold last line of block (not mixed "end begin")
if (EndFoldLevel(Result) > MinimumFoldLevel(Result)) then if (FoldBlockEndLevel(Result) > FoldBlockMinLevel(Result)) then
dec(Result); dec(Result);
// Amount of lines, that will become invisible (excludes the cfCollapsed line) // Amount of lines, that will become invisible (excludes the cfCollapsed line)
Result := Result - ALineIndex; Result := Result - ALineIndex;
@ -672,13 +835,12 @@ var
lvl, cnt: Integer; lvl, cnt: Integer;
e, m: Integer; e, m: Integer;
begin begin
//atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
cnt := CurrentLines.Count; cnt := CurrentLines.Count;
e := EndFoldLevel(ALineIndex); e := FoldBlockEndLevel(ALineIndex);
m := MinimumFoldLevel(ALineIndex); m := FoldBlockMinLevel(ALineIndex);
lvl := Min(m+1+FoldIndex, e); lvl := Min(m+1+FoldIndex, e);
Result := ALineIndex + 1; Result := ALineIndex + 1;
while (Result < cnt) and (MinimumFoldLevel(Result) >= lvl) do inc(Result); while (Result < cnt) and (FoldBlockMinLevel(Result) >= lvl) do inc(Result);
if (Result = cnt) then if (Result = cnt) then
dec(Result); dec(Result);
end; end;

View File

@ -75,13 +75,6 @@ type
procedure EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = ''); procedure EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
public public
procedure SetLine({$IFDEF FPC}const {$ENDIF}NewValue: string; LineNumber:Integer); override; procedure SetLine({$IFDEF FPC}const {$ENDIF}NewValue: string; LineNumber:Integer); override;
public
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
// TODO: make private
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
function EndFoldLevel(ALineIndex: Integer): integer; override;
end; end;
implementation implementation
@ -122,50 +115,6 @@ begin
FXmlRangeInfoClosePos := 0; FXmlRangeInfoClosePos := 0;
end; end;
function TSynCustomXmlHighlighter.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
end;
function TSynCustomXmlHighlighter.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
end;
function TSynCustomXmlHighlighter.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex);
end;
function TSynCustomXmlHighlighter.MinimumFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.MinimumCodeFoldBlockLevel
else
Result := 0;
end;
function TSynCustomXmlHighlighter.EndFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize
else
Result := 0;
end;
function TSynCustomXmlHighlighter.StartXmlCodeFoldBlock(ABlockType: Integer): TSynCustomCodeFoldBlock; function TSynCustomXmlHighlighter.StartXmlCodeFoldBlock(ABlockType: Integer): TSynCustomCodeFoldBlock;
var var
FoldBlock: Boolean; FoldBlock: Boolean;
@ -232,11 +181,11 @@ begin
if i = 0 then begin if i = 0 then begin
i := LineIndex - 1; i := LineIndex - 1;
lvl := EndFoldLevel(i); lvl := FoldBlockEndLevel(i);
while i >= 0 do begin while i >= 0 do begin
if MinimumFoldLevel(i) < lvl then begin if FoldBlockMinLevel(i) < lvl then begin
LInfo := TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[i].ElementOpenList; LInfo := TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[i].ElementOpenList;
k := length(LInfo) - Max(EndFoldLevel(i) - lvl, 0) - 1; k := length(LInfo) - Max(FoldBlockEndLevel(i) - lvl, 0) - 1;
while (k >= 0) do begin while (k >= 0) do begin
if (LInfo[k] = AName) then if (LInfo[k] = AName) then
break; break;

View File

@ -140,7 +140,10 @@ var
exit; exit;
inc(YIndex); inc(YIndex);
while (YIndex < LCnt) and (HL.MinimumFoldLevel(YIndex) > StartNode.NestLvlStart) do while (YIndex < LCnt) and
(HL.FoldBlockMinLevel(YIndex, StartNode.FoldGroup, [sfbIncludeDisabled])
> StartNode.NestLvlStart)
do
inc(YIndex); inc(YIndex);
if YIndex = LCnt then if YIndex = LCnt then
exit; exit;
@ -172,7 +175,9 @@ var
exit; exit;
dec(YIndex); dec(YIndex);
while (YIndex >= 0) and (HL.MinimumFoldLevel(YIndex) > EndNode.NestLvlEnd) do while (YIndex >= 0) and
(HL.FoldBlockMinLevel(YIndex, EndNode.FoldGroup, [sfbIncludeDisabled]) > EndNode.NestLvlEnd)
do
dec(YIndex); dec(YIndex);
if YIndex < 0 then if YIndex < 0 then
exit; exit;

View File

@ -157,14 +157,6 @@ type
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override; function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigCount: Integer; override; function GetFoldConfigCount: Integer; override;
function GetFoldConfigInternalCount: Integer; override; function GetFoldConfigInternalCount: Integer; override;
public
// folding
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
// TODO: make private
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
function EndFoldLevel(ALineIndex: Integer): integer; override;
published published
property UnknownAttri: TSynHighlighterAttributes read FUnknownAttri write FUnknownAttri; property UnknownAttri: TSynHighlighterAttributes read FUnknownAttri write FUnknownAttri;
property SpaceAttri: TSynHighlighterAttributes read FSpaceAttri write FSpaceAttri; property SpaceAttri: TSynHighlighterAttributes read FSpaceAttri write FSpaceAttri;
@ -747,56 +739,6 @@ begin
Result := ord(high(TDiffCodeFoldBlockType)) - ord(low(TDiffCodeFoldBlockType)) + 1; Result := ord(high(TDiffCodeFoldBlockType)) - ord(low(TDiffCodeFoldBlockType)) + 1;
end; end;
// EndLvl = MinLvl(+1)
// MinLvl = Min(Min, Min(+1))
function TSynDiffSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := Max(0, MinimumFoldLevel(ALineIndex+1) - MinimumFoldLevel(ALineIndex));
//Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
end;
function TSynDiffSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := Max(0, MinimumFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex+1));
//Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
end;
function TSynDiffSyn.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := MinimumFoldLevel(ALineIndex+1);
//Result := EndFoldLevel(ALineIndex);
end;
function TSynDiffSyn.MinimumFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.MinimumCodeFoldBlockLevel
else
Result := 0;
end;
function TSynDiffSyn.EndFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize
else
Result := 0;
end;
initialization initialization
RegisterPlaceableHighlighter(TSynDiffSyn); RegisterPlaceableHighlighter(TSynDiffSyn);

View File

@ -65,6 +65,7 @@ type
// internal type / no config // internal type / no config
cfbtLfmNone cfbtLfmNone
); );
TLfmCodeFoldBlockTypes = set of TLfmCodeFoldBlockType;
TProcTableProc = procedure of object; TProcTableProc = procedure of object;
@ -148,14 +149,6 @@ type
procedure SetRange(Value: Pointer); override; procedure SetRange(Value: Pointer); override;
procedure ResetRange; override; procedure ResetRange; override;
property IdentChars; property IdentChars;
public
// folding
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
// TODO: make private
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
function EndFoldLevel(ALineIndex: Integer): integer; override;
published published
property CommentAttri: TSynHighlighterAttributes read fCommentAttri property CommentAttri: TSynHighlighterAttributes read fCommentAttri
write fCommentAttri; write fCommentAttri;
@ -612,50 +605,6 @@ begin
fRange := rsUnknown; fRange := rsUnknown;
end; end;
function TSynLFMSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
end;
function TSynLFMSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
end;
function TSynLFMSyn.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex);
end;
function TSynLFMSyn.MinimumFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.MinimumCodeFoldBlockLevel
else
Result := 0;
end;
function TSynLFMSyn.EndFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize
else
Result := 0;
end;
procedure TSynLFMSyn.SetRange(Value: Pointer); procedure TSynLFMSyn.SetRange(Value: Pointer);
begin begin
inherited; inherited;

View File

@ -174,6 +174,11 @@ const
cfbtNone cfbtNone
); );
FOLDGROUP_PASCAL = 1;
FOLDGROUP_REGION = 2;
FOLDGROUP_IFDEF = 3;
type type
TPascalCompilerMode = ( TPascalCompilerMode = (
@ -319,7 +324,9 @@ type
fD4syntax: boolean; fD4syntax: boolean;
FCatchNodeInfo: Boolean; FCatchNodeInfo: Boolean;
FCatchNodeInfoList: TLazSynPasFoldNodeInfoList; FCatchNodeInfoList: TLazSynPasFoldNodeInfoList;
// Divider
FDividerDrawConfig: Array [TSynPasDividerDrawLocation] of TSynDividerDrawConfig; FDividerDrawConfig: Array [TSynPasDividerDrawLocation] of TSynDividerDrawConfig;
function GetPasCodeFoldRange: TSynPasSynRange; function GetPasCodeFoldRange: TSynPasSynRange;
procedure SetCompilerMode(const AValue: TPascalCompilerMode); procedure SetCompilerMode(const AValue: TPascalCompilerMode);
procedure SetExtendedKeywordsMode(const AValue: Boolean); procedure SetExtendedKeywordsMode(const AValue: Boolean);
@ -449,9 +456,10 @@ type
procedure SymbolProc; procedure SymbolProc;
procedure UnknownProc; procedure UnknownProc;
procedure SetD4syntax(const Value: boolean); procedure SetD4syntax(const Value: boolean);
procedure InitNode(var Node: TSynFoldNodeInfo; EndOffs: Integer; procedure InitNode(out Node: TSynFoldNodeInfo; EndOffs: Integer;
ABlockType: TPascalCodeFoldBlockType; aActions: TSynFoldActions; ABlockType: TPascalCodeFoldBlockType; aActions: TSynFoldActions;
AIsFold: Boolean); AIsFold: Boolean);
// Divider
procedure CreateDividerDrawConfig; procedure CreateDividerDrawConfig;
procedure DestroyDividerDrawConfig; procedure DestroyDividerDrawConfig;
protected protected
@ -459,11 +467,17 @@ type
function GetIdentChars: TSynIdentChars; override; function GetIdentChars: TSynIdentChars; override;
function IsFilterStored: boolean; override; //mh 2000-10-08 function IsFilterStored: boolean; override; //mh 2000-10-08
protected protected
// "Range"
function GetRangeClass: TSynCustomHighlighterRangeClass; override; function GetRangeClass: TSynCustomHighlighterRangeClass; override;
procedure CreateRootCodeFoldBlock; override; procedure CreateRootCodeFoldBlock; override;
function CreateRangeList(ALines: TSynEditStringsBase): TSynHighlighterRangeList; override; function CreateRangeList(ALines: TSynEditStringsBase): TSynHighlighterRangeList; override;
function UpdateRangeInfoAtLine(Index: Integer): Boolean; override; // Returns true if range changed function UpdateRangeInfoAtLine(Index: Integer): Boolean; override; // Returns true if range changed
property PasCodeFoldRange: TSynPasSynRange read GetPasCodeFoldRange;
function TopPascalCodeFoldBlockType
(DownIndex: Integer = 0): TPascalCodeFoldBlockType;
// Open/Close Folds
function StartPascalCodeFoldBlock function StartPascalCodeFoldBlock
(ABlockType: TPascalCodeFoldBlockType): TSynCustomCodeFoldBlock; (ABlockType: TPascalCodeFoldBlockType): TSynCustomCodeFoldBlock;
procedure EndPascalCodeFoldBlock(NoMarkup: Boolean = False); procedure EndPascalCodeFoldBlock(NoMarkup: Boolean = False);
@ -473,24 +487,19 @@ type
procedure StartCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType); procedure StartCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType);
procedure EndCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType); procedure EndCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType);
// Info about Folds
function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; override; function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; override;
procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); override; procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); override;
protected
property PasCodeFoldRange: TSynPasSynRange read GetPasCodeFoldRange;
function TopPascalCodeFoldBlockType
(DownIndex: Integer = 0): TPascalCodeFoldBlockType;
public
function MinimumPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
function EndPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
protected protected
function LastLinePasFoldLevelFix(Index: Integer; AType: Integer = 1): integer; // foldable nodes function LastLinePasFoldLevelFix(Index: Integer; AType: Integer = 1): integer; // TODO deprecated; // foldable nodes
function LastLineFoldLevelFix(Index: Integer): integer; // all nodes
// Divider
function GetDrawDivider(Index: integer): TSynDividerDrawConfigSetting; override; function GetDrawDivider(Index: integer): TSynDividerDrawConfigSetting; override;
function GetDividerDrawConfig(Index: Integer): TSynDividerDrawConfig; override; function GetDividerDrawConfig(Index: Integer): TSynDividerDrawConfig; override;
function GetDividerDrawConfigCount: Integer; override; function GetDividerDrawConfigCount: Integer; override;
// Fold Config
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override; function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigCount: Integer; override; function GetFoldConfigCount: Integer; override;
function GetFoldConfigInternalCount: Integer; override; function GetFoldConfigInternalCount: Integer; override;
@ -523,19 +532,18 @@ type
function UseUserSettings(settingIndex: integer): boolean; override; function UseUserSettings(settingIndex: integer): boolean; override;
procedure EnumUserSettings(settings: TStrings); override; procedure EnumUserSettings(settings: TStrings); override;
// fold-nodes that can be collapsed // Info about Folds
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override; //function FoldBlockOpeningCount(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override; //function FoldBlockClosingCount(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override; function FoldBlockEndLevel(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
function FoldBlockMinLevel(ALineIndex: TLineIdx; const AFilter: TSynFoldBlockFilter): integer; override; overload;
function FoldTypeCount: integer; override; function FoldTypeCount: integer; override;
function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer; // accesses FoldNodeInfo function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer; // accesses FoldNodeInfo
UseCloseNodes: boolean = false): integer; override; UseCloseNodes: boolean = false): integer; override;
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override; // accesses FoldNodeInfo function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override; // accesses FoldNodeInfo
function FoldEndLine(ALineIndex, FoldIndex: Integer): integer; override; // accesses FoldNodeInfo function FoldEndLine(ALineIndex, FoldIndex: Integer): integer; override; // accesses FoldNodeInfo
// All fold nodes // TODO: make private
function MinimumFoldLevel(Index: Integer): integer; override;
function EndFoldLevel(Index: Integer): integer; override;
published published
property AsmAttri: TSynHighlighterAttributes read fAsmAttri write fAsmAttri; property AsmAttri: TSynHighlighterAttributes read fAsmAttri write fAsmAttri;
property CommentAttri: TSynHighlighterAttributes read fCommentAttri property CommentAttri: TSynHighlighterAttributes read fCommentAttri
@ -1091,7 +1099,6 @@ begin
if TopPascalCodeFoldBlockType in [cfbtVarType, cfbtLocalVarType] then if TopPascalCodeFoldBlockType in [cfbtVarType, cfbtLocalVarType] then
EndPascalCodeFoldBlockLastLine; EndPascalCodeFoldBlockLastLine;
StartPascalCodeFoldBlock(cfbtAsm); StartPascalCodeFoldBlock(cfbtAsm);
//debugln('TSynPasSyn.Func37 BEGIN ',dbgs(ord(TopPascalCodeFoldBlockType)),' LineNumber=',dbgs(fLineNumber),' ',dbgs(MinimumCodeFoldBlockLevel),' ',dbgs(CurrentCodeFoldBlockLevel));
end end
else Result := tkIdentifier; else Result := tkIdentifier;
end; end;
@ -2361,7 +2368,7 @@ begin
fLine:=PChar(Pointer(fLineStr)); fLine:=PChar(Pointer(fLineStr));
Run := 0; Run := 0;
Inherited SetLine(NewValue,LineNumber); Inherited SetLine(NewValue,LineNumber);
FStartCodeFoldBlockLevel := MinimumCodeFoldBlockLevel; FStartCodeFoldBlockLevel := PasCodeFoldRange.MinimumCodeFoldBlockLevel;
PasCodeFoldRange.LastLineCodeFoldLevelFix := 0; PasCodeFoldRange.LastLineCodeFoldLevelFix := 0;
PasCodeFoldRange.PasFoldFixLevel := 0; PasCodeFoldRange.PasFoldFixLevel := 0;
PasCodeFoldRange.PasFoldMinLevel := PasCodeFoldRange.PasFoldEndLevel; PasCodeFoldRange.PasFoldMinLevel := PasCodeFoldRange.PasFoldEndLevel;
@ -3156,6 +3163,100 @@ begin
end; end;
end; end;
function TSynPasSyn.FoldBlockEndLevel(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer;
var
inf: TSynPasRangeInfo;
r, r2: Pointer;
begin
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockEndLevel requires CurrentRanges');
Result := 0;
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count - 1) then
exit;
if AFilter.FoldGroup in [0, FOLDGROUP_REGION, FOLDGROUP_IFDEF] then
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
if AFilter.FoldGroup in [0, FOLDGROUP_PASCAL] then begin
// All or Pascal
r := CurrentRanges[ALineIndex];
if (r <> nil) and (r <> NullRange) then begin
r2 := TSynPasSynRange(CurrentRanges[ALineIndex + 1]);
if sfbIncludeDisabled in AFilter.Flags then begin
Result := TSynPasSynRange(r).CodeFoldStackSize;
if (r2 <> nil) and (r2 <> NullRange) then
Result := Result + TSynPasSynRange(r2).LastLineCodeFoldLevelFix;
end
else begin
Result := TSynPasSynRange(r).PasFoldEndLevel;
if (r2 <> nil) and (r2 <> NullRange) then
Result := Result + TSynPasSynRange(r2).PasFoldFixLevel;
end;
end;
end;
if AFilter.FoldGroup in [0, FOLDGROUP_REGION] then begin
// All or REGION
Result := Result + inf.EndLevelRegion;
end;
if AFilter.FoldGroup in [0, FOLDGROUP_IFDEF] then begin
// All or IFDEF
Result := Result + inf.EndLevelIfDef;
end;
end;
function TSynPasSyn.FoldBlockMinLevel(ALineIndex: TLineIdx;
const AFilter: TSynFoldBlockFilter): integer;
var
inf: TSynPasRangeInfo;
r, r2: Pointer;
begin
Assert(CurrentRanges <> nil, 'TSynCustomFoldHighlighter.FoldBlockMinLevel requires CurrentRanges');
Result := 0;
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count - 1) then
exit;
if AFilter.FoldGroup in [0, FOLDGROUP_REGION, FOLDGROUP_IFDEF] then
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
if AFilter.FoldGroup in [0, FOLDGROUP_PASCAL] then begin
// All or Pascal
(* Range.EndLevel can be smaller. because it Range.MinLevel does not know the LastLiineFix
Using a copy of FoldBlockEndLevel *)
r := CurrentRanges[ALineIndex];
if (r <> nil) and (r <> NullRange) then begin
r2 := TSynPasSynRange(CurrentRanges[ALineIndex + 1]);
if sfbIncludeDisabled in AFilter.Flags then begin
Result := TSynPasSynRange(r).CodeFoldStackSize;
if (r2 <> nil) and (r2 <> NullRange) then
Result := Result + TSynPasSynRange(r2).LastLineCodeFoldLevelFix;
// now Result = FoldBlockEndLevel
Result := Min(Result, TSynPasSynRange(r).MinimumCodeFoldBlockLevel);
end
else begin
Result := TSynPasSynRange(r).PasFoldEndLevel;
if (r2 <> nil) and (r2 <> NullRange) then
Result := Result + TSynPasSynRange(r2).PasFoldFixLevel;
// now Result = FoldBlockEndLevel
Result := Min(Result, TSynPasSynRange(r).PasFoldMinLevel);
end;
end;
end;
if AFilter.FoldGroup in [0, FOLDGROUP_REGION] then begin
// All or REGION
Result := Result + inf.MinLevelRegion;
end;
if AFilter.FoldGroup in [0, FOLDGROUP_IFDEF] then begin
// All or IFDEF
Result := Result + inf.MinLevelIfDef;
end;
end;
function TSynPasSyn.TopPascalCodeFoldBlockType(DownIndex: Integer = 0): TPascalCodeFoldBlockType; function TSynPasSyn.TopPascalCodeFoldBlockType(DownIndex: Integer = 0): TPascalCodeFoldBlockType;
var var
p: Pointer; p: Pointer;
@ -3166,63 +3267,6 @@ begin
Result := TPascalCodeFoldBlockType(PtrUInt(p)); Result := TPascalCodeFoldBlockType(PtrUInt(p));
end; end;
function TSynPasSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer;
var
inf: TSynPasRangeInfo;
begin
Result := 0;
if not(AType in [1, 4]) then
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
if (AType = 0) or (AType = 1) then
Result := EndPasFoldLevel(ALineIndex) - MinimumPasFoldLevel(ALineIndex);
if (AType = 0) or (AType = 2) then
Result := Result + inf.EndLevelRegion - inf.MinLevelRegion;
if (AType = 0) or (AType = 3) then
Result := Result + inf.EndLevelIfDef - inf.MinLevelIfDef;
if (AType = 4) then
Result := EndPasFoldLevel(ALineIndex, 4) - MinimumPasFoldLevel(ALineIndex, 4);
if Result < 0 then
Result := 0;
end;
function TSynPasSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer;
var
inf, inf2: TSynPasRangeInfo;
begin
Result := 0;
if not(AType in [1, 4]) then begin
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
inf2 := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex - 1];
end;
if (AType = 0) or (AType = 1) then
Result := EndPasFoldLevel(ALineIndex - 1)
- min(MinimumPasFoldLevel(ALineIndex), EndPasFoldLevel(ALineIndex));
if (AType = 0) or (AType = 2) then
Result := Result + inf2.EndLevelRegion - inf.MinLevelRegion;
if (AType = 0) or (AType = 3) then
Result := Result + inf2.EndLevelIfDef - inf.MinLevelIfDef;
if (AType = 4) then
Result := EndPasFoldLevel(ALineIndex - 1, 4)
- min(MinimumPasFoldLevel(ALineIndex, 4), EndPasFoldLevel(ALineIndex, 4));
end;
function TSynPasSyn.FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer;
var
inf: TSynPasRangeInfo;
begin
Result := 0;
if not(AType in [1, 4]) then
inf := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex];
if (AType = 0) or (AType = 1) then
Result := EndPasFoldLevel(ALineIndex);
if (AType = 0) or (AType = 2) then
Result := Result + inf.EndLevelRegion;
if (AType = 0) or (AType = 3) then
Result := Result + inf.EndLevelIfDef;
if (AType = 4) then
Result := EndPasFoldLevel(ALineIndex, 4);
end;
function TSynPasSyn.FoldTypeCount: integer; function TSynPasSyn.FoldTypeCount: integer;
begin begin
Result := 3; Result := 3;
@ -3264,7 +3308,7 @@ begin
Result := FoldEndLine(ALineIndex, FoldIndex); Result := FoldEndLine(ALineIndex, FoldIndex);
// check if fold last line of block (not mixed "end begin") // check if fold last line of block (not mixed "end begin")
if (EndPasFoldLevel(Result, atype) > MinimumPasFoldLevel(Result, atype)) then if (FoldBlockEndLevel(Result, atype) > FoldBlockMinLevel(Result, atype)) then
dec(Result); dec(Result);
// Amount of lines, that will become invisible (excludes the cfCollapsed line) // Amount of lines, that will become invisible (excludes the cfCollapsed line)
Result := Result - ALineIndex; Result := Result - ALineIndex;
@ -3292,81 +3336,13 @@ begin
lvl := node.FoldLvlEnd; lvl := node.FoldLvlEnd;
Result := ALineIndex + 1; Result := ALineIndex + 1;
while (Result < cnt) and (MinimumPasFoldLevel(Result, atype) >= lvl) do inc(Result); while (Result < cnt) and (FoldBlockMinLevel(Result, atype) >= lvl) do inc(Result);
// check if fold last line of block (not mixed "end begin") // check if fold last line of block (not mixed "end begin")
// and not lastlinefix // and not lastlinefix
if (Result = cnt) then if (Result = cnt) then
dec(Result); dec(Result);
end; end;
function TSynPasSyn.MinimumPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
var
r: TSynPasSynRange;
begin
case AType of
2:
Result := TSynHighlighterPasRangeList(CurrentRanges).
PasRangeInfo[Index].MinLevelRegion;
3:
Result := TSynHighlighterPasRangeList(CurrentRanges).
PasRangeInfo[Index].MinLevelIfDef;
4: // all pascal nodes (incl. not folded)
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then begin
Result := Min(r.CodeFoldStackSize + LastLinePasFoldLevelFix(Index + 1, 4),
r.MinimumCodeFoldBlockLevel);
end else
Result := 0;
end;
else
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then begin
Result := Min(r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1),
r.PasFoldMinLevel)
end else
Result := 0;
end;
end;
end;
function TSynPasSyn.EndPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count - 1) then
exit(0);
case AType of
2:
Result := TSynHighlighterPasRangeList(CurrentRanges).
PasRangeInfo[Index].EndLevelRegion;
3:
Result := TSynHighlighterPasRangeList(CurrentRanges).
PasRangeInfo[Index].EndLevelIfDef;
4: // all pascal nodes (incl. not folded)
begin
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize
else
Result := 0;
end;
else
begin
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1)
else
Result := 0;
end;
end;
end;
function TSynPasSyn.LastLinePasFoldLevelFix(Index: Integer; AType: Integer = 1): integer; function TSynPasSyn.LastLinePasFoldLevelFix(Index: Integer; AType: Integer = 1): integer;
var var
r: TSynPasSynRange; r: TSynPasSynRange;
@ -3397,49 +3373,7 @@ begin
end; end;
end; end;
procedure TSynPasSyn.InitNode(out Node: TSynFoldNodeInfo; EndOffs: Integer;
function TSynPasSyn.MinimumFoldLevel(Index: Integer): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := Min(r.CodeFoldStackSize + LastLineFoldLevelFix(Index + 1),
r.MinimumCodeFoldBlockLevel)
else
Result := 0;
end;
function TSynPasSyn.EndFoldLevel(Index: Integer): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize + LastLineFoldLevelFix(Index + 1)
else
Result := 0;
end;
function TSynPasSyn.LastLineFoldLevelFix(Index: Integer): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.LastLineCodeFoldLevelFix
else
Result := 0;
end;
procedure TSynPasSyn.InitNode(var Node: TSynFoldNodeInfo; EndOffs: Integer;
ABlockType: TPascalCodeFoldBlockType; aActions: TSynFoldActions; AIsFold: Boolean); ABlockType: TPascalCodeFoldBlockType; aActions: TSynFoldActions; AIsFold: Boolean);
var var
OneLine: Boolean; OneLine: Boolean;
@ -3455,30 +3389,29 @@ begin
case ABlockType of case ABlockType of
cfbtRegion: cfbtRegion:
begin begin
node.FoldGroup := 2; node.FoldGroup := FOLDGROUP_REGION;
Node.FoldLvlStart := FSynPasRangeInfo.EndLevelRegion; Node.FoldLvlStart := FSynPasRangeInfo.EndLevelRegion;
Node.NestLvlStart := FSynPasRangeInfo.EndLevelRegion; Node.NestLvlStart := FSynPasRangeInfo.EndLevelRegion;
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelRegion); OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelRegion);
end; end;
cfbtIfDef: cfbtIfDef:
begin begin
node.FoldGroup := 3; node.FoldGroup := FOLDGROUP_IFDEF;
Node.FoldLvlStart := FSynPasRangeInfo.EndLevelIfDef; Node.FoldLvlStart := FSynPasRangeInfo.EndLevelIfDef;
Node.NestLvlStart := FSynPasRangeInfo.EndLevelIfDef; Node.NestLvlStart := FSynPasRangeInfo.EndLevelIfDef;
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelIfDef); OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelIfDef);
end; end;
else else
begin begin
node.FoldGroup := FOLDGROUP_PASCAL;
if AIsFold then begin if AIsFold then begin
node.FoldGroup := 1;
Node.FoldLvlStart := PasCodeFoldRange.PasFoldEndLevel; Node.FoldLvlStart := PasCodeFoldRange.PasFoldEndLevel;
Node.NestLvlStart := CurrentCodeFoldBlockLevel; Node.NestLvlStart := PasCodeFoldRange.CodeFoldStackSize;
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.PasFoldMinLevel); // MinimumCodeFoldBlockLevel); OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.PasFoldMinLevel); // MinimumCodeFoldBlockLevel);
end else begin end else begin
node.FoldGroup := 4;
Node.FoldLvlStart := PasCodeFoldRange.CodeFoldStackSize; Node.FoldLvlStart := PasCodeFoldRange.CodeFoldStackSize;
Node.NestLvlStart := CurrentCodeFoldBlockLevel; Node.NestLvlStart := PasCodeFoldRange.CodeFoldStackSize;
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.MinimumCodeFoldBlockLevel); // MinimumCodeFoldBlockLevel); OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.MinimumCodeFoldBlockLevel);
end; end;
end; end;
end; end;
@ -3584,7 +3517,7 @@ begin
NextToEol; NextToEol;
fStringLen := 0; fStringLen := 0;
i := LastLineFoldLevelFix(Line+1); i := LastLinePasFoldLevelFix(Line+1, 4);
while i < 0 do begin while i < 0 do begin
EndPascalCodeFoldBlock; EndPascalCodeFoldBlock;
inc(i); inc(i);
@ -3706,7 +3639,7 @@ begin
EndPascalCodeFoldBlock; EndPascalCodeFoldBlock;
if FAtLineStart then begin if FAtLineStart then begin
// If we are not at linestart, new folds could have been opened => handle as normal close // If we are not at linestart, new folds could have been opened => handle as normal close
if (CurrentCodeFoldBlockLevel < FStartCodeFoldBlockLevel) and if (PasCodeFoldRange.CodeFoldStackSize < FStartCodeFoldBlockLevel) and
(FStartCodeFoldBlockLevel > 0) (FStartCodeFoldBlockLevel > 0)
then begin then begin
PasCodeFoldRange.DecLastLineCodeFoldLevelFix; PasCodeFoldRange.DecLastLineCodeFoldLevelFix;
@ -3738,7 +3671,7 @@ function TSynPasSyn.GetDrawDivider(Index: integer): TSynDividerDrawConfigSetting
begin begin
i := 0; i := 0;
j := StartLvl; j := StartLvl;
m := CurrentCodeFoldBlockLevel; m := PasCodeFoldRange.CodeFoldStackSize;;
t := TopPascalCodeFoldBlockType(j); t := TopPascalCodeFoldBlockType(j);
while (i <= MaxDepth) and (j < m) and while (i <= MaxDepth) and (j < m) and
((t in CountTypes) or (t in SkipTypes)) do begin ((t in CountTypes) or (t in SkipTypes)) do begin
@ -3759,17 +3692,20 @@ var
begin begin
Result := inherited; Result := inherited;
if (index = 0) then exit; if (index = 0) then exit;
CloseCnt := EndFoldLevel(Index - 1) - MinimumFoldLevel(Index); CloseCnt := FoldBlockClosingCount(Index, FOLDGROUP_PASCAL, [sfbIncludeDisabled]);
if (CloseCnt = 0) or (MinimumFoldLevel(Index) <> EndFoldLevel(Index)) then // not a mixed line if (CloseCnt = 0) or
(FoldBlockMinLevel(Index, FOLDGROUP_PASCAL, [sfbIncludeDisabled])
<> FoldBlockEndLevel(Index, FOLDGROUP_PASCAL, [sfbIncludeDisabled]))
then // not a mixed line
exit; exit;
// SetRange[Index] has the folds at the start of this line // SetRange[Index] has the folds at the start of this line
// ClosedByNextLine: Folds closed by the next lines LastLineFix // ClosedByNextLine: Folds closed by the next lines LastLineFix
// must be taken from SetRange[Index+1] (end of this line) // must be taken from SetRange[Index+1] (end of this line)
ClosedByNextLine := -LastLineFoldLevelFix(Index + 1); ClosedByNextLine := -LastLinePasFoldLevelFix(Index + 1, 4);
// ClosedInLastLine: Folds Closed by this lines LastLineFix // ClosedInLastLine: Folds Closed by this lines LastLineFix
// must be ignored. (They are part of SetRange[Index] / this line) // must be ignored. (They are part of SetRange[Index] / this line)
ClosedInLastLine := -LastLineFoldLevelFix(Index); ClosedInLastLine := -LastLinePasFoldLevelFix(Index, 4);
// Get the highest close-offset // Get the highest close-offset
i := ClosedByNextLine - 1; i := ClosedByNextLine - 1;

View File

@ -56,7 +56,7 @@ interface
{$I SynEdit.inc} {$I SynEdit.inc}
uses uses
Classes, math, Graphics, SynEditTypes, SynEditHighlighter, Classes, Graphics, SynEditTypes, SynEditHighlighter,
SynEditHighlighterFoldBase, SynEditHighlighterXMLBase; SynEditHighlighterFoldBase, SynEditHighlighterXMLBase;
type type
@ -98,22 +98,6 @@ type
type type
{ TSynHighlighterXmlRangeList }
TSynHighlighterXmlRangeList = class(TSynHighlighterRangeList)
private
FItemOffset: Integer;
function GetXmlRangeInfo(Index: Integer): TSynXmlRangeInfo;
procedure SetXmlRangeInfo(Index: Integer; const AValue: TSynXmlRangeInfo);
protected
procedure SetCapacity(const AValue: Integer); override;
public
constructor Create;
procedure Move(AFrom, ATo, ALen: Integer); override;
property XmlRangeInfo[Index: Integer]: TSynXmlRangeInfo
read GetXmlRangeInfo write SetXmlRangeInfo;
end;
TProcTableProc = procedure of object; TProcTableProc = procedure of object;
{ TSynXMLSyn } { TSynXMLSyn }
@ -1010,65 +994,8 @@ begin
Result := ord(high(TXmlCodeFoldBlockType)) - ord(low(TXmlCodeFoldBlockType)) + 1; Result := ord(high(TXmlCodeFoldBlockType)) - ord(low(TXmlCodeFoldBlockType)) + 1;
end; end;
{ TSynHighlighterXmlRangeList }
function TSynHighlighterXmlRangeList.GetXmlRangeInfo(Index: Integer): TSynXmlRangeInfo;
begin
if (Index < 0) or (Index >= Count) then begin
Result.ElementOpenList := nil;
exit;
end;
Result := TSynXmlRangeInfo((ItemPointer[Index] + FItemOffset)^);
end;
procedure TSynHighlighterXmlRangeList.SetXmlRangeInfo(Index: Integer;
const AValue: TSynXmlRangeInfo);
begin
TSynXmlRangeInfo((ItemPointer[Index] + FItemOffset)^) := AValue;
end;
procedure TSynHighlighterXmlRangeList.SetCapacity(const AValue: Integer);
var
i: LongInt;
begin
for i := AValue to Capacity-1 do
with TSynXmlRangeInfo((ItemPointer[i] + FItemOffset)^) do begin
ElementOpenList := nil;
ElementCloseList := nil;
end;
inherited SetCapacity(AValue);
end;
constructor TSynHighlighterXmlRangeList.Create;
begin
inherited;
FItemOffset := ItemSize;
ItemSize := FItemOffset + SizeOf(TSynXmlRangeInfo);
end;
procedure TSynHighlighterXmlRangeList.Move(AFrom, ATo, ALen: Integer);
var
i: LongInt;
begin
if ATo > AFrom then
for i:= Max(AFrom + ALen, ATo) to ATo + ALen - 1 do // move forward
with TSynXmlRangeInfo((ItemPointer[i] + FItemOffset)^) do begin
ElementOpenList := nil;
ElementCloseList := nil;
end
else
for i:= ATo to Min(ATo + ALen , AFrom) - 1 do // move backward
with TSynXmlRangeInfo((ItemPointer[i] + FItemOffset)^) do begin
ElementOpenList := nil;
ElementCloseList := nil;
end;
inherited Move(AFrom, ATo, ALen);
end;
initialization initialization
RegisterPlaceableHighlighter(TSynXMLSyn); RegisterPlaceableHighlighter(TSynXMLSyn);
end. end.

View File

@ -39,13 +39,14 @@ type
function TestText5: TStringArray; function TestText5: TStringArray;
function TestText6: TStringArray; function TestText6: TStringArray;
function TestText7: TStringArray; function TestText7: TStringArray;
function TestText8: TStringArray;
function TestTextHide(ALen: Integer): TStringArray; function TestTextHide(ALen: Integer): TStringArray;
function TestTextHide2(ALen: Integer): TStringArray; function TestTextHide2(ALen: Integer): TStringArray;
function TestTextHide3: TStringArray; function TestTextHide3: TStringArray;
function TestTextHide4: TStringArray; function TestTextHide4: TStringArray;
function TestTextPlain: TStringArray; function TestTextPlain: TStringArray;
protected protected
procedure TstSetText(AName: String; AText: TStringArray); procedure TstSetText(AName: String; AText: Array of String);
procedure TstFold(AName: String; AFoldAtIndex: integer; AExpectedLines: Array of Integer); procedure TstFold(AName: String; AFoldAtIndex: integer; AExpectedLines: Array of Integer);
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum: integer; AExpectedLines: Array of Integer); procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum: integer; AExpectedLines: Array of Integer);
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer; procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
@ -66,6 +67,7 @@ type
procedure TestFoldEdit; procedure TestFoldEdit;
procedure TestFoldStateFromText; procedure TestFoldStateFromText;
procedure TestFoldStateDesc; procedure TestFoldStateDesc;
procedure TestFoldProvider;
end; end;
implementation implementation
@ -73,7 +75,7 @@ implementation
type type
TSynEditFoldedViewHack = class(TSynEditFoldedView) end; TSynEditFoldedViewHack = class(TSynEditFoldedView) end;
procedure TTestFoldedView.TstSetText(AName: String; AText: TStringArray); procedure TTestFoldedView.TstSetText(AName: String; AText: array of String);
begin begin
PopBaseName; PopBaseName;
ReCreateEdit; ReCreateEdit;
@ -406,6 +408,32 @@ begin
Result[26] := ''; Result[26] := '';
end; end;
function TTestFoldedView.TestText8: TStringArray;
begin
// end begin lines, with mixed type
SetLength(Result, 20);
Result[0] := 'program Foo;';
Result[1] := 'procedure a;';
Result[2] := 'begin';
Result[3] := '{%region}';
Result[4] := '{%endregion} {$ifdef x}';
Result[5] := ' {$endif} if a then begin';
Result[6] := ' end; {%region}';
Result[7] := '{%endregion} {$ifdef x}';
Result[8] := ' {$endif} if a then begin';
Result[9] := ' writeln(1);';
Result[10] := '{%region} end;';
Result[11] := ' writeln(1);';
Result[12] := '{%endregion} if a then begin';
Result[13] := ' writeln(1);';
Result[14] := '{$ifdef x} end;';
Result[15] := ' writeln(1);';
Result[16] := '{$endif}';
Result[17] := ' writeln(1);';
Result[18] := 'end';
Result[19] := '';
end;
function TTestFoldedView.TestTextHide(ALen: Integer): TStringArray; function TTestFoldedView.TestTextHide(ALen: Integer): TStringArray;
begin begin
SetLength(Result, 3+ALen); SetLength(Result, 3+ALen);
@ -1457,6 +1485,161 @@ begin
end; end;
procedure TTestFoldedView.TestFoldProvider;
procedure DoTestOpenCounts(AName: string; AType: Integer; AExp: Array of Integer);
var
i: Integer;
begin
AName := AName + ' (type=' + IntToStr(AType)+') ';
for i := low(AExp) to high(AExp) do
DebugLn([BaseTestName+AName+ ' line=' + IntToStr(i)+ ' exp=', AExp[i],' Got=', FoldedView.FoldProvider.FoldOpenCount(i, AType)]);
for i := low(AExp) to high(AExp) do
AssertEquals(BaseTestName+AName+ ' line=' + IntToStr(i),
AExp[i], FoldedView.FoldProvider.FoldOpenCount(i, AType));
end;
var
i: Integer;
begin
// TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
PushBaseName('');
TstSetText('TestText1', TestText);
EnableFolds([cfbtBeginEnd..cfbtNone]);
// p P B ~ -
DoTestOpenCounts('', 0, [1, 1, 1, 0, 0]); // all (fold conf)
DoTestOpenCounts('', 1, [1, 1, 1, 0, 0]); // pas
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0]); // pas (incl unfolded)
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0]); // $if
TstSetText('TestText1 (2)', TestText);
EnableFolds([cfbtTopBeginEnd]);
// p P B ~ -
DoTestOpenCounts('', 0, [0, 0, 1, 0, 0]); // all (fold conf)
DoTestOpenCounts('', 1, [0, 0, 1, 0, 0]); // pas
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0]); // pas (incl unfolded)
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0]); // $if
TstSetText('TestText1 (3)', TestText);
EnableFolds([cfbtProcedure, cfbtBeginEnd]);
// p P B ~ -
DoTestOpenCounts('', 0, [0, 1, 0, 0, 0]); // all (fold conf)
DoTestOpenCounts('', 1, [0, 1, 0, 0, 0]); // pas
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0]); // pas (incl unfolded)
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0]); // $if
TstSetText('TestText2', TestText2);
EnableFolds([cfbtBeginEnd..cfbtNone]);
// if else
// p PP B - B B ~ -B ~ - - ~
DoTestOpenCounts('', 0, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
DoTestOpenCounts('', 1, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
//DoTestOpenCounts('', 4, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
TstSetText('TestText2 (2)', TestText2);
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtProgram, cfbtRegion]);
// p PP B - B B ~ -B ~ - - ~
DoTestOpenCounts('', 0, [0, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
DoTestOpenCounts('', 1, [0, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
//DoTestOpenCounts('', 4, [1, 2, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
TstSetText('TestText3', TestText3);
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
// if else // one-line-comment
// p $ P - B %B ~ --B~ - - /
DoTestOpenCounts('', 0, [1, 1, 1, 0, 1, 2, 0, 1, 0, 0, 0, 1]);
DoTestOpenCounts('', 1, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
//DoTestOpenCounts('', 4, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %if
TstSetText('TestText3 (2)', TestText3);
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtProgram, cfbtRegion], [cfbtSlashComment]);
// p $ P - B %B ~ --B~ - - /
DoTestOpenCounts('', 0, [0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
DoTestOpenCounts('', 1, [0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
//DoTestOpenCounts('', 4, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %if
TstSetText('TestText3 (3)', TestText3);
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtProgram, cfbtIfDef], []);
// p $ P - B %B ~ --B~ - - /
DoTestOpenCounts('', 0, [0, 0, 1, 0, 1, 2, 0, 1, 0, 0, 0, 0]);
DoTestOpenCounts('', 1, [0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0]);
//DoTestOpenCounts('', 4, [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); // %if
for i := 0 to 2 do begin // pos of $IFDEF does not matter
TstSetText('TestTextPasHl-'+IntToStr(i)+'', TestTextPasHl(i));
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
// if $E // one-line-comment
// p P $bb- - - /
DoTestOpenCounts('', 0, [1, 1, 3, 0, 0, 0, 1]);
DoTestOpenCounts('', 1, [1, 1, 2, 0, 0, 0, 1]);
//DoTestOpenCounts('', 4, [1, 1, 2, 0, 0, 0, 1]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 0, 1, 0, 0, 0, 0]); // %if
TstSetText('TestTextPasHl-'+IntToStr(i)+'', TestTextPasHl(i));
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtBeginEnd], [cfbtSlashComment]);
// if $E // one-line-comment
// p P $bb- - - /
DoTestOpenCounts('', 0, [1, 1, 2, 0, 0, 0, 1]);
DoTestOpenCounts('', 1, [1, 1, 1, 0, 0, 0, 1]);
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0, 0, 1]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 0, 1, 0, 0, 0, 0]); // %if
TstSetText('TestTextPasHl-'+IntToStr(i)+'', TestTextPasHl(i));
EnableFolds([cfbtBeginEnd..cfbtNone]-[cfbtIfDef], [cfbtSlashComment]);
// if $E // one-line-comment
// p P $bb- - - /
DoTestOpenCounts('', 0, [1, 1, 2, 0, 0, 0, 1]);
DoTestOpenCounts('', 1, [1, 1, 2, 0, 0, 0, 1]);
//DoTestOpenCounts('', 4, [1, 1, 2, 0, 0, 0, 1]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0, 0]); // %region
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0, 0]); // %if
end;
TstSetText('TestText4', TestText4);
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
// pPBB - B - B -
DoTestOpenCounts('', 0, [3, 1, 0, 1, 0, 1]);
DoTestOpenCounts('', 1, [3, 1, 0, 1, 0, 1]);
//DoTestOpenCounts('', 4, [3, 1, 0, 1, 0, 1]);
DoTestOpenCounts('', 2, [0, 0, 0, 0, 0, 0]);
DoTestOpenCounts('', 3, [0, 0, 0, 0, 0, 0]);
TstSetText('TestText8', TestText8);
EnableFolds([cfbtBeginEnd..cfbtNone], [cfbtSlashComment]);
// p P B % $ B % $ B ~ % ~ B ~ $ ~ - ~ -
DoTestOpenCounts('', 0, [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]);
DoTestOpenCounts('', 1, [1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]);
//DoTestOpenCounts('', 4, [1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]);
DoTestOpenCounts('', 2, [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]);
DoTestOpenCounts('', 3, [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]);
end;
initialization initialization
RegisterTest(TTestFoldedView); RegisterTest(TTestFoldedView);

View File

@ -0,0 +1,136 @@
unit TestHighlighterLfm;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc, TestHighlightFoldBase,
SynEdit, SynEditTypes, SynHighlighterLFM, SynEditHighlighterFoldBase;
type
{ TTestBaseHighlighterLem }
TTestBaseHighlighterLem = class(TTestBaseHighlighterFoldBase)
protected
function LfmHighLighter: TSynLFMSyn;
function CreateTheHighLighter: TSynCustomFoldHighlighter; override;
procedure EnableFolds(AEnbledTypes: TLfmCodeFoldBlockTypes;
AHideTypes: TLfmCodeFoldBlockTypes = [];
ANoFoldTypes: TLfmCodeFoldBlockTypes = []
);
//procedure DebugFoldInfo(ALineIdx: Integer; AFilter: TSynFoldActions; Group: Integer=0);
//procedure DebugFoldInfo(AFilter: TSynFoldActions; Group: Integer=0);
//function FoldActionsToString(AFoldActions: TSynFoldActions): String;
end;
{ TTestHighlighterLfm }
TTestHighlighterLfm = class(TTestBaseHighlighterLem)
protected
function TestTextFoldInfo1: TStringArray;
procedure CheckTokensForLine(Name: String; LineIdx: Integer; ExpTokens: Array of TtkTokenKind);
published
procedure TestFoldInfo;
end;
implementation
{ TTestBaseHighlighterLem }
function TTestBaseHighlighterLem.LfmHighLighter: TSynLFMSyn;
begin
Result := TSynLFMSyn(FTheHighLighter);
end;
function TTestBaseHighlighterLem.CreateTheHighLighter: TSynCustomFoldHighlighter;
begin
Result := TSynLFMSyn.Create(nil);
end;
procedure TTestBaseHighlighterLem.EnableFolds(AEnbledTypes: TLfmCodeFoldBlockTypes;
AHideTypes: TLfmCodeFoldBlockTypes; ANoFoldTypes: TLfmCodeFoldBlockTypes);
var
i: TLfmCodeFoldBlockType;
begin
for i := low(TLfmCodeFoldBlockType) to high(TLfmCodeFoldBlockType) do begin
LfmHighLighter.FoldConfig[ord(i)].Enabled := i in AEnbledTypes;
if (i in ANoFoldTypes) then
LfmHighLighter.FoldConfig[ord(i)].Modes := []
else
LfmHighLighter.FoldConfig[ord(i)].Modes := [fmFold];
if i in AHideTypes then
LfmHighLighter.FoldConfig[ord(i)].Modes := LfmHighLighter.FoldConfig[ord(i)].Modes + [fmHide]
end;
end;
function TTestHighlighterLfm.TestTextFoldInfo1: TStringArray;
begin
SetLength(Result, 11);
Result[0] := 'object BreakPointGroupDlg: TBreakPointGroupDlg';
Result[1] := ' Left = 431';
Result[2] := ' Height = 225';
Result[3] := ' object ButtonPanel1: TButtonPanel';
Result[4] := ' Left = 6';
Result[5] := ' end';
Result[6] := ' object Label1: TLabel';
Result[7] := ' Left = 0';
Result[8] := ' end';
Result[9] := 'end';
Result[10] := '';
end;
procedure TTestHighlighterLfm.CheckTokensForLine(Name: String; LineIdx: Integer;
ExpTokens: array of TtkTokenKind);
var
c: Integer;
begin
LfmHighLighter.StartAtLineIndex(LineIdx);
c := 0;
while not LfmHighLighter.GetEol do begin
//DebugLn([LfmHighLighter.GetToken,' (',PasHighLighter.GetTokenID ,') at ', PasHighLighter.GetTokenPos]);
AssertEquals(Name + 'TokenId Line='+IntToStr(LineIdx)+' pos='+IntToStr(c), ord(ExpTokens[c]), ord(LfmHighLighter.GetTokenID));
LfmHighLighter.Next;
inc(c);
if c >= length(ExpTokens) then
break;
end;
AssertEquals(Name+ 'TokenId Line='+IntToStr(LineIdx)+' amount of tokens', length(ExpTokens), c );
end;
procedure TTestHighlighterLfm.TestFoldInfo;
begin
ReCreateEdit;
// DebugFoldInfo([]);
{%region}
SetLines(TestTextFoldInfo1);
EnableFolds([cfbtLfmObject..cfbtLfmNone]);
PushBaseName('Text 1 all folds');
EnableFolds([cfbtLfmObject..cfbtLfmNone], [cfbtLfmNone]);
AssertEquals('Len 0', 9, LfmHighLighter.FoldLineLength(0,0));
//AssertEquals('Len 1', 0, LfmHighLighter.FoldLineLength(1,0));
AssertEquals('Len 3', 2, LfmHighLighter.FoldLineLength(3,0));
//AssertEquals('Len 4', 0, LfmHighLighter.FoldLineLength(4,0));
//AssertEquals('Len 5', 0, LfmHighLighter.FoldLineLength(5,0));
AssertEquals('Len 6', 2, LfmHighLighter.FoldLineLength(6,0));
CheckFoldOpenCounts('', [1, 0, 0, 1, 0, 0, 1, 0, 0, 0]);
{%endregion}
end;
initialization
RegisterTest(TTestHighlighterLfm);
end.

View File

@ -0,0 +1,116 @@
unit TestHighlightFoldBase;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc,
SynEdit, SynEditTypes, SynEditHighlighterFoldBase;
type
// used by Fold / MarkupWord
{ TTestBaseHighlighterPas }
{ TTestBaseHighlighterFoldBase }
TTestBaseHighlighterFoldBase = class(TTestBase)
protected
FTheHighLighter: TSynCustomFoldHighlighter;
function CreateTheHighLighter: TSynCustomFoldHighlighter; virtual; abstract;
procedure SetUp; override;
procedure TearDown; override;
procedure ReCreateEdit; reintroduce;
procedure CheckFoldOpenCounts(Name: String; Expected: Array of Integer);
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Expected: Array of Integer);
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Group: Integer; Expected: Array of Integer);
function FoldActionsToString(AFoldActions: TSynFoldActions): String;
end;
implementation
{ TTestBaseHighlighterFoldBase }
procedure TTestBaseHighlighterFoldBase.SetUp;
begin
FTheHighLighter := nil;
inherited SetUp;
end;
procedure TTestBaseHighlighterFoldBase.TearDown;
begin
if Assigned(SynEdit) then
SynEdit.Highlighter := nil;
FreeAndNil(FTheHighLighter);
inherited TearDown;
end;
procedure TTestBaseHighlighterFoldBase.ReCreateEdit;
begin
if Assigned(SynEdit) then
SynEdit.Highlighter := nil;
FreeAndNil(FTheHighLighter);
inherited ReCreateEdit;
FTheHighLighter := CreateTheHighLighter;
SynEdit.Highlighter := FTheHighLighter;
end;
procedure TTestBaseHighlighterFoldBase.CheckFoldOpenCounts(Name: String;
Expected: array of Integer);
var
i: Integer;
begin
for i := 0 to high(Expected) do
AssertEquals(Name + 'OpenCount Line OLD='+IntToStr(i), Expected[i], FTheHighLighter.FoldOpenCount(i));
for i := 0 to high(Expected) do
AssertEquals(Name + 'OpenCount Line='+IntToStr(i), Expected[i], FTheHighLighter.FoldBlockOpeningCount(i));
end;
procedure TTestBaseHighlighterFoldBase.CheckFoldInfoCounts(Name: String;
Filter: TSynFoldActions; Expected: array of Integer);
begin
CheckFoldInfoCounts(Name, Filter, 0, Expected);
end;
procedure TTestBaseHighlighterFoldBase.CheckFoldInfoCounts(Name: String;
Filter: TSynFoldActions; Group: Integer; Expected: array of Integer);
var
i: Integer;
l: TLazSynFoldNodeInfoList;
begin
for i := 0 to high(Expected) do begin
l := FTheHighLighter.FoldNodeInfo[i];
AssertEquals(Name + 'InfoCount(Ex) Line='+IntToStr(i),
Expected[i],
l.CountEx(Filter, Group));
l.ClearFilter;
l.ActionFilter := Filter;
l.GroupFilter := Group;
AssertEquals(Name + 'InfoCount Line='+IntToStr(i),
Expected[i],
FTheHighLighter.FoldNodeInfo[i].Count);
end;
end;
function TTestBaseHighlighterFoldBase.FoldActionsToString(AFoldActions: TSynFoldActions): String;
var
s: string;
i: TSynFoldAction;
begin
Result:='';
for i := low(TSynFoldAction) to high(TSynFoldAction) do
if i in AFoldActions then begin
WriteStr(s, i);
Result := Result + s + ',';
end;
if Result <> '' then SetLength(Result, Length(Result)-1);
end;
end.

View File

@ -5,7 +5,7 @@ unit TestHighlightPas;
interface interface
uses uses
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc, Classes, SysUtils, testregistry, TestBase, Forms, LCLProc, TestHighlightFoldBase,
SynEdit, SynEditTypes, SynHighlighterPas, SynEditHighlighterFoldBase; SynEdit, SynEditTypes, SynHighlighterPas, SynEditHighlighterFoldBase;
type type
@ -14,12 +14,10 @@ type
{ TTestBaseHighlighterPas } { TTestBaseHighlighterPas }
TTestBaseHighlighterPas = class(TTestBase) TTestBaseHighlighterPas = class(TTestBaseHighlighterFoldBase)
protected protected
PasHighLighter: TSynPasSyn; function PasHighLighter: TSynPasSyn;
procedure SetUp; override; function CreateTheHighLighter: TSynCustomFoldHighlighter; override;
procedure TearDown; override;
procedure ReCreateEdit; reintroduce;
procedure EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes; procedure EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes;
AHideTypes: TPascalCodeFoldBlockTypes = []; AHideTypes: TPascalCodeFoldBlockTypes = [];
ANoFoldTypes: TPascalCodeFoldBlockTypes = [] ANoFoldTypes: TPascalCodeFoldBlockTypes = []
@ -38,12 +36,8 @@ type
function TestTextFoldInfo3: TStringArray; function TestTextFoldInfo3: TStringArray;
function TestTextFoldInfo4(AIfCol: Integer): TStringArray; function TestTextFoldInfo4(AIfCol: Integer): TStringArray;
procedure CheckFoldOpenCounts(Name: String; Expected: Array of Integer);
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Expected: Array of Integer);
procedure CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions; Group: Integer; Expected: Array of Integer);
procedure CheckTokensForLine(Name: String; LineIdx: Integer; ExpTokens: Array of TtkTokenKind); procedure CheckTokensForLine(Name: String; LineIdx: Integer; ExpTokens: Array of TtkTokenKind);
function FoldActionsToString(AFoldActions: TSynFoldActions): String;
published published
procedure TestFoldInfo; procedure TestFoldInfo;
procedure TestExtendedKeywordsAndStrings; procedure TestExtendedKeywordsAndStrings;
@ -60,28 +54,14 @@ implementation
{ TTestBaseHighlighterPas } { TTestBaseHighlighterPas }
procedure TTestBaseHighlighterPas.SetUp; function TTestBaseHighlighterPas.PasHighLighter: TSynPasSyn;
begin begin
PasHighLighter := nil; Result := TSynPasSyn(FTheHighLighter);
inherited SetUp;
end; end;
procedure TTestBaseHighlighterPas.TearDown; function TTestBaseHighlighterPas.CreateTheHighLighter: TSynCustomFoldHighlighter;
begin begin
if Assigned(SynEdit) then Result := TSynPasSyn.Create(nil);
SynEdit.Highlighter := nil;
FreeAndNil(PasHighLighter);
inherited TearDown;
end;
procedure TTestBaseHighlighterPas.ReCreateEdit;
begin
if Assigned(SynEdit) then
SynEdit.Highlighter := nil;
FreeAndNil(PasHighLighter);
inherited ReCreateEdit;
PasHighLighter := TSynPasSyn.Create(nil);
SynEdit.Highlighter := PasHighLighter;
end; end;
procedure TTestBaseHighlighterPas.EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes; procedure TTestBaseHighlighterPas.EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes;
@ -114,8 +94,8 @@ begin
l.GroupFilter := Group; l.GroupFilter := Group;
debugln(['### Foldinfo Line: ', ALineIdx, debugln(['### Foldinfo Line: ', ALineIdx,
' Cnt=', l.Count, ' CntEx=', c, ' Cnt=', l.Count, ' CntEx=', c,
' PasMinLvl=',PasHighLighter.MinimumPasFoldLevel(ALineIdx,1), ' PasMinLvl=', PasHighLighter.FoldBlockMinLevel(ALineIdx,1),
' EndLvl=',PasHighLighter.EndPasFoldLevel(ALineIdx,1), ' EndLvl=',PasHighLighter.FoldBlockEndLevel(ALineIdx,1),
//' Nestcnt=',PasHighLighter.FoldNestCount(ALineIdx,1), //' Nestcnt=',PasHighLighter.FoldNestCount(ALineIdx,1),
' : ', copy(SynEdit.Lines[ALineIdx],1,40)]); ' : ', copy(SynEdit.Lines[ALineIdx],1,40)]);
debugln('Idx: LogXStart End FldLvlStart End NestLvlStart End FldType FldTypeCompat FldGroup FldAction'); debugln('Idx: LogXStart End FldLvlStart End NestLvlStart End FldType FldTypeCompat FldGroup FldAction');
@ -231,40 +211,6 @@ begin
end; end;
procedure TTestHighlighterPas.CheckFoldOpenCounts(Name: String; Expected: array of Integer);
var
i: Integer;
begin
for i := 0 to high(Expected) do
AssertEquals(Name + 'OpenCount Line='+IntToStr(i), Expected[i], PasHighLighter.FoldOpenCount(i));
end;
procedure TTestHighlighterPas.CheckFoldInfoCounts(Name: String; Filter: TSynFoldActions;
Expected: array of Integer);
begin
CheckFoldInfoCounts(Name, Filter, 0, Expected);
end;
procedure TTestHighlighterPas.CheckFoldInfoCounts(Name: String;
Filter: TSynFoldActions; Group: Integer; Expected: array of Integer);
var
i: Integer;
l: TLazSynFoldNodeInfoList;
begin
for i := 0 to high(Expected) do begin
l := PasHighLighter.FoldNodeInfo[i];
AssertEquals(Name + 'InfoCount(Ex) Line='+IntToStr(i),
Expected[i],
l.CountEx(Filter, Group));
l.ClearFilter;
l.ActionFilter := Filter;
l.GroupFilter := Group;
AssertEquals(Name + 'InfoCount Line='+IntToStr(i),
Expected[i],
PasHighLighter.FoldNodeInfo[i].Count);
end;
end;
procedure TTestHighlighterPas.CheckTokensForLine(Name: String; LineIdx: Integer; procedure TTestHighlighterPas.CheckTokensForLine(Name: String; LineIdx: Integer;
ExpTokens: array of TtkTokenKind); ExpTokens: array of TtkTokenKind);
var var
@ -283,21 +229,6 @@ begin
AssertEquals(Name+ 'TokenId Line='+IntToStr(LineIdx)+' amount of tokens', length(ExpTokens), c ); AssertEquals(Name+ 'TokenId Line='+IntToStr(LineIdx)+' amount of tokens', length(ExpTokens), c );
end; end;
function TTestHighlighterPas.FoldActionsToString(AFoldActions: TSynFoldActions
): String;
var
s: string;
i: TSynFoldAction;
begin
Result:='';
for i := low(TSynFoldAction) to high(TSynFoldAction) do
if i in AFoldActions then begin
WriteStr(s, i);
Result := Result + s + ',';
end;
if Result <> '' then SetLength(Result, Length(Result)-1);
end;
procedure TTestHighlighterPas.TestFoldInfo; procedure TTestHighlighterPas.TestFoldInfo;
begin begin
ReCreateEdit; ReCreateEdit;
@ -1013,12 +944,12 @@ begin
CheckFoldInfoCounts('', [], 4, [1, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 2]); CheckFoldInfoCounts('', [], 4, [1, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 2]);
//### Foldinfo Line: 0 PasMinLvl=0 EndLvl=0 : program Foo; //### Foldinfo Line: 0 PasMinLvl=0 EndLvl=0 : program Foo;
CheckNode( 0, [], 4, 0, 0, 7, 0, 0, 0, 1, 10, 10, 4, [sfaOpen,sfaMarkup]); // program CheckNode( 0, [], 4, 0, 0, 7, 0, 0, 0, 1, 10, 10, 1, [sfaOpen,sfaMarkup]); // program
//### Foldinfo Line: 1 PasMinLvl=0 EndLvl=0 : procedure a; //### Foldinfo Line: 1 PasMinLvl=0 EndLvl=0 : procedure a;
CheckNode( 1, [], 4, 0, 0, 9, 1, 1, 1, 2, 3, 3, 4, [sfaOpen,sfaMarkup]); // procedure CheckNode( 1, [], 4, 0, 0, 9, 1, 1, 1, 2, 3, 3, 1, [sfaOpen,sfaMarkup]); // procedure
//### Foldinfo Line: 2 PasMinLvl=0 EndLvl=0 : {$IFDEF A} //### Foldinfo Line: 2 PasMinLvl=0 EndLvl=0 : {$IFDEF A}
//### Foldinfo Line: 3 PasMinLvl=0 EndLvl=0 : begin //### Foldinfo Line: 3 PasMinLvl=0 EndLvl=0 : begin
CheckNode( 3, [], 4, 0, 0, 5, 2, 2, 2, 3, 1, 0, 4, [sfaOpen,sfaMarkup]); // begin CheckNode( 3, [], 4, 0, 0, 5, 2, 2, 2, 3, 1, 0, 1, [sfaOpen,sfaMarkup]); // begin
//### Foldinfo Line: 4 PasMinLvl=0 EndLvl=0 : {$ENDIF} //### Foldinfo Line: 4 PasMinLvl=0 EndLvl=0 : {$ENDIF}
//### Foldinfo Line: 5 PasMinLvl=0 EndLvl=1 : {$IFDEF B} if a then begin {$ENDIF} //### Foldinfo Line: 5 PasMinLvl=0 EndLvl=1 : {$IFDEF B} if a then begin {$ENDIF}
CheckNode( 5, [], 4, 0, 23, 28, 0, 1, 3, 4, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); // begin CheckNode( 5, [], 4, 0, 23, 28, 0, 1, 3, 4, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); // begin
@ -1026,16 +957,16 @@ begin
//### Foldinfo Line: 7 PasMinLvl=0 EndLvl=0 : end; //### Foldinfo Line: 7 PasMinLvl=0 EndLvl=0 : end;
CheckNode( 7, [], 4, 0, 2, 5, 1, 0, 4, 3, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]); // end CheckNode( 7, [], 4, 0, 2, 5, 1, 0, 4, 3, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]); // end
//### Foldinfo Line: 8 PasMinLvl=0 EndLvl=0 : end; //### Foldinfo Line: 8 PasMinLvl=0 EndLvl=0 : end;
CheckNode( 8, [], 4, 0, 0, 3, 3, 3, 3, 2, 1, 0, 4, [sfaClose,sfaMarkup]); // end; CheckNode( 8, [], 4, 0, 0, 3, 3, 3, 3, 2, 1, 0, 1, [sfaClose,sfaMarkup]); // end;
CheckNode( 8, [], 4, 1, 0, 3, 2, 2, 2, 1, 3, 3, 4, [sfaClose,sfaMarkup]); // end; CheckNode( 8, [], 4, 1, 0, 3, 2, 2, 2, 1, 3, 3, 1, [sfaClose,sfaMarkup]); // end;
//### Foldinfo Line: 9 PasMinLvl=0 EndLvl=1 : begin //### Foldinfo Line: 9 PasMinLvl=0 EndLvl=1 : begin
CheckNode( 9, [], 4, 0, 0, 5, 0, 1, 1, 2, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); // begin CheckNode( 9, [], 4, 0, 0, 5, 0, 1, 1, 2, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); // begin
//### Foldinfo Line: 10 PasMinLvl=0 EndLvl=0 : end. //### Foldinfo Line: 10 PasMinLvl=0 EndLvl=0 : end.
CheckNode(10, [], 4, 0, 0, 3, 1, 0, 2, 1, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]); // end. CheckNode(10, [], 4, 0, 0, 3, 1, 0, 2, 1, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]); // end.
CheckNode(10, [], 4, 1, 0, 3, 1, 1, 1, 0, 10, 10, 4, [sfaClose,sfaMarkup]); // end. CheckNode(10, [], 4, 1, 0, 3, 1, 1, 1, 0, 10, 10, 1, [sfaClose,sfaMarkup]); // end.
//### Foldinfo Line: 11 PasMinLvl=0 EndLvl=0 : // //### Foldinfo Line: 11 PasMinLvl=0 EndLvl=0 : //
CheckNode(11, [], 4, 0, 0, 2, 0, 0, 0, 1, 22, 22, 4, [sfaOpen]); // // CheckNode(11, [], 4, 0, 0, 2, 0, 0, 0, 1, 22, 22, 1, [sfaOpen]); // //
CheckNode(11, [], 4, 1, 2, 2, 1, 1, 1, 0, 22, 22, 4, [sfaClose,sfaLastLineClose]); // / CheckNode(11, [], 4, 1, 2, 2, 1, 1, 1, 0, 22, 22, 1, [sfaClose,sfaLastLineClose]); // /
{%endregion TEXT 1 -- [cfbtBeginEnd..cfbtNone], [] grp=4} {%endregion TEXT 1 -- [cfbtBeginEnd..cfbtNone], [] grp=4}
{%region TEXT 1 -- [cfbtBeginEnd..cfbtNone], [sfaFold]} {%region TEXT 1 -- [cfbtBeginEnd..cfbtNone], [sfaFold]}
@ -1116,7 +1047,7 @@ begin
//### Foldinfo Line: 0 PasMinLvl=0 EndLvl=1 : program Foo; //### Foldinfo Line: 0 PasMinLvl=0 EndLvl=1 : program Foo;
CheckNode( 0, [], 0, 0, 0, 7, 0, 1, 0, 1, 10, 10, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); CheckNode( 0, [], 0, 0, 0, 7, 0, 1, 0, 1, 10, 10, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]);
//### Foldinfo Line: 1 PasMinLvl=1 EndLvl=1 : procedure a; //### Foldinfo Line: 1 PasMinLvl=1 EndLvl=1 : procedure a;
CheckNode( 1, [], 0, 0, 0, 9, 1, 1, 1, 2, 3, 3, 4, [sfaOpen,sfaMarkup]); CheckNode( 1, [], 0, 0, 0, 9, 1, 1, 1, 2, 3, 3, 1, [sfaOpen,sfaMarkup]);
//### Foldinfo Line: 2 PasMinLvl=1 EndLvl=1 : {$IFDEF A} //### Foldinfo Line: 2 PasMinLvl=1 EndLvl=1 : {$IFDEF A}
CheckNode( 2, [], 0, 0, 2, 7, 0, 1, 0, 1, 18, 18, 3, [sfaOpen,sfaFold,sfaFoldFold]); CheckNode( 2, [], 0, 0, 2, 7, 0, 1, 0, 1, 18, 18, 3, [sfaOpen,sfaFold,sfaFoldFold]);
//### Foldinfo Line: 3 PasMinLvl=1 EndLvl=2 : begin //### Foldinfo Line: 3 PasMinLvl=1 EndLvl=2 : begin
@ -1132,7 +1063,7 @@ begin
CheckNode( 7, [], 0, 0, 2, 5, 3, 2, 4, 3, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]); CheckNode( 7, [], 0, 0, 2, 5, 3, 2, 4, 3, 0, 0, 1, [sfaClose,sfaMarkup,sfaFold]);
//### Foldinfo Line: 8 PasMinLvl=1 EndLvl=1 : end; //### Foldinfo Line: 8 PasMinLvl=1 EndLvl=1 : end;
CheckNode( 8, [], 0, 0, 0, 3, 2, 1, 3, 2, 1, 0, 1, [sfaClose,sfaMarkup,sfaFold]); CheckNode( 8, [], 0, 0, 0, 3, 2, 1, 3, 2, 1, 0, 1, [sfaClose,sfaMarkup,sfaFold]);
CheckNode( 8, [], 0, 1, 0, 3, 2, 2, 2, 1, 3, 3, 4, [sfaClose,sfaMarkup]); CheckNode( 8, [], 0, 1, 0, 3, 2, 2, 2, 1, 3, 3, 1, [sfaClose,sfaMarkup]);
//### Foldinfo Line: 9 PasMinLvl=1 EndLvl=2 : begin //### Foldinfo Line: 9 PasMinLvl=1 EndLvl=2 : begin
CheckNode( 9, [], 0, 0, 0, 5, 1, 2, 1, 2, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]); CheckNode( 9, [], 0, 0, 0, 5, 1, 2, 1, 2, 0, 0, 1, [sfaOpen,sfaMarkup,sfaFold,sfaFoldFold]);
//### Foldinfo Line: 10 PasMinLvl=0 EndLvl=0 : end. //### Foldinfo Line: 10 PasMinLvl=0 EndLvl=0 : end.