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/testbookmarks.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/testhighlightpas.pas svneol=native#text/pascal
components/synedit/test/testhighlightxml.pas svneol=native#text/pascal

View File

@ -284,6 +284,50 @@ type
end;
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
private
@ -292,17 +336,21 @@ type
FSelection: TSynEditSelection;
FFoldTree : TSynTextFoldAVLTree;
function GetFoldsAvailable: Boolean;
function GetHighLighterWithLines: TSynCustomFoldHighlighter;
function GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
function GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
procedure SetHighLighter(const AValue: TSynCustomFoldHighlighter);
protected
property HighLighterWithLines: TSynCustomFoldHighlighter read GetHighLighterWithLines;
public
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 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;
HideLen: Boolean = False;
NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo;
@ -2724,6 +2772,131 @@ begin
fNestedNodesTree := nil;
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 }
function TSynEditFoldProvider.GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
@ -2744,8 +2917,8 @@ begin
exit;
FHighlighter.CurrentLines := FLines;
if FHighlighter.FoldNestCount(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
if FHighlighter.FoldCloseCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
if FHighlighter.FoldBlockEndLevel(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
if FHighlighter.FoldBlockClosingCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([]);
if c > 0 then begin
@ -2761,7 +2934,7 @@ begin
Result := Result + [cfHideStart, cfSingleLineHide];
end
else
if FHighlighter.FoldOpenCount(ALineIdx) > 0 then include(Result, cfFoldStart);
if FHighlighter.FoldBlockOpeningCount(ALineIdx) > 0 then include(Result, cfFoldStart);
end;
function TSynEditFoldProvider.GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
@ -2777,6 +2950,14 @@ begin
((FSelection <> nil) and FSelection.SelAvail);
end;
function TSynEditFoldProvider.GetHighLighterWithLines: TSynCustomFoldHighlighter;
begin
Result := FHighlighter;
if (Result = nil) then
exit;
Result.CurrentLines := FLines;
end;
procedure TSynEditFoldProvider.SetHighLighter(const AValue: TSynCustomFoldHighlighter);
begin
if FHighlighter = AValue then exit;
@ -2790,30 +2971,18 @@ begin
end;
function TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
var
i: Integer;
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);
exit(0);
end;
// Need to check alll nodes with FoldNodeInfoCount
// Hide-able nodes can open and close on the same line "(* cmment *)"
FHighlighter.CurrentLines := FLines;
Result := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold]);
if (result > 0) and (AType > 0) then begin
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
Result := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold], AType);
// fallback for HL without GetFoldNodeInfoCountEx
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
inc(Result);
end;
@ -2837,8 +3006,6 @@ function TSynEditFoldProvider.FoldOpenInfo(ALineIdx, AFoldIdx: Integer;
Result.FoldGroup := -1;
end;
var
i, x: Integer;
begin
Result.FoldAction := [sfaInvalid];
if (FHighlighter = nil) or (ALineIdx < 0) then begin
@ -2848,27 +3015,13 @@ begin
end;
FHighlighter.CurrentLines := FLines;
if AType = 0 then
if (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) and
(AFoldIdx = FoldOpenCount(ALineIdx, 0)-1)
then
Result := BlockSelInfo(AFoldIdx-1)
else
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(AFoldIdx, [sfaOpen, sfaFold])
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;
if (AType = 0) and (FSelection <> nil) and FSelection.SelAvail and
(FSelection.FirstLineBytePos.Y=ALineIdx+1) and
(AFoldIdx = FoldOpenCount(ALineIdx, AType)-1)
then
Result := BlockSelInfo(AFoldIdx)
else
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(AFoldIdx, [sfaOpen, sfaFold], AType);
end;
function TSynEditFoldProvider.FoldLineLength(ALine, AFoldIndex: Integer): integer;
@ -3369,7 +3522,7 @@ begin
while i < fLines.Count do begin
// Todo: Highlighter should return a list of types that can return default folded
// Currently PascalHl Type 2 = Region
c := hl.FoldOpenCount(i, 2);
c := hl.FoldBlockOpeningCount(i, 2);
if c > 0 then begin
c := hl.FoldNodeInfo[i].CountEx([sfaOpen, sfaFold]);
j := 0;
@ -3855,9 +4008,9 @@ begin
fFoldTree.Clear;
i := 0;
while i < fLines.Count do begin
if (hl.FoldOpenCount(i, t) > 0)
and (hl.FoldNestCount(i, t) > StartLevel) then begin
c := hl.FoldOpenCount(i) -1;
if (hl.FoldBlockOpeningCount(i, t) > 0)
and (hl.FoldBlockEndLevel(i, t) > StartLevel) then begin
c := hl.FoldBlockOpeningCount(i) -1;
fldinf := FoldProvider.InfoForFoldAtTextIndex(i, c);
// i is 0-based
// FoldTree is 1-based AND first line remains visble
@ -4111,7 +4264,7 @@ begin
hl := TSynCustomFoldHighlighter(HighLighter);
if not assigned(hl) then
exit(-1);
Result := hl.FoldNestCount(AStartIndex-1, AType) + FoldProvider.FoldOpenCount(AStartIndex);
Result := hl.FoldBlockEndLevel(AStartIndex-1, AType) + FoldProvider.FoldOpenCount(AStartIndex);
end;
function TSynEditFoldedView.OpenFoldInfo(aStartIndex, ColIndex: Integer; AType: Integer = 0): TFoldViewNodeInfo;
@ -4126,13 +4279,13 @@ var
begin
if AType = 0 then 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);
CurLvl[i] := EndLvl[i];
end;
end
else begin
EndLvl[0] := hl.FoldNestCount(l-1, AType);
EndLvl[0] := hl.FoldBlockEndLevel(l-1, AType);
EndLvl[0] := EndLvl[0] + FoldProvider.FoldOpenCount(l, AType);
CurLvl[0] := EndLvl[0];
end;
@ -4146,7 +4299,7 @@ begin
TypeCnt := 1
else
TypeCnt := hl.FoldTypeCount;
Lvl := hl.FoldNestCount(AStartIndex-1, AType);
Lvl := hl.FoldBlockEndLevel(AStartIndex-1, AType);
if ColIndex >= Lvl then begin
n := ColIndex - Lvl;
if AType = 0 then begin
@ -4165,8 +4318,8 @@ begin
aStartIndex := aStartIndex;
while (ColIndex < Lvl) and (aStartIndex > 0) do begin
dec(aStartIndex);
o := hl.FoldOpenCount(AStartIndex, AType);
if (o > 0) or (hl.FoldCloseCount(aStartIndex, AType) > 0) then begin
o := hl.FoldBlockOpeningCount(AStartIndex, AType);
if (o > 0) or (hl.FoldBlockClosingCount(aStartIndex, AType) > 0) then begin
n := o;
c := hl.FoldNodeInfo[aStartIndex].CountEx([], AType) - 1;
for i := c downto 0 do begin
@ -4194,7 +4347,7 @@ begin
end;
end
else
if hl.FoldNestCount(AStartIndex-1, AType) = 0 then break;
if hl.FoldBlockEndLevel(AStartIndex-1, AType) = 0 then break;
end;
end;
Result.HNode := nd;
@ -4220,7 +4373,7 @@ begin
exit;
i := ALine;
l := hl.FoldOpenCount(i - 1);
l := hl.FoldBlockOpeningCount(i - 1);
if l > 0 then begin
node := fFoldTree.FindFoldForLine(ALine, true);
if node.IsInFold and (node.StartLine = ALine +1) then begin
@ -4234,19 +4387,19 @@ begin
else
exit(ALine);
end
else if hl.FoldCloseCount(i - 1) > 0 then
else if hl.FoldBlockClosingCount(i - 1) > 0 then
dec(i);
if (i < 0) or (hl.FoldNestCount(i-1) = 0) then
if (i < 0) or (hl.FoldBlockEndLevel(i-1) = 0) then
exit;
l := 0;
while (i > 0) and (l >= 0) do begin // (FoldMinLevel[i] >= l) do
dec(i);
l := l - hl.FoldOpenCount(i);
l := l - hl.FoldBlockOpeningCount(i);
if l >= 0 then
l := l + hl.FoldCloseCount(i);
l := l + hl.FoldBlockClosingCount(i);
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;
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,
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;
{$I synedit.inc}
@ -54,6 +70,42 @@ type
);
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
LineIndex: Integer;
NodeIndex: Integer; // Indicates the position within the list of info nodes (depends on search-Filter)
@ -204,7 +256,7 @@ type
TSynCustomFoldHighlighter = class(TSynCustomHighlighter)
protected
// Config
// Fold Config
FFoldConfig: Array of TSynCustomFoldConfig;
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; virtual;
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); virtual;
@ -220,36 +272,55 @@ type
FRootCodeFoldBlock: TSynCustomCodeFoldBlock;
FFoldNodeInfoList: TLazSynFoldNodeInfoList;
protected
function CreateFoldNodeInfoList: TLazSynFoldNodeInfoList; virtual;
function GetFoldNodeInfo(Line: TLineIdx): TLazSynFoldNodeInfoList;
procedure InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx); virtual;
protected
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
// "Range"
function GetRangeClass: TSynCustomHighlighterRangeClass; virtual;
procedure CreateRootCodeFoldBlock; virtual; // set RootCodeFoldBlock
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
function TopCodeFoldBlockType(DownIndex: Integer = 0): Pointer;
property RootCodeFoldBlock: TSynCustomCodeFoldBlock read FRootCodeFoldBlock
write FRootCodeFoldBlock;
// Open/Close Folds
function StartCodeFoldBlock(ABlockType: Pointer;
IncreaseLevel: Boolean = true): TSynCustomCodeFoldBlock; virtual;
procedure EndCodeFoldBlock(DecreaseLevel: Boolean = True); virtual;
procedure CreateRootCodeFoldBlock; virtual;
property RootCodeFoldBlock: TSynCustomCodeFoldBlock read FRootCodeFoldBlock
write FRootCodeFoldBlock;
// Info about Folds
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
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetRange: Pointer; override;
function MinimumCodeFoldBlockLevel: integer; virtual;
function CurrentCodeFoldBlockLevel: integer; virtual;
// Info about Folds
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 MinimumFoldLevel(Index: Integer): integer; virtual; abstract; // TODO: Move to Fold*
function EndFoldLevel(Index: Integer): integer; virtual; abstract; // TODO: Replace with FoldNestCount
function FoldBlockOpeningCount(ALineIndex: TLineIdx; AFoldGroup: integer = 0;
AFlags: TSynFoldBlockFilterFlags = []): integer; overload;
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 FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer;
UseCloseNodes: boolean = false): integer; virtual; // TODO: could be deprecated ./ only child-classes
@ -296,6 +367,13 @@ function AllocateHighlighterRanges(
implementation
procedure InitFoldBlockFilter(out AFilter: TSynFoldBlockFilter; AFoldGroup: Integer;
AFlag: TSynFoldBlockFilterFlags = []);
begin
AFilter.FoldGroup := AFoldGroup;
AFilter.Flags := AFlag;
end;
function CompareSynHighlighterRanges(Data1, Data2: Pointer): integer;
var
Range1: TSynCustomHighlighterRange;
@ -597,6 +675,92 @@ begin
Result:=fRanges.GetEqual(FCodeFoldRange);
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;
begin
FCodeFoldRange.Clear;
@ -605,6 +769,7 @@ end;
function TSynCustomFoldHighlighter.MinimumCodeFoldBlockLevel: integer;
begin
assert(FCodeFoldRange <> nil, 'MinimumCodeFoldBlockLevel requires FCodeFoldRange');
Result := FCodeFoldRange.MinimumCodeFoldBlockLevel;
end;
@ -625,25 +790,23 @@ end;
function TSynCustomFoldHighlighter.CurrentCodeFoldBlockLevel: integer;
begin
if CodeFoldRange<>nil then
Result:=CodeFoldRange.CodeFoldStackSize
else
Result:=0;
assert(FCodeFoldRange <> nil, 'MinimumCodeFoldBlockLevel requires FCodeFoldRange');
Result := FCodeFoldRange.CodeFoldStackSize;
end;
function TSynCustomFoldHighlighter.FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer;
begin
result := 0;
result := FoldBlockOpeningCount(ALineIndex, AType);
end;
function TSynCustomFoldHighlighter.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer;
begin
result := 0;
result := FoldBlockClosingCount(ALineIndex, AType);
end;
function TSynCustomFoldHighlighter.FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer;
begin
Result := 0;
Result := FoldBlockEndLevel(ALineIndex, AType);
end;
function TSynCustomFoldHighlighter.FoldTypeCount: integer;
@ -661,7 +824,7 @@ function TSynCustomFoldHighlighter.FoldLineLength(ALineIndex, FoldIndex: Integer
begin
Result := FoldEndLine(ALineIndex, FoldIndex);
// 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);
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
Result := Result - ALineIndex;
@ -672,13 +835,12 @@ var
lvl, cnt: Integer;
e, m: Integer;
begin
//atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
cnt := CurrentLines.Count;
e := EndFoldLevel(ALineIndex);
m := MinimumFoldLevel(ALineIndex);
e := FoldBlockEndLevel(ALineIndex);
m := FoldBlockMinLevel(ALineIndex);
lvl := Min(m+1+FoldIndex, e);
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
dec(Result);
end;

View File

@ -75,13 +75,6 @@ type
procedure EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
public
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;
implementation
@ -122,50 +115,6 @@ begin
FXmlRangeInfoClosePos := 0;
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;
var
FoldBlock: Boolean;
@ -232,11 +181,11 @@ begin
if i = 0 then begin
i := LineIndex - 1;
lvl := EndFoldLevel(i);
lvl := FoldBlockEndLevel(i);
while i >= 0 do begin
if MinimumFoldLevel(i) < lvl then begin
if FoldBlockMinLevel(i) < lvl then begin
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
if (LInfo[k] = AName) then
break;

View File

@ -140,7 +140,10 @@ var
exit;
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);
if YIndex = LCnt then
exit;
@ -172,7 +175,9 @@ var
exit;
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);
if YIndex < 0 then
exit;

