mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-20 05:09:05 +02:00
SynEdit, Fold: Fixed a bug when deleting folded text, in such manner that another fold moves to the same line
git-svn-id: trunk@35498 -
This commit is contained in:
parent
4f15b0fa87
commit
3d4c144f90
@ -45,7 +45,7 @@ unit SynEditFoldedView;
|
||||
interface
|
||||
|
||||
uses
|
||||
LCLProc, Graphics,
|
||||
LCLProc, LazLogger, Graphics,
|
||||
Classes, SysUtils, LazSynEditText, SynEditTypes, SynEditMiscClasses,
|
||||
SynEditMiscProcs, SynEditPointClasses,
|
||||
SynEditHighlighter, SynEditHighlighterFoldBase;
|
||||
@ -105,6 +105,7 @@ type
|
||||
|
||||
TSynTextFoldAVLNode = object
|
||||
private
|
||||
function GetClassification: TFoldNodeClassification;
|
||||
function GetFoldColumn: Integer;
|
||||
function GetFoldColumnLen: Integer;
|
||||
function GetFoldIndex: Integer;
|
||||
@ -134,6 +135,7 @@ type
|
||||
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
|
||||
property Classification: TFoldNodeClassification read GetClassification;
|
||||
end;
|
||||
|
||||
{ TSynTextFoldAVLNodeNestedIterator:
|
||||
@ -575,9 +577,14 @@ type
|
||||
|
||||
property DisplayView: TLazSynDisplayView read GetDisplayView;
|
||||
end;
|
||||
|
||||
|
||||
function dbgs(AClassification: TFoldNodeClassification): String; overload;
|
||||
|
||||
implementation
|
||||
|
||||
//var
|
||||
// SYN_FOLD_DEBUG: PLazLoggerLogGroup;
|
||||
|
||||
type
|
||||
TFoldExportEntry = Record
|
||||
// Lines and Pos (o 1st line) are relative to Scan-Start
|
||||
@ -1753,6 +1760,13 @@ end;
|
||||
|
||||
{ TSynTextFoldAVLNode }
|
||||
|
||||
function TSynTextFoldAVLNode.GetClassification: TFoldNodeClassification;
|
||||
begin
|
||||
if fData = nil
|
||||
then Result := fncInvalid
|
||||
else Result := fData.Classification;
|
||||
end;
|
||||
|
||||
function TSynTextFoldAVLNode.GetFoldColumn: Integer;
|
||||
begin
|
||||
if fData = nil
|
||||
@ -4127,6 +4141,7 @@ function TSynEditFoldedView.FixFolding(AStart: Integer; AMinEnd: Integer;
|
||||
aFoldTree: TSynTextFoldAVLTree): Boolean;
|
||||
var
|
||||
FirstchangedLine, MaxCol: Integer;
|
||||
SrcLineForFldInfos: Integer;
|
||||
FldInfos: TSynEditFoldProviderNodeInfoList;
|
||||
|
||||
function DoFixFolding(doStart: Integer; doMinEnd, AtColumn: Integer;
|
||||
@ -4150,13 +4165,14 @@ var
|
||||
var
|
||||
FldSrcLine, FldSrcIndex, FLdNodeLine, FldLen, FndLen: Integer;
|
||||
i, j, CurLen: Integer;
|
||||
PrevFldSrcLine: Integer;
|
||||
SubTree: TSynTextFoldAVLTree;
|
||||
begin
|
||||
{$IFDEF SynFoldDebug}try DebugLnEnter(['>>FOLD-- DoFixFolding: doStart=', doStart, ' AMinEnd=',AMinEnd]);{$ENDIF}
|
||||
{$IFDEF SynFoldDebug}aFoldTree.Debug;{$ENDIF}
|
||||
Result := False;
|
||||
FldSrcLine := doStart;
|
||||
while node.IsInFold do begin
|
||||
PrevFldSrcLine := FldSrcLine;
|
||||
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- Node StartLine=', node.StartLine, ' FoldColumn=', node.FoldColumn, ' FoldIndex=', node.FoldIndex, ' FullCount=', node.FullCount, ' Classification=', dbgs(node.Classification)]);{$ENDIF}
|
||||
FldSrcLine := node.SourceLine; // the 1-based cfCollapsed (last visible) Line (or 1st hidden)
|
||||
FLdNodeLine := node.StartLine; // the 1 based, first hidden line
|
||||
FldSrcIndex := FldSrcLine - 1;
|
||||
@ -4169,15 +4185,17 @@ var
|
||||
|
||||
//{$IFDEF SynAssertFold}
|
||||
//With mixed fold/hide => line goes up/down
|
||||
//SynAssert(FldSrcLine >= PrevFldSrcLine, 'TSynEditFoldedView.FixFolding: FoldLine went backwards now %d was %d', [FldSrcLine, PrevFldSrcLine]);
|
||||
//SynAssert(FldSrcLine >= SrcLineForFldInfos, 'TSynEditFoldedView.FixFolding: FoldLine went backwards now %d was %d', [FldSrcLine, SrcLineForFldInfos]);
|
||||
//{$ENDIF}
|
||||
if (FldSrcLine <> PrevFldSrcLine) then begin
|
||||
if (FldSrcLine <> SrcLineForFldInfos) then begin
|
||||
// Next Line
|
||||
SrcLineForFldInfos := FldSrcLine;
|
||||
AtColumn := 0;
|
||||
// AtColumn is used for nodes, behing the HLs index-range (fncHighlighterEx, fncBlockSelection)
|
||||
// TODO: At Colum may be wrong for mixed fold/hide
|
||||
FldInfos := FoldProvider.InfoListForFoldsAtTextIndex(FldSrcIndex, False);
|
||||
MaxCol := length(FldInfos)-1;
|
||||
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- Got FldInfos for FldSrcIndex=', FldSrcIndex, ' MaxCol=', MaxCol]);{$ENDIF}
|
||||
end;
|
||||
|
||||
if node.fData.Classification in [fncHighlighter, fncHighlighterEx] then begin
|
||||
@ -4196,7 +4214,7 @@ var
|
||||
FndLen := FoldProvider.FoldLineLength(FldSrcIndex, i);
|
||||
if node.IsHide then inc(FndLen);
|
||||
if FndLen <> node.FullCount then Continue;
|
||||
debugln('******** FixFolding: Adjusting x pos');
|
||||
{$IFDEF SynFoldDebug}debugln('******** FixFolding: Adjusting x pos');{$ENDIF}
|
||||
//FldInfos[i].Column := node.FoldColumn;
|
||||
end;
|
||||
if (FndLen > 0) or (FldInfos[i].Column = node.FoldColumn) then begin
|
||||
@ -4251,12 +4269,13 @@ var
|
||||
if node.StartLine >= doMinEnd then break;
|
||||
node := node.Next;
|
||||
end;
|
||||
{$IFDEF SynFoldDebug}finally DebugLnExit(['<<FOLD-- DoFixFolding: DONE=', Result]); end{$ENDIF}
|
||||
end;
|
||||
|
||||
var
|
||||
node, tmpnode: TSynTextFoldAVLNode;
|
||||
begin
|
||||
{$IFDEF SynFoldDebug}debugln(['>>FOLD-- FixFolding: Start=', AStart, ' AMinEnd=',AMinEnd]);{$ENDIF}
|
||||
{$IFDEF SynFoldDebug}try DebugLnEnter(['>>FOLD-- FixFolding: Start=', AStart, ' AMinEnd=',AMinEnd]);{$ENDIF}
|
||||
Result := false;
|
||||
if fLockCount > 0 then begin
|
||||
fNeedCaretCheck := true; // We may be here as a result of lines deleted/inserted
|
||||
@ -4284,12 +4303,13 @@ begin
|
||||
|
||||
FirstchangedLine := -1;
|
||||
FldInfos := nil;
|
||||
MaxCol := 0;
|
||||
MaxCol := -1;
|
||||
SrcLineForFldInfos := -1;
|
||||
Result := DoFixFolding(-1, AMinEnd, 0, aFoldTree, node);
|
||||
CalculateMaps;
|
||||
if Assigned(fOnFoldChanged) and (FirstchangedLine >= 0) then
|
||||
fOnFoldChanged(FirstchangedLine);
|
||||
{$IFDEF SynFoldDebug}debugln(['<<FOLD-- FixFolding: DONE=', Result]);{$ENDIF}
|
||||
{$IFDEF SynFoldDebug}finally DebugLnExit(['<<FOLD-- FixFolding: DONE=', Result]); end{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.DoCaretChanged(Sender : TObject);
|
||||
@ -4524,6 +4544,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function dbgs(AClassification: TFoldNodeClassification): String;
|
||||
begin
|
||||
WriteStr(Result, AClassification);
|
||||
end;
|
||||
|
||||
{$IFDEF SynDebug}
|
||||
procedure TSynEditFoldedView.debug;
|
||||
begin
|
||||
@ -4533,6 +4558,7 @@ end;
|
||||
|
||||
initialization
|
||||
InitNumEncodeValues;
|
||||
//SYN_FOLD_DEBUG := DebugLogger.RegisterLogGroup('SynFoldDebug' {$IFDEF SynFoldDebug} , True {$ENDIF} );
|
||||
|
||||
end.
|
||||
|
||||
|
@ -41,6 +41,7 @@ type
|
||||
function TestText7: TStringArray;
|
||||
function TestText8: TStringArray;
|
||||
function TestText9: TStringArray;
|
||||
function TestText10: TStringArray;
|
||||
function TestTextHide(ALen: Integer): TStringArray;
|
||||
function TestTextHide2(ALen: Integer): TStringArray;
|
||||
function TestTextHide3: TStringArray;
|
||||
@ -452,6 +453,29 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
function TTestFoldedView.TestText10: TStringArray;
|
||||
begin
|
||||
SetLength(Result, 17);
|
||||
Result[0] := 'program Project1;';
|
||||
Result[1] := 'begin';
|
||||
Result[2] := '';
|
||||
Result[3] := ' if 1=2 then begin';
|
||||
Result[4] := '';
|
||||
Result[5] := ' end;';
|
||||
Result[6] := '';
|
||||
Result[7] := ' if 1=3 then begin';
|
||||
Result[8] := '';
|
||||
Result[9] := '';
|
||||
Result[10] := '';
|
||||
Result[11] := '';
|
||||
Result[12] := ' end;';
|
||||
Result[13] := '';
|
||||
Result[14] := 'end.';
|
||||
Result[15] := '';
|
||||
Result[16] := '';
|
||||
|
||||
end;
|
||||
|
||||
function TTestFoldedView.TestTextHide(ALen: Integer): TStringArray;
|
||||
begin
|
||||
SetLength(Result, 3+ALen);
|
||||
@ -881,12 +905,13 @@ procedure TTestFoldedView.TestFoldEdit;
|
||||
SynEdit.CommandProcessor(ecDeleteLastChar, '', nil);
|
||||
end;
|
||||
|
||||
procedure TestNodeAtPos(name: string; x, y: integer);
|
||||
procedure TestNodeAtPos(name: string; x, y: integer; ExpClassification: TFoldNodeClassification = fncHighlighter);
|
||||
var
|
||||
n: TSynTextFoldAVLNode;
|
||||
begin
|
||||
n := TSynEditFoldedViewHack(FoldedView).FoldTree.FindFoldForLine(y, true);
|
||||
AssertTrue(BaseTestName+' '+ name+ ' got node for line '+inttostr(y), n.IsInFold);
|
||||
AssertTrue(BaseTestName+' '+ name+ ' got node Classification for line '+inttostr(y), n.Classification = ExpClassification);
|
||||
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;
|
||||
@ -1356,6 +1381,21 @@ begin
|
||||
PopBaseName;
|
||||
{%endregion}
|
||||
|
||||
{%region}
|
||||
TstSetText('TestText10 remove one entire fold', TestText10);
|
||||
TstFold('f1', 7, -1, 1, False, 1, [0, 1, 2, 3, 4, 5, 6, 7, 13, 14, 15]);
|
||||
TstFold('f2', 3, -1, 1, False, 1, [0, 1, 2, 3, 6, 7, 13, 14, 15]);
|
||||
TestNodeAtPos('n1', 15, 4);
|
||||
TestNodeAtPos('n2', 15, 8);
|
||||
|
||||
SetCaretAndSel(1, 4, 1, 8);
|
||||
SynEdit.CutToClipboard;
|
||||
|
||||
TstFold('f2', 3, -1, 1, False, 1, [0, 1, 2, 3, 9, 10, 11]);
|
||||
TestNodeAtPos('n3', 15, 4);
|
||||
|
||||
{%endregion}
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestFoldedView.TestFoldStateFromText;
|
||||
|
Loading…
Reference in New Issue
Block a user