diff --git a/components/synedit/syneditfoldedview.pp b/components/synedit/syneditfoldedview.pp index 6e613503a9..ca5b09887f 100644 --- a/components/synedit/syneditfoldedview.pp +++ b/components/synedit/syneditfoldedview.pp @@ -173,7 +173,7 @@ type TFoldViewNodeInfo = record HNode: TSynFoldNodeInfo; Text, Keyword: String; - LineNum, ColIndex, OpenIndex: Integer; + LineNum, ColIndex: Integer; OpenCount: Integer; Folded: boolean; end; @@ -2170,36 +2170,72 @@ end; function TSynEditFoldedView.OpenFoldInfo(aStartIndex, ColIndex: Integer): TFoldViewNodeInfo; var hl: TSynCustomFoldHighlighter; - n, o: Integer; + TypeCnt, Lvl: Integer; + EndLvl, CurLvl: Array of integer; + i, t, n, o: Integer; nd: TSynFoldNodeInfo; + procedure GetEndLvl(l: Integer); + var i: integer; + begin + for i := 1 to TypeCnt do begin + EndLvl[i] := hl.FoldNestCount(l-1, i); + EndLvl[i] := EndLvl[i] + hl.FoldOpenCount(l, i); + CurLvl[i] := EndLvl[i]; + end + end; begin if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter)) then exit; hl := TSynCustomFoldHighlighter(FHighLighter); hl.CurrentLines := fLines; - n := hl.FoldNestCount(AStartIndex-1); - while (ColIndex < n) do begin + TypeCnt := hl.FoldTypeCount; + + Lvl := hl.FoldNestCount(AStartIndex-1); + i := 0; + if ColIndex >= Lvl then begin + // search current line + Lvl := Lvl + hl.FoldOpenCount(aStartIndex); + i := 1; + end; + SetLength(EndLvl, TypeCnt+1); + SetLength(CurLvl, TypeCnt+1); + GetEndLvl(aStartIndex); + GetEndLvl(aStartIndex); + aStartIndex := aStartIndex + i; + while (ColIndex < Lvl) and (aStartIndex > 0) do begin dec(aStartIndex); - n := hl.FoldNestCount(AStartIndex-1); + if (hl.FoldOpenCount(aStartIndex) > 0) or + (hl.FoldCloseCount(aStartIndex) > 0) then begin + o := hl.FoldOpenCount(AStartIndex); + n := o; + for i := hl.FoldNodeInfoCount[aStartIndex] - 1 downto 0 do begin + nd := hl.FoldNodeInfo[aStartIndex, i]; + t := nd.FoldGroup; + if sfaOpen in nd.FoldAction then begin + dec(n); + dec(CurLvl[t]); + if CurLvl[t] < EndLvl[t] then begin + dec(EndLvl[t]); + dec(Lvl); + if ColIndex = Lvl then begin + break; + end; + end; + end else + if sfaClose in nd.FoldAction then begin + inc(CurLvl[t]); + end; + end; + end + else + if hl.FoldNestCount(AStartIndex-1) = 0 then break; end; - ColIndex := ColIndex - n; - o := hl.FoldOpenCount(AStartIndex); - Result.OpenCount := o; - n := hl.FoldNodeInfoCount[aStartIndex] - 1; - while (o > ColIndex) and (n >= 0) do begin - nd := hl.FoldNodeInfo[aStartIndex, n]; - if sfaInvalid in nd.FoldAction then break; - if sfaClose in nd.FoldAction then inc(o); - if sfaOpen in nd.FoldAction then dec(o); - dec(n); - end; - inc(n); Result.HNode := nd; + Result.OpenCount := o; Result.Text := fLines[aStartIndex]; Result.Keyword := copy(Result.Text, 1 + nd.LogXStart, nd.LogXEnd-nd.LogXStart); Result.LineNum := aStartIndex + 1; - Result.ColIndex := ColIndex; // for FoldAction - Result.OpenIndex := ColIndex; // for (2/3) + Result.ColIndex := n; Result.Folded := IsFoldedAtTextIndex(aStartIndex, ColIndex); end; diff --git a/components/synedit/synedithighlighterfoldbase.pas b/components/synedit/synedithighlighterfoldbase.pas index 1a6e65ba1b..49581268c1 100644 --- a/components/synedit/synedithighlighterfoldbase.pas +++ b/components/synedit/synedithighlighterfoldbase.pas @@ -110,6 +110,7 @@ type FoldLvlStart, FoldLvlEnd: Integer; FoldAction: TSynFoldActions; FoldType: Pointer; + FoldGroup: Integer; end; { TSynCustomFoldHighlighter } @@ -152,6 +153,7 @@ type 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; function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; virtual; @@ -317,6 +319,11 @@ begin Result := 0; end; +function TSynCustomFoldHighlighter.FoldTypeCount: integer; +begin + Result := 1; +end; + function TSynCustomFoldHighlighter.FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer; UseCloseNodes: boolean): integer; begin diff --git a/components/synedit/synguttercodefolding.pp b/components/synedit/synguttercodefolding.pp index 50c261d9f8..58dcf67bd1 100644 --- a/components/synedit/synguttercodefolding.pp +++ b/components/synedit/synguttercodefolding.pp @@ -203,7 +203,7 @@ begin s := s + copy(inf.Text, inf.HNode.LogXStart, 30 + (30 - length(s))); s2 := ''; if inf.OpenCount > 1 then - s2 := format(' (%d/%d)', [inf.OpenIndex+1, inf.OpenCount]); + s2 := format(' (%d/%d)', [inf.ColIndex+1, inf.OpenCount]); m := TMenuItem.Create(FPopUp); m.Caption := format('%4d %-12s %s', [ inf.LineNum, inf.Keyword+s2+':', s]); m.ShowAlwaysCheckable := true; diff --git a/components/synedit/synhighlighterpas.pp b/components/synedit/synhighlighterpas.pp index e324e62078..8a47d3c346 100644 --- a/components/synedit/synhighlighterpas.pp +++ b/components/synedit/synhighlighterpas.pp @@ -472,6 +472,7 @@ type 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; + function FoldTypeCount: integer; override; function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer; UseCloseNodes: boolean = false): integer; override; function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override; @@ -1890,6 +1891,7 @@ begin end; '{': if NestedComments then begin + fStringLen := 1; StartPascalCodeFoldBlock(cfbtNestedComment); end; end; @@ -1949,8 +1951,10 @@ begin break; end; '{': - if NestedComments then + if NestedComments then begin + fStringLen := 1; StartPascalCodeFoldBlock(cfbtNestedComment); + end; end; Inc(Run); until (Run>=fLineLen); @@ -2104,8 +2108,9 @@ begin else if NestedComments and (fLine[Run] = '(') and (fLine[Run + 1] = '*') then begin - Inc(Run,2); + fStringLen := 2; StartPascalCodeFoldBlock(cfbtNestedComment); + Inc(Run,2); end else Inc(Run); until (Run>=fLineLen) or (fLine[Run] in [#0, #10, #13]); @@ -2490,6 +2495,7 @@ end; function TSynPasSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; var inf, inf2: TSynPasRangeInfo; + r: TSynPasSynRange; begin Result := 0; if (AType <> 1) then begin @@ -2497,7 +2503,8 @@ begin inf2 := TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[ALineIndex - 1]; end; if (AType = 0) or (AType = 1) then - Result := EndPasFoldLevel(ALineIndex - 1) - MinimumPasFoldLevel(ALineIndex); + 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 @@ -2519,6 +2526,11 @@ begin Result := Result + inf.EndLevelIfDef; end; +function TSynPasSyn.FoldTypeCount: integer; +begin + Result := 3; +end; + function TSynPasSyn.FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer; UseCloseNodes: boolean): integer; var @@ -2686,6 +2698,14 @@ begin Node.FoldLvlStart := CurrentCodeFoldBlockLevel; Node.FoldLvlEnd := CurrentCodeFoldBlockLevel + EndOffs; Node.FoldType := Pointer(PtrInt(ABlockType)); + case ABlockType of + cfbtRegion: + node.FoldGroup := 2; + cfbtIfDef: + node.FoldGroup := 3; + else + node.FoldGroup := 1; + end; if ABlockType in PascalWordTrippletRanges then Node.FoldAction := [sfaMarkup] else @@ -2825,6 +2845,7 @@ begin then begin PasCodeFoldRange.DecLastLineCodeFoldLevelFix; dec(FStartCodeFoldBlockLevel); + if FCatchNodeInfo then dec(FNodeInfoCount); end; if (PasCodeFoldRange.PasFoldEndLevel < FPasStartLevel) and (FPasStartLevel > 0) @@ -3059,12 +3080,12 @@ begin FNodeInfoCount := 0; StartAtLineIndex(Line); fStringLen := 0; - i := LastLineFoldLevelFix(Line); + NextToEol; + i := LastLineFoldLevelFix(Line+1); while i < 0 do begin EndCodeFoldBlock; inc(i); end; - NextToEol; FCatchNodeInfo := False; FNodeInfoLine := Line; end;