View File

@ -157,14 +157,6 @@ type
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigCount: 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
property UnknownAttri: TSynHighlighterAttributes read FUnknownAttri write FUnknownAttri;
property SpaceAttri: TSynHighlighterAttributes read FSpaceAttri write FSpaceAttri;
@ -747,56 +739,6 @@ begin
Result := ord(high(TDiffCodeFoldBlockType)) - ord(low(TDiffCodeFoldBlockType)) + 1;
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
RegisterPlaceableHighlighter(TSynDiffSyn);

View File

@ -65,6 +65,7 @@ type
// internal type / no config
cfbtLfmNone
);
TLfmCodeFoldBlockTypes = set of TLfmCodeFoldBlockType;
TProcTableProc = procedure of object;
@ -148,14 +149,6 @@ type
procedure SetRange(Value: Pointer); override;
procedure ResetRange; override;
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
property CommentAttri: TSynHighlighterAttributes read fCommentAttri
write fCommentAttri;
@ -612,50 +605,6 @@ begin
fRange := rsUnknown;
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);
begin
inherited;

View File

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

View File

@ -56,7 +56,7 @@ interface
{$I SynEdit.inc}
uses
Classes, math, Graphics, SynEditTypes, SynEditHighlighter,
Classes, Graphics, SynEditTypes, SynEditHighlighter,
SynEditHighlighterFoldBase, SynEditHighlighterXMLBase;
type
@ -98,22 +98,6 @@ 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;
{ TSynXMLSyn }
@ -1010,65 +994,8 @@ begin
Result := ord(high(TXmlCodeFoldBlockType)) - ord(low(TXmlCodeFoldBlockType)) + 1;
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
RegisterPlaceableHighlighter(TSynXMLSyn);
end.

