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:
martin 2012-02-20 01:54:28 +00:00
parent 4f15b0fa87
commit 3d4c144f90
2 changed files with 77 additions and 11 deletions

View File

@ -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.

View File

@ -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;