169
189
Function FindFoldForLine(ALine : Integer; FindNextNode : Boolean = False) : TSynTextFoldAVLNode;
170
190
(* Find Fold by Line in Folded Text // always returns unfolded, unless next=true *)
171
191
Function FindFoldForFoldedLine(ALine : Integer; FindNextNode: Boolean = False) : TSynTextFoldAVLNode;
172
Function InsertNewFold(ALine, AColumn, ACount, AVisibleLines: Integer) : TSynTextFoldAVLNode;
192
Function InsertNewFold(ALine, AFoldIndex, AColumn, AColumnLen, ACount, AVisibleLines: Integer;
193
AClassification: TFoldNodeClassification;
194
AFoldTypeCompatible: Pointer
195
) : TSynTextFoldAVLNode;
173
196
(* This will unfold the block which either contains tALine, or has Aline as its cgColapsed line
174
197
If IgnoreFirst, the cfCollapsed will *not* unfold => Hint: IgnoreFirst = Make folded visible
175
198
Returns the pos(1-based) of the cfCollapsed Line that was expanded; or ALine, if nothing was done
177
200
Function RemoveFoldForLine(ALine : Integer; OnlyCol: Integer = -1) : Integer; overload;
178
Procedure AdjustForLinesInserted(AStartLine, ALineCount : Integer);
179
Procedure AdjustForLinesDeleted(AStartLine, ALineCount : Integer);
201
Procedure AdjustForLinesInserted(AStartLine, ALineCount, ABytePos: Integer);
202
Procedure AdjustForLinesDeleted(AStartLine, ALineCount, ABytePos: Integer);
203
procedure AdjustColumn(ALine, ABytePos, ACount: Integer; InLineBreak: boolean = False);
180
204
Function FindLastFold : TSynTextFoldAVLNode;
181
205
Function FindFirstFold : TSynTextFoldAVLNode;
182
206
Function LastFoldedLine : integer; // The actual line; LastNode.StartLine + LastNode.LineCount - 1
247
278
{ TSynEditFoldProvider }
279
TSynEditFoldProviderNodeInfo = record
281
Column, ColumnLen: Integer;
282
DefaultCollapsed: Boolean;
283
FoldTypeCompatible: Pointer; // eg begin, var, procedure
284
FoldGroup: Integer; // eg.: pas, region, ifdef
285
Classification: TFoldNodeClassification;
288
TSynEditFoldProviderNodeInfoList = array of TSynEditFoldProviderNodeInfo;
289
TSynEditFoldProvider = class;
291
(* TLazSynEditNestedFoldsList
292
Provides Info on all foldable-blocks containing a given line (0 based index).
294
- All foldable blocks opening on a previous line, that are still open
295
at the start of the line. (May end on this line or later)
296
- Foldable blocks opening on that line. (OpeningOnLineCount)
298
The data is NOT automatically invalidated.
301
TLazSynEditNestedFoldsListEntry = record
302
HNode: TSynFoldNodeInfo; // Highlighter Node
303
//FNode: TSynTextFoldAVLNode; // AvlFoldNode
304
//Text, Keyword: String;
307
//OpenCount: Integer;
310
TLazSynEditNestedFoldsList = class
312
FFoldProvider: TSynEditFoldProvider;
315
procedure SetFoldGroup(AValue: Integer);
316
procedure SetLines(AValue: TLineIdx);
318
FFoldFlags: TSynFoldBlockFilterFlags;
319
FGroupCount: Integer;
320
FGroupEndLevels, FGroupEndLevelsAtEval: Array of integer;
321
FCount, FOpeningOnLineCount: Integer;
322
FIncludeOpeningOnLine: Boolean;
323
FNestInfo: Array of TLazSynEditNestedFoldsListEntry;
324
FEvaluationIndex: Integer;
325
function GetHLNode(Index: Integer): TSynFoldNodeInfo;
326
function GetNodeFoldGroup(Index: Integer): Integer;
327
function GetNodeFoldType(Index: Integer): Pointer;
328
procedure InitSubGroupEndLevels;
329
procedure InitNestInfoForIndex(AnIndex: Integer);
330
procedure SetFoldFlags(AValue: TSynFoldBlockFilterFlags);
331
procedure SetIncludeOpeningOnLine(AValue: Boolean);
333
constructor Create(aFoldProvider: TSynEditFoldProvider);
335
procedure ResetFilter;
336
function Count: Integer;
337
function OpeningOnLineCount: Integer; // ignores FFoldFlags
338
property Line: TLineIdx read FLine write SetLines;
339
property FoldGroup: Integer read FFoldGroup write SetFoldGroup;
340
property FoldFlags: TSynFoldBlockFilterFlags read FFoldFlags write SetFoldFlags;
341
property IncludeOpeningOnLine: Boolean read FIncludeOpeningOnLine write SetIncludeOpeningOnLine;
343
property HLNode[Index: Integer]: TSynFoldNodeInfo read GetHLNode;
344
property NodeFoldType[Index: Integer]: Pointer read GetNodeFoldType; // e.g.cfbtBeginEnd, cfbtcfbtProcedure ...
345
property NodeFoldGroup[Index: Integer]: Integer read GetNodeFoldGroup; // independend/overlapping folds, e.g begin/end; ifdef, region
249
349
TSynEditFoldProvider = class
251
351
FHighlighter: TSynCustomFoldHighlighter;
352
FLines : TSynEditStrings;
353
FSelection: TSynEditSelection;
354
FFoldTree : TSynTextFoldAVLTree;
355
FNestedFoldsList: TLazSynEditNestedFoldsList;
356
function GetFoldsAvailable: Boolean;
357
function GetHighLighterWithLines: TSynCustomFoldHighlighter;
252
358
function GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
359
function GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
360
function GetNestedFoldsList: TLazSynEditNestedFoldsList;
253
361
procedure SetHighLighter(const AValue: TSynCustomFoldHighlighter);
363
property HighLighterWithLines: TSynCustomFoldHighlighter read GetHighLighterWithLines;
255
function FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
256
function FoldOpenInfo(ALineIdx, AFoldIdx: Integer; AType: Integer = 0): TSynFoldNodeInfo;
365
constructor Create(aTextView : TSynEditStrings; AFoldTree : TSynTextFoldAVLTree);
366
destructor Destroy; override;
368
// Info about Folds opening on ALineIdx
369
function FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
370
function FoldOpenInfo(ALineIdx, AFoldIdx: Integer; AType: Integer = 0): TSynFoldNodeInfo;
257
371
//property FoldOpenInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldOpenInfo;
258
//property FoldInfoCount[ALineIdx: Integer]: Integer read GetFoldInfoCount;
259
//property FoldInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldInfo;
373
function FoldLineLength(ALine, AFoldIndex: Integer): integer;
374
function InfoForFoldAtTextIndex(ALine, AFoldIndex : Integer;
375
HideLen: Boolean = False;
376
NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo;
377
function InfoListForFoldsAtTextIndex(ALine: Integer; NeedLen: Boolean = False): TSynEditFoldProviderNodeInfoList;
260
379
property LineCapabilities[ALineIdx: Integer]: TSynEditFoldLineCapabilities
261
380
read GetLineCapabilities;
381
property LineClassification[ALineIdx: Integer]: TFoldNodeClassifications
382
read GetLineClassification;
383
property Lines: TSynEditStrings read FLines write FLines;
262
384
property HighLighter: TSynCustomFoldHighlighter read FHighlighter write SetHighLighter;
385
property FoldsAvailable: Boolean read GetFoldsAvailable;
386
property NestedFoldsList: TLazSynEditNestedFoldsList read GetNestedFoldsList;
389
TSynEditFoldedView = class;
391
{ TLazSynDisplayFold }
393
TLazSynDisplayFold = class(TLazSynDisplayViewEx)
395
FFoldView: TSynEditFoldedView;
397
FTokenAttr: TSynHighlighterAttributes;
399
constructor Create(AFoldView: TSynEditFoldedView);
400
destructor Destroy; override;
401
procedure SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx); override;
402
function GetNextHighlighterToken(out ATokenInfo: TLazSynDisplayTokenInfo): Boolean; override;
403
function GetLinesCount: Integer; override;
405
function TextToViewIndex(AIndex: TLineIdx): TLineRange; override;
406
function ViewToTextIndex(AIndex: TLineIdx): TLineIdx; override;
265
409
{ TSynTextFoldedView
271
415
{ TSynEditFoldedView }
273
TSynEditFoldedView = class // TODO: class(TSynEditStringsLinked)
417
TSynEditFoldedView = class
275
419
fCaret: TSynEditCaret;
420
FBlockSelection: TSynEditSelection;
276
421
FFoldProvider: TSynEditFoldProvider;
277
FHighLighter: TSynCustomFoldHighlighter;
278
422
fLines : TSynEditStrings;
279
423
fFoldTree : TSynTextFoldAVLTree; // Folds are stored 1-based (the 1st line is 1)
280
424
FMarkupInfoFoldedCode: TSynSelectedColor;
425
FOnLineInvalidate: TInvalidateLineProc;
281
426
fTopLine : Integer;
282
427
fLinesInWindow : Integer; // there may be an additional part visible line
283
428
fTextIndexList : Array of integer; (* Map each Screen line into a line in textbuffer *)
284
fFoldTypeList : Array of TSynEditFoldLineCapabilities;
429
fFoldTypeList : Array of TSynEditFoldLineMapInfo;
285
430
fOnFoldChanged : TFoldChangedEvent;
286
431
fLockCount : Integer;
287
432
fNeedFixFrom, fNeedFixMinEnd : Integer;
288
433
fNeedCaretCheck : Boolean;
434
FInTopLineChanged: Boolean;
435
FDisplayView: TLazSynDisplayFold;
290
437
function GetCount : integer;
438
function GetDisplayView: TLazSynDisplayView;
439
function GetFoldClasifications(index : Integer): TFoldNodeClassifications;
291
440
function GetHighLighter: TSynCustomHighlighter;
292
441
function GetLines(index : Integer) : String;
293
442
function GetDisplayNumber(index : Integer) : Integer;
294
443
function GetTextIndex(index : Integer) : Integer;
295
444
function GetFoldType(index : Integer) : TSynEditFoldLineCapabilities;
296
445
function IsFolded(index : integer) : Boolean; // TextIndex
446
procedure SetBlockSelection(const AValue: TSynEditSelection);
297
447
procedure SetHighLighter(AValue: TSynCustomHighlighter);
298
448
procedure SetTopLine(const ALine : integer);
299
449
function GetTopTextIndex : integer;
300
450
procedure SetTopTextIndex(const AIndex : integer);
301
451
procedure SetLinesInWindow(const AValue : integer);
453
procedure DoBlockSelChanged(Sender: TObject);
303
454
Procedure CalculateMaps;
304
function LengthForFoldAtTextIndex(ALine, AFoldIndex : Integer; HideLen: Boolean = False) : Integer;
305
455
function FoldNodeAtTextIndex(AStartIndex, ColIndex: Integer): TSynTextFoldAVLNode; (* Returns xth Fold at nth TextIndex (all lines in buffer) / 1-based *)
306
456
function FixFolding(AStart : Integer; AMinEnd : Integer; aFoldTree : TSynTextFoldAVLTree) : Boolean;
308
458
procedure DoCaretChanged(Sender : TObject);
309
459
Procedure LineCountChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
310
Procedure LinesInsertedAtTextIndex(AStartIndex, ALineCount : Integer;
460
Procedure LinesCleared(Sender: TObject);
461
Procedure LineEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount,
462
aLineBrkCnt: Integer; aText: String);
463
Procedure LinesInsertedAtTextIndex(AStartIndex, ALineCount, ABytePos: Integer;
311
464
SkipFixFolding : Boolean = False);
312
Procedure LinesInsertedAtViewPos(AStartPos, ALineCount : Integer;
313
SkipFixFolding : Boolean = False);
314
Procedure LinesDeletedAtTextIndex(AStartIndex, ALineCount : Integer;
465
//Procedure LinesInsertedAtViewPos(AStartPos, ALineCount : Integer;
466
// SkipFixFolding : Boolean = False);
467
Procedure LinesDeletedAtTextIndex(AStartIndex, ALineCount, ABytePos: Integer;
315
468
SkipFixFolding : Boolean = False);
316
Procedure LinesDeletedAtViewPos(AStartPos, ALineCount : Integer;
317
SkipFixFolding : Boolean = False);
469
//Procedure LinesDeletedAtViewPos(AStartPos, ALineCount : Integer;
470
// SkipFixFolding : Boolean = False);
471
property FoldTree: TSynTextFoldAVLTree read fFoldTree;
319
473
constructor Create(aTextView : TSynEditStrings; ACaret: TSynEditCaret);
320
474
destructor Destroy; override;
558
724
NumEncode86Values[NumEncode86Chars[i]] := i - 1;
727
{ TLazSynDisplayFold }
729
constructor TLazSynDisplayFold.Create(AFoldView: TSynEditFoldedView);
732
FFoldView := AFoldView;
733
FTokenAttr := TSynHighlighterAttributes.Create('');
736
destructor TLazSynDisplayFold.Destroy;
738
FreeAndNil(FTokenAttr);
742
procedure TLazSynDisplayFold.SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx);
745
CurrentTokenLine := ALine;
746
inherited SetHighlighterTokensLine(FFoldView.ViewPosToTextIndex(ALine + 1), ARealLine);
749
function TLazSynDisplayFold.GetNextHighlighterToken(out ATokenInfo: TLazSynDisplayTokenInfo): Boolean;
751
MarkSpaces: string = ' ';
752
MarkDots: string = '...';
754
EolAttr: TSynHighlighterAttributes;
758
Result := inherited GetNextHighlighterToken(ATokenInfo);
760
(FFoldView.FoldType[CurrentTokenLine + 1 - FFoldView.TopLine] * [cfCollapsedFold, cfCollapsedHide] <> [])
763
ATokenInfo.TokenStart := PChar(MarkSpaces);
764
ATokenInfo.TokenLength := 3;
765
if Assigned(CurrentTokenHighlighter)
766
then EolAttr := CurrentTokenHighlighter.GetEndOfLineAttribute
768
if EolAttr <> nil then begin
769
FTokenAttr.Assign(EolAttr);
770
ATokenInfo.TokenAttr := FTokenAttr;
773
ATokenInfo.TokenAttr := nil;
779
FTokenAttr.Assign(FFoldView.MarkupInfoFoldedCode);
780
FTokenAttr.SetAllPriorities(MaxInt);
781
ATokenInfo.TokenStart := PChar(MarkDots);
782
ATokenInfo.TokenLength := 3;
783
ATokenInfo.TokenAttr := FTokenAttr;
791
function TLazSynDisplayFold.GetLinesCount: Integer;
793
Result := FFoldView.Count;
796
function TLazSynDisplayFold.TextToViewIndex(AIndex: TLineIdx): TLineRange;
798
Result := inherited TextToViewIndex(AIndex);
799
if Result.Top = Result.Bottom then begin
800
Result.Top := FFoldView.TextIndexToViewPos(Result.Top) - 1;
801
Result.Bottom := Result.Top;
804
Result.Top := FFoldView.TextIndexToViewPos(Result.Top) - 1;
805
Result.Bottom := FFoldView.TextIndexToViewPos(Result.Bottom) - 1;
809
function TLazSynDisplayFold.ViewToTextIndex(AIndex: TLineIdx): TLineIdx;
811
Result := FFoldView.ViewPosToTextIndex(inherited ViewToTextIndex(AIndex)+1);
561
814
{ TSynEditFoldExportStream }
563
816
constructor TSynEditFoldExportStream.Create;
1811
2091
Cnt, EndCol, EndLineIdx: Integer;
1813
2093
FActions := [sfaClose, sfaFold];
1814
NdInfo := FHighlighter.FoldNodeInfo[ANode.StartLine - ANode.SourceLineOffset - 1,
1815
ANode.FoldIndex, [sfaOpen, sfaFold]];
2094
NdInfo := FHighlighter.FoldNodeInfo[ANode.StartLine - ANode.SourceLineOffset - 1]
2095
.NodeInfoEx(ANode.FoldIndex, [sfaOpen, sfaFold]);
2096
if sfaInvalid in NdInfo.FoldAction then exit(NdInfo);
1817
2098
EndLineIdx := FHighlighter.FoldEndLine(ANode.StartLine - ANode.SourceLineOffset - 1,
1818
2099
ANode.FoldIndex);
1819
Cnt := FHighlighter.FoldNodeInfoCount[EndLineIdx, [sfaClose, sfaFold]];
2100
{$IFDEF SynAssertFold}
2101
SynAssert(EndLineIdx >= 0, 'TSynFoldNodeInfoHelper.GotoNodeClosePos: Bad EndLineIdx=%d # Anode: StartLine=%d SrcLOffs=%d ColIdx=%d FoldCol=%d', [EndLineIdx, ANode.StartLine, ANode.SourceLineOffset, ANode.FoldIndex, ANode.FoldColumn]);
2103
Cnt := FHighlighter.FoldNodeInfo[EndLineIdx].CountEx([sfaClose, sfaFold]);
1821
2105
while EndCol < Cnt do begin
1822
NdInfo2 := FHighlighter.FoldNodeInfo[EndLineIdx, EndCol, [sfaClose, sfaFold]];
2106
NdInfo2 := FHighlighter.FoldNodeInfo[EndLineIdx].NodeInfoEx(EndCol, [sfaClose, sfaFold]);
1823
2107
if (NdInfo2.FoldLvlStart = NdInfo.FoldLvlEnd) and
1824
2108
(NdInfo2.FoldType = NdInfo.FoldType) then break;
2380
{$IFDEF SynFoldDebug}debugln(['FOLD-- AdjustForLinesDeleted AStartLine:=', AStartLine, ' ALineCount=',ALineCount, ' ABytePos=',ABytePos ]); {$ENDIF}
2381
if ABytePos > 1 then
2382
AdjustColumn(AStartLine+ALineCount-1, 1, ABytePos-1);
2087
2383
AdjustNodeForLinesDeleted(TSynTextFoldAVLNodeData(fRoot), fRootOffset, AStartLine, ALineCount);
2386
procedure TSynTextFoldAVLTree.AdjustColumn(ALine, ABytePos, ACount: Integer;
2387
InLineBreak: boolean = False);
2389
Node: TSynTextFoldAVLNode;
2391
Node := FindFoldForLine(ALine, True);
2392
{$IFDEF SynFoldDebug}debugln(['FOLD-- AdjustColumn ALine:=', ALine, ' ABytePos=',ABytePos, ' ACount=',ACount, ' // node.srcline=',Node.SourceLine, ' StartLine=', node.StartLine, 'column=',Node.FoldColumn ]); {$ENDIF}
2393
if (not Node.IsInFold) or (Node.SourceLine > ALine) then exit;
2394
if (Node.SourceLine = ALine) and (node.FoldColumn >= ABytePos) then begin
2395
node.FoldColumn := Node.FoldColumn + ACount;
2396
if (not InLineBreak) and (node.FoldColumn < ABytePos) then node.FoldColumn := ABytePos;
2398
TreeForNestedNode(Node.fData, node.StartLine).AdjustColumn(ALine, ABytePos, ACount);
2090
2401
function TSynTextFoldAVLTree.FindLastFold : TSynTextFoldAVLNode;
2092
2403
r : TSynTextFoldAVLNodeData;
2152
2464
Result := Result + ANode.MergedLineCount;
2467
debugln('StartLine, EndLine (MergedEnd, FoldIndex) - Column:Len; MergedLineCnt / FullCCnt | .. (LineOffset) ...');
2155
2468
debug2('', ' -', TSynTextFoldAVLNodeData(fRoot), nil, 0);
2159
function TSynTextFoldAVLTree.InsertNewFold(ALine, AColumn, ACount, AVisibleLines: Integer) : TSynTextFoldAVLNode;
2472
function TSynTextFoldAVLTree.InsertNewFold(ALine, AFoldIndex, AColumn, AColumnLen,
2473
ACount, AVisibleLines: Integer; AClassification: TFoldNodeClassification;
2474
AFoldTypeCompatible: Pointer) : TSynTextFoldAVLNode;
2161
2476
r : TSynTextFoldAVLNodeData;
2163
{$IFDEF SynFoldDebug}debugln(['FOLD-- InsertNewFold ALine:=', ALine, ' AColumn=', AColumn]);{$ENDIF}
2478
{$IFDEF SynFoldDebug}debugln(['FOLD-- InsertNewFold ALine:=', ALine, ' AFoldIndex=', AFoldIndex]);{$ENDIF}
2165
2480
r.LineOffset := ALine; // 1-based
2166
r.FoldIndex := AColumn;
2481
r.FoldIndex := AFoldIndex;
2482
r.FoldColumn := AColumn;
2483
r.FoldColumnLen := AColumnLen;
2167
2484
r.MergedLineCount := ACount;
2168
2485
r.FullCount := ACount;
2169
2486
r.LeftCount := 0;
2170
2487
r.VisibleLines := AVisibleLines;
2488
r.Classification := AClassification;
2489
r.FoldTypeCompatible := AFoldTypeCompatible;
2172
Result.Init(r, ALine, 0);
2491
Result{%H-}.Init(r, ALine, 0);
2173
2492
Result.fFoldedBefore := InsertNode(r);
2486
2805
fNestedNodesTree := nil;
2808
{ TLazSynEditNestedFoldsList }
2810
procedure TLazSynEditNestedFoldsList.SetLines(AValue: TLineIdx);
2812
if FLine = AValue then Exit;
2814
// Todo: might be able to re-use old data
2818
procedure TLazSynEditNestedFoldsList.Clear;
2822
FOpeningOnLineCount := -1;
2823
FEvaluationIndex := -1;
2824
SetLength(FNestInfo, 0);
2827
procedure TLazSynEditNestedFoldsList.ResetFilter;
2829
FIncludeOpeningOnLine := True;
2835
procedure TLazSynEditNestedFoldsList.InitSubGroupEndLevels;
2837
hl: TSynCustomFoldHighlighter;
2840
if FGroupCount > 0 then
2843
hl := FFoldProvider.HighLighterWithLines;
2844
if hl = nil then exit;
2846
if FFoldGroup = 0 then begin
2847
// special, join other groups (or some other...)
2848
FGroupCount := hl.FoldTypeCount;
2849
// start at 1, so FoldGroup can be used as index
2850
SetLength(FGroupEndLevels, FGroupCount + 1);
2851
SetLength(FGroupEndLevelsAtEval, FGroupCount + 1);
2852
for i := 1 to FGroupCount do begin
2853
FGroupEndLevels[i] := hl.FoldBlockEndLevel(FLine - 1, i, FFoldFlags);
2854
if FIncludeOpeningOnLine then
2855
FGroupEndLevels[i] := FGroupEndLevels[i] + FFoldProvider.FoldOpenCount(FLine, i);
2856
FGroupEndLevelsAtEval[i] := FGroupEndLevels[i];
2861
SetLength(FGroupEndLevels, 1);
2862
SetLength(FGroupEndLevelsAtEval, 1);
2863
FGroupEndLevels[0] := Count; // includes OpeningOnLineCount
2864
FGroupEndLevelsAtEval[0] := FGroupEndLevels[0];
2868
function TLazSynEditNestedFoldsList.GetHLNode(Index: Integer): TSynFoldNodeInfo;
2870
if (Index < 0) or (Index >= Count) then begin
2871
Result.FoldAction := [sfaInvalid];
2874
InitNestInfoForIndex(Index);
2875
Result := FNestInfo[Index].HNode;
2878
function TLazSynEditNestedFoldsList.GetNodeFoldGroup(Index: Integer): Integer;
2880
if FoldGroup <> 0 then
2883
Result := HLNode[Index].FoldGroup;
2886
function TLazSynEditNestedFoldsList.GetNodeFoldType(Index: Integer): Pointer;
2888
hl: TSynCustomFoldHighlighter;
2891
hl := FFoldProvider.HighLighterWithLines;
2892
if hl = nil then exit;
2894
if hl.FoldBlockNestedTypes(Line - 1, Index, Result, FFoldGroup, FFoldFlags) then
2897
Result := HLNode[Index].FoldType;
2900
procedure TLazSynEditNestedFoldsList.InitNestInfoForIndex(AnIndex: Integer);
2903
hl: TSynCustomFoldHighlighter;
2904
i, c, t, l: Integer;
2905
NFilter: TSynFoldActions;
2906
nd: TSynFoldNodeInfo;
2908
if (AnIndex >= Count) or (AnIndex >= FEvaluationIndex) then exit;
2909
hl := FFoldProvider.HighLighterWithLines;
2910
if hl = nil then exit;
2911
InitSubGroupEndLevels;
2913
if FEvaluationIndex = Count then
2916
CurLine := FNestInfo[FEvaluationIndex].LineIdx - 1;
2917
// need index/column...
2920
while CurLine > 0 do begin
2923
if FFoldGroup = 0 then begin
2925
while (i > 0) do begin
2926
if hl.FoldBlockMinLevel(CurLine, i, FFoldFlags) < FGroupEndLevelsAtEval[i] then break;
2929
if i <= 0 then continue;
2932
if hl.FoldBlockMinLevel(CurLine, FFoldGroup, FFoldFlags) >= FGroupEndLevelsAtEval[0] then continue;
2935
// something of interest closes on this line
2936
NFilter := [sfaOpen];
2937
if not(sfbIncludeDisabled in FFoldFlags) then Include(NFilter, sfaFold);
2938
c := hl.FoldNodeInfo[CurLine].CountEx(NFilter, FFoldGroup) - 1;
2939
for i := c downto 0 do begin
2940
nd := hl.FoldNodeInfo[CurLine].NodeInfoEx(i, NFilter, FFoldGroup);
2942
if FFoldGroup = 0 then
2947
if (sfbIncludeDisabled in FFoldFlags)
2948
then l := nd.NestLvlStart
2949
else l := nd.FoldLvlStart;
2950
if l >= FGroupEndLevelsAtEval[t] then continue;
2952
dec(FGroupEndLevelsAtEval[t]);
2953
dec(FEvaluationIndex);
2955
assert(FGroupEndLevelsAtEval[t] >= 0, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex GroupEndLevel < 0');
2956
assert(FEvaluationIndex >= 0, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex FEvaluationIndex < 0');
2958
FNestInfo[FEvaluationIndex].LineIdx := CurLine;
2959
FNestInfo[FEvaluationIndex].HNode := nd;
2962
if (AnIndex >= FEvaluationIndex) then Break;
2966
assert(AnIndex >= FEvaluationIndex, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex Index not found');
2969
procedure TLazSynEditNestedFoldsList.SetFoldFlags(AValue: TSynFoldBlockFilterFlags);
2971
if FFoldFlags = AValue then Exit;
2972
FFoldFlags := AValue;
2976
procedure TLazSynEditNestedFoldsList.SetIncludeOpeningOnLine(AValue: Boolean);
2978
if FIncludeOpeningOnLine = AValue then Exit;
2979
FIncludeOpeningOnLine := AValue;
2983
procedure TLazSynEditNestedFoldsList.SetFoldGroup(AValue: Integer);
2985
if FFoldGroup = AValue then Exit;
2986
FFoldGroup := AValue;
2990
constructor TLazSynEditNestedFoldsList.Create(aFoldProvider: TSynEditFoldProvider);
2992
FFoldProvider := aFoldProvider;
2993
FIncludeOpeningOnLine := True;
2998
function TLazSynEditNestedFoldsList.Count: Integer;
3000
hl: TSynCustomFoldHighlighter;
3003
if Result >= 0 then exit;
3004
hl := FFoldProvider.HighLighterWithLines;
3005
if hl = nil then exit(-1);
3007
FCount := hl.FoldBlockEndLevel(FLine - 1, FFoldGroup, FFoldFlags) + OpeningOnLineCount;
3008
FEvaluationIndex := FCount;
3009
SetLength(FNestInfo, FCount);
3013
function TLazSynEditNestedFoldsList.OpeningOnLineCount: Integer;
3015
if not FIncludeOpeningOnLine then
3018
Result := FOpeningOnLineCount;
3019
if Result >= 0 then exit;
3021
FOpeningOnLineCount := FFoldProvider.FoldOpenCount(FLine, FFoldGroup);
3022
Result := FOpeningOnLineCount;
2489
3025
{ TSynEditFoldProvider }
2491
3027
function TSynEditFoldProvider.GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
2496
if (FHighlighter = nil) or (ALineIdx < 0) then exit;
2497
if FHighlighter.FoldNestCount(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
2498
if FHighlighter.FoldCloseCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
2500
c := FHighlighter.FoldNodeInfoCount[ALineIdx, []];
3032
if (FSelection <> nil) and (FSelection.SelAvail) then begin
3033
if (FSelection.FirstLineBytePos.Y < ALineIdx+1) and
3034
(FSelection.LastLineBytePos.Y > ALineIdx+1)
3035
then Result := [cfFoldBody];
3036
if (FSelection.LastLineBytePos.Y = ALineIdx+1) then Result := [cfFoldEnd];
3037
if (FSelection.FirstLineBytePos.Y = ALineIdx+1) then Result := [cfHideStart];
3038
if (FSelection.FirstLineBytePos.Y = ALineIdx+1) and
3039
(FSelection.LastLineBytePos.Y = ALineIdx+1) then Result := [cfHideStart, cfSingleLineHide];
3041
if (FHighlighter = nil) or (ALineIdx < 0) then
3044
FHighlighter.CurrentLines := FLines;
3045
if FHighlighter.FoldBlockEndLevel(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
3046
if FHighlighter.FoldBlockClosingCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
3048
c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([]);
2501
3049
if c > 0 then begin
2502
c := FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFoldFold]];
3050
c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFoldFold]);
2504
3052
include(Result, cfFoldStart);
2505
c := FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFoldHide]];
3053
c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFoldHide]);
2507
3055
include(Result, cfHideStart);
2508
c := FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOneLineOpen, sfaFoldHide]]; // TODO: Include scftFoldEnd ?
3056
c := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOneLineOpen, sfaFoldHide]); // TODO: Include scftFoldEnd ?
2509
3057
// Todo: cfSingleLineHide only, if there is no other hide
2511
3059
Result := Result + [cfHideStart, cfSingleLineHide];
2514
if FHighlighter.FoldOpenCount(ALineIdx) > 0 then include(Result, cfFoldStart);
3062
if FHighlighter.FoldBlockOpeningCount(ALineIdx) > 0 then include(Result, cfFoldStart);
3065
function TSynEditFoldProvider.GetLineClassification(ALineIdx: Integer): TFoldNodeClassifications;
3068
if (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y = ALineIdx+1) then
3069
Result := [fncBlockSelection];
3072
function TSynEditFoldProvider.GetNestedFoldsList: TLazSynEditNestedFoldsList;
3074
if FNestedFoldsList = nil then
3075
FNestedFoldsList := TLazSynEditNestedFoldsList.Create(Self);
3076
Result := FNestedFoldsList;
3079
function TSynEditFoldProvider.GetFoldsAvailable: Boolean;
3081
Result := (FHighlighter <> nil) or
3082
((FSelection <> nil) and FSelection.SelAvail);
3085
function TSynEditFoldProvider.GetHighLighterWithLines: TSynCustomFoldHighlighter;
3087
Result := FHighlighter;
3088
if (Result = nil) then
3090
Result.CurrentLines := FLines;
2517
3093
procedure TSynEditFoldProvider.SetHighLighter(const AValue: TSynCustomFoldHighlighter);
2520
3096
FHighlighter := AValue;
3099
constructor TSynEditFoldProvider.Create(aTextView: TSynEditStrings; AFoldTree : TSynTextFoldAVLTree);
3101
FLines := aTextView;
3102
FFoldTree := AFoldTree;
3105
destructor TSynEditFoldProvider.Destroy;
3108
FreeAndNil(FNestedFoldsList);
2523
3111
function TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
2527
if (FHighlighter = nil) or (ALineIdx < 0) then exit(0);
2529
Result := FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFold]];
2530
if (result > 0) and (AType > 0) then begin
2533
while i > 0 do begin
2535
if FHighlighter.FoldNodeInfo[ALineIdx, i, [sfaOpen, sfaFold]].FoldGroup = AType then
2539
//Result := Result + FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFoldHide]];
2540
//Result := Result + FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOneLineOpen, sfaFoldHide]];
3113
if (FHighlighter = nil) or (ALineIdx < 0) then begin
3114
if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then exit(1);
3117
// Need to check alll nodes with FoldNodeInfoCount
3118
// Hide-able nodes can open and close on the same line "(* cmment *)"
3119
FHighlighter.CurrentLines := FLines;
3120
Result := FHighlighter.FoldNodeInfo[ALineIdx].CountEx([sfaOpen, sfaFold], AType);
3121
// fallback for HL without GetFoldNodeInfoCountEx
2542
3122
if Result < 0 then
2543
Result := FHighlighter.FoldOpenCount(ALineIdx, AType);
3123
Result := FHighlighter.FoldBlockOpeningCount(ALineIdx, AType);
3124
if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then
2546
3128
function TSynEditFoldProvider.FoldOpenInfo(ALineIdx, AFoldIdx: Integer;
2547
3129
AType: Integer = 0): TSynFoldNodeInfo;
3131
function BlockSelInfo(NIdx: Integer): TSynFoldNodeInfo;
3133
Result.LineIndex := ALineIdx;
3134
Result.NodeIndex := NIdx;
3135
Result.LogXStart := FSelection.FirstLineBytePos.x;
3136
Result.LogXEnd := FSelection.FirstLineBytePos.x;
3137
Result.FoldLvlStart := 0;
3138
Result.NestLvlStart := 0;
3139
Result.NestLvlEnd := 1;
3140
Result.FoldLvlEnd := 1;
3141
Result.FoldAction := [sfaOpen, sfaFold, sfaFoldHide];
3142
Result.FoldType := nil;
3143
Result.FoldTypeCompatible := nil;
3144
Result.FoldGroup := -1;
2551
3148
Result.FoldAction := [sfaInvalid];
2552
if (FHighlighter = nil) or (ALineIdx < 0) then exit;
2555
Result := FHighlighter.FoldNodeInfo[ALineIdx, AFoldIdx, [sfaOpen, sfaFold]]
2557
x := FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFold]];
2559
while i < x do begin
2560
Result := FHighlighter.FoldNodeInfo[ALineIdx, i, [sfaOpen, sfaFold]];
2561
if (Result.FoldGroup = AType) then begin
2562
if AFoldIdx = 0 then
2568
Result.FoldAction := [sfaInvalid];
3149
if (FHighlighter = nil) or (ALineIdx < 0) then begin
3150
if (AType=0) and (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALineIdx+1) then
3151
exit(BlockSelInfo(0));
3155
FHighlighter.CurrentLines := FLines;
3156
if (AType = 0) and (FSelection <> nil) and FSelection.SelAvail and
3157
(FSelection.FirstLineBytePos.Y=ALineIdx+1) and
3158
(AFoldIdx = FoldOpenCount(ALineIdx, AType)-1)
3160
Result := BlockSelInfo(AFoldIdx)
3162
Result := FHighlighter.FoldNodeInfo[ALineIdx].NodeInfoEx(AFoldIdx, [sfaOpen, sfaFold], AType);
3165
function TSynEditFoldProvider.FoldLineLength(ALine, AFoldIndex: Integer): integer;
3167
if (FSelection <> nil) and FSelection.SelAvail and (FSelection.FirstLineBytePos.Y=ALine+1) and
3168
(AFoldIndex = FoldOpenCount(ALine, 0)-1)
3170
exit(FSelection.LastLineBytePos.y - FSelection.FirstLineBytePos.y);
3172
FHighlighter.CurrentLines := FLines;
3173
Result := FHighlighter.FoldLineLength(ALine, AFoldIndex);
3176
function TSynEditFoldProvider.InfoForFoldAtTextIndex(ALine, AFoldIndex: Integer;
3177
HideLen: Boolean; NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo;
3179
nd: TSynFoldNodeInfo;
3181
Result.LineCount := 0;
3183
Result.ColumnLen := 0;
3184
Result.DefaultCollapsed := False;
3185
Result.Classification := fncInvalid;
3186
if not FoldsAvailable then
3189
if NeedLen then begin
3190
Result.LineCount := FoldLineLength(ALine, AFoldIndex);
3192
inc(Result.LineCount);
3195
Result.LineCount := -1;
3196
nd := FoldOpenInfo(ALine, AFoldIndex, 0);
3197
Result.Column := nd.LogXStart+1;
3198
Result.ColumnLen := nd.LogXEnd - nd.LogXStart;
3199
Result.DefaultCollapsed := (sfaDefaultCollapsed in nd.FoldAction);
3200
Result.FoldTypeCompatible := nd.FoldTypeCompatible;
3201
Result.FoldGroup := nd.FoldGroup;
3202
if Result.FoldGroup = -1 then
3203
Result.Classification := fncBlockSelection
3205
Result.Classification := fncHighlighter;
3208
function TSynEditFoldProvider.InfoListForFoldsAtTextIndex(ALine: Integer;
3209
NeedLen: Boolean): TSynEditFoldProviderNodeInfoList;
3213
i := FoldOpenCount(ALine);
3214
SetLength(Result, i);
3215
while i > 0 do begin
3217
Result[i] := InfoForFoldAtTextIndex(ALine, i, False, NeedLen);
2614
3269
if AStartIndex < top + ALineCount then CalculateMaps;
2617
procedure TSynEditFoldedView.LinesInsertedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
2619
LinesInsertedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
3272
//procedure TSynEditFoldedView.LinesInsertedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
3274
// LinesInsertedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
2622
procedure TSynEditFoldedView.LinesDeletedAtTextIndex(AStartIndex, ALineCount : Integer; SkipFixFolding : Boolean);
3277
procedure TSynEditFoldedView.LinesDeletedAtTextIndex(AStartIndex, ALineCount, ABytePos: Integer; SkipFixFolding : Boolean);
2623
3278
var top : Integer;
2625
3280
top := TopTextIndex;
2626
3281
// topline may get out of sync => synedit is always going to change it back
2627
fFoldTree.AdjustForLinesDeleted(AStartIndex+1, ALineCount);
3282
fFoldTree.AdjustForLinesDeleted(AStartIndex+1, ALineCount, ABytePos);
2628
3283
if not(SkipFixFolding) then
2629
3284
FixFoldingAtTextIndex(AStartIndex, AStartIndex+ALineCount+1)
2631
3286
if AStartIndex < top - ALineCount then CalculateMaps;
2634
procedure TSynEditFoldedView.LinesDeletedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
2636
LinesDeletedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
3289
//procedure TSynEditFoldedView.LinesDeletedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
3291
// LinesDeletedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
2639
3294
function TSynEditFoldedView.TextIndexToViewPos(aTextIndex : Integer) : Integer;
2798
3465
{$IFDEF SynFoldDebug}debugln(['FOLD-- CalculateMaps fTopLine:=', fTopLine, ' tpos=',tpos]);{$ENDIF}
2799
3466
cnt := fLines.Count;
2800
3469
for i := 0 to fLinesInWindow + 2 do begin
2801
3470
if (tpos > cnt) or (tpos < 0) then begin
2802
3471
// Past end of Text
2803
3472
fTextIndexList[i] := -1;
2804
fFoldTypeList[i] := [];
3473
NewCapability := [];
3474
NewClassifications := [];
2806
3476
fTextIndexList[i] := tpos - 1; // TextIndex is 0-based
2807
fFoldTypeList[i] := FFoldProvider.LineCapabilities[tpos - 1];
3477
NewCapability := FFoldProvider.LineCapabilities[tpos - 1];
3478
NewClassifications := FFoldProvider.LineClassification[tpos - 1];
2808
3479
if (node.IsInFold) then begin
2809
if (tpos = node.SourceLine) then
2810
include(fFoldTypeList[i], cfCollapsedFold)
2811
else if node.IsHide and (tpos + 1 = node.SourceLine) then
2812
include(fFoldTypeList[i], cfCollapsedHide);
3480
if (tpos = node.SourceLine) then begin
3481
include(NewCapability, cfCollapsedFold);
3482
include(NewClassifications, node.fData.Classification);
3484
else if node.IsHide and (tpos + 1 = node.SourceLine) then begin
3485
include(NewCapability, cfCollapsedHide);
3486
include(NewClassifications, node.fData.Classification);
2980
3660
while i < fLines.Count do begin
2981
3661
// Todo: Highlighter should return a list of types that can return default folded
2982
3662
// Currently PascalHl Type 2 = Region
2983
c := hl.FoldOpenCount(i, 2);
3663
c := hl.FoldBlockOpeningCount(i, 2);
2984
3664
if c > 0 then begin
2985
c := hl.FoldNodeInfoCount[i, [sfaOpen, sfaFold]];
3665
c := hl.FoldNodeInfo[i].CountEx([sfaOpen, sfaFold]);
2987
3667
while j < c do begin
2988
nd := hl.FoldNodeInfo[i, j, [sfaOpen, sfaFold]];
2989
if (sfaDefaultCollapsed in nd.FoldAction) and
2990
(not IsFoldedAtTextIndex(i, j))
3668
fldinf := FoldProvider.InfoForFoldAtTextIndex(i, j);
3669
if (fldinf.DefaultCollapsed) and (not IsFoldedAtTextIndex(i, j))
2992
3671
// TODO: detect default hide too
2993
3672
// currently always VisibleLines=1 => since region only folds
2994
fFoldTree.InsertNewFold(i+2, j, LengthForFoldAtTextIndex(i, j), 1);
3673
fFoldTree.InsertNewFold(i+2, j, fldinf.Column, fldinf.ColumnLen, fldinf.LineCount, 1,
3674
fldinf.Classification, fldinf.FoldTypeCompatible);
2995
3675
if Assigned(fOnFoldChanged) then
2996
3676
fOnFoldChanged(i);
3073
3758
NodeFoldType := scftFold;
3074
3759
if Node.SourceLineOffset = 0 then
3075
3760
NodeFoldType := scftHide;
3076
if not(sfaDefaultCollapsed in NdInfo.FoldAction) then // Currently skip default nodes
3761
if (NdInfo.FoldAction * [sfaInvalid, sfaDefaultCollapsed] = []) then // Currently skip default nodes
3077
3762
FoldCoderForType(NdInfo.FoldType).AddNode
3078
3763
(NdInfo.LogXStart, NdInfo.LineIndex, Node.FullCount, NodeFoldType);
3079
3765
Node := NodeIterator.Next;
3766
while Node.IsInFold and (Node.fData.Classification <> fncHighlighter) do
3767
Node := NodeIterator.Next;
3080
3768
if not Node.IsInFold then
3083
3771
NdInfo := NdiHelper1.Next;
3084
3772
while NdiHelper1.IsValid and (not NdiHelper1.IsAtNodeOpenPos(Node)) do begin
3085
3773
// Add unfolded nodes
3086
if not(sfaDefaultCollapsed in NdInfo.FoldAction) then // Currently skip default nodes
3774
if (NdInfo.FoldAction * [sfaInvalid, sfaDefaultCollapsed] = []) then // Currently skip default nodes
3087
3775
FoldCoderForType(NdInfo.FoldType).AddNode
3088
3776
(NdInfo.LogXStart, NdInfo.LineIndex, 0, scftOpen);
3089
3777
NdInfo := NdiHelper1.Next;
4009
// TODO: missing check, that hl-node is hideable
4010
fldinf := FoldProvider.InfoForFoldAtTextIndex(AStartIndex, ColIndex, IsHide);
3323
4011
if not NFolded.IsInFold then
3324
4012
fFoldTree.InsertNewFold(AStartIndex+1+AVisibleLines, ColIndex,
3325
LengthForFoldAtTextIndex(AStartIndex, ColIndex, IsHide),
4013
fldinf.Column, fldinf.ColumnLen, fldinf.LineCount,
4015
fldinf.Classification, fldinf.FoldTypeCompatible)
3328
4017
if (AVisibleLines=0) and (not NFolded.IsHide) then begin
3329
4018
// upgrade to hide
3330
4019
fFoldTree.RemoveFoldForNodeAtLine(NFolded, -1);
3331
4020
fFoldTree.InsertNewFold(AStartIndex+1, ColIndex,
3332
LengthForFoldAtTextIndex(AStartIndex, ColIndex, IsHide),
4021
fldinf.Column, fldinf.ColumnLen, fldinf.LineCount,
4023
fldinf.Classification, fldinf.FoldTypeCompatible);
3336
4026
then dec(ColIndex)
3447
4146
fFoldTree.Clear;
3449
4148
while i < fLines.Count do begin
3450
if (hl.FoldOpenCount(i, t) > 0)
3451
and (hl.FoldNestCount(i, t) > StartLevel) then begin
3452
c := hl.FoldOpenCount(i) -1;
3453
l := LengthForFoldAtTextIndex(i, c);
4149
if (hl.FoldBlockOpeningCount(i, t) > 0)
4150
and (hl.FoldBlockEndLevel(i, t) > StartLevel) then begin
4151
c := hl.FoldBlockOpeningCount(i) -1;
4152
fldinf := FoldProvider.InfoForFoldAtTextIndex(i, c);
3454
4153
// i is 0-based
3455
4154
// FoldTree is 1-based AND first line remains visble
3456
fFoldTree.InsertNewFold(i+2, c, l, 1); // TODO: hide too? currently VisibleLines=1
4155
fFoldTree.InsertNewFold(i+2, c, fldinf.Column, fldinf.ColumnLen, fldinf.LineCount, 1,
4156
fldinf.Classification, fldinf.FoldTypeCompatible); // TODO: hide too? currently VisibleLines=1
3457
4157
if IgnoreNested then
4158
i := i + fldinf.LineCount;
3493
FldLine, FldIndex, FldLen, FldCol: Integer;
3494
MaxCol, CurLen: Integer;
3495
PrevFldLine: Integer;
4194
FldSrcLine, FldSrcIndex, FLdNodeLine, FldLen, FndLen: Integer;
4195
i, j, CurLen: Integer;
3496
4196
SubTree: TSynTextFoldAVLTree;
4198
{$IFDEF SynFoldDebug}try DebugLnEnter(['>>FOLD-- DoFixFolding: doStart=', doStart, ' AMinEnd=',AMinEnd]);{$ENDIF}
4199
{$IFDEF SynFoldDebug}aFoldTree.Debug;{$ENDIF}
3499
4200
Result := False;
4201
FldSrcLine := doStart;
3501
4202
while node.IsInFold do begin
3502
PrevFldLine := FldLine;
3503
FldLine := node.SourceLine; // the 1-based cfCollapsed (last visible) Line (or 1st hidden)
3504
FldIndex := FldLine - 1;
4203
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- Node StartLine=', node.StartLine, ' FoldColumn=', node.FoldColumn, ' FoldIndex=', node.FoldIndex, ' FullCount=', node.FullCount, ' Classification=', dbgs(node.Classification)]);{$ENDIF}
4204
FldSrcLine := node.SourceLine; // the 1-based cfCollapsed (last visible) Line (or 1st hidden)
4205
FLdNodeLine := node.StartLine; // the 1 based, first hidden line
4206
FldSrcIndex := FldSrcLine - 1;
3505
4207
FldLen := node.FullCount;
3506
4208
if (FldLen <= 0) then begin
3507
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- FixFolding: Remove node with len<0 FldLine=', FldLine]);{$ENDIF}
4209
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- FixFolding: Remove node with len<0 FldSrcLine=', FldSrcLine]);{$ENDIF}
3508
4210
DoRemoveNode(node);
3512
if (FldLine > PrevFldLine) then
4214
//{$IFDEF SynAssertFold}
4215
//With mixed fold/hide => line goes up/down
4216
//SynAssert(FldSrcLine >= SrcLineForFldInfos, 'TSynEditFoldedView.FixFolding: FoldLine went backwards now %d was %d', [FldSrcLine, SrcLineForFldInfos]);
4218
if (FldSrcLine <> SrcLineForFldInfos) then begin
4220
SrcLineForFldInfos := FldSrcLine;
3514
// check the fold-length
3515
MaxCol := FoldProvider.FoldOpenCount(FldIndex) - 1;
3516
FldCol := node.FoldIndex;
3517
IsHide := node.SourceLineOffset = 0;
3518
if (FldCol < AtColumn) then FldCol := AtColumn;
3519
if (FldCol <= MaxCol) and (FldCol >= AtColumn) and
3520
(FldLen = LengthForFoldAtTextIndex(FldIndex, FldCol, IsHide)) then begin
3523
else if (FldCol - 1 <= MaxCol) and (FldCol > AtColumn) and (FldCol > 0) and
3524
(FldLen = LengthForFoldAtTextIndex(FldIndex, FldCol - 1, IsHide)) then begin
3528
else if (FldCol + 1 <= MaxCol) and (FldCol + 1 >= AtColumn) and
3529
(FldLen = LengthForFoldAtTextIndex(FldIndex, FldCol + 1, IsHide)) then begin
4222
// AtColumn is used for nodes, behing the HLs index-range (fncHighlighterEx, fncBlockSelection)
4223
// TODO: At Colum may be wrong for mixed fold/hide
4224
FldInfos := FoldProvider.InfoListForFoldsAtTextIndex(FldSrcIndex, False);
4225
MaxCol := length(FldInfos)-1;
4226
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- Got FldInfos for FldSrcIndex=', FldSrcIndex, ' MaxCol=', MaxCol]);{$ENDIF}
3536
if CurLen <> FldLen then begin
3537
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- FixFolding: Remove node with len<>len FldLine=', FldLine, ' curlen=',CurLen, ' FldLen=',FldLen]);{$ENDIF}
4229
if node.fData.Classification in [fncHighlighter, fncHighlighterEx] then begin
4230
// find node in list
4232
while (i < MaxCol) do begin
4234
if (FldInfos[i].Classification <> fncHighlighter) or
4235
(FldInfos[i].FoldTypeCompatible <> node.fData.FoldTypeCompatible)
4239
j := abs(FldInfos[i].Column - node.FoldColumn);
4240
if (j > 0) and (j < node.FoldColumnLen) then begin
4242
FndLen := FoldProvider.FoldLineLength(FldSrcIndex, i);
4243
if node.IsHide then inc(FndLen);
4244
if FndLen <> node.FullCount then Continue;
4245
{$IFDEF SynFoldDebug}debugln('******** FixFolding: Adjusting x pos');{$ENDIF}
4246
//FldInfos[i].Column := node.FoldColumn;
4248
if (FndLen > 0) or (FldInfos[i].Column = node.FoldColumn) then begin
4249
if FndLen < 0 then begin
4250
FndLen := FoldProvider.FoldLineLength(FldSrcIndex, i);
4251
if node.IsHide then inc(FndLen);
4253
if abs(FndLen - node.FullCount) > 1 then continue;
4254
if (node.fData.Classification <> fncHighlighter) or
4255
(node.FoldColumn <> FldInfos[i].Column) or
4256
(node.FoldIndex <> i)
4259
{$IFDEF SynFoldDebug}if (node.fData.Classification <> fncHighlighter) then debugln(['>>FOLD-- FixFolding: set Node to fncHighlighter (FOUND) FldSrcLine=', FldSrcLine]);{$ENDIF}
4260
node.fData.Classification := fncHighlighter;
4261
node.FoldColumn := FldInfos[i].Column;
4262
node.fData.FoldIndex := i;
4267
if i = MaxCol then begin
4268
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- FixFolding: set Node to fncHighlighterEx (NOT FOUND) FldSrcLine=', FldSrcLine]);{$ENDIF}
4269
node.fData.Classification := fncHighlighterEx;
4270
node.fData.FoldIndex := MaxCol + AtColumn;
4276
if node.fData.FoldIndex <> MaxCol + AtColumn then
4278
node.fData.FoldIndex := MaxCol + AtColumn;
3541
node.fData.FoldIndex := FldCol;
3542
AtColumn := FldCol + 1;
3544
4282
if (node.fData.Nested <> nil) then begin
3545
SubTree := doFoldTree.TreeForNestedNode(node.fData, FldLine+1);
4283
SubTree := doFoldTree.TreeForNestedNode(node.fData, FLdNodeLine);
3546
4284
CurLen := node.MergedLineCount;
3547
if DoFixFolding(FldLine, FldLine + CurLen + 1, AtColumn, SubTree, SubTree.FindFirstFold)
4285
if DoFixFolding(FldSrcLine, FLdNodeLine + CurLen, AtColumn, SubTree, SubTree.FindFirstFold)
3549
4287
if CurLen > FldLen then begin
3550
4288
node.fData.MergedLineCount:= max(node.FullCount,
3631
4366
if (ACount < 0) and (AIndex < fNeedFixFrom) then inc(fNeedFixFrom, ACount);
3632
4367
if (ACount > 0) and (AIndex < fNeedFixMinEnd) then inc(fNeedFixMinEnd, ACount);
4369
if fLines.IsInEditAction then exit;
3635
then LinesDeletedAtTextIndex(AIndex, -ACount, true)
3636
else LinesInsertedAtTextIndex(AIndex, ACount, true);
4371
then LinesDeletedAtTextIndex(AIndex+1, -ACount, 1, true)
4372
else LinesInsertedAtTextIndex(AIndex+1, ACount, 1, true);
4373
{$IFDEF SynFoldDebug}finally DebugLnExit(['<< FOLD-- LineCountChanged']); end;{$ENDIF}
4376
procedure TSynEditFoldedView.LinesCleared(Sender: TObject);
4381
procedure TSynEditFoldedView.LineEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount,
4382
aLineBrkCnt: Integer; aText: String);
4384
{$IFDEF SynFoldDebug}try DebugLnEnter(['>> FOLD-- LineEditied aLinePos=', aLinePos, ' aBytePos=', aBytePos, ' Acount=',ACount, ' aLineBrkCnt=',aLineBrkCnt]);{$ENDIF}
4386
then LinesDeletedAtTextIndex(aLinePos, -aLineBrkCnt, ABytePos, true)
4387
else if aLineBrkCnt > 0
4388
then LinesInsertedAtTextIndex(aLinePos, aLineBrkCnt, ABytePos, true)
4390
fFoldTree.AdjustColumn(aLinePos, aBytePos, aCount);
4391
//if not(SkipFixFolding) then FixFoldingAtTextIndex(AStartIndex, AStartIndex+ALineCount+1)
4393
//if aLinePos < top + ALineCount then CalculateMaps;
4395
{$IFDEF SynFoldDebug}finally DebugLnExit(['<< FOLD-- LineEditied']); end;{$ENDIF}
3639
4398
procedure TSynEditFoldedView.FixFoldingAtTextIndex(AStartIndex: Integer; AMinEndLine : Integer);
3649
4408
hl := TSynCustomFoldHighlighter(HighLighter);
3650
4409
if not assigned(hl) then
3652
Result := hl.FoldNestCount(AStartIndex-1) + FoldProvider.FoldOpenCount(AStartIndex);
4411
Result := hl.FoldBlockEndLevel(AStartIndex-1, AType) + FoldProvider.FoldOpenCount(AStartIndex);
3655
function TSynEditFoldedView.OpenFoldInfo(aStartIndex, ColIndex: Integer): TFoldViewNodeInfo;
4414
function TSynEditFoldedView.OpenFoldInfo(aStartIndex, ColIndex: Integer; AType: Integer = 0): TFoldViewNodeInfo;
3657
4416
hl: TSynCustomFoldHighlighter;
3658
4417
TypeCnt, Lvl: Integer;
3659
4418
EndLvl, CurLvl: Array of integer;
3660
i, t, n, o: Integer;
4419
i, c, t, n, o: Integer;
3661
4420
nd: TSynFoldNodeInfo;
3662
4421
procedure GetEndLvl(l: Integer);
3663
4422
var i: integer;
3665
for i := 1 to TypeCnt do begin
3666
EndLvl[i] := hl.FoldNestCount(l-1, i);
3667
EndLvl[i] := EndLvl[i] + FoldProvider.FoldOpenCount(l, i);
3668
CurLvl[i] := EndLvl[i];
4424
if AType = 0 then begin;
4425
for i := 1 to TypeCnt do begin
4426
EndLvl[i] := hl.FoldBlockEndLevel(l-1, i);
4427
EndLvl[i] := EndLvl[i] + FoldProvider.FoldOpenCount(l, i);
4428
CurLvl[i] := EndLvl[i];
4432
EndLvl[0] := hl.FoldBlockEndLevel(l-1, AType);
4433
EndLvl[0] := EndLvl[0] + FoldProvider.FoldOpenCount(l, AType);
4434
CurLvl[0] := EndLvl[0];
3672
4438
hl := TSynCustomFoldHighlighter(HighLighter);
3673
4439
if not assigned(hl) then
3676
TypeCnt := hl.FoldTypeCount;
3677
Lvl := hl.FoldNestCount(AStartIndex-1);
4445
TypeCnt := hl.FoldTypeCount;
4446
Lvl := hl.FoldBlockEndLevel(AStartIndex-1, AType);
3679
4447
if ColIndex >= Lvl then begin
3680
4448
n := ColIndex - Lvl;
3681
o := hl.FoldNodeInfoCount[aStartIndex, [sfaOpen, sfaFold]];
3682
nd := hl.FoldNodeInfo[aStartIndex, n, [sfaOpen, sfaFold]];
4449
if AType = 0 then begin
4450
o := hl.FoldNodeInfo[aStartIndex].CountEx([sfaOpen, sfaFold]);
4451
nd := hl.FoldNodeInfo[aStartIndex].NodeInfoEx(n, [sfaOpen, sfaFold]);
4454
o := hl.FoldNodeInfo[aStartIndex].CountEx([sfaOpen],AType);
4455
nd := hl.FoldNodeInfo[aStartIndex].NodeInfoEx(n, [sfaOpen], AType);
3685
4459
SetLength(EndLvl, TypeCnt+1);
3686
4460
SetLength(CurLvl, TypeCnt+1);
3687
4461
GetEndLvl(aStartIndex);
3688
aStartIndex := aStartIndex + i;
4462
aStartIndex := aStartIndex;
3689
4463
while (ColIndex < Lvl) and (aStartIndex > 0) do begin
3690
4464
dec(aStartIndex);
3691
o := hl.FoldOpenCount(AStartIndex);
3692
if (o > 0) or (hl.FoldCloseCount(aStartIndex) > 0) then begin
4465
o := hl.FoldBlockOpeningCount(AStartIndex, AType);
4466
if (o > 0) or (hl.FoldBlockClosingCount(aStartIndex, AType) > 0) then begin
3694
for i := hl.FoldNodeInfoCount[aStartIndex, []] - 1 downto 0 do begin
3695
nd := hl.FoldNodeInfo[aStartIndex, i, []];
3696
if not(sfaFold in nd.FoldAction) then
4468
c := hl.FoldNodeInfo[aStartIndex].CountEx([], AType) - 1;
4469
for i := c downto 0 do begin
4470
nd := hl.FoldNodeInfo[aStartIndex].NodeInfoEx(i, [], AType);
4471
if (AType = 0) and not(sfaFold in nd.FoldAction) then
3699
4477
if sfaOpen in nd.FoldAction then begin
3701
4479
dec(CurLvl[t]);