View File

@ -39,13 +39,14 @@ type
function TestText5: TStringArray;
function TestText6: TStringArray;
function TestText7: TStringArray;
function TestText8: TStringArray;
function TestTextHide(ALen: Integer): TStringArray;
function TestTextHide2(ALen: Integer): TStringArray;
function TestTextHide3: TStringArray;
function TestTextHide4: TStringArray;
function TestTextPlain: TStringArray;
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, AFoldAtColum: integer; AExpectedLines: Array of Integer);
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
@ -66,6 +67,7 @@ type
procedure TestFoldEdit;
procedure TestFoldStateFromText;
procedure TestFoldStateDesc;
procedure TestFoldProvider;
end;
implementation
@ -73,7 +75,7 @@ implementation
type
TSynEditFoldedViewHack = class(TSynEditFoldedView) end;
procedure TTestFoldedView.TstSetText(AName: String; AText: TStringArray);
procedure TTestFoldedView.TstSetText(AName: String; AText: array of String);
begin
PopBaseName;
ReCreateEdit;
@ -406,6 +408,32 @@ begin
Result[26] := '';
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;
begin
SetLength(Result, 3+ALen);
@ -1457,6 +1485,161 @@ begin
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
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
uses
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc,
Classes, SysUtils, testregistry, TestBase, Forms, LCLProc, TestHighlightFoldBase,
SynEdit, SynEditTypes, SynHighlighterPas, SynEditHighlighterFoldBase;
type
@ -14,12 +14,10 @@ type
{ TTestBaseHighlighterPas }
TTestBaseHighlighterPas = class(TTestBase)
TTestBaseHighlighterPas = class(TTestBaseHighlighterFoldBase)
protected
PasHighLighter: TSynPasSyn;
procedure SetUp; override;
procedure TearDown; override;
procedure ReCreateEdit; reintroduce;
function PasHighLighter: TSynPasSyn;
function CreateTheHighLighter: TSynCustomFoldHighlighter; override;
procedure EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes;
AHideTypes: TPascalCodeFoldBlockTypes = [];
ANoFoldTypes: TPascalCodeFoldBlockTypes = []
@ -38,12 +36,8 @@ type
function TestTextFoldInfo3: 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);
function FoldActionsToString(AFoldActions: TSynFoldActions): String;
published
procedure TestFoldInfo;
procedure TestExtendedKeywordsAndStrings;
@ -60,28 +54,14 @@ implementation
{ TTestBaseHighlighterPas }
procedure TTestBaseHighlighterPas.SetUp;
function TTestBaseHighlighterPas.PasHighLighter: TSynPasSyn;
begin
PasHighLighter := nil;
inherited SetUp;
Result := TSynPasSyn(FTheHighLighter);
end;
procedure TTestBaseHighlighterPas.TearDown;
function TTestBaseHighlighterPas.CreateTheHighLighter: TSynCustomFoldHighlighter;
begin
if Assigned(SynEdit) then
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;
Result := TSynPasSyn.Create(nil);
end;
procedure TTestBaseHighlighterPas.EnableFolds(AEnbledTypes: TPascalCodeFoldBlockTypes;
@ -114,8 +94,8 @@ begin
l.GroupFilter := Group;
debugln(['### Foldinfo Line: ', ALineIdx,
' Cnt=', l.Count, ' CntEx=', c,
' PasMinLvl=',PasHighLighter.MinimumPasFoldLevel(ALineIdx,1),
' EndLvl=',PasHighLighter.EndPasFoldLevel(ALineIdx,1),
' PasMinLvl=', PasHighLighter.FoldBlockMinLevel(ALineIdx,1),
' EndLvl=',PasHighLighter.FoldBlockEndLevel(ALineIdx,1),
//' Nestcnt=',PasHighLighter.FoldNestCount(ALineIdx,1),
' : ', copy(SynEdit.Lines[ALineIdx],1,40)]);
debugln('Idx: LogXStart End FldLvlStart End NestLvlStart End FldType FldTypeCompat FldGroup FldAction');
@ -231,40 +211,6 @@ begin
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;
ExpTokens: array of TtkTokenKind);
var
@ -283,21 +229,6 @@ begin
AssertEquals(Name+ 'TokenId Line='+IntToStr(LineIdx)+' amount of tokens', length(ExpTokens), c );
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;
begin
ReCreateEdit;
@ -1013,12 +944,12 @@ begin
CheckFoldInfoCounts('', [], 4, [1, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 2]);
//### 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;
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: 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: 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
@ -1026,16 +957,16 @@ begin
//### 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
//### 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, 1, 0, 3, 2, 2, 2, 1, 3, 3, 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, 1, [sfaClose,sfaMarkup]); // end;
//### 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
//### 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, 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 : //
CheckNode(11, [], 4, 0, 0, 2, 0, 0, 0, 1, 22, 22, 4, [sfaOpen]); // //
CheckNode(11, [], 4, 1, 2, 2, 1, 1, 1, 0, 22, 22, 4, [sfaClose,sfaLastLineClose]); // /
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, 1, [sfaClose,sfaLastLineClose]); // /
{%endregion TEXT 1 -- [cfbtBeginEnd..cfbtNone], [] grp=4}
{%region TEXT 1 -- [cfbtBeginEnd..cfbtNone], [sfaFold]}
@ -1116,7 +1047,7 @@ begin
//### 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]);
//### 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}
CheckNode( 2, [], 0, 0, 2, 7, 0, 1, 0, 1, 18, 18, 3, [sfaOpen,sfaFold,sfaFoldFold]);
//### 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]);
//### 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, 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
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.