mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-14 19:39:39 +02:00
SynEdit: keep folds, even if a the keyword is no longer recognized (e.g becomes part of a comment). Such folds are however not saved in the session-info
git-svn-id: trunk@30141 -
This commit is contained in:
parent
13d98e0553
commit
49611fd177
@ -45,6 +45,9 @@ uses
|
||||
|
||||
type
|
||||
|
||||
TFoldNodeClassification = (fncInvalid, fncHighlighter, fncHighlighterEx);
|
||||
TFoldNodeClassifications = set of TFoldNodeClassification;
|
||||
|
||||
{ TSynTextFoldAVLNodeData }
|
||||
|
||||
TSynTextFoldAVLNodeData = class(TSynSizedDifferentialAVLNode)
|
||||
@ -75,6 +78,9 @@ type
|
||||
|
||||
(* Source Info *)
|
||||
FoldIndex: Integer; (* Index of fold in line; if a line has more than one fold starting *)
|
||||
FoldColumn, FoldColumnLen: Integer; (* The column (1-based) and len of the keywordm which starts this fold *)
|
||||
FoldTypeCompatible: Pointer; (* help identifying in FixFolding *)
|
||||
Classification: TFoldNodeClassification;
|
||||
VisibleLines: Integer; (* Visible Source lines, containing the "fold keyword"
|
||||
0: Hiden block (the fold-keyword is inside the fold)
|
||||
1: Normal fold (There is *1* visible line with the fold-keyword)
|
||||
@ -92,11 +98,14 @@ type
|
||||
|
||||
TSynTextFoldAVLNode = object
|
||||
private
|
||||
function GetFoldColumn: Integer;
|
||||
function GetFoldColumnLen: Integer;
|
||||
function GetFoldIndex: Integer;
|
||||
function GetMergedLineCount : Integer;
|
||||
function GetFullCount : Integer;
|
||||
function GetSourceLine: integer;
|
||||
function GetSourceLineOffset: integer;
|
||||
procedure SetFoldColumn(const AValue: Integer);
|
||||
protected
|
||||
fData : TSynTextFoldAVLNodeData; // nil if unfolded
|
||||
fStartLine : Integer; // start of folded
|
||||
@ -114,6 +123,8 @@ type
|
||||
|
||||
function IsHide: Boolean;
|
||||
property FoldIndex: Integer read GetFoldIndex;
|
||||
property FoldColumn: Integer read GetFoldColumn write SetFoldColumn;
|
||||
property FoldColumnLen: Integer read GetFoldColumnLen;
|
||||
property SourceLine: integer read GetSourceLine; // The SourceLine with the fold-keyword
|
||||
property SourceLineOffset: integer read GetSourceLineOffset; // The SourceLine with the fold-keyword
|
||||
end;
|
||||
@ -169,14 +180,18 @@ type
|
||||
Function FindFoldForLine(ALine : Integer; FindNextNode : Boolean = False) : TSynTextFoldAVLNode;
|
||||
(* Find Fold by Line in Folded Text // always returns unfolded, unless next=true *)
|
||||
Function FindFoldForFoldedLine(ALine : Integer; FindNextNode: Boolean = False) : TSynTextFoldAVLNode;
|
||||
Function InsertNewFold(ALine, AColumn, ACount, AVisibleLines: Integer) : TSynTextFoldAVLNode;
|
||||
Function InsertNewFold(ALine, AFoldIndex, AColumn, AColumnLen, ACount, AVisibleLines: Integer;
|
||||
AClassification: TFoldNodeClassification;
|
||||
AFoldTypeCompatible: Pointer
|
||||
) : TSynTextFoldAVLNode;
|
||||
(* This will unfold the block which either contains tALine, or has Aline as its cgColapsed line
|
||||
If IgnoreFirst, the cfCollapsed will *not* unfold => Hint: IgnoreFirst = Make folded visible
|
||||
Returns the pos(1-based) of the cfCollapsed Line that was expanded; or ALine, if nothing was done
|
||||
*)
|
||||
Function RemoveFoldForLine(ALine : Integer; OnlyCol: Integer = -1) : Integer; overload;
|
||||
Procedure AdjustForLinesInserted(AStartLine, ALineCount : Integer);
|
||||
Procedure AdjustForLinesDeleted(AStartLine, ALineCount : Integer);
|
||||
Procedure AdjustForLinesInserted(AStartLine, ALineCount, ABytePos: Integer);
|
||||
Procedure AdjustForLinesDeleted(AStartLine, ALineCount, ABytePos: Integer);
|
||||
procedure AdjustColumn(ALine, ABytePos, ACount: Integer; InLineBreak: boolean = False);
|
||||
Function FindLastFold : TSynTextFoldAVLNode;
|
||||
Function FindFirstFold : TSynTextFoldAVLNode;
|
||||
Function LastFoldedLine : integer; // The actual line; LastNode.StartLine + LastNode.LineCount - 1
|
||||
@ -237,6 +252,12 @@ type
|
||||
);
|
||||
TSynEditFoldLineCapabilities = set of TSynEditFoldLineCapability;
|
||||
TSynEditFoldType = (scftOpen, scftFold, scftHide, scftAll, scftInvalid);
|
||||
|
||||
TSynEditFoldLineMapInfo = record
|
||||
Capability: TSynEditFoldLineCapabilities;
|
||||
Classifications :TFoldNodeClassifications;
|
||||
end;
|
||||
|
||||
{$IFDEF SynFoldSaveDebug}
|
||||
const
|
||||
SynEditFoldTypeNames: Array [TSynEditFoldType] of string =
|
||||
@ -245,20 +266,39 @@ type
|
||||
{$ENDIF}
|
||||
|
||||
{ TSynEditFoldProvider }
|
||||
TSynEditFoldProviderNodeInfo = record
|
||||
LineCount: Integer;
|
||||
Column, ColumnLen: Integer;
|
||||
DefaultCollapsed: Boolean;
|
||||
FoldTypeCompatible: Pointer; // eg begin, var, procedure
|
||||
FoldGroup: Integer; // eg.: pas, region, ifdef
|
||||
Classification: TFoldNodeClassification;
|
||||
end;
|
||||
|
||||
TSynEditFoldProviderNodeInfoList = array of TSynEditFoldProviderNodeInfo;
|
||||
|
||||
TSynEditFoldProvider = class
|
||||
private
|
||||
FHighlighter: TSynCustomFoldHighlighter;
|
||||
FLines : TSynEditStrings;
|
||||
function GetLineCapabilities(ALineIdx: Integer): TSynEditFoldLineCapabilities;
|
||||
procedure SetHighLighter(const AValue: TSynCustomFoldHighlighter);
|
||||
public
|
||||
constructor Create(aTextView : TSynEditStrings);
|
||||
function FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
|
||||
function FoldOpenInfo(ALineIdx, AFoldIdx: Integer; AType: Integer = 0): TSynFoldNodeInfo;
|
||||
//property FoldOpenInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldOpenInfo;
|
||||
//property FoldInfoCount[ALineIdx: Integer]: Integer read GetFoldInfoCount;
|
||||
//property FoldInfo[ALineIdx, AColumnIdx: Integer]: Integer read GetFoldInfo;
|
||||
function FoldLineLength(ALine, AFoldIndex: Integer): integer;
|
||||
function InfoForFoldAtTextIndex(ALine, AFoldIndex : Integer;
|
||||
HideLen: Boolean = False;
|
||||
NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo;
|
||||
function InfoListForFoldsAtTextIndex(ALine: Integer; NeedLen: Boolean = False): TSynEditFoldProviderNodeInfoList;
|
||||
|
||||
property LineCapabilities[ALineIdx: Integer]: TSynEditFoldLineCapabilities
|
||||
read GetLineCapabilities;
|
||||
property Lines: TSynEditStrings read FLines write FLines;
|
||||
property HighLighter: TSynCustomFoldHighlighter read FHighlighter write SetHighLighter;
|
||||
end;
|
||||
|
||||
@ -274,20 +314,20 @@ type
|
||||
private
|
||||
fCaret: TSynEditCaret;
|
||||
FFoldProvider: TSynEditFoldProvider;
|
||||
FHighLighter: TSynCustomFoldHighlighter;
|
||||
fLines : TSynEditStrings;
|
||||
fFoldTree : TSynTextFoldAVLTree; // Folds are stored 1-based (the 1st line is 1)
|
||||
FMarkupInfoFoldedCode: TSynSelectedColor;
|
||||
fTopLine : Integer;
|
||||
fLinesInWindow : Integer; // there may be an additional part visible line
|
||||
fTextIndexList : Array of integer; (* Map each Screen line into a line in textbuffer *)
|
||||
fFoldTypeList : Array of TSynEditFoldLineCapabilities;
|
||||
fFoldTypeList : Array of TSynEditFoldLineMapInfo;
|
||||
fOnFoldChanged : TFoldChangedEvent;
|
||||
fLockCount : Integer;
|
||||
fNeedFixFrom, fNeedFixMinEnd : Integer;
|
||||
fNeedCaretCheck : Boolean;
|
||||
|
||||
function GetCount : integer;
|
||||
function GetFoldClasifications(index : Integer): TFoldNodeClassifications;
|
||||
function GetHighLighter: TSynCustomHighlighter;
|
||||
function GetLines(index : Integer) : String;
|
||||
function GetDisplayNumber(index : Integer) : Integer;
|
||||
@ -301,20 +341,23 @@ type
|
||||
procedure SetLinesInWindow(const AValue : integer);
|
||||
protected
|
||||
Procedure CalculateMaps;
|
||||
function LengthForFoldAtTextIndex(ALine, AFoldIndex : Integer; HideLen: Boolean = False) : Integer;
|
||||
function FoldNodeAtTextIndex(AStartIndex, ColIndex: Integer): TSynTextFoldAVLNode; (* Returns xth Fold at nth TextIndex (all lines in buffer) / 1-based *)
|
||||
function FixFolding(AStart : Integer; AMinEnd : Integer; aFoldTree : TSynTextFoldAVLTree) : Boolean;
|
||||
|
||||
procedure DoCaretChanged(Sender : TObject);
|
||||
Procedure LineCountChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
|
||||
Procedure LinesInsertedAtTextIndex(AStartIndex, ALineCount : Integer;
|
||||
Procedure LinesCleared(Sender: TObject);
|
||||
Procedure LineEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount,
|
||||
aLineBrkCnt: Integer; aText: String);
|
||||
Procedure LinesInsertedAtTextIndex(AStartIndex, ALineCount, ABytePos: Integer;
|
||||
SkipFixFolding : Boolean = False);
|
||||
Procedure LinesInsertedAtViewPos(AStartPos, ALineCount : Integer;
|
||||
SkipFixFolding : Boolean = False);
|
||||
Procedure LinesDeletedAtTextIndex(AStartIndex, ALineCount : Integer;
|
||||
//Procedure LinesInsertedAtViewPos(AStartPos, ALineCount : Integer;
|
||||
// SkipFixFolding : Boolean = False);
|
||||
Procedure LinesDeletedAtTextIndex(AStartIndex, ALineCount, ABytePos: Integer;
|
||||
SkipFixFolding : Boolean = False);
|
||||
Procedure LinesDeletedAtViewPos(AStartPos, ALineCount : Integer;
|
||||
SkipFixFolding : Boolean = False);
|
||||
//Procedure LinesDeletedAtViewPos(AStartPos, ALineCount : Integer;
|
||||
// SkipFixFolding : Boolean = False);
|
||||
property FoldTree: TSynTextFoldAVLTree read fFoldTree;
|
||||
public
|
||||
constructor Create(aTextView : TSynEditStrings; ACaret: TSynEditCaret);
|
||||
destructor Destroy; override;
|
||||
@ -335,6 +378,8 @@ type
|
||||
read GetDisplayNumber;
|
||||
property FoldType[index : Integer] : TSynEditFoldLineCapabilities (* FoldIcon / State *)
|
||||
read GetFoldType;
|
||||
property FoldClasifications[index : Integer] : TFoldNodeClassifications (* FoldIcon / State *)
|
||||
read GetFoldClasifications;
|
||||
property TextIndex[index : Integer] : Integer (* Position in SynTextBuffer / result is 0-based *)
|
||||
read GetTextIndex; // maybe writable
|
||||
|
||||
@ -1512,6 +1557,20 @@ end;
|
||||
|
||||
{ TSynTextFoldAVLNode }
|
||||
|
||||
function TSynTextFoldAVLNode.GetFoldColumn: Integer;
|
||||
begin
|
||||
if fData = nil
|
||||
then Result := -1
|
||||
else Result := fData.FoldColumn;
|
||||
end;
|
||||
|
||||
function TSynTextFoldAVLNode.GetFoldColumnLen: Integer;
|
||||
begin
|
||||
if fData = nil
|
||||
then Result := -1
|
||||
else Result := fData.FoldColumnLen;
|
||||
end;
|
||||
|
||||
function TSynTextFoldAVLNode.GetFoldIndex: Integer;
|
||||
begin
|
||||
if fData = nil
|
||||
@ -1549,6 +1608,12 @@ begin
|
||||
Result := fData.VisibleLines;
|
||||
end;
|
||||
|
||||
procedure TSynTextFoldAVLNode.SetFoldColumn(const AValue: Integer);
|
||||
begin
|
||||
if fData <> nil then
|
||||
fData.FoldColumn := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynTextFoldAVLNode.Init(aData: TSynTextFoldAVLNodeData; aStartLine,
|
||||
aFoldedBefore: Integer);
|
||||
begin
|
||||
@ -1977,7 +2042,7 @@ begin
|
||||
Result.Init(r, rStartLine, rFoldedBefore);
|
||||
end;
|
||||
|
||||
procedure TSynTextFoldAVLTree.AdjustForLinesInserted(AStartLine, ALineCount : Integer);
|
||||
procedure TSynTextFoldAVLTree.AdjustForLinesInserted(AStartLine, ALineCount, ABytePos: Integer);
|
||||
Procedure DoAdjustForLinesInserted(Current : TSynTextFoldAVLNodeData;
|
||||
CurrentLine : Integer);
|
||||
var
|
||||
@ -1986,7 +2051,10 @@ procedure TSynTextFoldAVLTree.AdjustForLinesInserted(AStartLine, ALineCount : In
|
||||
while (Current <> nil) do begin
|
||||
CurrentLine := CurrentLine + Current.LineOffset;
|
||||
|
||||
if AStartLine < CurrentLine then begin
|
||||
if (AStartLine <= CurrentLine - Current.VisibleLines) or
|
||||
( (AStartLine - 1 = CurrentLine - Current.VisibleLines) and
|
||||
(ABytePos <= Current.FoldColumn) )
|
||||
then begin
|
||||
// move current node
|
||||
Current.LineOffset := Current.LineOffset + ALineCount;
|
||||
CurrentLine := CurrentLine + ALineCount;
|
||||
@ -1999,14 +2067,14 @@ procedure TSynTextFoldAVLTree.AdjustForLinesInserted(AStartLine, ALineCount : In
|
||||
Current := Current.Right;
|
||||
end
|
||||
else begin
|
||||
// grow current node
|
||||
// grow current node (there is only one node one the line, the others are nested)
|
||||
// CurrentLine <= AStartLine <= CurrentLine + Current.FullCount - 1
|
||||
t := Current.FullCount;
|
||||
if AStartLine <= CurrentLine + t - 1 then
|
||||
Current.FullCount := t + ALineCount;
|
||||
Current.MergedLineCount:= Current.MergedLineCount+ ALineCount;
|
||||
Current.AdjustParentLeftCount(ALineCount);
|
||||
TreeForNestedNode(Current, CurrentLine).AdjustForLinesInserted(AStartLine, ALineCount);
|
||||
TreeForNestedNode(Current, CurrentLine).AdjustForLinesInserted(AStartLine, ALineCount, ABytePos);
|
||||
|
||||
if Current.Right <> nil then // and move entire right
|
||||
Current.Right.LineOffset := Current.Right.LineOffset + ALineCount;
|
||||
@ -2016,11 +2084,13 @@ procedure TSynTextFoldAVLTree.AdjustForLinesInserted(AStartLine, ALineCount : In
|
||||
end;
|
||||
|
||||
begin
|
||||
{$IFDEF SynFoldDebug}debugln(['FOLD-- AdjustForLinesInsertedAStartLine:=', AStartLine, ' ALineCount=',ALineCount, ' ABytePos=',ABytePos ]); {$ENDIF}
|
||||
DoAdjustForLinesInserted(TSynTextFoldAVLNodeData(fRoot), fRootOffset);
|
||||
AdjustColumn(AStartLine+ALineCount-1, ABytePos, -ABytePos+1, True);
|
||||
end;
|
||||
|
||||
procedure TSynTextFoldAVLTree.AdjustForLinesDeleted(AStartLine,
|
||||
ALineCount : Integer);
|
||||
ALineCount, ABytePos: Integer);
|
||||
Procedure AdjustNodeForLinesDeleted(Current : TSynTextFoldAVLNodeData;
|
||||
CurrentLine, FirstLineToDelete, CountLinesToDelete : Integer);
|
||||
var
|
||||
@ -2031,9 +2101,9 @@ procedure TSynTextFoldAVLTree.AdjustForLinesDeleted(AStartLine,
|
||||
while (Current <> nil) do begin
|
||||
CurrentLine := CurrentLine + Current.LineOffset;
|
||||
|
||||
if FirstLineToDelete < CurrentLine then begin
|
||||
if FirstLineToDelete <= CurrentLine - Current.VisibleLines then begin
|
||||
// move current node
|
||||
if LastLineToDelete >= CurrentLine then begin
|
||||
if LastLineToDelete > CurrentLine - Current.VisibleLines then begin
|
||||
// overlap => shrink
|
||||
LinesBefore := CurrentLine - FirstLineToDelete;
|
||||
LinesInside := CountLinesToDelete - LinesBefore;
|
||||
@ -2042,7 +2112,7 @@ procedure TSynTextFoldAVLTree.AdjustForLinesDeleted(AStartLine,
|
||||
Current.FullCount := Max(Current.FullCount - LinesInside, -1);
|
||||
Current.MergedLineCount := Max(Current.MergedLineCount - LinesInside, 0);
|
||||
Current.AdjustParentLeftCount(Current.MergedLineCount - t); // If LineCount = -1; LeftCount will be correctd on delete node
|
||||
TreeForNestedNode(Current, CurrentLine).AdjustForLinesDeleted(CurrentLine, LinesInside);
|
||||
TreeForNestedNode(Current, CurrentLine).AdjustForLinesDeleted(CurrentLine, LinesInside, ABytePos);
|
||||
|
||||
if (Current.Right <> nil) then begin
|
||||
// move right // Calculate from the new curent.LineOffset, as below
|
||||
@ -2055,6 +2125,10 @@ procedure TSynTextFoldAVLTree.AdjustForLinesDeleted(AStartLine,
|
||||
// move current node (includes right subtree / left subtree needs eval)
|
||||
Current.LineOffset := Current.LineOffset - LinesBefore;
|
||||
CurrentLine := CurrentLine - LinesBefore;
|
||||
//if AStartLine = CurrentLine then begin
|
||||
// Current.FoldColumn := Current.FoldColumn + ABytePos-1;
|
||||
// TreeForNestedNode(Current, CurrentLine).AdjustColumn(CurrentLine, 1, ABytePos-1);
|
||||
//end;
|
||||
if Current.Left <> nil then
|
||||
Current.Left.LineOffset := Current.Left.LineOffset + LinesBefore;
|
||||
Current := Current.Left;
|
||||
@ -2076,7 +2150,7 @@ procedure TSynTextFoldAVLTree.AdjustForLinesDeleted(AStartLine,
|
||||
Current.FullCount := Current.MergedLineCount;
|
||||
Current.AdjustParentLeftCount(Current.MergedLineCount - t); // If MergedLineCount = -1; LeftCount will be correctd on delete node
|
||||
|
||||
TreeForNestedNode(Current, CurrentLine).AdjustForLinesDeleted(FirstLineToDelete, LinesInside);
|
||||
TreeForNestedNode(Current, CurrentLine).AdjustForLinesDeleted(FirstLineToDelete, LinesInside, ABytePos);
|
||||
Current := Current.Right;
|
||||
end;
|
||||
|
||||
@ -2084,9 +2158,27 @@ procedure TSynTextFoldAVLTree.AdjustForLinesDeleted(AStartLine,
|
||||
end;
|
||||
|
||||
begin
|
||||
{$IFDEF SynFoldDebug}debugln(['FOLD-- AdjustForLinesDeleted AStartLine:=', AStartLine, ' ALineCount=',ALineCount, ' ABytePos=',ABytePos ]); {$ENDIF}
|
||||
if ABytePos > 1 then
|
||||
AdjustColumn(AStartLine+ALineCount-1, 1, ABytePos-1);
|
||||
AdjustNodeForLinesDeleted(TSynTextFoldAVLNodeData(fRoot), fRootOffset, AStartLine, ALineCount);
|
||||
end;
|
||||
|
||||
procedure TSynTextFoldAVLTree.AdjustColumn(ALine, ABytePos, ACount: Integer;
|
||||
InLineBreak: boolean = False);
|
||||
var
|
||||
Node: TSynTextFoldAVLNode;
|
||||
begin
|
||||
Node := FindFoldForLine(ALine, True);
|
||||
{$IFDEF SynFoldDebug}debugln(['FOLD-- AdjustColumn ALine:=', ALine, ' ABytePos=',ABytePos, ' ACount=',ACount, ' // node.srcline=',Node.SourceLine, ' StartLine=', node.StartLine, 'column=',Node.FoldColumn ]); {$ENDIF}
|
||||
if (not Node.IsInFold) or (Node.SourceLine > ALine) then exit;
|
||||
if (Node.SourceLine = ALine) and (node.FoldColumn >= ABytePos) then begin
|
||||
node.FoldColumn := Node.FoldColumn + ACount;
|
||||
if (not InLineBreak) and (node.FoldColumn < ABytePos) then node.FoldColumn := ABytePos;
|
||||
end;
|
||||
TreeForNestedNode(Node.fData, node.StartLine).AdjustColumn(ALine, ABytePos, ACount);
|
||||
end;
|
||||
|
||||
function TSynTextFoldAVLTree.FindLastFold : TSynTextFoldAVLNode;
|
||||
var
|
||||
r : TSynTextFoldAVLNodeData;
|
||||
@ -2138,9 +2230,10 @@ procedure TSynTextFoldAVLTree.debug;
|
||||
result := 0;
|
||||
if ANode = nil then exit;
|
||||
with ANode do
|
||||
DebugLn([Format('Lines=%3d-%3d (e=%3d / idx=%d): Lcnt=%2d / Fcnt=%2d | ',
|
||||
DebugLn([Format('Lines=%3d-%3d (e=%3d / idx=%d) %2d:%d; Lcnt=%2d / Fcnt=%2d | ',
|
||||
[offset + ANode.LineOffset, offset + ANode.LineOffset + ANode.FullCount -1,
|
||||
offset + ANode.LineOffset + ANode.MergedLineCount-1, ANode.FoldIndex,
|
||||
ANode.FoldColumn, ANode.FoldColumnLen,
|
||||
MergedLineCount, FullCount]),
|
||||
ind, typ, ' (',LineOffset, ') LeftCount: ', LeftCount,
|
||||
' Balance: ',FBalance]);
|
||||
@ -2152,22 +2245,29 @@ procedure TSynTextFoldAVLTree.debug;
|
||||
Result := Result + ANode.MergedLineCount;
|
||||
end;
|
||||
begin
|
||||
debugln('StartLine, EndLine (MergedEnd, FoldIndex) - Column:Len; MergedLineCnt / FullCCnt | .. (LineOffset) ...');
|
||||
debug2('', ' -', TSynTextFoldAVLNodeData(fRoot), nil, 0);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function TSynTextFoldAVLTree.InsertNewFold(ALine, AColumn, ACount, AVisibleLines: Integer) : TSynTextFoldAVLNode;
|
||||
function TSynTextFoldAVLTree.InsertNewFold(ALine, AFoldIndex, AColumn, AColumnLen,
|
||||
ACount, AVisibleLines: Integer; AClassification: TFoldNodeClassification;
|
||||
AFoldTypeCompatible: Pointer) : TSynTextFoldAVLNode;
|
||||
var
|
||||
r : TSynTextFoldAVLNodeData;
|
||||
begin
|
||||
{$IFDEF SynFoldDebug}debugln(['FOLD-- InsertNewFold ALine:=', ALine, ' AColumn=', AColumn]);{$ENDIF}
|
||||
{$IFDEF SynFoldDebug}debugln(['FOLD-- InsertNewFold ALine:=', ALine, ' AFoldIndex=', AFoldIndex]);{$ENDIF}
|
||||
r := NewNode;
|
||||
r.LineOffset := ALine; // 1-based
|
||||
r.FoldIndex := AColumn;
|
||||
r.FoldIndex := AFoldIndex;
|
||||
r.FoldColumn := AColumn;
|
||||
r.FoldColumnLen := AColumnLen;
|
||||
r.MergedLineCount := ACount;
|
||||
r.FullCount := ACount;
|
||||
r.LeftCount := 0;
|
||||
r.VisibleLines := AVisibleLines;
|
||||
r.Classification := AClassification;
|
||||
r.FoldTypeCompatible := AFoldTypeCompatible;
|
||||
|
||||
Result.Init(r, ALine, 0);
|
||||
Result.fFoldedBefore := InsertNode(r);
|
||||
@ -2494,6 +2594,8 @@ var
|
||||
begin
|
||||
Result := [];
|
||||
if (FHighlighter = nil) or (ALineIdx < 0) then exit;
|
||||
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
if FHighlighter.FoldNestCount(ALineIdx - 1) > 0 then Result := Result + [cfFoldBody];
|
||||
if FHighlighter.FoldCloseCount(ALineIdx) > 0 then Result := Result + [cfFoldEnd, cfFoldBody];
|
||||
|
||||
@ -2520,12 +2622,18 @@ begin
|
||||
FHighlighter := AValue;
|
||||
end;
|
||||
|
||||
constructor TSynEditFoldProvider.Create(aTextView: TSynEditStrings);
|
||||
begin
|
||||
FLines := aTextView;
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.FoldOpenCount(ALineIdx: Integer; AType: Integer = 0): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if (FHighlighter = nil) or (ALineIdx < 0) then exit(0);
|
||||
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
Result := FHighlighter.FoldNodeInfoCount[ALineIdx, [sfaOpen, sfaFold]];
|
||||
if (result > 0) and (AType > 0) then begin
|
||||
i := Result ;
|
||||
@ -2551,6 +2659,7 @@ begin
|
||||
Result.FoldAction := [sfaInvalid];
|
||||
if (FHighlighter = nil) or (ALineIdx < 0) then exit;
|
||||
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
if AType = 0 then
|
||||
Result := FHighlighter.FoldNodeInfo[ALineIdx, AFoldIdx, [sfaOpen, sfaFold]]
|
||||
else begin
|
||||
@ -2569,11 +2678,59 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.FoldLineLength(ALine, AFoldIndex: Integer): integer;
|
||||
begin
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
Result := FHighlighter.FoldLineLength(ALine, AFoldIndex);
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.InfoForFoldAtTextIndex(ALine, AFoldIndex: Integer;
|
||||
HideLen: Boolean; NeedLen: Boolean = True): TSynEditFoldProviderNodeInfo;
|
||||
var
|
||||
c: LongInt;
|
||||
nd: TSynFoldNodeInfo;
|
||||
begin
|
||||
Result.LineCount := 0;
|
||||
Result.Column := 0;
|
||||
Result.ColumnLen := 0;
|
||||
Result.DefaultCollapsed := False;
|
||||
if not assigned(FHighlighter) then
|
||||
exit;
|
||||
FHighlighter.CurrentLines := FLines;
|
||||
if NeedLen then begin
|
||||
Result.LineCount := FHighlighter.FoldLineLength(ALine, AFoldIndex);
|
||||
if HideLen then
|
||||
inc(Result.LineCount);
|
||||
end
|
||||
else
|
||||
Result.LineCount := -1;
|
||||
nd := FHighlighter.FoldNodeInfo[ALine, AFoldIndex, [sfaOpen, sfaFold]];
|
||||
Result.Column := nd.LogXStart+1;
|
||||
Result.ColumnLen := nd.LogXEnd - nd.LogXStart;
|
||||
Result.DefaultCollapsed := (sfaDefaultCollapsed in nd.FoldAction);
|
||||
Result.FoldTypeCompatible := nd.FoldTypeCompatible;
|
||||
Result.FoldGroup := nd.FoldGroup;
|
||||
Result.Classification := fncHighlighter;
|
||||
end;
|
||||
|
||||
function TSynEditFoldProvider.InfoListForFoldsAtTextIndex(ALine: Integer;
|
||||
NeedLen: Boolean): TSynEditFoldProviderNodeInfoList;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
i := FoldOpenCount(ALine);
|
||||
SetLength(Result, i);
|
||||
while i > 0 do begin
|
||||
dec(i);
|
||||
Result[i] := InfoForFoldAtTextIndex(ALine, i, False, NeedLen);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TSynEditFoldedView }
|
||||
|
||||
constructor TSynEditFoldedView.Create(aTextView : TSynEditStrings; ACaret: TSynEditCaret);
|
||||
begin
|
||||
FFoldProvider := TSynEditFoldProvider.Create;
|
||||
FFoldProvider := TSynEditFoldProvider.Create(aTextView);
|
||||
fLines := aTextView;
|
||||
fCaret := ACaret;
|
||||
fCaret.AddChangeHandler({$IFDEF FPC}@{$ENDIF}DoCaretChanged);
|
||||
@ -2587,11 +2744,15 @@ begin
|
||||
FMarkupInfoFoldedCode.FrameColor := clDkGray;
|
||||
|
||||
fLines.AddChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
fLines.AddNotifyHandler(senrCleared, {$IFDEF FPC}@{$ENDIF}LinesCleared);
|
||||
fLines.AddEditHandler({$IFDEF FPC}@{$ENDIF}LineEdited);
|
||||
end;
|
||||
|
||||
destructor TSynEditFoldedView.Destroy;
|
||||
begin
|
||||
fLines.RemoveChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
fLines.RemoveNotifyHandler(senrCleared, {$IFDEF FPC}@{$ENDIF}LinesCleared);
|
||||
fLines.RemoveEditHandler({$IFDEF FPC}@{$ENDIF}LineEdited);
|
||||
fCaret.RemoveChangeHandler({$IFDEF FPC}@{$ENDIF}DoCaretChanged);
|
||||
fFoldTree.Free;
|
||||
fTextIndexList := nil;
|
||||
@ -2601,12 +2762,12 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.LinesInsertedAtTextIndex(AStartIndex, ALineCount : Integer; SkipFixFolding : Boolean);
|
||||
procedure TSynEditFoldedView.LinesInsertedAtTextIndex(AStartIndex, ALineCount, ABytePos: Integer; SkipFixFolding : Boolean);
|
||||
var top : Integer;
|
||||
begin
|
||||
if ALineCount = 0 then exit;
|
||||
top := TopTextIndex;
|
||||
fFoldTree.AdjustForLinesInserted(AStartIndex+1, ALineCount);
|
||||
fFoldTree.AdjustForLinesInserted(AStartIndex+1, ALineCount, ABytePos);
|
||||
if AStartIndex < top then
|
||||
TopTextIndex := top + ALineCount;
|
||||
if not(SkipFixFolding) then FixFoldingAtTextIndex(AStartIndex, AStartIndex+ALineCount+1)
|
||||
@ -2614,27 +2775,27 @@ begin
|
||||
if AStartIndex < top + ALineCount then CalculateMaps;
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.LinesInsertedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
|
||||
begin
|
||||
LinesInsertedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
|
||||
end;
|
||||
//procedure TSynEditFoldedView.LinesInsertedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
|
||||
//begin
|
||||
// LinesInsertedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
|
||||
//end;
|
||||
|
||||
procedure TSynEditFoldedView.LinesDeletedAtTextIndex(AStartIndex, ALineCount : Integer; SkipFixFolding : Boolean);
|
||||
procedure TSynEditFoldedView.LinesDeletedAtTextIndex(AStartIndex, ALineCount, ABytePos: Integer; SkipFixFolding : Boolean);
|
||||
var top : Integer;
|
||||
begin
|
||||
top := TopTextIndex;
|
||||
// topline may get out of sync => synedit is always going to change it back
|
||||
fFoldTree.AdjustForLinesDeleted(AStartIndex+1, ALineCount);
|
||||
fFoldTree.AdjustForLinesDeleted(AStartIndex+1, ALineCount, ABytePos);
|
||||
if not(SkipFixFolding) then
|
||||
FixFoldingAtTextIndex(AStartIndex, AStartIndex+ALineCount+1)
|
||||
else
|
||||
if AStartIndex < top - ALineCount then CalculateMaps;
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.LinesDeletedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
|
||||
begin
|
||||
LinesDeletedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
|
||||
end;
|
||||
//procedure TSynEditFoldedView.LinesDeletedAtViewPos(AStartPos, ALineCount : Integer; SkipFixFolding : Boolean);
|
||||
//begin
|
||||
// LinesDeletedAtTextIndex(ViewPosToTextIndex(AStartPos), ALineCount, SkipFixFolding);
|
||||
//end;
|
||||
|
||||
function TSynEditFoldedView.TextIndexToViewPos(aTextIndex : Integer) : Integer;
|
||||
var
|
||||
@ -2732,9 +2893,15 @@ begin
|
||||
Result := fLines.Count - fFoldTree.FindLastFold.FoldedBefore;
|
||||
end;
|
||||
|
||||
function TSynEditFoldedView.GetFoldClasifications(index : Integer): TFoldNodeClassifications;
|
||||
begin
|
||||
if (index < -1) or (index > fLinesInWindow + 1) then exit([]);
|
||||
Result := fFoldTypeList[index+1].Classifications;
|
||||
end;
|
||||
|
||||
function TSynEditFoldedView.GetHighLighter: TSynCustomHighlighter;
|
||||
begin
|
||||
Result := FHighLighter;
|
||||
Result := FFoldProvider.HighLighter;
|
||||
if assigned(Result) then
|
||||
Result.CurrentLines := fLines;
|
||||
end;
|
||||
@ -2778,7 +2945,8 @@ begin
|
||||
if not assigned(hl) then begin
|
||||
for i := 0 to fLinesInWindow+2 do begin
|
||||
fTextIndexList[i] := fTopLine + i - 2;
|
||||
fFoldTypeList[i] := [];
|
||||
fFoldTypeList[i].Capability := [];
|
||||
fFoldTypeList[i].Classifications := [];
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
@ -2798,18 +2966,23 @@ begin
|
||||
{$IFDEF SynFoldDebug}debugln(['FOLD-- CalculateMaps fTopLine:=', fTopLine, ' tpos=',tpos]);{$ENDIF}
|
||||
cnt := fLines.Count;
|
||||
for i := 0 to fLinesInWindow + 2 do begin
|
||||
fFoldTypeList[i].Classifications := [];
|
||||
if (tpos > cnt) or (tpos < 0) then begin
|
||||
// Past end of Text
|
||||
fTextIndexList[i] := -1;
|
||||
fFoldTypeList[i] := [];
|
||||
fFoldTypeList[i].Capability := [];
|
||||
end else begin
|
||||
fTextIndexList[i] := tpos - 1; // TextIndex is 0-based
|
||||
fFoldTypeList[i] := FFoldProvider.LineCapabilities[tpos - 1];
|
||||
fFoldTypeList[i].Capability := FFoldProvider.LineCapabilities[tpos - 1];
|
||||
if (node.IsInFold) then begin
|
||||
if (tpos = node.SourceLine) then
|
||||
include(fFoldTypeList[i], cfCollapsedFold)
|
||||
else if node.IsHide and (tpos + 1 = node.SourceLine) then
|
||||
include(fFoldTypeList[i], cfCollapsedHide);
|
||||
if (tpos = node.SourceLine) then begin
|
||||
include(fFoldTypeList[i].Capability, cfCollapsedFold);
|
||||
include(fFoldTypeList[i].Classifications, node.fData.Classification);
|
||||
end
|
||||
else if node.IsHide and (tpos + 1 = node.SourceLine) then begin
|
||||
include(fFoldTypeList[i].Capability, cfCollapsedHide);
|
||||
include(fFoldTypeList[i].Classifications, node.fData.Classification);
|
||||
end;
|
||||
end;
|
||||
|
||||
inc(tpos);
|
||||
@ -2846,7 +3019,7 @@ end;
|
||||
function TSynEditFoldedView.GetFoldType(index : Integer) : TSynEditFoldLineCapabilities;
|
||||
begin
|
||||
if (index < -1) or (index > fLinesInWindow + 1) then exit([]);
|
||||
Result := fFoldTypeList[index+1];
|
||||
Result := fFoldTypeList[index+1].Capability;
|
||||
end;
|
||||
|
||||
function TSynEditFoldedView.IsFolded(index : integer) : Boolean;
|
||||
@ -2858,9 +3031,7 @@ procedure TSynEditFoldedView.SetHighLighter(AValue: TSynCustomHighlighter);
|
||||
begin
|
||||
if not(AValue is TSynCustomFoldHighlighter) then
|
||||
AValue := nil;
|
||||
if FHighLighter = AValue then exit;
|
||||
FHighLighter := TSynCustomFoldHighlighter(AValue);
|
||||
FFoldProvider.HighLighter := FHighLighter;
|
||||
FFoldProvider.HighLighter := TSynCustomFoldHighlighter(AValue);
|
||||
UnfoldAll;
|
||||
end;
|
||||
|
||||
@ -2881,19 +3052,6 @@ begin
|
||||
ColIndex, ColCount, Skip, AVisibleLines);
|
||||
end;
|
||||
|
||||
function TSynEditFoldedView.LengthForFoldAtTextIndex(ALine, AFoldIndex: Integer;
|
||||
HideLen: Boolean = False) : Integer;
|
||||
var
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
hl := TSynCustomFoldHighlighter(HighLighter);
|
||||
if not assigned(hl) then
|
||||
exit(0);
|
||||
Result := hl.FoldLineLength(ALine, AFoldIndex);
|
||||
if HideLen then
|
||||
inc(Result);
|
||||
end;
|
||||
|
||||
function TSynEditFoldedView.FoldNodeAtTextIndex(AStartIndex,
|
||||
ColIndex: Integer): TSynTextFoldAVLNode;
|
||||
var
|
||||
@ -2969,7 +3127,7 @@ procedure TSynEditFoldedView.CollapseDefaultFolds;
|
||||
var
|
||||
i, j, c: Integer;
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
nd: TSynFoldNodeInfo;
|
||||
fldinf: TSynEditFoldProviderNodeInfo;
|
||||
begin
|
||||
hl := TSynCustomFoldHighlighter(HighLighter);
|
||||
if not assigned(hl) then
|
||||
@ -2984,13 +3142,13 @@ begin
|
||||
c := hl.FoldNodeInfoCount[i, [sfaOpen, sfaFold]];
|
||||
j := 0;
|
||||
while j < c do begin
|
||||
nd := hl.FoldNodeInfo[i, j, [sfaOpen, sfaFold]];
|
||||
if (sfaDefaultCollapsed in nd.FoldAction) and
|
||||
(not IsFoldedAtTextIndex(i, j))
|
||||
fldinf := FoldProvider.InfoForFoldAtTextIndex(i, j);
|
||||
if (fldinf.DefaultCollapsed) and (not IsFoldedAtTextIndex(i, j))
|
||||
then begin
|
||||
// TODO: detect default hide too
|
||||
// currently always VisibleLines=1 => since region only folds
|
||||
fFoldTree.InsertNewFold(i+2, j, LengthForFoldAtTextIndex(i, j), 1);
|
||||
fFoldTree.InsertNewFold(i+2, j, fldinf.Column, fldinf.ColumnLen, fldinf.LineCount, 1,
|
||||
fldinf.Classification, fldinf.FoldTypeCompatible);
|
||||
if Assigned(fOnFoldChanged) then
|
||||
fOnFoldChanged(i);
|
||||
end;
|
||||
@ -3223,7 +3381,7 @@ begin
|
||||
end;
|
||||
Coder := FoldCoderForType(NdInfo.FoldType);
|
||||
if coder <> nil then begin
|
||||
i := LengthForFoldAtTextIndex(NdInfo.LineIndex, NdInfo.NodeIndex);
|
||||
i := FoldProvider.InfoForFoldAtTextIndex(NdInfo.LineIndex, NdInfo.NodeIndex).LineCount;
|
||||
case coder.ReadNode(NdInfo.LogXStart, NdInfo.LineIndex, i) of
|
||||
scftFold: FoldAtTextIndex(NdInfo.LineIndex, NdInfo.NodeIndex);
|
||||
scftHide: FoldAtTextIndex(NdInfo.LineIndex, NdInfo.NodeIndex, 1, False, 0);
|
||||
@ -3248,7 +3406,7 @@ begin
|
||||
continue;
|
||||
|
||||
ndinfo :=NdiHelper1.GotoOpenAtChar(Line, entry.LogX);
|
||||
Fl := LengthForFoldAtTextIndex(Line, ndinfo.NodeIndex);
|
||||
Fl := FoldProvider.InfoForFoldAtTextIndex(Line, ndinfo.NodeIndex).LineCount;
|
||||
IsFold := (sfaFoldFold in NdInfo.FoldAction) and (entry.LinesFolded = FL);
|
||||
IsHide := (sfaFoldHide in NdInfo.FoldAction) and (entry.LinesFolded = FL + 1);
|
||||
if (sfaInvalid in ndinfo.FoldAction) or
|
||||
@ -3288,6 +3446,7 @@ var
|
||||
down: Boolean;
|
||||
NFolded: TSynTextFoldAVLNode;
|
||||
IsHide: Boolean;
|
||||
fldinf: TSynEditFoldProviderNodeInfo;
|
||||
begin
|
||||
hl := TSynCustomFoldHighlighter(HighLighter);
|
||||
if not assigned(hl) then
|
||||
@ -3319,17 +3478,20 @@ begin
|
||||
continue;
|
||||
end;
|
||||
|
||||
fldinf := FoldProvider.InfoForFoldAtTextIndex(AStartIndex, ColIndex, IsHide);
|
||||
if not NFolded.IsInFold then
|
||||
fFoldTree.InsertNewFold(AStartIndex+1+AVisibleLines, ColIndex,
|
||||
LengthForFoldAtTextIndex(AStartIndex, ColIndex, IsHide),
|
||||
AVisibleLines)
|
||||
fldinf.Column, fldinf.ColumnLen, fldinf.LineCount,
|
||||
AVisibleLines,
|
||||
fldinf.Classification, fldinf.FoldTypeCompatible)
|
||||
else
|
||||
if (AVisibleLines=0) and (not NFolded.IsHide) then begin
|
||||
// upgrade to hide
|
||||
fFoldTree.RemoveFoldForNodeAtLine(NFolded, -1);
|
||||
fFoldTree.InsertNewFold(AStartIndex+1, ColIndex,
|
||||
LengthForFoldAtTextIndex(AStartIndex, ColIndex, IsHide),
|
||||
AVisibleLines);
|
||||
fldinf.Column, fldinf.ColumnLen, fldinf.LineCount,
|
||||
AVisibleLines,
|
||||
fldinf.Classification, fldinf.FoldTypeCompatible);
|
||||
end;
|
||||
if down
|
||||
then dec(ColIndex)
|
||||
@ -3434,8 +3596,9 @@ end;
|
||||
|
||||
procedure TSynEditFoldedView.FoldAll(StartLevel : Integer = 0; IgnoreNested : Boolean = False);
|
||||
var
|
||||
c, i, l, top, t: Integer;
|
||||
c, i, top, t: Integer;
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
fldinf: TSynEditFoldProviderNodeInfo;
|
||||
begin
|
||||
hl := TSynCustomFoldHighlighter(HighLighter);
|
||||
if not assigned(hl) then
|
||||
@ -3449,12 +3612,13 @@ begin
|
||||
if (hl.FoldOpenCount(i, t) > 0)
|
||||
and (hl.FoldNestCount(i, t) > StartLevel) then begin
|
||||
c := hl.FoldOpenCount(i) -1;
|
||||
l := LengthForFoldAtTextIndex(i, c);
|
||||
fldinf := FoldProvider.InfoForFoldAtTextIndex(i, c);
|
||||
// i is 0-based
|
||||
// FoldTree is 1-based AND first line remains visble
|
||||
fFoldTree.InsertNewFold(i+2, c, l, 1); // TODO: hide too? currently VisibleLines=1
|
||||
fFoldTree.InsertNewFold(i+2, c, fldinf.Column, fldinf.ColumnLen, fldinf.LineCount, 1,
|
||||
fldinf.Classification, fldinf.FoldTypeCompatible); // TODO: hide too? currently VisibleLines=1
|
||||
if IgnoreNested then
|
||||
i := i + l;
|
||||
i := i + fldinf.LineCount;
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
@ -3470,6 +3634,9 @@ var
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
FirstchangedLine: Integer;
|
||||
|
||||
FldInfos: TSynEditFoldProviderNodeInfoList;
|
||||
GotFldInfos: Integer;
|
||||
|
||||
function DoFixFolding(doStart: Integer; doMinEnd, AtColumn: Integer;
|
||||
doFoldTree: TSynTextFoldAVLTree; node: TSynTextFoldAVLNode) : Boolean;
|
||||
|
||||
@ -3489,8 +3656,8 @@ var
|
||||
end;
|
||||
|
||||
var
|
||||
FldLine, FldIndex, FldLen, FldCol: Integer;
|
||||
MaxCol, CurLen: Integer;
|
||||
FldLine, FldIndex, FldLen, FndLen, FldCol: Integer;
|
||||
i, j, MaxCol, CurLen: Integer;
|
||||
PrevFldLine: Integer;
|
||||
SubTree: TSynTextFoldAVLTree;
|
||||
IsHide: Boolean;
|
||||
@ -3508,37 +3675,63 @@ var
|
||||
continue;
|
||||
end;
|
||||
|
||||
if (FldLine > PrevFldLine) then
|
||||
if (FldLine > PrevFldLine) then begin
|
||||
// Next Line
|
||||
AtColumn := 0;
|
||||
// check the fold-length
|
||||
MaxCol := FoldProvider.FoldOpenCount(FldIndex) - 1;
|
||||
FldCol := node.FoldIndex;
|
||||
IsHide := node.SourceLineOffset = 0;
|
||||
if (FldCol < AtColumn) then FldCol := AtColumn;
|
||||
if (FldCol <= MaxCol) and (FldCol >= AtColumn) and
|
||||
(FldLen = LengthForFoldAtTextIndex(FldIndex, FldCol, IsHide)) then begin
|
||||
CurLen := FldLen;
|
||||
end
|
||||
else if (FldCol - 1 <= MaxCol) and (FldCol > AtColumn) and (FldCol > 0) and
|
||||
(FldLen = LengthForFoldAtTextIndex(FldIndex, FldCol - 1, IsHide)) then begin
|
||||
CurLen := FldLen;
|
||||
dec(FldCol);
|
||||
end
|
||||
else if (FldCol + 1 <= MaxCol) and (FldCol + 1 >= AtColumn) and
|
||||
(FldLen = LengthForFoldAtTextIndex(FldIndex, FldCol + 1, IsHide)) then begin
|
||||
CurLen := FldLen;
|
||||
inc(FldCol);
|
||||
end
|
||||
else
|
||||
CurLen := -1;
|
||||
|
||||
if CurLen <> FldLen then begin
|
||||
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- FixFolding: Remove node with len<>len FldLine=', FldLine, ' curlen=',CurLen, ' FldLen=',FldLen]);{$ENDIF}
|
||||
DoRemoveNode(node);
|
||||
continue;
|
||||
FldInfos := nil;
|
||||
GotFldInfos := -2;
|
||||
end;
|
||||
node.fData.FoldIndex := FldCol;
|
||||
AtColumn := FldCol + 1;
|
||||
|
||||
if node.fData.Classification in [fncHighlighter, fncHighlighterEx] then begin
|
||||
// find node in list
|
||||
if GotFldInfos <> FldIndex then begin
|
||||
FldInfos := FoldProvider.InfoListForFoldsAtTextIndex(FldIndex, False);
|
||||
GotFldInfos := FldIndex;
|
||||
MaxCol := length(FldInfos)-1;
|
||||
end;
|
||||
i := -1;
|
||||
while (i < MaxCol) do begin
|
||||
inc(i);
|
||||
if (FldInfos[i].Classification <> fncHighlighter) or
|
||||
(FldInfos[i].FoldTypeCompatible <> node.fData.FoldTypeCompatible)
|
||||
then
|
||||
continue;
|
||||
FndLen := -1;
|
||||
j := abs(FldInfos[i].Column - node.FoldColumn);
|
||||
if (j > 0) and (j < node.FoldColumnLen) then begin
|
||||
//maybe
|
||||
FndLen := FoldProvider.FoldLineLength(FldIndex, i);
|
||||
if node.IsHide then inc(FndLen);
|
||||
if FndLen <> node.FullCount then Continue;
|
||||
debugln('******** FixFolding: Adjusting x pos');
|
||||
//FldInfos[i].Column := node.FoldColumn;
|
||||
end;
|
||||
if (FndLen > 0) or (FldInfos[i].Column = node.FoldColumn) then begin
|
||||
if FndLen < 0 then begin
|
||||
FndLen := FoldProvider.FoldLineLength(FldIndex, i);
|
||||
if node.IsHide then inc(FndLen);
|
||||
end;
|
||||
if abs(FndLen - node.FullCount) > 1 then continue;
|
||||
if (node.fData.Classification <> fncHighlighter) or
|
||||
(node.FoldColumn <> FldInfos[i].Column) or
|
||||
(node.FoldIndex <> i)
|
||||
then
|
||||
Result := true;
|
||||
{$IFDEF SynFoldDebug}if (node.fData.Classification <> fncHighlighter) then debugln(['>>FOLD-- FixFolding: set Node to fncHighlighter (FOUND) FldLine=', FldLine]);{$ENDIF}
|
||||
node.fData.Classification := fncHighlighter;
|
||||
node.FoldColumn := FldInfos[i].Column;
|
||||
node.fData.FoldIndex := i;
|
||||
i := -1;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if i = MaxCol then begin
|
||||
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- FixFolding: set Node to fncHighlighterEx (NOT FOUND) FldLine=', FldLine]);{$ENDIF}
|
||||
node.fData.Classification := fncHighlighterEx;
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
if (node.fData.Nested <> nil) then begin
|
||||
SubTree := doFoldTree.TreeForNestedNode(node.fData, FldLine+1);
|
||||
@ -3551,7 +3744,6 @@ var
|
||||
if CurLen <> node.MergedLineCount then
|
||||
node.fData.AdjustParentLeftCount(node.MergedLineCount - CurLen);
|
||||
end;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -3597,6 +3789,7 @@ begin
|
||||
end;
|
||||
|
||||
FirstchangedLine := -1;
|
||||
GotFldInfos := -2;
|
||||
Result := DoFixFolding(-1, AMinEnd, 0, aFoldTree, node);
|
||||
CalculateMaps;
|
||||
if Assigned(fOnFoldChanged) and (FirstchangedLine >= 0) then
|
||||
@ -3620,7 +3813,7 @@ end;
|
||||
|
||||
procedure TSynEditFoldedView.LineCountChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
|
||||
begin
|
||||
{$IFDEF SynFoldDebug}debugln(['FOLD-- LineCountChanged AIndex=', AIndex, ' Acount=',ACount]);{$ENDIF}
|
||||
{$IFDEF SynFoldDebug}try DebugLnEnter(['>> FOLD-- LineCountChanged AIndex=', AIndex, ' Acount=',ACount]);{$ENDIF}
|
||||
// no need for fix folding => synedit will be called, and scanlines will call fixfolding
|
||||
{TODO: a "need fix folding" flag => to ensure it will be called if synedit doesnt}
|
||||
if (fLockCount > 0) and (AIndex < max(fNeedFixFrom, fNeedFixMinEnd)) then begin
|
||||
@ -3628,9 +3821,33 @@ begin
|
||||
if (ACount < 0) and (AIndex < fNeedFixFrom) then inc(fNeedFixFrom, ACount);
|
||||
if (ACount > 0) and (AIndex < fNeedFixMinEnd) then inc(fNeedFixMinEnd, ACount);
|
||||
end;
|
||||
if fLines.IsInEditAction then exit;
|
||||
if ACount<0
|
||||
then LinesDeletedAtTextIndex(AIndex, -ACount, true)
|
||||
else LinesInsertedAtTextIndex(AIndex, ACount, true);
|
||||
then LinesDeletedAtTextIndex(AIndex+1, -ACount, 1, true)
|
||||
else LinesInsertedAtTextIndex(AIndex+1, ACount, 1, true);
|
||||
{$IFDEF SynFoldDebug}finally DebugLnExit(['<< FOLD-- LineCountChanged']); end;{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.LinesCleared(Sender: TObject);
|
||||
begin
|
||||
UnfoldAll;
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.LineEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount,
|
||||
aLineBrkCnt: Integer; aText: String);
|
||||
begin
|
||||
{$IFDEF SynFoldDebug}try DebugLnEnter(['>> FOLD-- LineEditied aLinePos=', aLinePos, ' aBytePos=', aBytePos, ' Acount=',ACount, ' aLineBrkCnt=',aLineBrkCnt]);{$ENDIF}
|
||||
if aLineBrkCnt<0
|
||||
then LinesDeletedAtTextIndex(aLinePos, -aLineBrkCnt, ABytePos, true)
|
||||
else if aLineBrkCnt > 0
|
||||
then LinesInsertedAtTextIndex(aLinePos, aLineBrkCnt, ABytePos, true)
|
||||
else begin
|
||||
fFoldTree.AdjustColumn(aLinePos, aBytePos, aCount);
|
||||
//if not(SkipFixFolding) then FixFoldingAtTextIndex(AStartIndex, AStartIndex+ALineCount+1)
|
||||
//else
|
||||
//if aLinePos < top + ALineCount then CalculateMaps;
|
||||
end;
|
||||
{$IFDEF SynFoldDebug}finally DebugLnExit(['<< FOLD-- LineEditied']); end;{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.FixFoldingAtTextIndex(AStartIndex: Integer; AMinEndLine : Integer);
|
||||
|
@ -62,6 +62,7 @@ type
|
||||
NestLvlStart, NestLvlEnd: Integer; // include disabled nodes, e.g markup (within each FoldGroup)
|
||||
FoldAction: TSynFoldActions;
|
||||
FoldType: Pointer; // e.g.cfbtBeginEnd, cfbtcfbtProcedure ...
|
||||
FoldTypeCompatible: Pointer; // map outer and inner begin, and other exchangeable types
|
||||
FoldGroup: Integer; // independend/overlapping folds, e.g begin/end; ifdef, region
|
||||
end;
|
||||
|
||||
|
@ -183,6 +183,9 @@ type
|
||||
function GetTextChangeStamp: int64; virtual; abstract;
|
||||
function GetViewChangeStamp: int64; virtual;
|
||||
|
||||
function GetIsInEditAction: Boolean; virtual; abstract;
|
||||
procedure IncIsInEditAction; virtual; abstract;
|
||||
procedure DecIsInEditAction; virtual; abstract;
|
||||
function GetUndoList: TSynEditUndoList; virtual; abstract;
|
||||
function GetRedoList: TSynEditUndoList; virtual; abstract;
|
||||
function GetCurUndoList: TSynEditUndoList; virtual; abstract;
|
||||
@ -252,6 +255,7 @@ type
|
||||
procedure EditLinesDelete(LogY, ACount: Integer); virtual; abstract;
|
||||
procedure EditUndo(Item: TSynEditUndoItem); virtual; abstract;
|
||||
procedure EditRedo(Item: TSynEditUndoItem); virtual; abstract;
|
||||
property IsInEditAction: Boolean read GetIsInEditAction;
|
||||
property UndoList: TSynEditUndoList read GetUndoList;
|
||||
property RedoList: TSynEditUndoList read GetRedoList;
|
||||
property CurUndoList: TSynEditUndoList read GetCurUndoList; // Re or Undo (Redo while undoing)
|
||||
@ -284,6 +288,9 @@ type
|
||||
|
||||
procedure IgnoreSendNotification(AReason: TSynEditNotifyReason;
|
||||
IncIgnore: Boolean); override;
|
||||
function GetIsInEditAction: Boolean; override;
|
||||
procedure IncIsInEditAction; override;
|
||||
procedure DecIsInEditAction; override;
|
||||
function GetUndoList: TSynEditUndoList; override;
|
||||
function GetRedoList: TSynEditUndoList; override;
|
||||
function GetCurUndoList: TSynEditUndoList; override;
|
||||
@ -1079,6 +1086,21 @@ begin
|
||||
fSynStrings.IgnoreSendNotification(AReason, IncIgnore);
|
||||
end;
|
||||
|
||||
function TSynEditStringsLinked.GetIsInEditAction: Boolean;
|
||||
begin
|
||||
Result := fSynStrings.GetIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.IncIsInEditAction;
|
||||
begin
|
||||
fSynStrings.IncIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.DecIsInEditAction;
|
||||
begin
|
||||
fSynStrings.DecIsInEditAction;
|
||||
end;
|
||||
|
||||
{ TSynEditUndoList }
|
||||
|
||||
constructor TSynEditUndoList.Create;
|
||||
|
@ -115,6 +115,7 @@ type
|
||||
FCachedNotifyStart, FCachedNotifyCount: Integer;
|
||||
FCachedNotifySender: TSynEditStrings;
|
||||
|
||||
FIsInEditAction: Integer;
|
||||
FIgnoreSendNotification: array [TSynEditNotifyReason] of Integer;
|
||||
fDosFileFormat: boolean;
|
||||
fIndexOfLongestLine: integer;
|
||||
@ -138,6 +139,9 @@ type
|
||||
function GetLengthOfLongestLine: integer; override;
|
||||
function GetTextChangeStamp: int64; override;
|
||||
|
||||
function GetIsInEditAction: Boolean; override;
|
||||
procedure IncIsInEditAction; override;
|
||||
procedure DecIsInEditAction; override;
|
||||
function GetRedoList: TSynEditUndoList; override;
|
||||
function GetUndoList: TSynEditUndoList; override;
|
||||
function GetCurUndoList: TSynEditUndoList; override;
|
||||
@ -457,6 +461,7 @@ begin
|
||||
FIsUndoing := False;
|
||||
FIsRedoing := False;
|
||||
FModified := False;
|
||||
FIsInEditAction := 0;
|
||||
|
||||
for r := low(TSynEditNotifyReason) to high(TSynEditNotifyReason)
|
||||
do case r of
|
||||
@ -647,6 +652,21 @@ begin
|
||||
Result := FTextChangeStamp;
|
||||
end;
|
||||
|
||||
function TSynEditStringList.GetIsInEditAction: Boolean;
|
||||
begin
|
||||
Result := FIsInEditAction > 0;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringList.IncIsInEditAction;
|
||||
begin
|
||||
inc(FIsInEditAction);
|
||||
end;
|
||||
|
||||
procedure TSynEditStringList.DecIsInEditAction;
|
||||
begin
|
||||
dec(FIsInEditAction);
|
||||
end;
|
||||
|
||||
function TSynEditStringList.GetRedoList: TSynEditUndoList;
|
||||
begin
|
||||
Result := fRedoList;
|
||||
@ -979,6 +999,7 @@ procedure TSynEditStringList.EditInsert(LogX, LogY: Integer; AText: String);
|
||||
var
|
||||
s: string;
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
s := Strings[LogY - 1];
|
||||
if LogX - 1 > Length(s) then begin
|
||||
AText := StringOfChar(' ', LogX - 1 - Length(s)) + AText;
|
||||
@ -988,12 +1009,14 @@ begin
|
||||
CurUndoList.AddChange(TSynEditUndoTxtInsert.Create(LogX, LogY, Length(AText)));
|
||||
MarkModified(LogY, LogY);
|
||||
SendNotification(senrEditAction, self, LogY, 0, LogX, length(AText), AText);
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
function TSynEditStringList.EditDelete(LogX, LogY, ByteLen: Integer): String;
|
||||
var
|
||||
s: string;
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
s := Strings[LogY - 1];
|
||||
if LogX - 1 > Length(s) then
|
||||
exit;
|
||||
@ -1002,12 +1025,14 @@ begin
|
||||
CurUndoList.AddChange(TSynEditUndoTxtDelete.Create(LogX, LogY, Result));
|
||||
MarkModified(LogY, LogY);
|
||||
SendNotification(senrEditAction, self, LogY, 0, LogX, -ByteLen, '');
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringList.EditLineBreak(LogX, LogY: Integer);
|
||||
var
|
||||
s: string;
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
if Count = 0 then Add('');
|
||||
s := Strings[LogY - 1];
|
||||
if LogX - 1 < length(s) then
|
||||
@ -1016,12 +1041,14 @@ begin
|
||||
CurUndoList.AddChange(TSynEditUndoTxtLineBreak.Create(LogY));
|
||||
MarkModified(LogY, LogY + 1);
|
||||
SendNotification(senrEditAction, self, LogY, 1, LogX, 0, '');
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringList.EditLineJoin(LogY: Integer; FillText: String = '');
|
||||
var
|
||||
t: string;
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
t := Strings[LogY - 1];
|
||||
if FillText <> '' then
|
||||
EditInsert(1 + Length(t), LogY, FillText);
|
||||
@ -1032,28 +1059,33 @@ begin
|
||||
Delete(LogY);
|
||||
MarkModified(LogY, LogY);
|
||||
SendNotification(senrEditAction, self, LogY, -1, 1+length(t), 0, '');
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringList.EditLinesInsert(LogY, ACount: Integer;
|
||||
AText: String = '');
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
InsertLines(LogY - 1, ACount);
|
||||
CurUndoList.AddChange(TSynEditUndoTxtLinesIns.Create(LogY, ACount));
|
||||
SendNotification(senrEditAction, self, LogY, ACount, 1, 0, '');
|
||||
if AText <> '' then
|
||||
EditInsert(1, LogY, AText);
|
||||
MarkModified(LogY, LogY + ACount - 1);
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringList.EditLinesDelete(LogY, ACount: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
for i := LogY to LogY + ACount - 1 do
|
||||
EditDelete(1, i, length(Strings[i-1]));
|
||||
DeleteLines(LogY - 1, ACount);
|
||||
CurUndoList.AddChange(TSynEditUndoTxtLinesDel.Create(LogY, ACount));
|
||||
SendNotification(senrEditAction, self, LogY, -ACount, 1, 0, '');
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringList.EditUndo(Item: TSynEditUndoItem);
|
||||
|
@ -861,6 +861,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
IncIsInEditAction;
|
||||
if Count = 0 then fSynStrings.Add('');
|
||||
FlushNotificationCache;
|
||||
IgnoreSendNotification(senrEditAction, True);
|
||||
@ -911,6 +912,7 @@ begin
|
||||
UpdateLineText(LogY);
|
||||
IgnoreSendNotification(senrEditAction, False);
|
||||
SendNotification(senrEditAction, self, LogY, 0, SaveLogX, length(SaveText), SaveText);
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
Function TSynEditStringTrimmingList.EditDelete(LogX, LogY, ByteLen: Integer): String;
|
||||
@ -924,6 +926,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
IncIsInEditAction;
|
||||
FlushNotificationCache;
|
||||
SaveByteLen := ByteLen;
|
||||
Result := '';
|
||||
@ -953,6 +956,7 @@ begin
|
||||
|
||||
IgnoreSendNotification(senrEditAction, False);
|
||||
SendNotification(senrEditAction, self, LogY, 0, LogX, -SaveByteLen, '');
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.EditLineBreak(LogX, LogY: Integer);
|
||||
@ -964,6 +968,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
IncIsInEditAction;
|
||||
FlushNotificationCache;
|
||||
IgnoreSendNotification(senrEditAction, True);
|
||||
s := Spaces(LogY - 1);
|
||||
@ -988,6 +993,7 @@ begin
|
||||
EditMoveToTrim(LogY + 1, length(s) - LastNoneSpacePos(s));
|
||||
IgnoreSendNotification(senrEditAction, False);
|
||||
SendNotification(senrEditAction, self, LogY, 1, LogX, 0, '');
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.EditLineJoin(LogY: Integer;
|
||||
@ -1000,6 +1006,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
IncIsInEditAction;
|
||||
FlushNotificationCache;
|
||||
EditMoveFromTrim(LogY, length(Spaces(LogY - 1)));
|
||||
|
||||
@ -1013,6 +1020,7 @@ begin
|
||||
// Trim any existing (committed/real) spaces
|
||||
s := fSynStrings[LogY - 1];
|
||||
EditMoveToTrim(LogY, length(s) - LastNoneSpacePos(s));
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.EditLinesInsert(LogY, ACount: Integer;
|
||||
@ -1020,20 +1028,24 @@ procedure TSynEditStringTrimmingList.EditLinesInsert(LogY, ACount: Integer;
|
||||
var
|
||||
s: string;
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
FlushNotificationCache;
|
||||
fSynStrings.EditLinesInsert(LogY, ACount, AText);
|
||||
s := fSynStrings[LogY - 1];
|
||||
EditMoveToTrim(LogY, length(s) - LastNoneSpacePos(s));
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.EditLinesDelete(LogY, ACount: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
IncIsInEditAction;
|
||||
FlushNotificationCache;
|
||||
for i := LogY to LogY + ACount - 1 do
|
||||
EditMoveFromTrim(i, length(Spaces(i - 1)));
|
||||
fSynStrings.EditLinesDelete(LogY, ACount);
|
||||
DecIsInEditAction;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.EditUndo(Item: TSynEditUndoItem);
|
||||
|
@ -57,6 +57,8 @@ type
|
||||
procedure ResetDefaults; override;
|
||||
end;
|
||||
|
||||
TDrawNodeSymbolOptions = set of (nsoSubtype, nsoLostHl);
|
||||
|
||||
{ TSynGutterCodeFolding }
|
||||
|
||||
TSynGutterCodeFolding = class(TSynGutterPartBase)
|
||||
@ -76,7 +78,7 @@ type
|
||||
procedure InitPopUpImageList;
|
||||
procedure DrawNodeSymbol(Canvas: TCanvas; Rect: TRect;
|
||||
NodeType: TSynEditFoldLineCapability;
|
||||
SubType: Integer);
|
||||
SubType: TDrawNodeSymbolOptions);
|
||||
protected
|
||||
function PreferedWidth: Integer; override;
|
||||
procedure CreatePopUpMenuEntries(APopUp: TPopupMenu; ALine: Integer); virtual;
|
||||
@ -197,22 +199,22 @@ begin
|
||||
FPopUpImageList.DrawingStyle := dsTransparent;
|
||||
|
||||
NewImg;
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfFoldStart, 0); // [-]
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfFoldStart, []); // [-]
|
||||
FPopUpImageList.Add(img, nil);
|
||||
img.Free;
|
||||
|
||||
NewImg;
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfCollapsedFold, 0); // [+]
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfCollapsedFold, []); // [+]
|
||||
FPopUpImageList.Add(img, nil);
|
||||
img.Free;
|
||||
|
||||
NewImg;
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfHideStart, 0); // [.]
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfHideStart, []); // [.]
|
||||
FPopUpImageList.Add(img, nil);
|
||||
img.Free;
|
||||
|
||||
NewImg;
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfCollapsedHide, 0); // [v]
|
||||
DrawNodeSymbol(img.Canvas, Rect(3,3,14,14), cfCollapsedHide, []); // [v]
|
||||
FPopUpImageList.Add(img, nil);
|
||||
img.Free;
|
||||
|
||||
@ -437,15 +439,23 @@ begin
|
||||
end;
|
||||
|
||||
procedure TSynGutterCodeFolding.DrawNodeSymbol(Canvas: TCanvas; Rect: TRect;
|
||||
NodeType: TSynEditFoldLineCapability; SubType: Integer);
|
||||
NodeType: TSynEditFoldLineCapability; SubType: TDrawNodeSymbolOptions);
|
||||
var
|
||||
Points: Array [0..3] of TPoint;
|
||||
X, Y: Integer;
|
||||
AliasMode: TAntialiasingMode;
|
||||
OdlCosmetic: Boolean;
|
||||
begin
|
||||
AliasMode := Canvas.AntialiasingMode;
|
||||
Canvas.AntialiasingMode:=amOff;
|
||||
if nsoLostHl in SubType then begin
|
||||
Canvas.Pen.Style := psDot;
|
||||
OdlCosmetic := Canvas.Pen.Cosmetic;
|
||||
Canvas.Pen.Cosmetic := False;
|
||||
end;
|
||||
Canvas.Rectangle(Rect);
|
||||
Canvas.Pen.Style := psSolid;
|
||||
Canvas.Pen.Cosmetic := OdlCosmetic;
|
||||
X := (Rect.Left - 1 + Rect.Right) div 2;
|
||||
Y := (Rect.Top - 1 + Rect.Bottom) div 2;
|
||||
|
||||
@ -472,8 +482,8 @@ begin
|
||||
end;
|
||||
cfCollapsedHide:
|
||||
begin
|
||||
case SubType of
|
||||
0: begin
|
||||
case nsoSubtype in SubType of
|
||||
false: begin
|
||||
// [v]
|
||||
Points[0].X := X;
|
||||
Points[0].y := Y + 2;
|
||||
@ -484,7 +494,7 @@ begin
|
||||
Points[3].X := X;
|
||||
Points[3].y := Y + 2;
|
||||
end;
|
||||
1: begin
|
||||
true: begin
|
||||
// [v]
|
||||
Points[0].X := X;
|
||||
Points[0].y := Y - 2;
|
||||
@ -522,9 +532,14 @@ var
|
||||
ptCenter : TPoint;
|
||||
isPrevLine: Boolean;
|
||||
i: Integer;
|
||||
HasExHl: Boolean;
|
||||
DrawOpts: TDrawNodeSymbolOptions;
|
||||
begin
|
||||
isPrevLine := IsFoldHidePreviousLine(iLine);
|
||||
LineOffset := 0;
|
||||
DrawOpts := [];
|
||||
if fncHighlighterEx in FoldView.FoldClasifications[iLine] then
|
||||
include(DrawOpts, nsoLostHl);
|
||||
|
||||
//center of the draw area
|
||||
ptCenter.X := (rcCodeFold.Left + rcCodeFold.Right) div 2;
|
||||
@ -566,8 +581,9 @@ var
|
||||
Canvas.Pen.Color := MarkupInfo.FrameColor;
|
||||
|
||||
i:= 0;
|
||||
if isPrevLine and (NodeType = cfCollapsedHide) then i := 1;
|
||||
DrawNodeSymbol(Canvas, rcNode, NodeType, i);
|
||||
if isPrevLine and (NodeType = cfCollapsedHide) then
|
||||
include(DrawOpts, nsoSubtype);
|
||||
DrawNodeSymbol(Canvas, rcNode, NodeType, DrawOpts);
|
||||
|
||||
Canvas.Pen.Color := MarkupInfo.Foreground;
|
||||
Canvas.Brush.Style := bsSolid;
|
||||
|
@ -150,6 +150,34 @@ const
|
||||
cfbtUnitSection, // unitsection, actually interface only
|
||||
cfbtVarType, cfbtLocalVarType];
|
||||
|
||||
PascalFoldTypeCompatibility: Array [TPascalCodeFoldBlockType] of TPascalCodeFoldBlockType =
|
||||
( cfbtBeginEnd, // Nested
|
||||
cfbtBeginEnd, // cfbtTopBeginEnd, // Begin of Procedure
|
||||
cfbtNestedComment,
|
||||
cfbtProcedure,
|
||||
cfbtUses,
|
||||
cfbtVarType,
|
||||
cfbtVarType, // cfbtLocalVarType,
|
||||
cfbtClass,
|
||||
cfbtClassSection,
|
||||
cfbtUnitSection,
|
||||
cfbtProgram,
|
||||
cfbtUnit,
|
||||
cfbtRecord,
|
||||
cfbtTry,
|
||||
cfbtExcept,
|
||||
cfbtRepeat,
|
||||
cfbtAsm,
|
||||
cfbtCase,
|
||||
cfbtIfDef, // {$IfDef} directive, this is not counted in the Range-Node
|
||||
cfbtRegion, // {%Region} user folds, not counted in the Range-Node
|
||||
cfbtNestedComment, //cfbtAnsiComment, // (* ... *)
|
||||
cfbtNestedComment, //cfbtBorCommand, // { ... }
|
||||
cfbtSlashComment, // //
|
||||
// Internal type / not configurable
|
||||
cfbtNone
|
||||
);
|
||||
|
||||
type
|
||||
|
||||
TPascalCompilerMode = (
|
||||
@ -3422,6 +3450,7 @@ begin
|
||||
Node.LogXStart := Run;
|
||||
Node.LogXEnd := Run + fStringLen;
|
||||
Node.FoldType := Pointer(PtrInt(ABlockType));
|
||||
Node.FoldTypeCompatible := Pointer(PascalFoldTypeCompatibility[ABlockType]);
|
||||
Node.FoldAction := aActions;
|
||||
case ABlockType of
|
||||
cfbtRegion:
|
||||
|
@ -13,7 +13,7 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, testregistry, TestBase, TestHighlightPas, Forms, LCLProc,
|
||||
SynEdit, SynHighlighterPas, SynEditFoldedView, SynEditHighlighterFoldBase,
|
||||
SynGutterCodeFolding;
|
||||
SynGutterCodeFolding, SynEditKeyCmds;
|
||||
|
||||
type
|
||||
|
||||
@ -37,18 +37,142 @@ type
|
||||
function TestTextPasHl(AIfCol: Integer): TStringArray;
|
||||
function TestText4: TStringArray;
|
||||
function TestText5: TStringArray;
|
||||
function TestText6: TStringArray;
|
||||
function TestTextHide(ALen: Integer): TStringArray;
|
||||
function TestTextHide2(ALen: Integer): TStringArray;
|
||||
function TestTextHide3: TStringArray;
|
||||
function TestTextHide4: TStringArray;
|
||||
protected
|
||||
procedure TstSetText(AName: String; AText: TStringArray);
|
||||
procedure TstFold(AName: String; AFoldAtIndex: integer; AExpectedLines: Array of Integer);
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum: integer; AExpectedLines: Array of Integer);
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AExpectedLines: Array of Integer);
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AFoldAtSkip: Boolean; AExpectedLines: Array of Integer);
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AFoldAtSkip: Boolean; AVisibleLines: Integer; AExpectedLines: Array of Integer);
|
||||
procedure TstUnFoldAtCaret(AName: String; X, Y: integer; AExpectedLines: Array of Integer);
|
||||
procedure TstTxtIndexToViewPos(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
procedure TstViewPosToTextIndex(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
procedure TstTextIndexToScreenLine(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
procedure TstScreenLineToTextIndex(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
published
|
||||
procedure TestFold;
|
||||
procedure TestFoldEdit;
|
||||
procedure TestFoldStateFromText;
|
||||
procedure TestFoldStateDesc;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
TSynEditFoldedViewHack = class(TSynEditFoldedView) end;
|
||||
|
||||
procedure TTestFoldedView.TstSetText(AName: String; AText: TStringArray);
|
||||
begin
|
||||
PopBaseName;
|
||||
ReCreateEdit;
|
||||
SetLines(AText);
|
||||
PushBaseName(AName);
|
||||
end;
|
||||
|
||||
procedure TTestFoldedView.TstFold(AName: String; AFoldAtIndex: integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TTestFoldedView.TstFold(AName: String; AFoldAtIndex, AFoldAtColum: integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TTestFoldedView.TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum, AFoldAtColCnt);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TTestFoldedView.TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AFoldAtSkip: Boolean; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum, AFoldAtColCnt, AFoldAtSkip);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TTestFoldedView.TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AFoldAtSkip: Boolean; AVisibleLines: Integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum, AFoldAtColCnt, AFoldAtSkip, AVisibleLines);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
|
||||
procedure TTestFoldedView.TstUnFoldAtCaret(AName: String; X, Y: integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
SynEdit.CaretXY := Point(X, Y);
|
||||
TestFoldedText('UnfoldCaret - '+AName, AExpectedLines);
|
||||
end;
|
||||
|
||||
// ViewPos is 1 based
|
||||
procedure TTestFoldedView.TstTxtIndexToViewPos(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i])+') to ViewPos[1-based]('+IntToStr( AExpectedPairs[i+1])+') ',
|
||||
AExpectedPairs[i+1], FoldedView.TextIndexToViewPos(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' ViewPos[1-based]('+IntToStr( AExpectedPairs[i+1])+') to TxtIdx('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.ViewPosToTextIndex(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
// ViewPos is 1 based // Reverse of the above
|
||||
procedure TTestFoldedView.TstViewPosToTextIndex(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' ViewPos[1-based]('+IntToStr( AExpectedPairs[i])+') to TxtIdx('+IntToStr( AExpectedPairs[i+1])+')',
|
||||
AExpectedPairs[i+1], FoldedView.ViewPosToTextIndex(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i+1])+') to ViewPos[1-based]('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.TextIndexToViewPos(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ScreenLine is 0 based
|
||||
procedure TTestFoldedView.TstTextIndexToScreenLine(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i])+') to ScreenLine[0-based]('+IntToStr( AExpectedPairs[i+1])+') ',
|
||||
AExpectedPairs[i+1], FoldedView.TextIndexToScreenLine(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' ScreenLine[0-based]('+IntToStr( AExpectedPairs[i+1])+') to TxtIdx('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.ScreenLineToTextIndex(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
// ScreenLine is 0 based // Reverse of the above
|
||||
procedure TTestFoldedView.TstScreenLineToTextIndex(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' ScreenLine[0-based]('+IntToStr( AExpectedPairs[i])+') to TxtIdx('+IntToStr( AExpectedPairs[i+1])+') ',
|
||||
AExpectedPairs[i+1], FoldedView.ScreenLineToTextIndex(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i+1])+') to ScreenLine[0-based]('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.TextIndexToScreenLine(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure TTestFoldedView.TestFoldedText(AName: String; ALines: array of Integer);
|
||||
var
|
||||
ExpTxt: String;
|
||||
@ -210,6 +334,19 @@ begin
|
||||
Result[7] := '';
|
||||
end;
|
||||
|
||||
function TTestFoldedView.TestText6: TStringArray;
|
||||
begin
|
||||
SetLength(Result, 8);
|
||||
Result[0] := 'program Foo;';
|
||||
Result[1] := 'procedure a; procedure b;'; // 2 folds open on one line
|
||||
Result[2] := ' begin writeln(1);';
|
||||
Result[3] := ' end; // inner';
|
||||
Result[4] := 'begin';
|
||||
Result[5] := ' writeln(2)';
|
||||
Result[6]:= 'end;';
|
||||
Result[7]:= '';
|
||||
end;
|
||||
|
||||
function TTestFoldedView.TestTextHide(ALen: Integer): TStringArray;
|
||||
begin
|
||||
SetLength(Result, 3+ALen);
|
||||
@ -264,108 +401,6 @@ end;
|
||||
|
||||
|
||||
procedure TTestFoldedView.TestFold;
|
||||
|
||||
procedure TstSetText(AName: String; AText: TStringArray);
|
||||
begin
|
||||
PopBaseName;
|
||||
ReCreateEdit;
|
||||
SetLines(AText);
|
||||
PushBaseName(AName);
|
||||
end;
|
||||
|
||||
procedure TstFold(AName: String; AFoldAtIndex: integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum: integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum, AFoldAtColCnt);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AFoldAtSkip: Boolean; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum, AFoldAtColCnt, AFoldAtSkip);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
procedure TstFold(AName: String; AFoldAtIndex, AFoldAtColum, AFoldAtColCnt: integer;
|
||||
AFoldAtSkip: Boolean; AVisibleLines: Integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
FoldedView.FoldAtTextIndex(AFoldAtIndex, AFoldAtColum, AFoldAtColCnt, AFoldAtSkip, AVisibleLines);
|
||||
TestFoldedText(AName, AExpectedLines);
|
||||
end;
|
||||
|
||||
procedure TstUnFoldAtCaret(AName: String; X, Y: integer; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
SynEdit.CaretXY := Point(X, Y);
|
||||
TestFoldedText('UnfoldCaret - '+AName, AExpectedLines);
|
||||
end;
|
||||
|
||||
// ViewPos is 1 based
|
||||
procedure TstTxtIndexToViewPos(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i])+') to ViewPos[1-based]('+IntToStr( AExpectedPairs[i+1])+') ',
|
||||
AExpectedPairs[i+1], FoldedView.TextIndexToViewPos(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' ViewPos[1-based]('+IntToStr( AExpectedPairs[i+1])+') to TxtIdx('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.ViewPosToTextIndex(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
// ViewPos is 1 based // Reverse of the above
|
||||
procedure TstViewPosToTextIndex(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' ViewPos[1-based]('+IntToStr( AExpectedPairs[i])+') to TxtIdx('+IntToStr( AExpectedPairs[i+1])+')',
|
||||
AExpectedPairs[i+1], FoldedView.ViewPosToTextIndex(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i+1])+') to ViewPos[1-based]('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.TextIndexToViewPos(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ScreenLine is 0 based
|
||||
procedure TstTextIndexToScreenLine(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i])+') to ScreenLine[0-based]('+IntToStr( AExpectedPairs[i+1])+') ',
|
||||
AExpectedPairs[i+1], FoldedView.TextIndexToScreenLine(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' ScreenLine[0-based]('+IntToStr( AExpectedPairs[i+1])+') to TxtIdx('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.ScreenLineToTextIndex(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
// ScreenLine is 0 based // Reverse of the above
|
||||
procedure TstScreenLineToTextIndex(AName: String; AExpectedPairs: Array of Integer; ADoReverse: Boolean = false);
|
||||
var i: Integer;
|
||||
begin
|
||||
i := 0;
|
||||
while i < high(AExpectedPairs)-1 do begin
|
||||
AssertEquals(AName+' ScreenLine[0-based]('+IntToStr( AExpectedPairs[i])+') to TxtIdx('+IntToStr( AExpectedPairs[i+1])+') ',
|
||||
AExpectedPairs[i+1], FoldedView.ScreenLineToTextIndex(AExpectedPairs[i]));
|
||||
if ADoReverse then
|
||||
AssertEquals(AName+' TxtIdx('+IntToStr( AExpectedPairs[i+1])+') to ScreenLine[0-based]('+IntToStr( AExpectedPairs[i])+') [R]',
|
||||
AExpectedPairs[i], FoldedView.TextIndexToScreenLine(AExpectedPairs[i+1]));
|
||||
inc(i, 2);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RunTest;
|
||||
begin
|
||||
PushBaseName('');
|
||||
@ -587,14 +622,493 @@ begin
|
||||
RunTest;
|
||||
end;
|
||||
|
||||
procedure TTestFoldedView.TestFoldStateFromText;
|
||||
procedure TstSetText(AName: String; AText: TStringArray);
|
||||
procedure TTestFoldedView.TestFoldEdit;
|
||||
|
||||
procedure DoChar(x, y: integer; char: String);
|
||||
begin
|
||||
PopBaseName;
|
||||
ReCreateEdit;
|
||||
SetLines(AText);
|
||||
PushBaseName(AName);
|
||||
SynEdit.CaretXY := Point(x,y);
|
||||
SynEdit.CommandProcessor(ecChar, char, nil);
|
||||
end;
|
||||
procedure DoNewLine(x, y: integer);
|
||||
begin
|
||||
SynEdit.CaretXY := Point(x,y);
|
||||
SynEdit.CommandProcessor(ecLineBreak, '', nil);
|
||||
end;
|
||||
procedure DoBackspace(x, y: integer);
|
||||
begin
|
||||
SynEdit.CaretXY := Point(x,y);
|
||||
SynEdit.CommandProcessor(ecDeleteLastChar, '', nil);
|
||||
end;
|
||||
|
||||
procedure TestNodeAtPos(name: string; x, y: integer);
|
||||
var
|
||||
n: TSynTextFoldAVLNode;
|
||||
begin
|
||||
n := TSynEditFoldedViewHack(FoldedView).FoldTree.FindFoldForLine(y, true);
|
||||
AssertTrue(BaseTestName+' '+ name+ ' got node for line '+inttostr(y), n.IsInFold);
|
||||
AssertEquals(BaseTestName+' '+ name+ ' got node for src-line '+inttostr(y), y, n.SourceLine);
|
||||
AssertEquals(BaseTestName+' '+ name+ ' got node for src-line '+inttostr(y)+' col='+inttostr(x), x, n.FoldColumn);
|
||||
end;
|
||||
|
||||
var
|
||||
n: string;
|
||||
i: integer;
|
||||
begin
|
||||
|
||||
{%region simple}
|
||||
TstSetText('Simple: fold Prc', TestText);
|
||||
|
||||
TstFold('', 1, [0, 1]);
|
||||
TestNodeAtPos('', 1, 2);
|
||||
|
||||
DoChar(1,2, ' ');
|
||||
TestFoldedText('(ins char)', [0, 1]);
|
||||
TestNodeAtPos('(ins char)', 2, 2);
|
||||
|
||||
DoNewLine(13,1);
|
||||
TestFoldedText('(newline before)', [0, 1, 2]);
|
||||
TestNodeAtPos('(newline before)', 2, 3);
|
||||
|
||||
DoBackspace(1,2);
|
||||
TestFoldedText('(del newline)', [0, 1]);
|
||||
TestNodeAtPos('(del newline)', 2, 2);
|
||||
|
||||
DoBackspace(2,2);
|
||||
TestFoldedText('(del char)', [0, 1]);
|
||||
TestNodeAtPos('(del char)', 1, 2);
|
||||
|
||||
DoBackspace(1,2);
|
||||
TestFoldedText('(del to prev line)', [0]);
|
||||
TestNodeAtPos('(del to prev line)', 13, 1);
|
||||
|
||||
DoNewLine(13,1); // newline, on same line
|
||||
TestFoldedText('(newline on srcline)', [0, 1]);
|
||||
TestNodeAtPos('(newline on srcline)', 1, 2);
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region Nested}
|
||||
TstSetText('Nested: fold Prc Beg ', TestText);
|
||||
|
||||
for i := 0 to 63 do begin
|
||||
PushBaseName(inttostr(i));
|
||||
SetLines(TestText);
|
||||
SynEdit.UnfoldAll;
|
||||
n := '';
|
||||
TstFold(n, 2, [0, 1, 2]); TestNodeAtPos(n, 1, 3);
|
||||
n := 'outer';
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
|
||||
n := '(ins char)';
|
||||
//debugln(['############### ',n]);
|
||||
DoChar(1,2, ' ');
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 2, 2);
|
||||
if (i and 1) <> 0 then begin
|
||||
n := '(ins char) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,3, [0,1,2]); TestNodeAtPos(n, 1, 3);
|
||||
n := '(ins char) refold';
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 2, 2); // re-folded
|
||||
end;
|
||||
|
||||
n := '(newline before)';
|
||||
//debugln(['############### ',n]);
|
||||
DoNewLine(13,1);
|
||||
TestFoldedText(n, [0, 1, 2]); TestNodeAtPos(n, 2, 3);
|
||||
if (i and 2) <> 0 then begin
|
||||
n := '(newline before) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,4, [0,1,2,3]); TestNodeAtPos(n, 1, 4);
|
||||
n := '(newline before) refold';
|
||||
TstFold(n, 2, [0, 1, 2]); TestNodeAtPos(n, 2, 3); // re-folded
|
||||
end;
|
||||
|
||||
n := '(del newline)';
|
||||
//debugln(['############### ',n]);
|
||||
DoBackspace(1,2);
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 2, 2);
|
||||
if (i and 4) <> 0 then begin
|
||||
n := '(del newline) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,3, [0,1,2]); TestNodeAtPos(n, 1, 3);
|
||||
n := '(del newline) refold';
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 2, 2); // re-folded
|
||||
end;
|
||||
|
||||
n := '(del char)';
|
||||
//debugln(['############### ',n]);
|
||||
DoBackspace(2,2);
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
if (i and 8) <> 0 then begin
|
||||
n := '(del char) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,3, [0,1,2]); TestNodeAtPos(n, 1, 3);
|
||||
n := '(del char) refold';
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 1, 2); // re-folded
|
||||
end;
|
||||
|
||||
n := '(del to prev line)';
|
||||
//debugln(['############### ',n]);
|
||||
DoBackspace(1,2);
|
||||
TestFoldedText(n, [0]); TestNodeAtPos(n, 13, 1);
|
||||
if (i and 16) <> 0 then begin
|
||||
n := '(del to prev line) nested';
|
||||
TstUnFoldAtCaret(n, 1,2, [0,1]); TestNodeAtPos(n, 1, 2);
|
||||
n := '(del to prev line) refold';
|
||||
TstFold(n, 0, [0]); TestNodeAtPos(n, 13, 1); // re-folded
|
||||
end;
|
||||
|
||||
n := '(newline on srcline)';
|
||||
DoNewLine(13,1); // newline, on same line
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
if (i and 32) <> 0 then begin
|
||||
n := '(del to prev line) nested';
|
||||
TstUnFoldAtCaret(n, 1,3, [0,1,2]); TestNodeAtPos(n, 1, 3);
|
||||
n := '(del to prev line) refold';
|
||||
TstFold(n, 1, [0,1]); TestNodeAtPos(n, 1, 2); // re-folded
|
||||
end;
|
||||
|
||||
PopBaseName;
|
||||
end;
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region Nested}
|
||||
TstSetText('Nested, same line: fold Prc Beg', TestText6);
|
||||
|
||||
for i := 0 to 255 do begin
|
||||
PushBaseName(inttostr(i));
|
||||
SetLines(TestText6);
|
||||
SynEdit.UnfoldAll;
|
||||
n := '';
|
||||
TstFold(n, 1, 1, [0, 1, 4,5,6]); TestNodeAtPos(n, 14, 2);
|
||||
n := 'outer';
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
|
||||
n := '(ins char)';
|
||||
//debugln(['############### ',n]);
|
||||
DoChar(1,2, ' ');
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 2, 2);
|
||||
if (i and 1) <> 0 then begin
|
||||
n := '(ins char) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,5, [0,1,4,5,6]); TestNodeAtPos(n, 15, 2);
|
||||
n := '(ins char) refold';
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 2, 2); // re-folded
|
||||
end;
|
||||
|
||||
n := '(ins char middle)';
|
||||
//debugln(['############### ',n]);
|
||||
DoChar(14,2, ' ');
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 2, 2);
|
||||
if (i and 2) <> 0 then begin
|
||||
n := '(ins char middle) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,5, [0,1,4,5,6]); TestNodeAtPos(n, 16, 2);
|
||||
n := '(ins char middle) refold';
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 2, 2); // re-folded
|
||||
end;
|
||||
|
||||
|
||||
n := '(newline before)';
|
||||
//debugln(['############### ',n]);
|
||||
DoNewLine(13,1);
|
||||
TestFoldedText(n, [0, 1, 2]); TestNodeAtPos(n, 2, 3);
|
||||
if (i and 4) <> 0 then begin
|
||||
n := '(newline before) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,6, [0,1,2, 5,6,7]); TestNodeAtPos(n, 16, 3);
|
||||
n := '(newline before) refold';
|
||||
TstFold(n, 2, 0, [0, 1, 2]); TestNodeAtPos(n, 2, 3); // re-folded
|
||||
end;
|
||||
|
||||
n := '(del newline)';
|
||||
//debugln(['############### ',n]);
|
||||
DoBackspace(1,2);
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 2, 2);
|
||||
if (i and 8) <> 0 then begin
|
||||
n := '(del newline) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,5, [0,1, 4,5,6]); TestNodeAtPos(n, 16, 2);
|
||||
n := '(del newline) refold';
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 2, 2); // re-folded
|
||||
end;
|
||||
|
||||
n := '(del char)';
|
||||
//debugln(['############### ',n]);
|
||||
DoBackspace(2,2);
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
if (i and 16) <> 0 then begin
|
||||
n := '(del char) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,5, [0,1,4,5,6]); TestNodeAtPos(n, 15, 2);
|
||||
n := '(del char) refold';
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 1, 2); // re-folded
|
||||
end;
|
||||
|
||||
n := '(del char middle)';
|
||||
//debugln(['############### ',n]);
|
||||
DoBackspace(15,2);
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
if (i and 32) <> 0 then begin
|
||||
n := '(del char middle) nested';
|
||||
//debugln(['############### ',n]);
|
||||
TstUnFoldAtCaret(n, 1,5, [0,1,4,5,6]); TestNodeAtPos(n, 14, 2);
|
||||
n := '(del char middle) refold';
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 1, 2); // re-folded
|
||||
end;
|
||||
|
||||
|
||||
n := '(del to prev line)';
|
||||
//debugln(['############### ',n]);
|
||||
DoBackspace(1,2);
|
||||
TestFoldedText(n, [0]); TestNodeAtPos(n, 13, 1);
|
||||
if (i and 64) <> 0 then begin
|
||||
n := '(del to prev line) nested';
|
||||
TstUnFoldAtCaret(n, 1,4, [0,3,4,5]); TestNodeAtPos(n, 26, 1);
|
||||
n := '(del to prev line) refold';
|
||||
TstFold(n, 0,1, [0]); TestNodeAtPos(n, 13, 1); // re-folded idx=1, prg is at 0
|
||||
end;
|
||||
|
||||
n := '(newline on srcline)';
|
||||
DoNewLine(13,1); // newline, on same line
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
if (i and 128) <> 0 then begin
|
||||
n := '(del to prev line) nested';
|
||||
TstUnFoldAtCaret(n, 1,5, [0,1,4,5,6]); TestNodeAtPos(n, 14, 2);
|
||||
n := '(del to prev line) refold';
|
||||
TstFold(n, 1, 0, [0,1]); TestNodeAtPos(n, 1, 2); // re-folded
|
||||
end;
|
||||
|
||||
PopBaseName;
|
||||
end;
|
||||
{%endregion}
|
||||
|
||||
{%region}
|
||||
TstSetText('Nested, same line, new line in middle:', TestText6);
|
||||
SynEdit.UnfoldAll;
|
||||
n := '';
|
||||
TstFold(n, 1, 1, [0, 1, 4,5,6]); TestNodeAtPos(n, 14, 2);
|
||||
n := 'outer';
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
n := '(new line)';
|
||||
//debugln(['############### ',n]);
|
||||
DoNewLine(14,2);
|
||||
TestFoldedText(n, [0, 1, 2, 5,6,7]);
|
||||
TestNodeAtPos(n, 1, 3);
|
||||
PopBaseName;
|
||||
|
||||
TstSetText('Nested, same line, new line in middle: (2)', TestText6);
|
||||
SynEdit.UnfoldAll;
|
||||
n := '';
|
||||
TstFold(n, 1, 1, [0, 1, 4,5,6]); TestNodeAtPos(n, 14, 2);
|
||||
TstFold(n, 1, 0, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
n := '(new line)';
|
||||
//debugln(['############### ',n]);
|
||||
DoNewLine(13,2);
|
||||
TestFoldedText(n, [0, 1, 2, 5,6,7]);
|
||||
TestNodeAtPos(n, 2, 3);
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region simple, block edit}
|
||||
TstSetText('Simple: block edit', TestText);
|
||||
|
||||
TstFold('', 1, [0, 1]);
|
||||
TestNodeAtPos('', 1, 2);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(1,2)] := ' ';
|
||||
TestFoldedText('(ins char)', [0, 1]);
|
||||
TestNodeAtPos('(ins char)', 2, 2);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(13,1), point(13,1)] := LineEnding;
|
||||
TestFoldedText('(newline before)', [0, 1, 2]);
|
||||
TestNodeAtPos('(newline before)', 2, 3);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(13,1), point(1,2)] := '';
|
||||
TestFoldedText('(del newline)', [0, 1]);
|
||||
TestNodeAtPos('(del newline)', 2, 2);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(2,2)] := '';
|
||||
TestFoldedText('(del char)', [0, 1]);
|
||||
TestNodeAtPos('(del char)', 1, 2);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(13,1), point(1,2)] := '';
|
||||
TestFoldedText('(del to prev line)', [0]);
|
||||
TestNodeAtPos('(del to prev line)', 13, 1);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(13,1), point(13,1)] := LineEnding;
|
||||
TestFoldedText('(newline on srcline)', [0, 1]);
|
||||
TestNodeAtPos('(newline on srcline)', 1, 2);
|
||||
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1,3), point(1,3)] := LineEnding;
|
||||
TestFoldedText('(newline, 1st fold line)', [0, 1]);
|
||||
TestNodeAtPos('(newline 1st fold line)', 1, 2);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1,3), point(1,4)] := '';
|
||||
TestFoldedText('(del newline, 1st fold line)', [0, 1]);
|
||||
TestNodeAtPos('(del newline 1st fold line)', 1, 2);
|
||||
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region Nested block edit}
|
||||
TstSetText('Nested: block edit ', TestText);
|
||||
//SetLines(TestText);
|
||||
|
||||
n := '(ins char)';
|
||||
TstFold(n, 2, [0, 1, 2]); TestNodeAtPos(n, 1, 3);
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
//debugln(['############### ',n]);
|
||||
SynEdit.TextBetweenPoints[point(1,3), point(1,3)] := ' ';
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
TstUnFoldAtCaret(n, 1,3, [0,1,2]); TestNodeAtPos(n, 2, 3);
|
||||
|
||||
n := '(repl char to newline)';
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
//debugln(['############### ',n]);
|
||||
SynEdit.TextBetweenPoints[point(1,3), point(2,3)] := LineEnding;
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
TstUnFoldAtCaret(n, 1,4, [0,1,2,3]); TestNodeAtPos(n, 1, 4);
|
||||
|
||||
n := '(repl newline to char)';
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
//debugln(['############### ',n]);
|
||||
SynEdit.TextBetweenPoints[point(1,3), point(1,4)] := ' ';
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
TstUnFoldAtCaret(n, 1,3, [0,1,2]); TestNodeAtPos(n, 3, 3);
|
||||
|
||||
n := '(del char)';
|
||||
TstFold(n, 1, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
//debugln(['############### ',n]);
|
||||
SynEdit.TextBetweenPoints[point(1,3), point(3,3)] := '';
|
||||
TestFoldedText(n, [0, 1]); TestNodeAtPos(n, 1, 2);
|
||||
TstUnFoldAtCaret(n, 1,3, [0,1,2]); TestNodeAtPos(n, 1, 3);
|
||||
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region simple, lines access}
|
||||
TstSetText('Simple: lines access', TestText);
|
||||
|
||||
TstFold('', 1, [0, 1]);
|
||||
TestNodeAtPos('', 1, 2);
|
||||
|
||||
SynEdit.Lines.Insert(1,'// foo');
|
||||
TestFoldedText('(insert before)', [0, 1, 2]);
|
||||
TestNodeAtPos('(insert before)', 1, 3);
|
||||
|
||||
SynEdit.Lines.Delete(1);
|
||||
TestFoldedText('(del before)', [0, 1]);
|
||||
TestNodeAtPos('(del before)', 1, 2);
|
||||
|
||||
SynEdit.Lines.Insert(2,'// foo');
|
||||
TestFoldedText('(insert inside)', [0, 1]);
|
||||
TestNodeAtPos('(insert inside)', 1, 2);
|
||||
|
||||
SynEdit.Lines.Delete(2);
|
||||
TestFoldedText('(del inside)', [0, 1]);
|
||||
TestNodeAtPos('(del inside)', 1, 2);
|
||||
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
|
||||
{%region hide}
|
||||
TstSetText('Simple HIDE', TestTextHide(3));
|
||||
|
||||
TstFold('', 1, -1, 1, False, 0, [0, 4]);
|
||||
TestNodeAtPos('', 1, 2);
|
||||
|
||||
DoNewLine(13,1);
|
||||
TestFoldedText('(ins newline)', [0, 1, 5]);
|
||||
TestNodeAtPos('(ins newline)', 1, 3);
|
||||
|
||||
SynEdit.Undo; // cannot use backspace, since caret would unfold
|
||||
TestFoldedText('(del newline)', [0, 4]);
|
||||
TestNodeAtPos('(del newline)', 1, 2);
|
||||
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region hide, block edit}
|
||||
TstSetText('Simple HIDE: block edit', TestTextHide(3));
|
||||
|
||||
// TODO /newline BEFORE
|
||||
TstFold('', 1, -1, 1, False, 0, [0, 4]);
|
||||
TestNodeAtPos('', 1, 2);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(13,1), point(13,1)] := LineEnding;
|
||||
TestFoldedText('(newline before)', [0, 1, 5]);
|
||||
TestNodeAtPos('(newline before)', 1, 3);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(13,1), point(1,2)] := '';
|
||||
TestFoldedText('(del newline before)', [0, 4]);
|
||||
TestNodeAtPos('(del newline before)', 1, 2);
|
||||
|
||||
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(1,2)] := ' ';
|
||||
TestFoldedText('(ins char)', [0, 4]);
|
||||
TestNodeAtPos('(ins char)', 2, 2);
|
||||
|
||||
debugln(['############### ins newline']);
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(2,2)] := LineEnding;
|
||||
TestFoldedText('(ins newline)', [0, 1, 5]);
|
||||
TestNodeAtPos('(ins newline)', 1, 3);
|
||||
|
||||
debugln(['############### del newline']);
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(1,3)] := ' ';
|
||||
TestFoldedText('(del newline)', [0, 4]);
|
||||
TestNodeAtPos('(del newline)', 3, 2);
|
||||
|
||||
debugln(['############### del char']);
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(3,2)] := ' ';
|
||||
TestFoldedText('(del char)', [0, 4]);
|
||||
TestNodeAtPos('(del char)', 2, 2);
|
||||
|
||||
debugln(['############### ins newline (again)']);
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(2,2)] := LineEnding;
|
||||
TestFoldedText('(ins newline)', [0, 1, 5]);
|
||||
TestNodeAtPos('(ins newline)', 1, 3);
|
||||
|
||||
debugln(['############### del TWO newline']);
|
||||
SynEdit.TextBetweenPoints[point(1,2), point(1,4)] := '';
|
||||
TestFoldedText('(del newline)', [0, 3]);
|
||||
TestNodeAtPos('(del newline)', 1, 2);
|
||||
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region lines access}
|
||||
TstSetText('Simple HIDE: lines access', TestTextHide(3));
|
||||
|
||||
TstFold('', 1, -1, 1, False, 0, [0, 4]);
|
||||
TestNodeAtPos('', 1, 2);
|
||||
|
||||
SynEdit.Lines.Insert(1,'var a: integer;');
|
||||
TestFoldedText('(ins newline before)', [0, 1, 5]);
|
||||
TestNodeAtPos('(ins newline before)', 1, 3);
|
||||
|
||||
SynEdit.Lines.Delete(1);
|
||||
TestFoldedText('(del newline before)', [0, 4]);
|
||||
TestNodeAtPos('(del newline before)', 1, 2);
|
||||
|
||||
SynEdit.Lines.Insert(2,'// foo bar');
|
||||
TestFoldedText('(ins newline inside)', [0, 5]);
|
||||
TestNodeAtPos('(ins newline inside)', 1, 2);
|
||||
|
||||
SynEdit.Lines.Delete(2);
|
||||
TestFoldedText('(del newline inside)', [0, 4]);
|
||||
TestNodeAtPos('(del newline inside)', 1, 2);
|
||||
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestFoldedView.TestFoldStateFromText;
|
||||
|
||||
procedure TstFoldState(AName, AFoldDesc: String; AExpectedLines: Array of Integer);
|
||||
begin
|
||||
|
Loading…
Reference in New Issue
Block a user