mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 08:19:29 +02:00
SynEdit: Ifdef Markup: fix several crashes
git-svn-id: trunk@41217 -
This commit is contained in:
parent
1084ad7aed
commit
a6236159e9
@ -106,6 +106,7 @@ type
|
||||
|
||||
procedure ApplyNodeStateToLine(ARemove: Boolean = False);
|
||||
procedure RemoveNodeStateFromLine;
|
||||
procedure SetStartColumn(AValue: Integer);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
@ -126,10 +127,10 @@ type
|
||||
property NodeState: TSynMarkupIfdefNodeStateEx read GetNodeState write SetNodeState;
|
||||
property NodeFlags: SynMarkupIfDefNodeFlags read FNodeFlags write FNodeFlags;
|
||||
property Line: TSynMarkupHighIfDefLinesNode read FLine write SetLine;
|
||||
property StartColumn: Integer read FStartColumn write FStartColumn;
|
||||
property StartColumn: Integer read FStartColumn write SetStartColumn;// FStartColumn;
|
||||
property EndColumn: Integer read FEndColumn write FEndColumn;
|
||||
// RelativeNestDepth (opening depth)) First node is always 0 // nodes in line can be negative
|
||||
//property RelativeNestDepth: Integer read FRelativeNestDepth;
|
||||
////property RelativeNestDepth: Integer read FRelativeNestDepth;
|
||||
// COMMENT BEFORE AUTO COMPLETE !!!!!
|
||||
property OpeningPeer: TSynMarkupHighIfDefEntry index idpOpeningPeer read GetPeer write SetPeer;
|
||||
property ClosingPeer: TSynMarkupHighIfDefEntry index idpClosingPeer read GetPeer write SetPeer;
|
||||
@ -170,7 +171,7 @@ type
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure MakeDisposed;
|
||||
procedure MakeDisposed; // Also called to clear, on real destroy
|
||||
property LineFlags: SynMarkupIfDefLineFlags read FLineFlags;
|
||||
// LastEntryEndLineOffs: For last Entry only, if entry closing "}" is on a diff line. (can go one OVER ScanEndOffs)
|
||||
property LastEntryEndLineOffs: Integer read FLastEntryEndLineOffs write FLastEntryEndLineOffs;
|
||||
@ -783,6 +784,13 @@ begin
|
||||
ApplyNodeStateToLine(True);
|
||||
end;
|
||||
|
||||
procedure TSynMarkupHighIfDefEntry.SetStartColumn(AValue: Integer);
|
||||
begin
|
||||
if FStartColumn = AValue then Exit;
|
||||
FStartColumn := AValue;
|
||||
Assert(AValue>0, 'Startcol negative');
|
||||
end;
|
||||
|
||||
function TSynMarkupHighIfDefEntry.NodeStateForPeer(APeerType: TSynMarkupIfdefNodeType): TSynMarkupIfdefNodeStateEx;
|
||||
const
|
||||
NodeStateMap: array [Boolean] of TSynMarkupIfdefNodeStateEx =
|
||||
@ -817,9 +825,10 @@ end;
|
||||
|
||||
destructor TSynMarkupHighIfDefEntry.Destroy;
|
||||
begin
|
||||
NodeState := idnUnknown; // RemoveNodeStateFromLine;
|
||||
if (FLine <> nil) and not(idlInGlobalClear in FLine.LineFlags) then
|
||||
if (FLine <> nil) and not(idlInGlobalClear in FLine.LineFlags) then begin
|
||||
NodeState := idnUnknown; // RemoveNodeStateFromLine;
|
||||
ClearPeers;
|
||||
end;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
@ -900,12 +909,12 @@ begin
|
||||
MakeDisposed;
|
||||
end;
|
||||
|
||||
procedure TSynMarkupHighIfDefLinesNode.MakeDisposed;
|
||||
procedure TSynMarkupHighIfDefLinesNode.MakeDisposed; // Also called to clear, on real destroy
|
||||
begin
|
||||
FLineFlags := [idlDisposed] + FLineFlags * [idlInGlobalClear];
|
||||
while EntryCount > 0 do
|
||||
DeletEntry(EntryCount-1, True);
|
||||
assert((FDisabledEntryOpenCount =0) and (FDisabledEntryCloseCount = 0), 'no close count left over');
|
||||
assert((idlInGlobalClear in LineFlags) or ((FDisabledEntryOpenCount =0) and (FDisabledEntryCloseCount = 0)), 'no close count left over');
|
||||
FDisabledEntryOpenCount := 0;
|
||||
FDisabledEntryCloseCount := 0;
|
||||
end;
|
||||
@ -1522,7 +1531,8 @@ procedure TSynMarkupHighIfDefLinesTree.DoLinesEdited(Sender: TSynEditStrings; aL
|
||||
end;
|
||||
|
||||
procedure AdjustEntryXPos(ANode: TSynMarkupHighIfDefLinesNode; ADiffX: Integer;
|
||||
AStartIdx: Integer = 0; ADestNode: TSynMarkupHighIfDefLinesNode = nil);
|
||||
AStartIdx: Integer = 0; ADestNode: TSynMarkupHighIfDefLinesNode = nil;
|
||||
AMinXPos : Integer = 1);
|
||||
var
|
||||
Cnt, SkipEndIdx, DestPos, j: Integer;
|
||||
CurEntry: TSynMarkupHighIfDefEntry;
|
||||
@ -1538,9 +1548,10 @@ procedure TSynMarkupHighIfDefLinesTree.DoLinesEdited(Sender: TSynEditStrings; aL
|
||||
if ADestNode = nil then begin
|
||||
for j := AStartIdx to Cnt - 1 do begin
|
||||
CurEntry := aNode.Entry[j];
|
||||
CurEntry.StartColumn := CurEntry.StartColumn + ADiffX;
|
||||
assert(CurEntry.StartColumn >= AMinXPos, 'DoLinesEdited: CurEntry.StartColumn >= AMinXPos');
|
||||
CurEntry.StartColumn := Max(AMinXPos, CurEntry.StartColumn + ADiffX);
|
||||
if (j <> SkipEndIdx) then
|
||||
CurEntry.EndColumn := CurEntry.EndColumn + ADiffX;
|
||||
CurEntry.EndColumn := Max(CurEntry.StartColumn, CurEntry.EndColumn + ADiffX);
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
@ -1549,9 +1560,10 @@ procedure TSynMarkupHighIfDefLinesTree.DoLinesEdited(Sender: TSynEditStrings; aL
|
||||
for j := AStartIdx to Cnt - 1 do begin
|
||||
CurEntry := aNode.Entry[j];
|
||||
aNode.Entry[j] := nil;
|
||||
CurEntry.StartColumn := CurEntry.StartColumn + ADiffX;
|
||||
assert(CurEntry.StartColumn >= AMinXPos, 'DoLinesEdited: CurEntry.StartColumn >= AMinXPos');
|
||||
CurEntry.StartColumn := Max(AMinXPos, CurEntry.StartColumn + ADiffX);
|
||||
if (j <> SkipEndIdx) then
|
||||
CurEntry.EndColumn := CurEntry.EndColumn + ADiffX;
|
||||
CurEntry.EndColumn := Max(CurEntry.StartColumn, CurEntry.EndColumn + ADiffX);
|
||||
ADestNode.Entry[DestPos] := CurEntry;
|
||||
inc(DestPos);
|
||||
end;
|
||||
@ -1605,9 +1617,9 @@ begin
|
||||
then begin
|
||||
// Move Entire Line
|
||||
AdjustForLinesInserted(aLinePos, aLineBrkCnt);
|
||||
// Adjust the FIELD directly
|
||||
// Adjust the FIELD directly (the real node already moved)
|
||||
WorkNode.FStartLine := WorkNode.FStartLine + aLineBrkCnt;
|
||||
if aBytePos > 1 then
|
||||
if (aBytePos > 1) and (WorkLine = aLinePos) then
|
||||
AdjustEntryXPos(WorkNode.Node, (-aBytePos) + 1);
|
||||
end
|
||||
else begin
|
||||
@ -1731,7 +1743,7 @@ begin
|
||||
if aLinePos = WorkLine then begin
|
||||
i := IndexOfEntryAfter(WorkNode.Node, aBytePos);
|
||||
if i >= 0 then begin
|
||||
AdjustEntryXPos(WorkNode.Node, aCount, i);
|
||||
AdjustEntryXPos(WorkNode.Node, aCount, i, nil, aBytePos);
|
||||
if (i > 0) and (WorkNode.Entry[i-1].EndColumn > aBytePos) then begin
|
||||
WorkNode.Entry[i-1].EndColumn := Max(aBytePos, WorkNode.Entry[i-1].EndColumn + aCount);
|
||||
WorkNode.Entry[i-1].MakeUnknown;
|
||||
@ -1739,7 +1751,7 @@ begin
|
||||
if aCount < 0 then begin
|
||||
c := WorkNode.EntryCount - 1;
|
||||
while ( (i < c) or ((i = c) and (WorkNode.LastEntryEndLineOffs=0)) ) and
|
||||
(WorkNode.Entry[i].EndColumn < aBytePos)
|
||||
(WorkNode.Entry[i].EndColumn <= WorkNode.Entry[i].StartColumn)
|
||||
do begin
|
||||
WorkNode.Node.DeletEntry(i, True);
|
||||
dec(c);
|
||||
@ -2362,14 +2374,14 @@ begin
|
||||
Node.FStartLine := ALinePos; // directly to field
|
||||
end
|
||||
else begin
|
||||
DebugLn([ 'SetNodeState did not find a node (ScanLine) ', ALinePos, '/', 'AstartPos', ' ', dbgs(AState)]);
|
||||
DebugLn([ 'SetNodeState did not find a node (ScanLine) ', ALinePos, '/', 'AstartPos', AstartPos, ' ', dbgs(AState)]);
|
||||
//assert(false, 'SetNodeState did not find a node (ScanLine)');
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
i := Node.EntryCount;
|
||||
if i = 0 then begin DebugLn(['SetNodeState did not find a node (zero entries)', ALinePos, '/', 'AstartPos', ' ', dbgs(AState)]); exit; end;
|
||||
if i = 0 then begin DebugLn(['SetNodeState did not find a node (zero entries)', ALinePos, '/', 'AstartPos', AstartPos, ' ', dbgs(AState)]); exit; end;
|
||||
//assert(i > 0, 'SetNodeState did not find a node (zero entries)');
|
||||
e := nil;
|
||||
LineNeedReq := False;
|
||||
@ -2383,11 +2395,11 @@ begin
|
||||
until (i = 0) or (e <> nil);
|
||||
|
||||
//assert(e <> nil, 'SetNodeState did not find a node (no matching entry)');
|
||||
if (e = nil) then DebugLn([ 'SetNodeState did not find a matching node ', ALinePos, '/', 'AstartPos',AstartPos, ' ', dbgs(AState)]);
|
||||
//assert(e.NodeType in [idnIfdef, idnElseIf], 'SetNodeState did not find a node (e.NodeType <> idnIfdef)');
|
||||
if (e<> nil) and not(e.NodeType in [idnIfdef, idnElseIf]) then DebugLn([ 'SetNodeState did not find a node of useful type ', ALinePos, '/', 'AstartPos',AstartPos, ' ', dbgs(AState), ' ', dbgs(e.NodeType )]);
|
||||
if (e = nil) or not(e.NodeType in [idnIfdef, idnElseIf]) then
|
||||
begin DebugLn([ 'SetNodeState did not find a matching node ', ALinePos, '/', 'AstartPos', ' ', dbgs(AState)]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
e.NodeState := AState;
|
||||
|
||||
@ -2598,6 +2610,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
try
|
||||
LastLine := ScreenRowToRow(LinesInWindow+1);
|
||||
FOuterLines.Clear; // TODO: invalidate acording to actual lines edited
|
||||
FIfDefTree.ValidateRange(TopLine, LastLine, FOuterLines);
|
||||
@ -2735,6 +2748,9 @@ XXXCurTree := FIfDefTree; try
|
||||
end;
|
||||
|
||||
finally XXXCurTree := nil; end;
|
||||
except
|
||||
FIfDefTree.DebugPrint(true);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkupIfDef.DoFoldChanged(aLine: Integer);
|
||||
|
@ -752,6 +752,7 @@ begin
|
||||
// delete an entire node
|
||||
n := 'Delete full node';
|
||||
SynEdit.TextBetweenPoints[point(10, 7),point(27, 7)] := '';
|
||||
FTestTree.DebugPrint(true);
|
||||
CheckNodesXY(n+'', 7, [2,10, 10,20], 0);
|
||||
|
||||
{%endregion one line}
|
||||
@ -1010,6 +1011,39 @@ begin
|
||||
CheckNodesXY('', 6, [3, 14], 0);
|
||||
|
||||
|
||||
{%region Delete line with node}
|
||||
ReCreateEditForTreeTest(TestText7);
|
||||
FTestTree.ValidateRange( 1, 5, FOpenings);
|
||||
FTestTree.ValidateRange(10, 10, FOpenings);
|
||||
FTestTree.ValidateRange(14, 14, FOpenings);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef ) ]);
|
||||
CheckNodes(n, 4, [ ExpN( 1, 9, idnEndIf ) ]);
|
||||
CheckNodes(n,10, [ ExpN( 2,12, idnIfdef ) ]);
|
||||
CheckNodes(n,14, [ ExpN( 2,10, idnEndIf ) ]);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1, 4),point(1, 5)] := '';
|
||||
FOpenings.Clear;
|
||||
FTestTree.ValidateRange(3, 5, FOpenings); // only validate deleted line
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef) ]);
|
||||
CheckNodes(n, 3, [ ]);
|
||||
CheckNodes(n, 4, [ ]);
|
||||
CheckNodes(n, 5, [ ]);
|
||||
CheckNodes(n, 9, [ ExpN( 2,12, idnIfdef) ]);
|
||||
CheckNodes(n,13, [ ExpN( 2,10, idnEndIf) ]);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1, 4),point(1, 4)] := '{$ENDIF}' + LineEnding;
|
||||
FTestTree.ValidateRange(3, 5, FOpenings); // only validate deleted line
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef ) ]);
|
||||
CheckNodes(n, 4, [ ExpN( 1, 9, idnEndIf ) ]);
|
||||
CheckNodes(n,10, [ ExpN( 2,12, idnIfdef ) ]);
|
||||
CheckNodes(n,14, [ ExpN( 2,10, idnEndIf ) ]);
|
||||
|
||||
{%endregion }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Insert IFDEF into empty text
|
||||
ReCreateEditForTreeTest(TestTextNoIfDef);
|
||||
FTestTree.ValidateRange(1, 5, FOpenings);
|
||||
|
Loading…
Reference in New Issue
Block a user