mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-04 23:37:22 +01:00
Synedit/IDE: Added hiding of comment/region
git-svn-id: trunk@26814 -
This commit is contained in:
parent
8100a2780c
commit
86a9620e2c
@ -448,6 +448,7 @@ type
|
||||
FOnSpecialLineMarkup: TSpecialLineMarkupEvent;// needed, because bug fpc 11926
|
||||
FOnClickLink: TMouseEvent;
|
||||
FOnMouseLink: TSynMouseLinkEvent;
|
||||
FPendingFoldState: String;
|
||||
|
||||
procedure AquirePrimarySelection;
|
||||
function GetChangeStamp: int64;
|
||||
@ -2990,10 +2991,15 @@ begin
|
||||
if (iLine<=0) or (iLine>FTheLinesView.Count) then exit;
|
||||
dec(iLine);
|
||||
//DebugLn(['****** FoldAction at ',iLine,' scrline=',FFoldedLinesView.TextIndexToScreenLine(iLine), ' type ', SynEditCodeFoldTypeNames[FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]], ' view topline=',FFoldedLinesView.TopLine ]);
|
||||
case FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)] of
|
||||
cfCollapsed : FFoldedLinesView.UnFoldAtTextIndex(iLine);
|
||||
cfExpanded : FFoldedLinesView.FoldAtTextIndex(iLine);
|
||||
end;
|
||||
if FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]
|
||||
* [cfCollapsedFold, cfCollapsedHide] <> []
|
||||
then
|
||||
FFoldedLinesView.UnFoldAtTextIndex(iLine)
|
||||
else
|
||||
if FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]
|
||||
* [cfFoldStart] <> []
|
||||
then
|
||||
FFoldedLinesView.FoldAtTextIndex(iLine);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.FindNextUnfoldedLine(iLine: integer; Down: boolean
|
||||
@ -3001,9 +3007,12 @@ function TCustomSynEdit.FindNextUnfoldedLine(iLine: integer; Down: boolean
|
||||
// iLine is 1 based
|
||||
begin
|
||||
Result:=iLine;
|
||||
while (Result>0) and (Result<=FTheLinesView.Count)
|
||||
and (FFoldedLinesView.FoldedAtTextIndex[Result-1]) do
|
||||
if Down then inc(Result) else dec(Result);
|
||||
if Down then
|
||||
while (Result<FTheLinesView.Count) and (FFoldedLinesView.FoldedAtTextIndex[Result-1]) do
|
||||
inc(Result)
|
||||
else
|
||||
while (Result>1) and (FFoldedLinesView.FoldedAtTextIndex[Result-1]) do
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.CreateGutter(AOwner : TSynEditBase;
|
||||
@ -3317,7 +3326,7 @@ var
|
||||
LCLIntf.LineTo(dc, nRightEdge, rcLine.Bottom + 1);
|
||||
end;
|
||||
|
||||
if FFoldedLinesView.FoldType[CurLine] = cfCollapsed then
|
||||
if FFoldedLinesView.FoldType[CurLine] * [cfCollapsedFold, cfCollapsedHide] <> [] then
|
||||
begin
|
||||
FillFCol := Font.Color;
|
||||
FillBCol := colEditorBG;
|
||||
@ -4209,6 +4218,9 @@ begin
|
||||
Value := Max(Value, 1);
|
||||
if FFoldedLinesView.FoldedAtTextIndex[Value-1] then
|
||||
Value := FindNextUnfoldedLine(Value, False);
|
||||
if FFoldedLinesView.FoldedAtTextIndex[Value-1] then
|
||||
Value := FindNextUnfoldedLine(Value, True);
|
||||
Value := Min(Value, CurrentMaxTopLine);
|
||||
FFoldedLinesView.TopTextIndex := fTopLine - 1;
|
||||
if Value <> fTopLine then begin
|
||||
fTopLine := Value;
|
||||
@ -4757,6 +4769,8 @@ begin
|
||||
InvalidateLines(AIndex + 1, AIndex + 1 + ACount);
|
||||
InvalidateGutterLines(AIndex + 1, AIndex + 1 + ACount);
|
||||
FFoldedLinesView.FixFoldingAtTextIndex(AIndex, AIndex + ACount);
|
||||
if FPendingFoldState <> '' then
|
||||
SetFoldState(FPendingFoldState);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.ListCleared(Sender: TObject);
|
||||
@ -4789,8 +4803,8 @@ begin
|
||||
if eoAlwaysVisibleCaret in fOptions2 then
|
||||
MoveCaretToVisibleArea;
|
||||
UpdateScrollBars;
|
||||
if Index + 1 > ScreenRowToRow(LinesInWindow + 1) then exit;
|
||||
if Index + 1 < TopLine then Index := TopLine;
|
||||
if Index + 1 > Max(1, ScreenRowToRow(LinesInWindow + 1)) then exit;
|
||||
if Index + 1 < TopLine then Index := TopLine - 1;
|
||||
InvalidateLines(Index + 1, -1);
|
||||
InvalidateGutterLines(Index + 1, -1);
|
||||
end;
|
||||
@ -5093,10 +5107,22 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.SetFoldState(const AValue: String);
|
||||
begin
|
||||
if assigned(fHighlighter) then begin
|
||||
fHighlighter.CurrentLines := FTheLinesView;
|
||||
if fHighlighter.NeedScan then begin
|
||||
FPendingFoldState := AValue;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
if sfAfterLoadFromFileNeeded in fStateFlags then begin
|
||||
FPendingFoldState := AValue;
|
||||
exit;
|
||||
end;
|
||||
FFoldedLinesView.Lock;
|
||||
FFoldedLinesView.ApplyFoldDescription(0, 0, -1, -1, PChar(AValue), length(AValue), True);
|
||||
TopLine := TopLine; // Todo: reset topline on foldedview
|
||||
FFoldedLinesView.UnLock;
|
||||
FPendingFoldState := '';
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.SetMouseActions(const AValue: TSynEditMouseActions);
|
||||
@ -5555,6 +5581,7 @@ end;
|
||||
procedure TCustomSynEdit.SetHighlighter(const Value: TSynCustomHighlighter);
|
||||
begin
|
||||
if Value <> fHighlighter then begin
|
||||
FPendingFoldState := '';
|
||||
RemoveHooksFromHighlighter;
|
||||
if Assigned(Value) then begin
|
||||
Value.HookAttrChangeEvent(
|
||||
@ -5944,7 +5971,7 @@ begin
|
||||
end;
|
||||
ecEditorTop, ecSelEditorTop:
|
||||
begin
|
||||
FCaret.LineCharPos := Point(1, 1);
|
||||
FCaret.LineCharPos := Point(1, FFoldedLinesView.ViewPosToTextIndex(1)+1);
|
||||
end;
|
||||
ecEditorBottom, ecSelEditorBottom:
|
||||
begin
|
||||
@ -5955,7 +5982,7 @@ begin
|
||||
end;
|
||||
ecColSelEditorTop:
|
||||
begin
|
||||
FCaret.LinePos := 1;
|
||||
FCaret.LinePos := FFoldedLinesView.ViewPosToTextIndex(1)+1;
|
||||
end;
|
||||
ecColSelEditorBottom:
|
||||
begin
|
||||
@ -6517,6 +6544,8 @@ begin
|
||||
ScanRanges;
|
||||
FFoldedLinesView.UnfoldAll;
|
||||
FFoldedLinesView.CollapseDefaultFolds;
|
||||
if FPendingFoldState <> '' then
|
||||
SetFoldState(FPendingFoldState);
|
||||
TopLine := TopLine;
|
||||
end;
|
||||
end;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -312,6 +312,7 @@ type
|
||||
|
||||
procedure ScanRanges;
|
||||
function IdleScanRanges: Boolean; // Scan little by little during OnIdle; Return True, if more work avail
|
||||
function NeedScan: Boolean;
|
||||
procedure ScanAllRanges;
|
||||
procedure SetRange(Value: Pointer); virtual;
|
||||
procedure ResetRange; virtual;
|
||||
@ -1299,7 +1300,9 @@ begin
|
||||
end;
|
||||
StartIndex := CurrentRanges.NeedsReScanRealStartIndex; // include idle scanned
|
||||
CurrentRanges.ClearReScanNeeded;
|
||||
CurrentLines.SendHighlightChanged(StartIndex, EndIndex - StartIndex + 1);
|
||||
// Invalidate one line above, since folds can change depending on next line
|
||||
// TODO: only classes with end-fold-last-line
|
||||
CurrentLines.SendHighlightChanged(StartIndex - 1, EndIndex - StartIndex + 1);
|
||||
end;
|
||||
|
||||
function TSynCustomHighlighter.IdleScanRanges: Boolean;
|
||||
@ -1326,7 +1329,8 @@ begin
|
||||
StartIndex := CurrentRanges.NeedsReScanRealStartIndex; // include idle scanned
|
||||
//debugln(['=== IDLE SendHighlightChanged ',StartIndex,' - ',EndIndex]);
|
||||
CurrentRanges.ClearReScanNeeded;
|
||||
CurrentLines.SendHighlightChanged(StartIndex, EndIndex - StartIndex + 1);
|
||||
// Invalidate one line above, since folds can change depending on next line
|
||||
CurrentLines.SendHighlightChanged(StartIndex - 1, EndIndex - StartIndex + 1);
|
||||
exit;
|
||||
end
|
||||
else begin
|
||||
@ -1335,6 +1339,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynCustomHighlighter.NeedScan: Boolean;
|
||||
begin
|
||||
Result := (CurrentRanges.NeedsReScanStartIndex >= 0);
|
||||
end;
|
||||
|
||||
function TSynCustomHighlighter.PerformScan(StartIndex, EndIndex: Integer;
|
||||
ForceEndIndex: Boolean = False): Integer;
|
||||
var
|
||||
|
||||
@ -37,20 +37,58 @@ uses
|
||||
|
||||
type
|
||||
|
||||
TSynFoldAction = (sfaOpen, // At this node a new Fold can start
|
||||
sfaClose, // At this node a fold ends
|
||||
sfaMarkup, // This node can be highlighted, by the matching Word-Pair Markup
|
||||
sfaFold, // Part of a fold- or hide-able block (FoldConf.Enabled = True)
|
||||
sfaFoldFold, // Part of a fold-able block (FoldConf.Enabled = True / smFold in Modes)
|
||||
sfaFoldHide, // Part of a hide-able block (FoldConf.Enabled = True / smHide in Modes)
|
||||
sfaInvalid, // Wrong Index
|
||||
sfaDefaultCollapsed,
|
||||
sfaOneLineOpen, // Open, but closes on same line; *only* if hide-able has [sfaOpen, sfaFold]; always has [sfaFoldFold, sfaFoldHide]
|
||||
sfaOneLineClose, // Open, but closes on same line;
|
||||
sfaLastLineClose // Fold is incomplete, and closed at last line of file
|
||||
);
|
||||
TSynFoldActions = set of TSynFoldAction;
|
||||
|
||||
TSynFoldNodeInfo = record
|
||||
LineIndex: Integer;
|
||||
NodeIndex: Integer; // Indicates the position within the list of info nodes (depends on search-Filter)
|
||||
LogXStart, LogXEnd: Integer; // -1 previous line
|
||||
FoldLvlStart, FoldLvlEnd: Integer; // FoldLvl within each FoldGroup
|
||||
NestLvlStart, NestLvlEnd: Integer; // include disabled nodes, e.g markup (within each FoldGroup)
|
||||
FoldAction: TSynFoldActions;
|
||||
FoldType: Pointer; // e.g.cfbtBeginEnd, cfbtcfbtProcedure ...
|
||||
FoldGroup: Integer; // independend/overlapping folds, e.g begin/end; ifdef, region
|
||||
end;
|
||||
|
||||
TSynCustomFoldConfigMode = (fmFold, fmHide);
|
||||
TSynCustomFoldConfigModes = set of TSynCustomFoldConfigMode;
|
||||
|
||||
{ TSynCustomFoldConfig }
|
||||
|
||||
TSynCustomFoldConfig = class(TPersistent)
|
||||
private
|
||||
FEnabled: Boolean;
|
||||
FFoldActions: TSynFoldActions;
|
||||
FModes: TSynCustomFoldConfigModes;
|
||||
FOnChange: TNotifyEvent;
|
||||
FSupportedModes: TSynCustomFoldConfigModes;
|
||||
procedure SetFEnabled(const AValue: Boolean);
|
||||
procedure SetModes(const AValue: TSynCustomFoldConfigModes);
|
||||
protected
|
||||
procedure DoOnChange;
|
||||
public
|
||||
constructor Create;
|
||||
procedure Assign(Src: TSynCustomFoldConfig); reintroduce; virtual;
|
||||
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
||||
property SupportedModes: TSynCustomFoldConfigModes
|
||||
read FSupportedModes write FSupportedModes;
|
||||
// Actions representing the modes
|
||||
property FoldActions: TSynFoldActions read FFoldActions;
|
||||
published
|
||||
property Enabled: Boolean read FEnabled write SetFEnabled;
|
||||
property Modes: TSynCustomFoldConfigModes read FModes write SetModes default [fmFold];
|
||||
end;
|
||||
|
||||
{ TSynCustomCodeFoldBlock }
|
||||
@ -108,27 +146,6 @@ type
|
||||
|
||||
TSynCustomHighlighterRanges = class;
|
||||
|
||||
TSynFoldAction = (sfaOpen, // At this node a new Fold can start
|
||||
sfaClose, // At this node a fold ends
|
||||
sfaMarkup, // This node can be highlighted, by the matching Word-Pair Markup
|
||||
sfaFold, // Part of a foldable block
|
||||
sfaInvalid, // Wrong Index
|
||||
sfaDefaultCollapsed,
|
||||
sfaOneLineOpen, // Open, but closes on same line; does *not* have sfaOpen
|
||||
sfaOneLineClose // Open, but closes on same line; does *not* have sfaOpen
|
||||
);
|
||||
TSynFoldActions = set of TSynFoldAction;
|
||||
|
||||
TSynFoldNodeInfo = record
|
||||
LineIndex: Integer;
|
||||
NodeIndex: Integer; // Indicates the position within the list of info nodes (depends on search-Filter
|
||||
LogXStart, LogXEnd: Integer; // -1 previous line
|
||||
FoldLvlStart, FoldLvlEnd: Integer;
|
||||
FoldAction: TSynFoldActions;
|
||||
FoldType: Pointer;
|
||||
FoldGroup: Integer;
|
||||
end;
|
||||
|
||||
{ TSynCustomFoldHighlighter }
|
||||
|
||||
TSynCustomFoldHighlighter = class(TSynCustomHighlighter)
|
||||
@ -178,8 +195,9 @@ type
|
||||
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; virtual;
|
||||
function FoldTypeCount: integer; virtual;
|
||||
function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer;
|
||||
UseCloseNodes: boolean = false): integer; virtual;
|
||||
UseCloseNodes: boolean = false): integer; virtual; // TODO: could be deprecated ./ only child-classes
|
||||
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; virtual;
|
||||
function FoldEndLine(ALineIndex, FoldIndex: Integer): integer; virtual; // FoldEndLine, can be more than given by FoldLineLength, since Length my cut off early
|
||||
|
||||
// All fold-nodes
|
||||
property FoldNodeInfo[Line, Index: Integer; Filter: TSynFoldActions]: TSynFoldNodeInfo read GetFoldNodeInfo;
|
||||
@ -358,8 +376,18 @@ begin
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldLineLength(ALineIndex, FoldIndex: Integer): integer;
|
||||
begin
|
||||
Result := FoldLineLength(ALineIndex, FoldIndex);
|
||||
// check if fold last line of block (not mixed "end begin")
|
||||
if (EndFoldLevel(Result) > MinimumFoldLevel(Result)) then
|
||||
dec(Result);
|
||||
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
|
||||
Result := Result - ALineIndex;
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.FoldEndLine(ALineIndex, FoldIndex: Integer): integer;
|
||||
var
|
||||
i, lvl, cnt: Integer;
|
||||
lvl, cnt: Integer;
|
||||
e, m: Integer;
|
||||
begin
|
||||
//atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
|
||||
@ -367,20 +395,16 @@ begin
|
||||
e := EndFoldLevel(ALineIndex);
|
||||
m := MinimumFoldLevel(ALineIndex);
|
||||
lvl := Min(m+1+FoldIndex, e);
|
||||
i := ALineIndex + 1;
|
||||
while (i < cnt) and (MinimumFoldLevel(i) >= lvl) do inc(i);
|
||||
// check if fold last line of block (not mixed "end begin")
|
||||
// and not lastlinefix
|
||||
if (i = cnt) or (EndFoldLevel(i) > MinimumFoldLevel(i)) then
|
||||
dec(i);
|
||||
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
|
||||
Result := i - ALineIndex;
|
||||
Result := ALineIndex + 1;
|
||||
while (Result < cnt) and (MinimumFoldLevel(Result) >= lvl) do inc(Result);
|
||||
if (Result = cnt) then
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.GetFoldNodeInfoCount(Line: Integer;
|
||||
Filter: TSynFoldActions): Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.GetFoldConfig(Index: Integer): TSynCustomFoldConfig;
|
||||
@ -832,15 +856,35 @@ begin
|
||||
DoOnChange;
|
||||
end;
|
||||
|
||||
procedure TSynCustomFoldConfig.SetModes(const AValue: TSynCustomFoldConfigModes);
|
||||
begin
|
||||
if FModes = AValue then exit;
|
||||
FModes := AValue;
|
||||
FFoldActions := [];
|
||||
if AValue <> [] then FFoldActions := FFoldActions + [sfaFold];
|
||||
if fmFold in AValue then FFoldActions := FFoldActions + [sfaFoldFold];
|
||||
if fmHide in AValue then FFoldActions := FFoldActions + [sfaFoldHide];
|
||||
DoOnChange;
|
||||
end;
|
||||
|
||||
procedure TSynCustomFoldConfig.DoOnChange;
|
||||
begin
|
||||
if assigned(FOnChange) then
|
||||
FOnChange(self);
|
||||
end;
|
||||
|
||||
constructor TSynCustomFoldConfig.Create;
|
||||
begin
|
||||
Inherited;
|
||||
FSupportedModes := [fmFold];
|
||||
Modes := [fmFold];
|
||||
end;
|
||||
|
||||
procedure TSynCustomFoldConfig.Assign(Src: TSynCustomFoldConfig);
|
||||
begin
|
||||
Enabled := Src.Enabled;
|
||||
SupportedModes := Src.SupportedModes;
|
||||
Modes := Src.Modes;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -121,86 +121,64 @@ var
|
||||
|
||||
function FindEndNode(StartNode: TSynFoldNodeInfo;
|
||||
var YIndex, NIndex: Integer): TSynFoldNodeInfo;
|
||||
function SearchLine(ALineIdx: Integer; var ANodeIdx: Integer): TSynFoldNodeInfo;
|
||||
begin
|
||||
repeat
|
||||
inc(ANodeIdx);
|
||||
Result := HL.FoldNodeInfo[ALineIdx, ANodeIdx, [sfaMarkup]];
|
||||
until (sfaInvalid in Result.FoldAction)
|
||||
or (Result.NestLvlEnd <= StartNode.NestLvlStart);
|
||||
end;
|
||||
begin
|
||||
repeat
|
||||
inc(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex, []];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlEnd <= StartNode.FoldLvlStart);
|
||||
Result := SearchLine(YIndex, NIndex);
|
||||
if not (sfaInvalid in Result.FoldAction) then
|
||||
exit;
|
||||
|
||||
inc(YIndex);
|
||||
while (YIndex < LCnt) and
|
||||
(HL.MinimumFoldLevel(YIndex) > StartNode.FoldLvlStart) do
|
||||
while (YIndex < LCnt) and (HL.MinimumFoldLevel(YIndex) > StartNode.NestLvlStart) do
|
||||
inc(YIndex);
|
||||
if YIndex = LCnt then
|
||||
exit;
|
||||
|
||||
NIndex := -1;
|
||||
repeat
|
||||
inc(NIndex);
|
||||
Result:= HL.FoldNodeInfo[YIndex, NIndex, []];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlEnd <= StartNode.FoldLvlStart);
|
||||
if (Result.LogXEnd = 0) then
|
||||
Result := SearchLine(YIndex, NIndex);
|
||||
|
||||
if (Result.LogXEnd = 0) or (sfaLastLineClose in Result.FoldAction) then
|
||||
Result.FoldAction := [sfaInvalid]; // LastLine closed Node(maybe force-closed?)
|
||||
end;
|
||||
|
||||
function FindStartNode(EndNode: TSynFoldNodeInfo;
|
||||
var YIndex, NIndex: Integer): TSynFoldNodeInfo;
|
||||
function SearchLine(ALineIdx: Integer; var ANodeIdx: Integer): TSynFoldNodeInfo;
|
||||
begin
|
||||
repeat
|
||||
dec(ANodeIdx);
|
||||
Result := HL.FoldNodeInfo[ALineIdx, ANodeIdx, [sfaMarkup]];
|
||||
until (sfaInvalid in Result.FoldAction)
|
||||
or (Result.NestLvlStart <= EndNode.NestLvlEnd);
|
||||
end;
|
||||
begin
|
||||
repeat
|
||||
dec(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex, []];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlStart <= EndNode.FoldLvlEnd);
|
||||
Result := SearchLine(YIndex, NIndex);
|
||||
if not(sfaInvalid in Result.FoldAction) then
|
||||
exit;
|
||||
|
||||
dec(YIndex);
|
||||
while (YIndex >= 0) and (HL.MinimumFoldLevel(YIndex) > EndNode.FoldLvlEnd) do
|
||||
while (YIndex >= 0) and (HL.MinimumFoldLevel(YIndex) > EndNode.NestLvlEnd) do
|
||||
dec(YIndex);
|
||||
if YIndex < 0 then
|
||||
exit;
|
||||
NIndex := HL.FoldNodeInfoCount[YIndex, []];
|
||||
repeat
|
||||
dec(NIndex);
|
||||
Result:= HL.FoldNodeInfo[YIndex, NIndex, []];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlStart <= EndNode.FoldLvlEnd);
|
||||
end;
|
||||
|
||||
function FindMultiNode(OrigNode: TSynFoldNodeInfo;
|
||||
var YIndex, NIndex: Integer): TSynFoldNodeInfo;
|
||||
var
|
||||
i: LongInt;
|
||||
begin
|
||||
i := NIndex;
|
||||
repeat
|
||||
dec(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex, []];
|
||||
if (sfaMarkup in Result.FoldAction) and
|
||||
(Result.LogXStart = OrigNode.LogXStart) and (Result.LogXEnd > 0)
|
||||
then
|
||||
exit;
|
||||
until (sfaInvalid in Result.FoldAction) or (Result.LogXStart <> OrigNode.LogXStart);
|
||||
NIndex := i;
|
||||
repeat
|
||||
inc(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex, []];
|
||||
if (sfaMarkup in Result.FoldAction) and
|
||||
(Result.LogXStart = OrigNode.LogXStart) and (Result.LogXEnd > 0)
|
||||
then
|
||||
exit;
|
||||
until (sfaInvalid in Result.FoldAction) or (Result.LogXStart <> OrigNode.LogXStart);
|
||||
Result.FoldAction := [sfaInvalid];
|
||||
NIndex := HL.FoldNodeInfoCount[YIndex, [sfaMarkup]];
|
||||
Result := SearchLine(YIndex, NIndex);
|
||||
|
||||
if (Result.LogXEnd = 0) or (sfaLastLineClose in Result.FoldAction) then
|
||||
Result.FoldAction := [sfaInvalid]; // LastLine closed Node(maybe force-closed?)
|
||||
end;
|
||||
|
||||
var
|
||||
LogCaretXY: TPoint;
|
||||
i, i2, i3, y, y1, y2: integer;
|
||||
Node1, Node2, Node3: TSynFoldNodeInfo;
|
||||
i, i2, y, y2: integer;
|
||||
Node1, Node2, Node3, TmpNode: TSynFoldNodeInfo;
|
||||
begin
|
||||
Word1.Y := -1;
|
||||
Word2.Y := -1;
|
||||
@ -209,74 +187,83 @@ begin
|
||||
(PhysCaret.Y < 1) or (PhysCaret.Y > Lines.Count) or (PhysCaret.X < 1)
|
||||
then
|
||||
Exit;
|
||||
|
||||
if not (FHighlighter is TSynCustomFoldHighlighter) then
|
||||
exit;
|
||||
|
||||
hl := TSynCustomFoldHighlighter(FHighlighter);
|
||||
LogCaretXY := Lines.PhysicalToLogicalPos(PhysCaret);
|
||||
y := LogCaretXY.Y - 1;
|
||||
LCnt := Lines.Count;
|
||||
HL.CurrentLines := Lines;
|
||||
i := 0;
|
||||
repeat
|
||||
Node1 := HL.FoldNodeInfo[y, i, []];
|
||||
inc(i);
|
||||
until (sfaInvalid in Node1.FoldAction) or
|
||||
((Node1.LogXEnd >= LogCaretXY.X - 1) and (Node1.LogXEnd > 0));
|
||||
while not(Node1.FoldAction * [sfaInvalid, sfaMarkup] <> [])
|
||||
and (Node1.LogXStart <= LogCaretXY.X - 1) do
|
||||
begin
|
||||
Node1 := HL.FoldNodeInfo[y, i, []];
|
||||
inc(i);
|
||||
end;
|
||||
if (Node1.LogXStart > LogCaretXY.X - 1) or not(sfaMarkup in Node1.FoldAction) then
|
||||
exit;
|
||||
dec(i);
|
||||
|
||||
if sfaOpen in Node1.FoldAction then begin
|
||||
y1 := y;
|
||||
i := 0;
|
||||
Node1 := HL.FoldNodeInfo[y, i, [sfaMarkup]];
|
||||
while not(sfaInvalid in Node1.FoldAction) and (Node1.LogXEnd < LogCaretXY.X-1) do
|
||||
begin
|
||||
inc(i);
|
||||
Node1 := HL.FoldNodeInfo[y, i, [sfaMarkup]];
|
||||
end;
|
||||
if (Node1.LogXStart > LogCaretXY.X - 1) or (sfaInvalid in Node1.FoldAction) then
|
||||
exit;
|
||||
|
||||
if Node1.FoldAction * [sfaOpen, sfaOneLineOpen] <> [] then begin
|
||||
//y1 := y;
|
||||
Node2 := FindEndNode(Node1, y, i);
|
||||
if (sfaInvalid in Node2.FoldAction) or not(sfaMarkup in Node2.FoldAction) then
|
||||
if (sfaInvalid in Node2.FoldAction) then
|
||||
exit;
|
||||
y2 := y;
|
||||
i2 := i;
|
||||
i3 := i;
|
||||
Node3 := FindMultiNode(Node2, y, i3);
|
||||
end else begin
|
||||
Node2 := Node1;
|
||||
i3 := i;
|
||||
Node3 := FindMultiNode(Node2, y, i3);
|
||||
y2 := y;
|
||||
i2 := i;
|
||||
Node1 := FindStartNode(Node2, y, i);
|
||||
if (sfaInvalid in Node1.FoldAction) or not(sfaMarkup in Node1.FoldAction) then
|
||||
Node1 := FindStartNode(Node2, y, i); // skip = endnode => do not skup anything
|
||||
if (sfaInvalid in Node1.FoldAction) then
|
||||
exit;
|
||||
y1 := y;
|
||||
end;
|
||||
|
||||
Node3.FoldAction := [sfaInvalid];
|
||||
i := i2;
|
||||
y := y2;
|
||||
if not(sfaInvalid in Node3.FoldAction) then
|
||||
Node3 := FindStartNode(Node3, y, i);
|
||||
TmpNode := HL.FoldNodeInfo[y2, i2 - 1, [sfaMarkup]];
|
||||
if (not (sfaInvalid in TmpNode.FoldAction)) and
|
||||
(TmpNode.LogXStart = Node2.LogXStart) and (TmpNode.LogXEnd = Node2.LogXEnd)
|
||||
then begin
|
||||
// tripple node => 3rd start after current start
|
||||
TmpNode := FindStartNode(TmpNode, y2, i2);
|
||||
if (not (sfaInvalid in TmpNode.FoldAction)) then begin
|
||||
Node3 := Node2;
|
||||
Node2 := TmpNode;
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
y2 := y;
|
||||
i2 := i;
|
||||
TmpNode := HL.FoldNodeInfo[y2, i2 + 1, [sfaMarkup]];
|
||||
if (not (sfaInvalid in TmpNode.FoldAction)) and
|
||||
(TmpNode.LogXStart = Node2.LogXStart) and (TmpNode.LogXEnd = Node2.LogXEnd)
|
||||
then begin
|
||||
// tripple node => 3rd start before current start
|
||||
TmpNode := FindStartNode(TmpNode, y2, i2);
|
||||
if (not (sfaInvalid in TmpNode.FoldAction)) then begin
|
||||
Node3 := Node2;
|
||||
Node2 := Node1;
|
||||
Node1 := TmpNode;
|
||||
end;
|
||||
end
|
||||
end;
|
||||
|
||||
Word1.Y := y1 + 1;
|
||||
Word1.Y := Node1.LineIndex + 1;
|
||||
Word1.X := Node1.LogXStart + 1;
|
||||
Word1.X2 := Node1.LogXEnd + 1;
|
||||
Word2.Y := y2 + 1;
|
||||
Word2.Y := Node2.LineIndex + 1;
|
||||
Word2.X := Node2.LogXStart + 1;
|
||||
Word2.X2 := Node2.LogXEnd + 1;
|
||||
if (sfaMarkup in Node3.FoldAction) and not(sfaInvalid in Node3.FoldAction) then
|
||||
if not(sfaInvalid in Node3.FoldAction) then
|
||||
begin
|
||||
Word3 := Word2;
|
||||
if i3 > i2 then begin
|
||||
Word2 := Word1;
|
||||
Word1.Y := y + 1;
|
||||
Word1.X := Node3.LogXStart + 1;
|
||||
Word1.X2 := Node3.LogXEnd + 1;
|
||||
end else begin
|
||||
Word2.Y := y + 1;
|
||||
Word2.X := Node3.LogXStart + 1;
|
||||
Word2.X2 := Node3.LogXEnd + 1;
|
||||
end;
|
||||
Word3.Y := Node3.LineIndex + 1;
|
||||
Word3.X := Node3.LogXStart + 1;
|
||||
Word3.X2 := Node3.LogXEnd + 1;
|
||||
end;
|
||||
|
||||
if Word1.Y > 0 then begin
|
||||
|
||||
@ -44,8 +44,12 @@ type
|
||||
FMouseActionsExpanded: TSynEditMouseActions;
|
||||
FPopUp: TPopupMenu;
|
||||
FMenuInf: Array of TFoldViewNodeInfo;
|
||||
FIsFoldHidePreviousLine: Boolean;
|
||||
procedure SetMouseActionsCollapsed(const AValue: TSynEditMouseActions);
|
||||
procedure SetMouseActionsExpanded(const AValue: TSynEditMouseActions);
|
||||
function FoldTypeForLine(AScreenLine: Integer): TSynEditFoldLineCapability;
|
||||
function IsFoldHidePreviousLine(AScreenLine: Integer): Boolean;
|
||||
function IsSingleLineHide(AScreenLine: Integer): Boolean;
|
||||
protected
|
||||
procedure DoChange(Sender: TObject); override;
|
||||
procedure PopClicked(Sender: TObject);
|
||||
@ -91,6 +95,62 @@ begin
|
||||
FMouseActionsExpanded.Assign(AValue);
|
||||
end;
|
||||
|
||||
function TSynGutterCodeFolding.FoldTypeForLine(AScreenLine: Integer): TSynEditFoldLineCapability;
|
||||
var
|
||||
tmp, tmp2: TSynEditFoldLineCapabilities;
|
||||
begin
|
||||
tmp := FFoldView.FoldType[AScreenLine];
|
||||
tmp2 := FFoldView.FoldType[AScreenLine-1];
|
||||
FIsFoldHidePreviousLine := False;
|
||||
|
||||
if (AScreenLine = 0) and (FFoldView.TextIndexToViewPos(FFoldView.TextIndex[0]) = 1) and
|
||||
(cfCollapsedHide in tmp2)
|
||||
then begin
|
||||
Result := cfCollapsedHide;
|
||||
FIsFoldHidePreviousLine := True;
|
||||
end
|
||||
//if tmp * [cfHideStart, cfFoldStart, cfCollapsedFold] = [cfHideStart, cfFoldStart, cfCollapsedFold]
|
||||
// then Result := cfHideStart
|
||||
else if cfCollapsedFold in tmp then Result := cfCollapsedFold
|
||||
else if cfCollapsedHide in tmp then Result := cfCollapsedHide
|
||||
else if cfFoldStart in tmp then Result := cfFoldStart
|
||||
else if cfHideStart in tmp then Result := cfHideStart
|
||||
else if cfFoldEnd in tmp then Result := cfFoldEnd
|
||||
else if cfFoldBody in tmp then Result := cfFoldBody
|
||||
else
|
||||
Result := cfNone;
|
||||
|
||||
if Result in [cfFoldBody, cfFoldEnd] then begin
|
||||
tmp := FFoldView.FoldType[AScreenLine - 1];
|
||||
if tmp * [cfHideStart, cfFoldStart, cfCollapsedFold, cfCollapsedHide]
|
||||
= [cfHideStart, cfFoldStart]
|
||||
then begin
|
||||
FIsFoldHidePreviousLine := True;
|
||||
Result := cfHideStart // hide for previous line
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynGutterCodeFolding.IsFoldHidePreviousLine(AScreenLine: Integer): Boolean;
|
||||
begin
|
||||
FoldTypeForLine(AScreenLine);
|
||||
Result := FIsFoldHidePreviousLine;
|
||||
end;
|
||||
|
||||
function TSynGutterCodeFolding.IsSingleLineHide(AScreenLine: Integer): Boolean;
|
||||
var
|
||||
tmp: TSynEditFoldLineCapabilities;
|
||||
begin
|
||||
Result := False;
|
||||
tmp := FFoldView.FoldType[AScreenLine];
|
||||
if tmp * [cfHideStart, cfFoldStart, cfCollapsedFold] =
|
||||
[cfHideStart, cfFoldStart, cfCollapsedFold]
|
||||
then
|
||||
Result := True;
|
||||
if cfSingleLineHide in tmp then
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure TSynGutterCodeFolding.DoChange(Sender: TObject);
|
||||
begin
|
||||
if AutoSize then
|
||||
@ -152,14 +212,18 @@ end;
|
||||
|
||||
function TSynGutterCodeFolding.MaybeHandleMouseAction(var AnInfo: TSynEditMouseActionInfo;
|
||||
HandleActionProc: TSynEditMouseActionHandler): Boolean;
|
||||
var
|
||||
tmp: TSynEditFoldLineCapability;
|
||||
begin
|
||||
Result := False;
|
||||
case FFoldView.FoldType[FFoldView.TextIndexToScreenLine(AnInfo.NewCaret.LinePos-1)] of
|
||||
cfCollapsed :
|
||||
tmp := FoldTypeForLine(FFoldView.TextIndexToScreenLine(AnInfo.NewCaret.LinePos-1));
|
||||
case tmp of
|
||||
cfCollapsedFold, cfCollapsedHide:
|
||||
Result := HandleActionProc(MouseActionsCollapsed, AnInfo);
|
||||
cfExpanded :
|
||||
cfFoldStart, cfHideStart:
|
||||
Result := HandleActionProc(MouseActionsExpanded, AnInfo);
|
||||
end;
|
||||
|
||||
if not Result then
|
||||
Result := HandleActionProc(MouseActions, AnInfo);
|
||||
end;
|
||||
@ -167,17 +231,30 @@ end;
|
||||
function TSynGutterCodeFolding.DoHandleMouseAction(AnAction: TSynEditMouseAction;
|
||||
var AnInfo: TSynEditMouseActionInfo): Boolean;
|
||||
var
|
||||
c, i, line: Integer;
|
||||
c, i, line, ScrLine: Integer;
|
||||
inf: TFoldViewNodeInfo;
|
||||
m: TMenuItem;
|
||||
s, s2: String;
|
||||
ACommand: Word;
|
||||
KeepVisible: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
if AnAction = nil then exit;
|
||||
ACommand := AnAction.Command;
|
||||
if (ACommand = emcNone) then exit;
|
||||
line := AnInfo.NewCaret.LinePos;
|
||||
ScrLine := FFoldView.TextIndexToScreenLine(Line-1);
|
||||
KeepVisible := 1;
|
||||
if FoldTypeForLine(ScrLine) = cfHideStart then KeepVisible := 0;
|
||||
|
||||
if (FoldTypeForLine(ScrLine) = cfCollapsedHide) then begin
|
||||
if IsFoldHidePreviousLine(ScrLine) then
|
||||
line := FFoldView.TextIndex[ScrLine-1] + 1;
|
||||
inc(line);
|
||||
KeepVisible := 0;
|
||||
end
|
||||
else
|
||||
if IsFoldHidePreviousLine(ScrLine) then dec(line);
|
||||
|
||||
Result := True;
|
||||
case ACommand of
|
||||
@ -185,26 +262,32 @@ begin
|
||||
begin
|
||||
case AnAction.Option of
|
||||
emcoCodeFoldCollapsOne:
|
||||
FFoldView.FoldAtTextIndex(Line-1, -1, 1, True);
|
||||
begin
|
||||
FFoldView.FoldAtTextIndex(Line-1, -1, 1, True, KeepVisible);
|
||||
end;
|
||||
emcoCodeFoldCollapsAll:
|
||||
FFoldView.FoldAtTextIndex(Line-1, -1, 0);
|
||||
begin
|
||||
FFoldView.FoldAtTextIndex(Line-1, -1, 0, False, KeepVisible);
|
||||
end;
|
||||
emcoCodeFoldCollapsAtCaret:
|
||||
// Keyword at mouseclick/caret position
|
||||
begin
|
||||
i := FFoldView.LogicalPosToNodeIndex(Line-1, AnInfo.NewCaret.BytePos, False);
|
||||
if i >= 0 then
|
||||
FFoldView.FoldAtTextIndex(Line-1, i, 1, False)
|
||||
FFoldView.FoldAtTextIndex(Line-1, i, 1, False, KeepVisible)
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
emcoCodeFoldCollapsPreCaret:
|
||||
// mouseclick/caret position anywhere inside the fold
|
||||
begin
|
||||
i := FFoldView.LogicalPosToNodeIndex(Line-1, AnInfo.NewCaret.BytePos, True);
|
||||
if i >= 0 then
|
||||
FFoldView.FoldAtTextIndex(Line-1, i, 1, False)
|
||||
FFoldView.FoldAtTextIndex(Line-1, i, 1, False, KeepVisible)
|
||||
else begin
|
||||
i := FFoldView.ExpandedLineForBlockAtLine(Line);
|
||||
if i > 0 then
|
||||
FFoldView.FoldAtTextIndex(i-1, -1, 1, True);
|
||||
FFoldView.FoldAtTextIndex(i-1, -1, 1, True, KeepVisible);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -213,9 +296,9 @@ begin
|
||||
begin
|
||||
case AnAction.Option of
|
||||
emcoCodeFoldExpandOne:
|
||||
FFoldView.UnFoldAtTextIndex(line-1, 0, 1, True);
|
||||
FFoldView.UnFoldAtTextIndex(line-1, 0, 1, True, KeepVisible);
|
||||
emcoCodeFoldExpandAll:
|
||||
FFoldView.UnFoldAtTextIndex(line-1);
|
||||
FFoldView.UnFoldAtTextIndex(line-1, -1, 0, False, KeepVisible);
|
||||
end;
|
||||
end;
|
||||
emcCodeFoldContextMenu:
|
||||
@ -264,18 +347,27 @@ var
|
||||
iLine: integer;
|
||||
rcLine: TRect;
|
||||
rcCodeFold: TRect;
|
||||
tmp: TSynEditCodeFoldType;
|
||||
tmp: TSynEditFoldLineCapability;
|
||||
LineHeight, LineOffset, BoxSize: Integer;
|
||||
|
||||
procedure DrawNodeBox(rcCodeFold: TRect; Collapsed: boolean);
|
||||
procedure DrawNodeBox(rcCodeFold: TRect; NodeType: TSynEditFoldLineCapability);
|
||||
var
|
||||
rcNode: TRect;
|
||||
ptCenter : TPoint;
|
||||
isPrevLine: Boolean;
|
||||
Points: Array [0..3] of TPoint;
|
||||
begin
|
||||
isPrevLine := IsFoldHidePreviousLine(iLine);
|
||||
LineOffset := 0;
|
||||
|
||||
//center of the draw area
|
||||
ptCenter.X := (rcCodeFold.Left + rcCodeFold.Right) div 2;
|
||||
ptCenter.Y := (rcCodeFold.Top + rcCodeFold.Bottom) div 2;
|
||||
|
||||
// If belongs to line above, draw at very top
|
||||
if isPrevLine then
|
||||
ptCenter.Y := rcCodeFold.Top + (BoxSize div 2) - 1;
|
||||
|
||||
//area of drawbox
|
||||
rcNode.Left := ptCenter.X - (BoxSize div 2) + 1;
|
||||
rcNode.Right := ptCenter.X + (BoxSize div 2);
|
||||
@ -284,25 +376,79 @@ var
|
||||
|
||||
Canvas.Brush.Style := bsClear;
|
||||
|
||||
//draw Paragraph end
|
||||
if isPrevLine and (cfFoldEnd in FFoldView.FoldType[iLine]) and
|
||||
(rcCodeFold.Bottom-1 > rcNode.Bottom)
|
||||
then begin
|
||||
Canvas.MoveTo(ptCenter.X, rcNode.Bottom);
|
||||
Canvas.LineTo(ptCenter.X, rcCodeFold.Bottom-1);
|
||||
Canvas.LineTo(rcCodeFold.Right, rcCodeFold.Bottom-1);
|
||||
LineOffset := min(2, (rcCodeFold.Top + rcCodeFold.Bottom) div 2);
|
||||
end
|
||||
else
|
||||
//draw bottom handle to paragraph line
|
||||
Canvas.MoveTo(ptCenter.X, rcNode.Bottom);
|
||||
Canvas.LineTo(ptCenter.X, rcCodeFold.Bottom);
|
||||
if (cfFoldBody in FFoldView.FoldType[iLine + 1]) and
|
||||
(not IsSingleLineHide(iLine))
|
||||
then begin
|
||||
Canvas.MoveTo(ptCenter.X, rcNode.Bottom);
|
||||
Canvas.LineTo(ptCenter.X, rcCodeFold.Bottom);
|
||||
end;
|
||||
|
||||
if Collapsed and (MarkupInfo.FrameColor <> clNone) then
|
||||
if (NodeType in [cfCollapsedFold, cfCollapsedHide]) and
|
||||
(MarkupInfo.FrameColor <> clNone)
|
||||
then
|
||||
Canvas.Pen.Color := MarkupInfo.FrameColor;
|
||||
|
||||
Canvas.Rectangle(rcNode);
|
||||
|
||||
//draw unfolded sign in node box
|
||||
Canvas.MoveTo(ptCenter.X - 2, ptCenter.Y);
|
||||
Canvas.LineTo(ptCenter.X + 3, ptCenter.Y);
|
||||
|
||||
//draw folded sign
|
||||
if Collapsed then
|
||||
begin
|
||||
Canvas.MoveTo(ptCenter.X, ptCenter.Y - 2);
|
||||
Canvas.LineTo(ptCenter.X, ptCenter.Y + 3);
|
||||
case NodeType of
|
||||
cfFoldStart:
|
||||
begin
|
||||
// [-]
|
||||
Canvas.MoveTo(ptCenter.X - 2, ptCenter.Y);
|
||||
Canvas.LineTo(ptCenter.X + 3, ptCenter.Y);
|
||||
end;
|
||||
cfHideStart:
|
||||
begin
|
||||
// [.]
|
||||
Canvas.MoveTo(ptCenter.X, ptCenter.Y);
|
||||
Canvas.LineTo(ptCenter.X + 1, ptCenter.Y);
|
||||
end;
|
||||
cfCollapsedFold:
|
||||
begin
|
||||
// [+]
|
||||
Canvas.MoveTo(ptCenter.X - 2, ptCenter.Y);
|
||||
Canvas.LineTo(ptCenter.X + 3, ptCenter.Y);
|
||||
Canvas.MoveTo(ptCenter.X, ptCenter.Y - 2);
|
||||
Canvas.LineTo(ptCenter.X, ptCenter.Y + 3);
|
||||
end;
|
||||
cfCollapsedHide:
|
||||
begin
|
||||
if isPrevLine then begin
|
||||
// [v]
|
||||
Points[0].X := ptCenter.X;
|
||||
Points[0].y := ptCenter.Y - 2;
|
||||
Points[1].X := ptCenter.X - 2;
|
||||
Points[1].y := ptCenter.Y;
|
||||
Points[2].X := ptCenter.X + 2;
|
||||
Points[2].y := ptCenter.Y;
|
||||
Points[3].X := ptCenter.X;
|
||||
Points[3].y := ptCenter.Y - 2;
|
||||
end else begin
|
||||
// [v]
|
||||
Points[0].X := ptCenter.X;
|
||||
Points[0].y := ptCenter.Y + 2;
|
||||
Points[1].X := ptCenter.X - 2;
|
||||
Points[1].y := ptCenter.Y;
|
||||
Points[2].X := ptCenter.X + 2;
|
||||
Points[2].y := ptCenter.Y;
|
||||
Points[3].X := ptCenter.X;
|
||||
Points[3].y := ptCenter.Y + 2;
|
||||
end;
|
||||
Canvas.Polygon(Points);
|
||||
end;
|
||||
end;
|
||||
LineOffset := 0;
|
||||
Canvas.Pen.Color := MarkupInfo.Foreground;
|
||||
Canvas.Brush.Style := bsSolid;
|
||||
end;
|
||||
@ -336,16 +482,15 @@ begin
|
||||
if not Visible then exit;
|
||||
LineHeight := TSynEdit(SynEdit).LineHeight;
|
||||
LineOffset := 0;
|
||||
if (FirstLine > 0) and (FFoldView.FoldType[FirstLine-1] = cfEnd) then
|
||||
if (FirstLine > 0) and
|
||||
(FFoldView.FoldType[FirstLine-1] - [cfFoldBody] = [cfFoldEnd]) then
|
||||
LineOffset := 2;
|
||||
BoxSize := Min(Width, LineHeight - cNodeOffset*2);
|
||||
|
||||
if MarkupInfo.Background <> clNone then
|
||||
begin
|
||||
Canvas.Brush.Color := MarkupInfo.Background;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
LCLIntf.SetBkColor(Canvas.Handle, Canvas.Brush.Color);
|
||||
{$ENDIF}
|
||||
Canvas.FillRect(AClip);
|
||||
end;
|
||||
|
||||
@ -366,14 +511,16 @@ begin
|
||||
rcCodeFold.Top := rcLine.Top;
|
||||
rcCodeFold.Bottom := rcLine.Bottom;
|
||||
|
||||
tmp := FFoldView.FoldType[iLine];
|
||||
|
||||
tmp := FoldTypeForLine(iLine);
|
||||
case tmp of
|
||||
cfCollapsed: DrawNodeBox(rcCodeFold, True);
|
||||
cfExpanded: DrawNodeBox(rcCodeFold, False);
|
||||
cfContinue: DrawParagraphContinue(rcCodeFold);
|
||||
cfEnd: DrawParagraphEnd(rcCodeFold);
|
||||
else LineOffset := 0;
|
||||
cfFoldStart, cfHideStart, cfCollapsedFold, cfCollapsedHide:
|
||||
DrawNodeBox(rcCodeFold, tmp);
|
||||
cfFoldBody:
|
||||
DrawParagraphContinue(rcCodeFold);
|
||||
cfFoldEnd:
|
||||
DrawParagraphEnd(rcCodeFold);
|
||||
else
|
||||
LineOffset := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -70,6 +70,7 @@ type
|
||||
// rsAnsi, rsBor, rsDirective are exclusive to each other
|
||||
rsAnsi, // *) comment
|
||||
rsBor, // { comment
|
||||
rsSlash, // //
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
rsDirective,
|
||||
{$ENDIF}
|
||||
@ -91,7 +92,7 @@ type
|
||||
|
||||
type
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
TPascalCodeFoldBlockType = (
|
||||
TPascalCodeFoldBlockType = ( // Do *not* change the order
|
||||
cfbtBeginEnd, // Nested
|
||||
cfbtTopBeginEnd, // Begin of Procedure
|
||||
cfbtNestedComment,
|
||||
@ -407,6 +408,7 @@ type
|
||||
procedure EqualSignProc;
|
||||
procedure SemicolonProc; //mh 2000-10-08
|
||||
procedure SlashProc;
|
||||
procedure SlashContinueProc;
|
||||
procedure SpaceProc;
|
||||
procedure StringProc;
|
||||
procedure SymbolProc;
|
||||
@ -441,8 +443,10 @@ type
|
||||
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;
|
||||
|
||||
function LastLineFoldLevelFix(Index: Integer): integer;
|
||||
@ -453,6 +457,7 @@ type
|
||||
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
|
||||
function GetFoldConfigCount: Integer; override;
|
||||
function GetFoldConfigInternalCount: Integer; override;
|
||||
procedure DoFoldConfigChanged(Sender: TObject); override;
|
||||
public
|
||||
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
|
||||
function GetCapabilities: TSynHighlighterCapabilities; override;
|
||||
@ -493,8 +498,9 @@ type
|
||||
function FoldTypeAtNodeIndex(ALineIndex, FoldIndex: Integer;
|
||||
UseCloseNodes: boolean = false): integer; override;
|
||||
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override;
|
||||
function FoldEndLine(ALineIndex, FoldIndex: Integer): integer; override;
|
||||
|
||||
// Pascal coe only // TODO: make private
|
||||
// Pascal code only // TODO: make private
|
||||
function MinimumFoldLevel(Index: Integer): integer; override;
|
||||
function EndFoldLevel(Index: Integer): integer; override;
|
||||
published
|
||||
@ -939,13 +945,13 @@ begin
|
||||
EndPascalCodeFoldBlock;
|
||||
if TopPascalCodeFoldBlockType in [cfbtProcedure] then
|
||||
EndPascalCodeFoldBlock;
|
||||
if TopPascalCodeFoldBlockType = cfbtProgram then
|
||||
EndPascalCodeFoldBlock;
|
||||
end else if tfb in [cfbtCase] then begin
|
||||
EndPascalCodeFoldBlock;
|
||||
fRange := fRange - [rsAtCaseLabel];
|
||||
end else if tfb in [cfbtBeginEnd] then begin
|
||||
EndPascalCodeFoldBlock;
|
||||
if TopPascalCodeFoldBlockType = cfbtProgram then
|
||||
EndPascalCodeFoldBlock;
|
||||
end else if tfb = cfbtUnitSection then begin
|
||||
EndPascalCodeFoldBlockLastLine;
|
||||
if TopPascalCodeFoldBlockType = cfbtUnit then // "Unit".."end."
|
||||
@ -2317,6 +2323,7 @@ begin
|
||||
DirectiveProc;
|
||||
end else begin
|
||||
// curly bracket open -> borland comment
|
||||
fStringLen := 1; // length of "{"
|
||||
inc(Run);
|
||||
fRange := fRange + [rsBor];
|
||||
if (Run < fLineLen) and (fLine[Run] = '%') then begin
|
||||
@ -2333,11 +2340,17 @@ begin
|
||||
end
|
||||
else if KeyComp('endregion') then
|
||||
EndCustomCodeFoldBlock(cfbtRegion)
|
||||
else
|
||||
else begin
|
||||
dec(Run, 2);
|
||||
StartPascalCodeFoldBlock(cfbtBorCommand);
|
||||
inc(Run);
|
||||
end;
|
||||
end
|
||||
else
|
||||
else begin
|
||||
dec(Run);
|
||||
StartPascalCodeFoldBlock(cfbtBorCommand);
|
||||
inc(Run);
|
||||
end;
|
||||
BorProc;
|
||||
end;
|
||||
end;
|
||||
@ -2413,6 +2426,11 @@ end;
|
||||
|
||||
procedure TSynPasSyn.NullProc;
|
||||
begin
|
||||
if (Run = 0) and (rsSlash in fRange) then begin
|
||||
fRange := fRange - [rsSlash];
|
||||
if TopPascalCodeFoldBlockType = cfbtSlashComment then
|
||||
EndPascalCodeFoldBlockLastLine;
|
||||
end;
|
||||
fTokenID := tkNull;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
if Run<fLineLen then inc(Run);
|
||||
@ -2510,11 +2528,13 @@ begin
|
||||
case fLine[Run] of
|
||||
'*':
|
||||
begin
|
||||
Inc(Run);
|
||||
// We would not be here, if we were in a comment or directive already
|
||||
fRange := fRange + [rsAnsi];
|
||||
fTokenID := tkComment;
|
||||
fStringLen := 2; // length of "(*"
|
||||
Dec(Run);
|
||||
StartPascalCodeFoldBlock(cfbtAnsiComment);
|
||||
Inc(Run, 2);
|
||||
if not (fLine[Run] in [#0, #10, #13]) then begin
|
||||
AnsiProc;
|
||||
end;
|
||||
@ -2581,16 +2601,48 @@ end;
|
||||
|
||||
procedure TSynPasSyn.SlashProc;
|
||||
begin
|
||||
Inc(Run);
|
||||
if fLine[Run] = '/' then begin
|
||||
if fLine[Run+1] = '/' then begin
|
||||
fTokenID := tkComment;
|
||||
if FAtLineStart then
|
||||
include(fRange, rsLineIsAllComment);
|
||||
repeat
|
||||
if FAtLineStart then begin
|
||||
fRange := fRange + [rsSlash, rsLineIsAllComment];
|
||||
fStringLen := 2; // length of "//"
|
||||
if not(TopPascalCodeFoldBlockType = cfbtSlashComment) then
|
||||
StartPascalCodeFoldBlock(cfbtSlashComment);
|
||||
end;
|
||||
inc(Run, 2);
|
||||
while not(fLine[Run] in [#0, #10, #13]) do
|
||||
Inc(Run);
|
||||
until fLine[Run] in [#0, #10, #13];
|
||||
end else
|
||||
end else begin
|
||||
Inc(Run);
|
||||
fTokenID := tkSymbol;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynPasSyn.SlashContinueProc;
|
||||
begin
|
||||
if (fLine[Run] = '/') and (fLine[Run + 1] = '/') then begin
|
||||
// Continue fold block
|
||||
fTokenID := tkComment;
|
||||
while not(fLine[Run] in [#0, #10, #13]) do
|
||||
Inc(Run);
|
||||
exit;
|
||||
end;
|
||||
|
||||
fTokenID := tkUnknown;
|
||||
if IsSpaceChar[FLine[Run]] then begin
|
||||
fTokenID := tkSpace;
|
||||
inc(Run);
|
||||
while IsSpaceChar[FLine[Run]] do inc(Run);
|
||||
end;
|
||||
|
||||
if not((fLine[Run] = '/') and (fLine[Run + 1] = '/')) then begin
|
||||
fRange := fRange - [rsSlash];
|
||||
if TopPascalCodeFoldBlockType = cfbtSlashComment then
|
||||
EndPascalCodeFoldBlockLastLine;
|
||||
end;
|
||||
|
||||
if FTokenID = tkUnknown then
|
||||
Next;
|
||||
end;
|
||||
|
||||
procedure TSynPasSyn.SpaceProc;
|
||||
@ -2653,7 +2705,7 @@ begin
|
||||
fTokenPos := Run;
|
||||
FTokenIsCaseLabel := False;
|
||||
if Run>=fLineLen then begin
|
||||
fTokenID := tkNull;
|
||||
NullProc;
|
||||
exit;
|
||||
end;
|
||||
case fLine[Run] of
|
||||
@ -2667,6 +2719,8 @@ begin
|
||||
BorProc
|
||||
else if rsDirective in fRange then
|
||||
DirectiveProc
|
||||
else if rsSlash in fRange then
|
||||
SlashContinueProc
|
||||
else begin
|
||||
if rsAtEqual in fRange then
|
||||
fRange := fRange + [rsAfterEqual] - [rsAtEqual]
|
||||
@ -2674,7 +2728,9 @@ begin
|
||||
if rsAtClass in fRange then
|
||||
fRange := fRange + [rsAfterClass] - [rsAtClass];
|
||||
IsAtCaseLabel := rsAtCaseLabel in fRange;
|
||||
|
||||
fProcTable[fLine[Run]];
|
||||
|
||||
if (IsAtCaseLabel) and (rsAtCaseLabel in fRange) then begin
|
||||
FTokenIsCaseLabel := True;
|
||||
if (FTokenID = tkKey) then
|
||||
@ -2690,7 +2746,7 @@ begin
|
||||
fRange := fRange - [rsAtClosingBracket];
|
||||
end
|
||||
end;
|
||||
if not(FTokenID in [tkSpace, tkComment]) then
|
||||
if FAtLineStart and not(FTokenID in [tkSpace, tkComment]) then
|
||||
FAtLineStart := False;
|
||||
//DebugLn(['TSynPasSyn.Next Run=',Run,' fTokenPos=',fTokenPos,' fLineStr=',fLineStr,' Token=',GetToken]);
|
||||
end;
|
||||
@ -2882,6 +2938,8 @@ begin
|
||||
Result := Result + inf.EndLevelRegion - inf.MinLevelRegion;
|
||||
if (AType = 0) or (AType = 3) then
|
||||
Result := Result + inf.EndLevelIfDef - inf.MinLevelIfDef;
|
||||
if Result < 0 then
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer;
|
||||
@ -2941,28 +2999,62 @@ end;
|
||||
|
||||
function TSynPasSyn.FoldLineLength(ALineIndex, FoldIndex: Integer): integer;
|
||||
var
|
||||
i, lvl, cnt, atype : Integer;
|
||||
e, m: Integer;
|
||||
atype : Integer;
|
||||
node: TSynFoldNodeInfo;
|
||||
begin
|
||||
atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
|
||||
node := GetFoldNodeInfo(ALineIndex, FoldIndex, [sfaOpen, sfaFold]);
|
||||
if sfaInvalid in node.FoldAction then exit(-1);
|
||||
if sfaOneLineOpen in node.FoldAction then exit(0);
|
||||
case TPascalCodeFoldBlockType(PtrUInt(node.FoldType)) of
|
||||
cfbtRegion:
|
||||
atype := 2;
|
||||
cfbtIfDef:
|
||||
atype := 3;
|
||||
else
|
||||
atype := 1;
|
||||
end;
|
||||
|
||||
Result := FoldEndLine(ALineIndex, FoldIndex);
|
||||
// check if fold last line of block (not mixed "end begin")
|
||||
if (EndPasFoldLevel(Result, atype) > MinimumPasFoldLevel(Result, atype)) then
|
||||
dec(Result);
|
||||
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
|
||||
Result := Result - ALineIndex;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.FoldEndLine(ALineIndex, FoldIndex: Integer): integer;
|
||||
var
|
||||
lvl, cnt, atype : Integer;
|
||||
e, m: Integer;
|
||||
node: TSynFoldNodeInfo;
|
||||
begin
|
||||
node := GetFoldNodeInfo(ALineIndex, FoldIndex, [sfaOpen, sfaFold]);
|
||||
if sfaInvalid in node.FoldAction then exit(-1);
|
||||
if sfaOneLineOpen in node.FoldAction then exit(ALineIndex);
|
||||
case TPascalCodeFoldBlockType(PtrUInt(node.FoldType)) of
|
||||
cfbtRegion:
|
||||
atype := 2;
|
||||
cfbtIfDef:
|
||||
atype := 3;
|
||||
else
|
||||
atype := 1;
|
||||
end;
|
||||
|
||||
|
||||
cnt := CurrentLines.Count;
|
||||
e := EndPasFoldLevel(ALineIndex, atype);
|
||||
m := MinimumPasFoldLevel(ALineIndex, atype);
|
||||
lvl := Min(m+1+FoldIndex, e);
|
||||
i := ALineIndex + 1;
|
||||
while (i < cnt) and (MinimumPasFoldLevel(i, atype) >= lvl) do inc(i);
|
||||
lvl := node.FoldLvlEnd;
|
||||
|
||||
Result := ALineIndex + 1;
|
||||
while (Result < cnt) and (MinimumPasFoldLevel(Result, atype) >= lvl) do inc(Result);
|
||||
// check if fold last line of block (not mixed "end begin")
|
||||
// and not lastlinefix
|
||||
if (i = cnt) or (EndPasFoldLevel(i, atype) > MinimumPasFoldLevel(i, atype)) then
|
||||
dec(i);
|
||||
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
|
||||
Result := i - ALineIndex;
|
||||
if (Result = cnt) then
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
function TSynPasSyn.MinimumPasFoldLevel(Index: Integer; AType: Integer = 1): integer;
|
||||
var
|
||||
r: TSynPasSynRange;
|
||||
i1, i2: Integer;
|
||||
begin
|
||||
case AType of
|
||||
2:
|
||||
@ -2977,24 +3069,8 @@ begin
|
||||
exit(0);
|
||||
r := TSynPasSynRange(CurrentRanges[Index]);
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then begin
|
||||
i1 := 0;
|
||||
i2 := 0;
|
||||
// Increase result for multiline "//" comments
|
||||
if FFoldConfig[ord(cfbtSlashComment)].Enabled and
|
||||
(rsLineIsAllComment in TRangeStates(Integer(PtrUInt(r.RangeType)))) and
|
||||
(Index + 1 < CurrentLines.Count)
|
||||
then begin
|
||||
if rsLineIsAllComment in
|
||||
TRangeStates(Integer(PtrUInt(TSynPasSynRange(CurrentRanges[Index - 1]).RangeType)))
|
||||
then
|
||||
i1 := 1;
|
||||
if rsLineIsAllComment in
|
||||
TRangeStates(Integer(PtrUInt(TSynPasSynRange(CurrentRanges[Index + 1]).RangeType)))
|
||||
then
|
||||
i2 := 1;
|
||||
end;
|
||||
Result := Min(r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1) + i2,
|
||||
r.PasFoldMinLevel + i1)
|
||||
Result := Min(r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1),
|
||||
r.PasFoldMinLevel)
|
||||
end else
|
||||
Result := 0;
|
||||
end;
|
||||
@ -3005,6 +3081,8 @@ 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).
|
||||
@ -3014,24 +3092,10 @@ begin
|
||||
PasRangeInfo[Index].EndLevelIfDef;
|
||||
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 := r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1);
|
||||
// Increase result for multiline "//" comments
|
||||
if FFoldConfig[ord(cfbtSlashComment)].Enabled and
|
||||
(rsLineIsAllComment in TRangeStates(Integer(PtrUInt(r.RangeType)))) and
|
||||
(Index + 1 < CurrentLines.Count) and (Index > 0)
|
||||
// and not TopPascalCodeFoldBlockType() in [cfbtAnsiComment, cfbtBorCommand]
|
||||
then begin
|
||||
r := TSynPasSynRange(CurrentRanges[Index + 1]);
|
||||
if (r <> nil) and
|
||||
(rsLineIsAllComment in TRangeStates(Integer(PtrUInt(r.RangeType))))
|
||||
then
|
||||
inc(Result);
|
||||
end;
|
||||
end else
|
||||
if (r <> nil) and (Pointer(r) <> NullRange) then
|
||||
Result := r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1)
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
end;
|
||||
@ -3115,21 +3179,27 @@ begin
|
||||
begin
|
||||
node.FoldGroup := 2;
|
||||
Node.FoldLvlStart := FSynPasRangeInfo.EndLevelRegion;
|
||||
Node.NestLvlStart := FSynPasRangeInfo.EndLevelRegion;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelRegion);
|
||||
end;
|
||||
cfbtIfDef:
|
||||
begin
|
||||
node.FoldGroup := 3;
|
||||
Node.FoldLvlStart := FSynPasRangeInfo.EndLevelIfDef;
|
||||
Node.NestLvlStart := FSynPasRangeInfo.EndLevelIfDef;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > FSynPasRangeInfo.MinLevelIfDef);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
node.FoldGroup := 1;
|
||||
Node.FoldLvlStart := CurrentCodeFoldBlockLevel;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > MinimumCodeFoldBlockLevel);
|
||||
Node.FoldLvlStart := PasCodeFoldRange.PasFoldEndLevel;
|
||||
Node.NestLvlStart := CurrentCodeFoldBlockLevel;
|
||||
OneLine := (EndOffs < 0) and (Node.FoldLvlStart > PasCodeFoldRange.PasFoldMinLevel); // MinimumCodeFoldBlockLevel);
|
||||
end;
|
||||
end;
|
||||
Node.NestLvlEnd := Node.NestLvlStart + EndOffs;
|
||||
if not (sfaFold in aActions) then
|
||||
EndOffs := 0;
|
||||
Node.FoldLvlEnd := Node.FoldLvlStart + EndOffs;
|
||||
if OneLine then begin // find opening node
|
||||
i := FNodeInfoCount - 1;
|
||||
@ -3141,9 +3211,17 @@ begin
|
||||
) do
|
||||
dec(i);
|
||||
if i >= 0 then begin
|
||||
FNodeInfoList[i].FoldAction := FNodeInfoList[i].FoldAction
|
||||
- [sfaOpen, sfaFold] + [sfaOneLineOpen];
|
||||
Node.FoldAction := Node.FoldAction + [sfaOneLineClose] - [sfaClose, sfaFold];
|
||||
FNodeInfoList[i].FoldAction := FNodeInfoList[i].FoldAction + [sfaOneLineOpen];
|
||||
Node.FoldAction := Node.FoldAction + [sfaOneLineClose];
|
||||
if (sfaFoldHide in FNodeInfoList[i].FoldAction) then begin
|
||||
// one liner: hide-able / not fold-able
|
||||
FNodeInfoList[i].FoldAction := FNodeInfoList[i].FoldAction - [sfaFoldFold];
|
||||
Node.FoldAction := Node.FoldAction - [sfaFoldFold];
|
||||
end else begin
|
||||
// one liner: nether hide-able nore fold-able
|
||||
FNodeInfoList[i].FoldAction := FNodeInfoList[i].FoldAction - [sfaOpen, sfaFold];
|
||||
Node.FoldAction := Node.FoldAction - [sfaClose, sfaFold];
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if ABlockType in PascalWordTrippletRanges then
|
||||
@ -3151,11 +3229,16 @@ begin
|
||||
end;
|
||||
|
||||
procedure TSynPasSyn.StartCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType);
|
||||
var
|
||||
act: TSynFoldActions;
|
||||
begin
|
||||
if not FFoldConfig[ord(ABlockType)].Enabled then exit;
|
||||
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
|
||||
GrowNodeInfoList;
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], +1, ABlockType, [sfaOpen, sfaFold]);
|
||||
act := FFoldConfig[ord(ABlockType)].FoldActions;
|
||||
if not FAtLineStart then
|
||||
act := act - [sfaFoldHide];
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], +1, ABlockType, [sfaOpen] + act);
|
||||
inc(FNodeInfoCount);
|
||||
end;
|
||||
case ABlockType of
|
||||
@ -3171,7 +3254,8 @@ begin
|
||||
if not FFoldConfig[ord(ABlockType)].Enabled then exit;
|
||||
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
|
||||
GrowNodeInfoList;
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], -1, ABlockType, [sfaClose, sfaFold]);
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], -1, ABlockType,
|
||||
[sfaClose, sfaFold]); // + FFoldConfig[ord(ABlockType)].FoldActions);
|
||||
inc(FNodeInfoCount);
|
||||
end;
|
||||
case ABlockType of
|
||||
@ -3206,7 +3290,9 @@ begin
|
||||
GrowNodeInfoList;
|
||||
act := [sfaOpen];
|
||||
if FoldBlock then
|
||||
include(act, sfaFold);
|
||||
act := act + FFoldConfig[ord(ABlockType)].FoldActions;
|
||||
if not FAtLineStart then
|
||||
act := act - [sfaFoldHide];
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], +1, ABlockType, act);
|
||||
inc(FNodeInfoCount);
|
||||
end;
|
||||
@ -3220,13 +3306,15 @@ procedure TSynPasSyn.EndPascalCodeFoldBlock(NoMarkup: Boolean = False);
|
||||
var
|
||||
DecreaseLevel: Boolean;
|
||||
act: TSynFoldActions;
|
||||
BlockType: Pointer;
|
||||
begin
|
||||
DecreaseLevel := TopCodeFoldBlockType < CountPascalCodeFoldBlockOffset;
|
||||
BlockType := TopCodeFoldBlockType;
|
||||
DecreaseLevel := BlockType < CountPascalCodeFoldBlockOffset;
|
||||
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
|
||||
GrowNodeInfoList;
|
||||
act := [sfaClose];
|
||||
if DecreaseLevel then
|
||||
include(act, sfaFold);
|
||||
act := act + [sfaFold]; //FFoldConfig[PtrUInt(BlockType)].FoldActions;
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], -1, TopPascalCodeFoldBlockType, act);
|
||||
if NoMarkup then
|
||||
exclude(FNodeInfoList[FNodeInfoCount].FoldAction, sfaMarkup);
|
||||
@ -3460,6 +3548,12 @@ begin
|
||||
cfbtProcedure, cfbtUses, cfbtLocalVarType, cfbtClass,
|
||||
cfbtClassSection, cfbtRecord, cfbtRepeat, cfbtCase,
|
||||
cfbtAsm, cfbtRegion];
|
||||
if TPascalCodeFoldBlockType(Index) in
|
||||
[cfbtRegion, cfbtNestedComment, cfbtAnsiComment, cfbtBorCommand, cfbtSlashComment]
|
||||
then
|
||||
Result.SupportedModes := [fmFold, fmHide];
|
||||
if TPascalCodeFoldBlockType(Index) in [cfbtSlashComment] then
|
||||
Result.Modes := [fmFold, fmHide];
|
||||
end;
|
||||
|
||||
function TSynPasSyn.CreateRangeList(ALines: TSynEditStringsBase): TSynHighlighterRangeList;
|
||||
@ -3496,6 +3590,12 @@ begin
|
||||
+ 1;
|
||||
end;
|
||||
|
||||
procedure TSynPasSyn.DoFoldConfigChanged(Sender: TObject);
|
||||
begin
|
||||
FNodeInfoLine := -1;
|
||||
inherited DoFoldConfigChanged(Sender);
|
||||
end;
|
||||
|
||||
function TSynPasSyn.GetDividerDrawConfig(Index: Integer): TSynDividerDrawConfig;
|
||||
begin
|
||||
Result := FDividerDrawConfig[TSynPasDividerDrawLocation(Index)];
|
||||
@ -3518,11 +3618,27 @@ begin
|
||||
StartAtLineIndex(Line);
|
||||
fStringLen := 0;
|
||||
NextToEol;
|
||||
fStringLen := 0;
|
||||
i := LastLineFoldLevelFix(Line+1);
|
||||
while i < 0 do begin
|
||||
EndPascalCodeFoldBlock;
|
||||
inc(i);
|
||||
end;
|
||||
if Line = CurrentLines.Count - 1 then begin
|
||||
// last line, close all folds
|
||||
// Run (for LogXStart) is at line-end
|
||||
i := FNodeInfoCount;
|
||||
while TopPascalCodeFoldBlockType <> cfbtNone do
|
||||
EndPascalCodeFoldBlock(True);
|
||||
while FSynPasRangeInfo.EndLevelIfDef > 0 do
|
||||
EndCustomCodeFoldBlock(cfbtIfDef);
|
||||
while FSynPasRangeInfo.EndLevelRegion > 0 do
|
||||
EndCustomCodeFoldBlock(cfbtRegion);
|
||||
while i < FNodeInfoCount do begin
|
||||
FNodeInfoList[i].FoldAction := FNodeInfoList[i].FoldAction + [sfaLastLineClose];
|
||||
inc(i);
|
||||
end;
|
||||
end;
|
||||
FCatchNodeInfo := False;
|
||||
FNodeInfoLine := Line;
|
||||
end;
|
||||
@ -3534,6 +3650,7 @@ begin
|
||||
Result := FNodeInfoList[Index]
|
||||
else
|
||||
begin
|
||||
Result.FoldAction := [sfaInvalid];
|
||||
j := Index;
|
||||
for i := 0 to FNodeInfoCount - 1 do
|
||||
if FNodeInfoList[i].FoldAction * Filter = Filter then begin
|
||||
|
||||
@ -461,9 +461,6 @@ const
|
||||
(Name: dlgFoldPasRecord; Xml: 'Record';
|
||||
Index: ord(cfbtRecord); Enabled: True),
|
||||
|
||||
(Name: dlgFoldPasNestedComment; Xml: 'NestedComment';
|
||||
Index: ord(cfbtNestedComment);Enabled: True),
|
||||
|
||||
(Name: dlgFoldPasIfDef; Xml: 'IfDef';
|
||||
Index: ord(cfbtIfDef); Enabled: False),
|
||||
(Name: dlgFoldPasUserRegion; Xml: 'UserRegion';
|
||||
@ -474,7 +471,10 @@ const
|
||||
(Name: dlgFoldPasBorComment; Xml: 'BorComment';
|
||||
Index: ord(cfbtBorCommand); Enabled: True),
|
||||
(Name: dlgFoldPasSlashComment; Xml: 'SlashComment';
|
||||
Index: ord(cfbtSlashComment); Enabled: False)
|
||||
Index: ord(cfbtSlashComment); Enabled: False),
|
||||
|
||||
(Name: dlgFoldPasNestedComment; Xml: 'NestedComment';
|
||||
Index: ord(cfbtNestedComment);Enabled: True)
|
||||
);
|
||||
|
||||
EditorOptionsFoldInfoLFM: Array [0..2] of TEditorOptionsFoldInfo
|
||||
@ -1488,12 +1488,12 @@ begin
|
||||
EditorOptionsFoldInfoPas[14].Name := dlgFoldPasClass;
|
||||
EditorOptionsFoldInfoPas[15].Name := dlgFoldPasClassSection;
|
||||
EditorOptionsFoldInfoPas[16].Name := dlgFoldPasRecord;
|
||||
EditorOptionsFoldInfoPas[17].Name := dlgFoldPasNestedComment;
|
||||
EditorOptionsFoldInfoPas[18].Name := dlgFoldPasIfDef;
|
||||
EditorOptionsFoldInfoPas[19].Name := dlgFoldPasUserRegion;
|
||||
EditorOptionsFoldInfoPas[20].Name := dlgFoldPasAnsiComment;
|
||||
EditorOptionsFoldInfoPas[21].Name := dlgFoldPasBorComment;
|
||||
EditorOptionsFoldInfoPas[22].Name := dlgFoldPasSlashComment;
|
||||
EditorOptionsFoldInfoPas[17].Name := dlgFoldPasIfDef;
|
||||
EditorOptionsFoldInfoPas[18].Name := dlgFoldPasUserRegion;
|
||||
EditorOptionsFoldInfoPas[19].Name := dlgFoldPasAnsiComment;
|
||||
EditorOptionsFoldInfoPas[20].Name := dlgFoldPasBorComment;
|
||||
EditorOptionsFoldInfoPas[21].Name := dlgFoldPasSlashComment;
|
||||
EditorOptionsFoldInfoPas[22].Name := dlgFoldPasNestedComment;
|
||||
|
||||
EditorOptionsFoldInfoHTML[0].Name := dlgFoldHtmlNode;
|
||||
EditorOptionsFoldInfoHTML[1].Name := dlgFoldHtmlComment;
|
||||
|
||||
@ -4,7 +4,6 @@ inherited EditorCodefoldingOptionsFrame: TEditorCodefoldingOptionsFrame
|
||||
Anchors = [akTop]
|
||||
ClientHeight = 352
|
||||
ClientWidth = 511
|
||||
TabOrder = 0
|
||||
Visible = False
|
||||
DesignLeft = 346
|
||||
DesignTop = 366
|
||||
@ -16,7 +15,7 @@ inherited EditorCodefoldingOptionsFrame: TEditorCodefoldingOptionsFrame
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 2
|
||||
Top = 28
|
||||
Top = 25
|
||||
Width = 511
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Top = 6
|
||||
@ -27,9 +26,9 @@ inherited EditorCodefoldingOptionsFrame: TEditorCodefoldingOptionsFrame
|
||||
AnchorSideTop.Control = LanguageComboBox
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 206
|
||||
Height = 18
|
||||
Top = 40
|
||||
Width = 98
|
||||
Height = 16
|
||||
Top = 34
|
||||
Width = 81
|
||||
BorderSpacing.Left = 6
|
||||
Caption = 'LanguageLabel'
|
||||
ParentColor = False
|
||||
@ -38,9 +37,9 @@ inherited EditorCodefoldingOptionsFrame: TEditorCodefoldingOptionsFrame
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideTop.Control = Owner
|
||||
Left = 0
|
||||
Height = 22
|
||||
Height = 19
|
||||
Top = 0
|
||||
Width = 175
|
||||
Width = 149
|
||||
Caption = 'chkCodeFoldingEnabled'
|
||||
TabOrder = 0
|
||||
end
|
||||
@ -48,11 +47,11 @@ inherited EditorCodefoldingOptionsFrame: TEditorCodefoldingOptionsFrame
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideTop.Control = Bevel1
|
||||
Left = 0
|
||||
Height = 31
|
||||
Top = 34
|
||||
Height = 23
|
||||
Top = 31
|
||||
Width = 200
|
||||
BorderSpacing.Top = 6
|
||||
ItemHeight = 0
|
||||
ItemHeight = 15
|
||||
OnChange = LanguageComboBoxChange
|
||||
OnExit = LanguageComboBoxExit
|
||||
OnKeyDown = LanguageComboBoxKeyDown
|
||||
@ -68,13 +67,13 @@ inherited EditorCodefoldingOptionsFrame: TEditorCodefoldingOptionsFrame
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 281
|
||||
Top = 71
|
||||
Height = 292
|
||||
Top = 60
|
||||
Width = 511
|
||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||
BorderSpacing.Top = 6
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 281
|
||||
ClientHeight = 292
|
||||
ClientWidth = 511
|
||||
TabOrder = 2
|
||||
object FoldConfigCheckListBox: TCheckListBox
|
||||
@ -83,17 +82,61 @@ inherited EditorCodefoldingOptionsFrame: TEditorCodefoldingOptionsFrame
|
||||
AnchorSideBottom.Control = FoldConfPanel
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 281
|
||||
Height = 292
|
||||
Top = 0
|
||||
Width = 200
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
ExtendedSelect = False
|
||||
ItemHeight = 0
|
||||
OnClick = FoldConfigCheckListBoxClick
|
||||
OnClickCheck = FoldConfigCheckListBoxClickCheck
|
||||
OnExit = FoldConfigCheckListBoxClickCheck
|
||||
OnKeyUp = FoldConfigCheckListBoxKeyUp
|
||||
TabOrder = 0
|
||||
TopIndex = -1
|
||||
end
|
||||
object pnlFoldHide: TPanel
|
||||
AnchorSideLeft.Control = FoldConfigCheckListBox
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = FoldConfPanel
|
||||
Left = 206
|
||||
Height = 57
|
||||
Top = 0
|
||||
Width = 64
|
||||
AutoSize = True
|
||||
BorderSpacing.Left = 6
|
||||
BevelOuter = bvNone
|
||||
ChildSizing.Layout = cclTopToBottomThenLeftToRight
|
||||
ChildSizing.ControlsPerLine = 3
|
||||
ClientHeight = 57
|
||||
ClientWidth = 64
|
||||
TabOrder = 1
|
||||
object chkFold: TRadioButton
|
||||
Left = 0
|
||||
Height = 19
|
||||
Top = 0
|
||||
Width = 64
|
||||
Caption = 'chkFold'
|
||||
OnChange = chkFoldChange
|
||||
TabOrder = 0
|
||||
end
|
||||
object chkHide: TRadioButton
|
||||
Left = 0
|
||||
Height = 19
|
||||
Top = 19
|
||||
Width = 64
|
||||
Caption = 'chkHide'
|
||||
OnChange = chkFoldChange
|
||||
TabOrder = 1
|
||||
end
|
||||
object chkBoth: TRadioButton
|
||||
Left = 0
|
||||
Height = 19
|
||||
Top = 38
|
||||
Width = 64
|
||||
Caption = 'chkBoth'
|
||||
OnChange = chkFoldChange
|
||||
TabOrder = 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -40,6 +40,12 @@ type
|
||||
chkCodeFoldingEnabled: TCheckBox;
|
||||
LanguageLabel: TLabel;
|
||||
LanguageComboBox: TComboBox;
|
||||
pnlFoldHide: TPanel;
|
||||
chkFold: TRadioButton;
|
||||
chkHide: TRadioButton;
|
||||
chkBoth: TRadioButton;
|
||||
procedure chkFoldChange(Sender: TObject);
|
||||
procedure FoldConfigCheckListBoxClick(Sender: TObject);
|
||||
procedure FoldConfigCheckListBoxClickCheck(Sender: TObject);
|
||||
procedure FoldConfigCheckListBoxKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
procedure LanguageComboBoxChange(Sender: TObject);
|
||||
@ -50,6 +56,8 @@ type
|
||||
FHighlighters: array[TLazSyntaxHighlighter] of TSrcIDEHighlighter;
|
||||
FCurHighlighter: TSrcIDEHighlighter;
|
||||
FCurFoldInfo: TEditorOptionsFoldRecord;
|
||||
FModeLock: Boolean;
|
||||
procedure UpdateFoldHideRadio;
|
||||
protected
|
||||
function GetHighlighter(SynType: TLazSyntaxHighlighter;
|
||||
CreateIfNotExists: Boolean): TSrcIDEHighlighter;
|
||||
@ -88,6 +96,7 @@ var
|
||||
ComboBox: TComboBox absolute Sender;
|
||||
tp: TLazSyntaxHighlighter;
|
||||
i: Integer;
|
||||
Hl: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
tp := EditorOpts.HighlighterList
|
||||
[EditorOpts.HighlighterList.FindByName(ComboBox.Text)].TheType;
|
||||
@ -97,23 +106,77 @@ begin
|
||||
FoldConfigCheckListBox.Clear;
|
||||
if not (assigned(FCurHighlighter) and
|
||||
(FCurHighlighter is TSynCustomFoldHighlighter)) then exit;
|
||||
Hl := TSynCustomFoldHighlighter(FCurHighlighter);
|
||||
|
||||
for i := 0 to FCurFoldInfo.Count - 1 do begin
|
||||
FoldConfigCheckListBox.Items.add(FCurFoldInfo.Info^[i].Name);
|
||||
FoldConfigCheckListBox.Checked[i] :=
|
||||
TSynCustomFoldHighlighter(FCurHighlighter).FoldConfig[FCurFoldInfo.Info^[i].Index].Enabled;
|
||||
Hl.FoldConfig[FCurFoldInfo.Info^[i].Index].Enabled;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEditorCodefoldingOptionsFrame.FoldConfigCheckListBoxClickCheck(Sender: TObject);
|
||||
var
|
||||
i: Integer;
|
||||
Hl: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
if not (assigned(FCurHighlighter) and
|
||||
(FCurHighlighter is TSynCustomFoldHighlighter)) then exit;
|
||||
Hl := TSynCustomFoldHighlighter(FCurHighlighter);
|
||||
for i := 0 to FCurFoldInfo.Count - 1 do
|
||||
TSynCustomFoldHighlighter(FCurHighlighter).FoldConfig[FCurFoldInfo.Info^[i].Index].Enabled
|
||||
Hl.FoldConfig[FCurFoldInfo.Info^[i].Index].Enabled
|
||||
:= FoldConfigCheckListBox.Checked[i];
|
||||
|
||||
UpdateFoldHideRadio;
|
||||
end;
|
||||
|
||||
procedure TEditorCodefoldingOptionsFrame.UpdateFoldHideRadio;
|
||||
var
|
||||
i: LongInt;
|
||||
AvailModes, Modes: TSynCustomFoldConfigModes;
|
||||
Hl: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
if not (assigned(FCurHighlighter) and
|
||||
(FCurHighlighter is TSynCustomFoldHighlighter)) then exit;
|
||||
Hl := TSynCustomFoldHighlighter(FCurHighlighter);
|
||||
FModeLock := True;
|
||||
i := FoldConfigCheckListBox.ItemIndex;
|
||||
AvailModes := [];
|
||||
Modes := [fmFold];
|
||||
if i >= 0 then begin
|
||||
i := FCurFoldInfo.Info^[i].Index;
|
||||
AvailModes := Hl.FoldConfig[i].SupportedModes;
|
||||
Modes := Hl.FoldConfig[i].Modes;
|
||||
end;
|
||||
chkFold.Checked := Modes = [fmFold];
|
||||
chkHide.Checked := Modes = [fmHide];
|
||||
chkBoth.Checked := Modes = [fmFold, fmHide];
|
||||
pnlFoldHide.Enabled := AvailModes = [fmFold, fmHide];
|
||||
FModeLock := False;
|
||||
end;
|
||||
|
||||
procedure TEditorCodefoldingOptionsFrame.FoldConfigCheckListBoxClick(Sender: TObject);
|
||||
begin
|
||||
UpdateFoldHideRadio;
|
||||
end;
|
||||
|
||||
procedure TEditorCodefoldingOptionsFrame.chkFoldChange(Sender: TObject);
|
||||
var
|
||||
Hl: TSynCustomFoldHighlighter;
|
||||
Modes: TSynCustomFoldConfigModes;
|
||||
i: LongInt;
|
||||
begin
|
||||
if FModeLock then exit;
|
||||
if not (assigned(FCurHighlighter) and
|
||||
(FCurHighlighter is TSynCustomFoldHighlighter)) then exit;
|
||||
i := FoldConfigCheckListBox.ItemIndex;
|
||||
if i < 0 then exit;
|
||||
i := FCurFoldInfo.Info^[i].Index;
|
||||
Hl := TSynCustomFoldHighlighter(FCurHighlighter);
|
||||
Modes := [fmFold];
|
||||
if chkHide.Checked then Modes := [fmHide];
|
||||
if chkBoth.Checked then Modes := [fmFold, fmHide];
|
||||
Hl.FoldConfig[i].Modes := Modes;
|
||||
end;
|
||||
|
||||
procedure TEditorCodefoldingOptionsFrame.FoldConfigCheckListBoxKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
@ -159,7 +222,11 @@ end;
|
||||
procedure TEditorCodefoldingOptionsFrame.Setup(ADialog: TAbstractOptionsEditorDialog);
|
||||
begin
|
||||
chkCodeFoldingEnabled.Caption := dlgUseCodeFolding;
|
||||
chkFold.Caption := dlgCodeFoldEnableFold;
|
||||
chkHide.Caption := dlgCodeFoldEnableHide;
|
||||
chkBoth.Caption := dlgCodeFoldEnableBoth;
|
||||
LanguageLabel.Caption := dlgLang;
|
||||
FModeLock := False;
|
||||
end;
|
||||
|
||||
procedure TEditorCodefoldingOptionsFrame.ReadSettings(
|
||||
@ -168,6 +235,7 @@ var
|
||||
i: Integer;
|
||||
rf: TEditorOptionsFoldRecord;
|
||||
begin
|
||||
FModeLock := False;
|
||||
with AOptions as TEditorOptions do
|
||||
begin
|
||||
chkCodeFoldingEnabled.Checked := UseCodeFolding;
|
||||
@ -184,6 +252,7 @@ begin
|
||||
LanguageComboBox.ItemIndex := 0;
|
||||
LanguageComboBoxExit(LanguageComboBox);
|
||||
end;
|
||||
UpdateFoldHideRadio;
|
||||
end;
|
||||
|
||||
procedure TEditorCodefoldingOptionsFrame.WriteSettings(
|
||||
|
||||
@ -1270,6 +1270,9 @@ resourcestring
|
||||
dlgFindTextatCursor = 'Find text at cursor';
|
||||
dlgUseSyntaxHighlight = 'Use syntax highlight';
|
||||
dlgUseCodeFolding = 'Code folding';
|
||||
dlgCodeFoldEnableFold = 'Fold';
|
||||
dlgCodeFoldEnableHide = 'Hide';
|
||||
dlgCodeFoldEnableBoth = 'Both';
|
||||
dlgCodeFoldingMouse = 'Mouse';
|
||||
dlfMousePredefinedScheme = 'Use predefined scheme';
|
||||
dlfNoPredefinedScheme = '< None >';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user