mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-16 03:59:17 +02:00
SynEdit: Refactor/Cleanup Highlighter and Current-Word-Markup
git-svn-id: trunk@19079 -
This commit is contained in:
parent
941ebd42a6
commit
4fb2ec2495
@ -153,6 +153,7 @@ type
|
||||
fAttrChangeHooks: TSynNotifyEventChain;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
FCapabilities: TSynHighlighterCapabilities;
|
||||
FCurrentLines: TSynEditStrings;
|
||||
{$ENDIF}
|
||||
fUpdateCount: integer; //mh 2001-09-13
|
||||
fEnabled: Boolean;
|
||||
@ -176,7 +177,6 @@ type
|
||||
procedure SetDefaultFilter(Value: string); virtual;
|
||||
procedure SetSampleSource(Value: string); virtual;
|
||||
// code fold - only valid if hcCodeFolding in Capabilities
|
||||
function GetLastLineCodeFoldLevelFix: integer; virtual;
|
||||
public
|
||||
procedure DefHighlightChange(Sender: TObject);
|
||||
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
|
||||
@ -220,14 +220,12 @@ type
|
||||
property IdentChars: TSynIdentChars read GetIdentChars;
|
||||
property WordBreakChars: TSynIdentChars read fWordBreakChars write SetWordBreakChars;
|
||||
property LanguageName: string read GetLanguageName;
|
||||
property CurrentLines: TSynEditStrings read FCurrentLines write FCurrentLines;
|
||||
|
||||
// folding
|
||||
Function GetWordTriplet(LogicalCaret: TPoint; Lines: TSynEditStrings;
|
||||
out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer): Boolean; virtual;
|
||||
(* Methds for folding *)
|
||||
function MinimumCodeFoldBlockLevel: integer; virtual;
|
||||
function CurrentCodeFoldBlockLevel: integer; virtual;
|
||||
property LastLineCodeFoldLevelFix: integer read GetLastLineCodeFoldLevelFix;
|
||||
function LastLineCodeFoldLevelFix: integer; virtual;
|
||||
public
|
||||
property AttrCount: integer read GetAttribCount;
|
||||
property Attribute[idx: integer]: TSynHighlighterAttributes
|
||||
@ -1087,13 +1085,6 @@ begin
|
||||
fAttrChangeHooks.Remove(ANotifyEvent);
|
||||
end;
|
||||
|
||||
function TSynCustomHighlighter.GetWordTriplet(LogicalCaret: TPoint;
|
||||
Lines: TSynEditStrings; out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer
|
||||
): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TSynCustomHighlighter.MinimumCodeFoldBlockLevel: integer;
|
||||
begin
|
||||
Result := 0;
|
||||
@ -1111,7 +1102,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynCustomHighlighter.GetLastLineCodeFoldLevelFix: integer;
|
||||
function TSynCustomHighlighter.LastLineCodeFoldLevelFix: integer;
|
||||
begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
@ -94,6 +94,20 @@ type
|
||||
|
||||
TSynCustomHighlighterRanges = class;
|
||||
|
||||
TSynFoldAction = (sfaOpen, // At this node a new Fold can start
|
||||
sfaClose, // At this node a fold ends
|
||||
sfaMarkup, // This node can be highlighted, by the matching Word-Pair Markup
|
||||
sfaInvalid // Wrong Index
|
||||
);
|
||||
TSynFoldActions = set of TSynFoldAction;
|
||||
|
||||
TSynFoldNodeInfo = record
|
||||
LogXStart, LogXEnd: Integer; // -1 previous line
|
||||
FoldLvlStart, FoldLvlEnd: Integer;
|
||||
FoldAction: TSynFoldActions;
|
||||
FoldType: Pointer;
|
||||
end;
|
||||
|
||||
{ TSynCustomFoldHighlighter }
|
||||
|
||||
TSynCustomFoldHighlighter = class(TSynCustomHighlighter)
|
||||
@ -104,6 +118,8 @@ type
|
||||
protected
|
||||
FMinimumCodeFoldBlockLevel: integer;
|
||||
protected
|
||||
function GetFoldNodeInfo(Line, Index: Integer): TSynFoldNodeInfo; virtual;
|
||||
function GetFoldNodeInfoCount(Line: Integer): Integer; virtual;
|
||||
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
|
||||
function GetRangeClass: TSynCustomHighlighterRangeClass; virtual;
|
||||
function TopCodeFoldBlockType: Pointer;
|
||||
@ -125,6 +141,14 @@ type
|
||||
|
||||
function MinimumCodeFoldBlockLevel: integer; override;
|
||||
function CurrentCodeFoldBlockLevel: integer; override;
|
||||
|
||||
// requires CurrentLines;
|
||||
function MinimumFoldLevel(Index: Integer): integer; virtual; abstract;
|
||||
function EndFoldLevel(Index: Integer): integer; virtual; abstract;
|
||||
function LastLineFoldLevelFix(Index: Integer): integer; virtual; abstract;
|
||||
|
||||
property FoldNodeInfo[Line, Index: Integer]: TSynFoldNodeInfo read GetFoldNodeInfo;
|
||||
property FoldNodeInfoCount[Line: Integer]: Integer read GetFoldNodeInfoCount;
|
||||
end;
|
||||
|
||||
TSynCustomHighlighterClass = class of TSynCustomFoldHighlighter;
|
||||
@ -260,6 +284,16 @@ begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.GetFoldNodeInfoCount(Line: Integer): Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.GetFoldNodeInfo(Line, Index: Integer): TSynFoldNodeInfo;
|
||||
begin
|
||||
Result.FoldAction := [sfaInvalid];
|
||||
end;
|
||||
|
||||
function TSynCustomFoldHighlighter.GetRangeClass: TSynCustomHighlighterRangeClass;
|
||||
begin
|
||||
Result:=TSynCustomHighlighterRange;
|
||||
|
@ -27,7 +27,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Graphics, SynEditMarkup, SynEditMiscClasses, Controls,
|
||||
LCLProc, SynEditHighlighter;
|
||||
LCLProc, SynEditHighlighter, SynEditHighlighterFoldBase;
|
||||
|
||||
type
|
||||
|
||||
@ -108,8 +108,92 @@ end;
|
||||
|
||||
procedure TSynEditMarkupWordGroup.FindMatchingWords(PhysCaret: TPoint;
|
||||
out Word1, Word2, Word3: TWordPoint);
|
||||
var
|
||||
LCnt: Integer;
|
||||
HL: TSynCustomFoldHighlighter;
|
||||
|
||||
function FindEndNode(StartNode: TSynFoldNodeInfo;
|
||||
var YIndex, NIndex: Integer): TSynFoldNodeInfo;
|
||||
begin
|
||||
repeat
|
||||
inc(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlEnd <= StartNode.FoldLvlStart);
|
||||
if not (sfaInvalid in Result.FoldAction) then
|
||||
exit;
|
||||
|
||||
inc(YIndex);
|
||||
while (YIndex < LCnt) and
|
||||
(HL.MinimumFoldLevel(YIndex) > StartNode.FoldLvlStart) do
|
||||
inc(YIndex);
|
||||
if YIndex = LCnt then
|
||||
exit;
|
||||
|
||||
NIndex := -1;
|
||||
repeat
|
||||
inc(NIndex);
|
||||
Result:= HL.FoldNodeInfo[YIndex, NIndex];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlEnd <= StartNode.FoldLvlStart);
|
||||
if (Result.LogXEnd = 0) then
|
||||
Result.FoldAction := [sfaInvalid]; // LastLine closed Node(maybe force-closed?)
|
||||
end;
|
||||
|
||||
function FindStartNode(EndNode: TSynFoldNodeInfo;
|
||||
var YIndex, NIndex: Integer): TSynFoldNodeInfo;
|
||||
begin
|
||||
repeat
|
||||
dec(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlStart <= EndNode.FoldLvlEnd);
|
||||
if not(sfaInvalid in Result.FoldAction) then
|
||||
exit;
|
||||
|
||||
dec(YIndex);
|
||||
while (YIndex >= 0) and (HL.MinimumFoldLevel(YIndex) > EndNode.FoldLvlEnd) do
|
||||
dec(YIndex);
|
||||
if YIndex < 0 then
|
||||
exit;
|
||||
NIndex := HL.FoldNodeInfoCount[YIndex];
|
||||
repeat
|
||||
dec(NIndex);
|
||||
Result:= HL.FoldNodeInfo[YIndex, NIndex];
|
||||
until (sfaInvalid in Result.FoldAction) or
|
||||
(Result.FoldLvlStart <= EndNode.FoldLvlEnd);
|
||||
end;
|
||||
|
||||
function FindMultiNode(OrigNode: TSynFoldNodeInfo;
|
||||
var YIndex, NIndex: Integer): TSynFoldNodeInfo;
|
||||
var
|
||||
i: LongInt;
|
||||
begin
|
||||
i := NIndex;
|
||||
repeat
|
||||
dec(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex];
|
||||
if (sfaMarkup in Result.FoldAction) and
|
||||
(Result.LogXStart = OrigNode.LogXStart) and (Result.LogXEnd > 0)
|
||||
then
|
||||
exit;
|
||||
until (sfaInvalid in Result.FoldAction) or (Result.LogXStart <> OrigNode.LogXStart);
|
||||
NIndex := i;
|
||||
repeat
|
||||
inc(NIndex);
|
||||
Result := HL.FoldNodeInfo[YIndex, NIndex];
|
||||
if (sfaMarkup in Result.FoldAction) and
|
||||
(Result.LogXStart = OrigNode.LogXStart) and (Result.LogXEnd > 0)
|
||||
then
|
||||
exit;
|
||||
until (sfaInvalid in Result.FoldAction) or (Result.LogXStart <> OrigNode.LogXStart);
|
||||
Result.FoldAction := [sfaInvalid];
|
||||
end;
|
||||
|
||||
var
|
||||
LogCaretXY: TPoint;
|
||||
i, i2, i3, y, y1, y2: integer;
|
||||
Node1, Node2, Node3: TSynFoldNodeInfo;
|
||||
begin
|
||||
Word1.Y := -1;
|
||||
Word2.Y := -1;
|
||||
@ -119,34 +203,86 @@ begin
|
||||
then
|
||||
Exit;
|
||||
|
||||
// Check for Begin-End like pairs
|
||||
if not assigned(FHighlighter) then Exit;
|
||||
LogCaretXY := TSynEdit(SynEdit).PhysicalToLogicalPos(PhysCaret);
|
||||
if FHighlighter.GetWordTriplet(LogCaretXY, Lines,
|
||||
Word1.Y, Word1.X, Word1.X2,
|
||||
Word3.Y, Word3.X, Word3. X2,
|
||||
Word2.Y, Word2.X, Word2. X2
|
||||
) then
|
||||
begin
|
||||
if Word1.Y > 0 then begin
|
||||
Word1.X := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word1.X, Word1.Y)).X;
|
||||
Word1.X2 := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word1.X2, Word1.Y)).X;
|
||||
end;
|
||||
if Word2.Y > 0 then begin
|
||||
Word2.X := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word2.X, Word2.Y)).X;
|
||||
Word2.X2 := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word2.X2, Word2.Y)).X;
|
||||
end;
|
||||
if Word3.Y > 0 then begin
|
||||
Word3.X := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word3.X, Word3.Y)).X;
|
||||
Word3.X2 := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word3.X2, Word3.Y)).X;
|
||||
end;
|
||||
if not (FHighlighter is TSynCustomFoldHighlighter) then
|
||||
exit;
|
||||
hl := TSynCustomFoldHighlighter(FHighlighter);
|
||||
LogCaretXY := TSynEdit(SynEdit).PhysicalToLogicalPos(PhysCaret);
|
||||
y := LogCaretXY.Y - 1;
|
||||
LCnt := Lines.Count;
|
||||
HL.CurrentLines := Lines;
|
||||
i := 0;
|
||||
repeat
|
||||
Node1 := HL.FoldNodeInfo[y, i];
|
||||
inc(i);
|
||||
until (sfaInvalid in Node1.FoldAction) or
|
||||
((Node1.LogXEnd >= LogCaretXY.X - 1) and (Node1.LogXEnd > 0));
|
||||
while not(Node1.FoldAction * [sfaInvalid, sfaMarkup] <> [])
|
||||
and (Node1.LogXStart <= LogCaretXY.X - 1) do
|
||||
begin
|
||||
Node1 := HL.FoldNodeInfo[y, i];
|
||||
inc(i);
|
||||
end;
|
||||
if (Node1.LogXStart > LogCaretXY.X - 1) or not(sfaMarkup in Node1.FoldAction) then
|
||||
exit;
|
||||
dec(i);
|
||||
|
||||
if sfaOpen in Node1.FoldAction then begin
|
||||
y1 := y;
|
||||
Node2 := FindEndNode(Node1, y, i);
|
||||
if (sfaInvalid in Node2.FoldAction) then
|
||||
exit;
|
||||
y2 := y;
|
||||
i2 := i;
|
||||
i3 := i;
|
||||
Node3 := FindMultiNode(Node2, y, i3);
|
||||
end else begin
|
||||
Node2 := Node1;
|
||||
i3 := i;
|
||||
Node3 := FindMultiNode(Node2, y, i3);
|
||||
y2 := y;
|
||||
i2 := i;
|
||||
Node1 := FindStartNode(Node2, y, i);
|
||||
if (sfaInvalid in Node1.FoldAction) then
|
||||
exit;
|
||||
y1 := y;
|
||||
end;
|
||||
|
||||
// In Case GetWordTriplet did set them
|
||||
Word1.Y := -1;
|
||||
Word2.Y := -1;
|
||||
Word3.Y := -1;
|
||||
y := y2;
|
||||
if not(sfaInvalid in Node3.FoldAction) then
|
||||
Node3 := FindStartNode(Node3, y, i);
|
||||
|
||||
Word1.Y := y1 + 1;
|
||||
Word1.X := Node1.LogXStart + 1;
|
||||
Word1.X2 := Node1.LogXEnd + 1;
|
||||
Word2.Y := y2 + 1;
|
||||
Word2.X := Node2.LogXStart + 1;
|
||||
Word2.X2 := Node2.LogXEnd + 1;
|
||||
if not(sfaInvalid in Node3.FoldAction) then begin
|
||||
Word3 := Word2;
|
||||
if i3 > i2 then begin
|
||||
Word2 := Word1;
|
||||
Word1.Y := y + 1;
|
||||
Word1.X := Node3.LogXStart + 1;
|
||||
Word1.X2 := Node3.LogXEnd + 1;
|
||||
end else begin
|
||||
Word2.Y := y + 1;
|
||||
Word2.X := Node3.LogXStart + 1;
|
||||
Word2.X2 := Node3.LogXEnd + 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
if Word1.Y > 0 then begin
|
||||
Word1.X := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word1.X, Word1.Y)).X;
|
||||
Word1.X2 := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word1.X2, Word1.Y)).X;
|
||||
end;
|
||||
if Word2.Y > 0 then begin
|
||||
Word2.X := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word2.X, Word2.Y)).X;
|
||||
Word2.X2 := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word2.X2, Word2.Y)).X;
|
||||
end;
|
||||
if Word3.Y > 0 then begin
|
||||
Word3.X := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word3.X, Word3.Y)).X;
|
||||
Word3.X2 := TSynEdit(SynEdit).LogicalToPhysicalPos(Point(Word3.X2, Word3.Y)).X;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkupWordGroup.DoCaretChanged(OldCaret: TPoint);
|
||||
|
@ -57,7 +57,7 @@ uses
|
||||
{$ELSE}
|
||||
Windows, Messages,
|
||||
{$ENDIF}
|
||||
Classes, Registry, Controls, SynEditHighlighterFoldBase,
|
||||
Classes, Registry, Controls, SynEditHighlighterFoldBase, SynEditMiscProcs,
|
||||
SynEditTypes, SynEditHighlighter, SynEditTextBuffer, SynEditTextBase;
|
||||
|
||||
type
|
||||
@ -195,6 +195,10 @@ type
|
||||
{$ENDIF}
|
||||
fD4syntax: boolean;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
FCatchNodeInfo: Boolean;
|
||||
FNodeInfoLine, FNodeInfoCount: Integer;
|
||||
FNodeInfoList: Array of TSynFoldNodeInfo;
|
||||
procedure GrowNodeInfoList;
|
||||
function GetPasCodeFoldRange: TSynPasSynRange;
|
||||
procedure SetCompilerMode(const AValue: TPascalCompilerMode);
|
||||
function TextComp(aText: PChar): Boolean;
|
||||
@ -322,7 +326,11 @@ type
|
||||
procedure SymbolProc;
|
||||
procedure UnknownProc;
|
||||
procedure SetD4syntax(const Value: boolean);
|
||||
procedure InitNode(var Node: TSynFoldNodeInfo; EndOffs: Integer;
|
||||
ABlockType: TPascalCodeFoldBlockType);
|
||||
protected
|
||||
function GetFoldNodeInfo(Line, Index: Integer): TSynFoldNodeInfo; override;
|
||||
function GetFoldNodeInfoCount(Line: Integer): Integer; override;
|
||||
function GetIdentChars: TSynIdentChars; override;
|
||||
function IsFilterStored: boolean; override; //mh 2000-10-08
|
||||
procedure CreateRootCodeFoldBlock; override;
|
||||
@ -334,7 +342,6 @@ type
|
||||
function GetRangeClass: TSynCustomHighlighterRangeClass; override;
|
||||
{$ENDIF}
|
||||
procedure EndCodeFoldBlockLastLine;
|
||||
function GetLastLineCodeFoldLevelFix: integer; override;
|
||||
property PasCodeFoldRange: TSynPasSynRange read GetPasCodeFoldRange;
|
||||
public
|
||||
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
|
||||
@ -365,11 +372,14 @@ type
|
||||
procedure EnumUserSettings(settings: TStrings); override;
|
||||
|
||||
//code fold
|
||||
function LastLineCodeFoldLevelFix: integer; override;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function TopPascalCodeFoldBlockType: TPascalCodeFoldBlockType;
|
||||
{$ENDIF}
|
||||
Function GetWordTriplet(LogicalCaret: TPoint; Lines: TSynEditStrings;
|
||||
out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer): Boolean; override;
|
||||
|
||||
function MinimumFoldLevel(Index: Integer): integer; override;
|
||||
function EndFoldLevel(Index: Integer): integer; override;
|
||||
function LastLineFoldLevelFix(Index: Integer): integer; override;
|
||||
published
|
||||
property AsmAttri: TSynHighlighterAttributes read fAsmAttri write fAsmAttri;
|
||||
property CommentAttri: TSynHighlighterAttributes read fCommentAttri
|
||||
@ -746,6 +756,13 @@ begin
|
||||
//DebugLn(['TSynPasSyn.SetCompilerMode FCompilerMode=',ord(FCompilerMode),' FNestedComments=',FNestedComments]);
|
||||
end;
|
||||
|
||||
procedure TSynPasSyn.GrowNodeInfoList;
|
||||
begin
|
||||
if FNodeInfoCount < length(FNodeInfoList) then
|
||||
exit;
|
||||
SetLength(FNodeInfoList, FNodeInfoCount + Max(10, FNodeInfoCount div 4));
|
||||
end;
|
||||
|
||||
function TSynPasSyn.GetPasCodeFoldRange: TSynPasSynRange;
|
||||
begin
|
||||
Result := TSynPasSynRange(CodeFoldRange);
|
||||
@ -1646,6 +1663,7 @@ begin
|
||||
fRange := [];
|
||||
fAsmStart := False;
|
||||
fDefaultFilter := SYNS_FilterPascal;
|
||||
FNodeInfoLine := -1;
|
||||
end; { Create }
|
||||
|
||||
procedure TSynPasSyn.SetLine(const NewValue: string; LineNumber:Integer);
|
||||
@ -1663,8 +1681,10 @@ begin
|
||||
fLine := PChar(NewValue);
|
||||
Run := 0;
|
||||
{$ENDIF}
|
||||
FNodeInfoLine := -1;
|
||||
fLineNumber := LineNumber;
|
||||
Next;
|
||||
if not FCatchNodeInfo then
|
||||
Next;
|
||||
end; { SetLine }
|
||||
|
||||
procedure TSynPasSyn.AddressOpProc;
|
||||
@ -2210,6 +2230,7 @@ begin
|
||||
{$ELSE}
|
||||
fRange := TRangeStates(PtrUInt(Value));
|
||||
{$ENDIF}
|
||||
FNodeInfoLine := -1;
|
||||
FStartCodeFoldBlockLevel := FMinimumCodeFoldBlockLevel;
|
||||
end;
|
||||
|
||||
@ -2259,189 +2280,55 @@ begin
|
||||
Result := TPascalCodeFoldBlockType(PtrUInt(p));
|
||||
end;
|
||||
|
||||
// ToDO: pass in Max for the search lines (Begin must be found always)
|
||||
function TSynPasSyn.GetWordTriplet(LogicalCaret: TPoint; Lines: TSynEditStrings;
|
||||
out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer): Boolean;
|
||||
|
||||
function GetLevelBeforeCaret: Integer;
|
||||
var
|
||||
l: Integer;
|
||||
begin
|
||||
SetRange(Lines.Ranges[LogicalCaret.Y - 1]);
|
||||
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
|
||||
l := CurrentCodeFoldBlockLevel;
|
||||
SetLine(Lines[LogicalCaret.Y - 1], LogicalCaret.Y - 1);
|
||||
if (MinimumCodeFoldBlockLevel < CurrentCodeFoldBlockLevel)
|
||||
then Result := MinimumCodeFoldBlockLevel
|
||||
else Result := l;
|
||||
while (Run <= LogicalCaret.x - 1) and not GetEol do begin
|
||||
if (Run = LogicalCaret.x-1) and (Result <> CurrentCodeFoldBlockLevel) then
|
||||
break;
|
||||
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
|
||||
l := CurrentCodeFoldBlockLevel;
|
||||
Next;
|
||||
if (MinimumCodeFoldBlockLevel < CurrentCodeFoldBlockLevel)
|
||||
then Result := MinimumCodeFoldBlockLevel
|
||||
else Result := l;
|
||||
end;
|
||||
end;
|
||||
|
||||
function FindBegin(EndY, EndX, SeekLevel: Integer; out X1, X2: Integer;
|
||||
out FoldType: TPascalCodeFoldBlockType): integer; // Returns Line
|
||||
var
|
||||
MinLvl: Integer;
|
||||
begin
|
||||
Result := EndY;
|
||||
MinLvl := 0; // Search the current line always
|
||||
repeat
|
||||
SetRange(Lines.Ranges[Result - 1]);
|
||||
//PasCodeFoldRange.MinimumCodeFoldBlockLevel;
|
||||
if (EndX > 0) and (MinLvl <= SeekLevel) then begin
|
||||
// Search in current Line
|
||||
X1 := -1;
|
||||
// Use MinimumCodefoldlevel to detect theimplicit end of "var"/"type" blocks at the next "begin"
|
||||
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
|
||||
MinLvl := PasCodeFoldRange.MinimumCodeFoldBlockLevel; // Before SetLine = LastLine's MinLvl
|
||||
SetLine(Lines[Result - 1], Result - 1);
|
||||
while (Run <= EndX) and not GetEol do begin
|
||||
if (MinimumCodeFoldBlockLevel <= SeekLevel) then begin
|
||||
X1 := fTokenPos;
|
||||
X2 := Run;
|
||||
FoldType := TopPascalCodeFoldBlockType;
|
||||
end;
|
||||
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
|
||||
Next;
|
||||
end;
|
||||
if X1 >= 0 then exit;
|
||||
end
|
||||
else
|
||||
MinLvl := PasCodeFoldRange.MinimumCodeFoldBlockLevel; // Before SetLine = LastLine's MinLvl
|
||||
// Search previous lines
|
||||
EndX := MaxInt;
|
||||
dec(Result);
|
||||
until Result = 0; // should always exit before
|
||||
end;
|
||||
|
||||
function FindEnd(BeginY, BeginX2, SeekLevel: Integer;
|
||||
out X1, X2, LvlBefore: Integer): integer; // Returns Line
|
||||
var
|
||||
c, MinLvl : Integer;
|
||||
begin
|
||||
Result := BeginY;
|
||||
c := Lines.Count;
|
||||
MinLvl := 0; // CurrentLine always has samller Minlevel
|
||||
repeat
|
||||
SetRange(Lines.Ranges[Result-1]);
|
||||
if (MinLvl < SeekLevel) then begin
|
||||
// Search in current Line
|
||||
LvlBefore := CurrentCodeFoldBlockLevel;
|
||||
SetLine(Lines[Result - 1], Result - 1);
|
||||
if (FTokenPos < BeginX2) then
|
||||
begin
|
||||
while (FTokenPos < BeginX2) and not GetEol do
|
||||
Next;
|
||||
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
|
||||
end;
|
||||
while not GetEol do
|
||||
begin
|
||||
if CurrentCodeFoldBlockLevel < SeekLevel then
|
||||
begin
|
||||
X1 := fTokenPos;
|
||||
X2 := Run;
|
||||
exit
|
||||
end
|
||||
else if (MinimumCodeFoldBlockLevel < SeekLevel) or
|
||||
(CurrentCodeFoldBlockLevel + LastLineCodeFoldLevelFix < SeekLevel)
|
||||
then
|
||||
exit(-1); // This block ended in the previous line (implicit end)
|
||||
LvlBefore := CurrentCodeFoldBlockLevel;
|
||||
Next;
|
||||
end;
|
||||
end;
|
||||
// Search next lines
|
||||
BeginX2 := 0;
|
||||
inc(Result);
|
||||
if Result < c-1 then begin
|
||||
SetRange(Lines.Ranges[Result]);
|
||||
MinLvl := PasCodeFoldRange.MinimumCodeFoldBlockLevel;
|
||||
end else begin
|
||||
MinLvl := 0;
|
||||
end;
|
||||
until Result >= c;
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.MinimumFoldLevel(Index: Integer): integer;
|
||||
var
|
||||
CurStartLevel, CurEndLevel, CurStartPosX, CurEndPosX, CurPosY: Integer;
|
||||
EndStartLevel: Integer;
|
||||
ft, ft2: TPascalCodeFoldBlockType;
|
||||
r: Pointer;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
CurPosY := LogicalCaret.Y;
|
||||
CurStartLevel := GetLevelBeforeCaret;
|
||||
CurEndLevel := CurrentCodeFoldBlockLevel;
|
||||
CurStartPosX := fTokenPos; // 0 based
|
||||
CurEndPosX := Run; // 0 based
|
||||
|
||||
IF CurEndLevel > CurStartLevel then begin
|
||||
// block open: begin or middle
|
||||
if not (TopPascalCodeFoldBlockType in PascalWordTrippletRanges) then
|
||||
exit;
|
||||
|
||||
Y1 := CurPosY;
|
||||
XB1 := CurStartPosX;
|
||||
XE1 := CurEndPosX;
|
||||
|
||||
Y3 := FindEnd(CurPosY, CurEndPosX, CurEndLevel, XB3, XE3, EndStartLevel);
|
||||
if Y3 < 0 then exit(false);
|
||||
|
||||
Result := true;
|
||||
if (EndStartLevel - CurrentCodeFoldBlockLevel = 1) then begin;
|
||||
Y2:=-2;
|
||||
end else begin
|
||||
if CurStartLevel = CurrentCodeFoldBlockLevel
|
||||
then Y2 := FindBegin(Y3, XB3, CurrentCodeFoldBlockLevel+1, XB2, XE2, ft)
|
||||
else Y2 := FindBegin(Y3, XB3, CurrentCodeFoldBlockLevel, XB2, XE2, ft);
|
||||
if not (ft in PascalWordTrippletRanges) then
|
||||
Y2 := -1;
|
||||
end;
|
||||
end
|
||||
if Index = CurrentLines.Count - 1 then exit(0);
|
||||
r := CurrentLines.Ranges[Index + 1]; // stored as the start of the next line
|
||||
if (r <> nil) and (r <> NullRange) then
|
||||
Result := TSynPasSynRange(r).MinimumCodeFoldBlockLevel
|
||||
else
|
||||
if CurStartLevel - CurEndLevel = 1 then begin
|
||||
// block end, 1 lvl
|
||||
Y1 := FindBegin(CurPosY, CurStartPosX, CurEndLevel, XB1, XE1, ft);
|
||||
if not (ft in PascalWordTrippletRanges) then
|
||||
exit;
|
||||
Y2 := CurPosY;
|
||||
XB2 := CurStartPosX;
|
||||
XE2 := CurEndPosX;
|
||||
Y3 := -2;
|
||||
Result := true;
|
||||
end
|
||||
else
|
||||
if CurEndLevel < CurStartLevel then begin
|
||||
// block end, 2 lvl
|
||||
Y2 := FindBegin(CurPosY, CurStartPosX, CurEndLevel+1, XB2, XE2, ft);
|
||||
Y1 := FindBegin(Y2, XB2, CurEndLevel, XB1, XE1, ft2);
|
||||
if not (ft in PascalWordTrippletRanges) then
|
||||
Y2 := -1;
|
||||
if not (ft2 in PascalWordTrippletRanges) then
|
||||
Y1 := -1;
|
||||
if (Y2 = -1) and (Y1 = -1) then
|
||||
exit;
|
||||
Y3 := CurPosY;
|
||||
XB3 := CurStartPosX;
|
||||
XE3 := CurEndPosX;
|
||||
Result := true;
|
||||
end;
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
inc(XB1);
|
||||
inc(XE1);
|
||||
inc(XB2);
|
||||
inc(XE2);
|
||||
inc(XB3);
|
||||
inc(XE3);
|
||||
function TSynPasSyn.EndFoldLevel(Index: Integer): integer;
|
||||
var
|
||||
r: Pointer;
|
||||
begin
|
||||
if Index = CurrentLines.Count - 1 then exit(0);
|
||||
r := CurrentLines.Ranges[Index + 1]; // stored as the start of the next line
|
||||
if (r <> nil) and (r <> NullRange) then
|
||||
Result := TSynPasSynRange(r).CodeFoldStackSize
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.LastLineFoldLevelFix(Index: Integer): integer;
|
||||
var
|
||||
r: Pointer;
|
||||
begin
|
||||
if Index = CurrentLines.Count - 1 then exit(0);
|
||||
r := CurrentLines.Ranges[Index + 1]; // stored as the start of the next line
|
||||
if (r <> nil) and (r <> NullRange) then
|
||||
Result := TSynPasSynRange(r).LastLineCodeFoldLevelFix
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
|
||||
procedure TSynPasSyn.InitNode(var Node: TSynFoldNodeInfo; EndOffs: Integer;
|
||||
ABlockType: TPascalCodeFoldBlockType);
|
||||
begin
|
||||
Node.LogXStart := Run;
|
||||
Node.LogXEnd := Run + fStringLen;
|
||||
Node.FoldLvlStart := CurrentCodeFoldBlockLevel;
|
||||
Node.FoldLvlEnd := CurrentCodeFoldBlockLevel + EndOffs;
|
||||
Node.FoldType := Pointer(PtrInt(ABlockType));
|
||||
if ABlockType in PascalWordTrippletRanges then
|
||||
Node.FoldAction := [sfaMarkup]
|
||||
else
|
||||
Node.FoldAction := [];
|
||||
end;
|
||||
|
||||
function TSynPasSyn.StartPascalCodeFoldBlock(
|
||||
@ -2451,15 +2338,29 @@ var
|
||||
p: PtrInt;
|
||||
begin
|
||||
p := 0;
|
||||
if FCatchNodeInfo and not SubBlock then begin // exclude subblocks, because they do not increase the foldlevel yet
|
||||
GrowNodeInfoList;
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], +1, ABlockType);
|
||||
if not SubBlock then
|
||||
include(FNodeInfoList[FNodeInfoCount].FoldAction, sfaOpen);
|
||||
inc(FNodeInfoCount);
|
||||
end;
|
||||
if SubBlock then
|
||||
p := PtrInt(CountPascalCodeFoldBlockOffset);
|
||||
Result:=TSynCustomCodeFoldBlock(
|
||||
inherited StartCodeFoldBlock(p+Pointer(PtrInt(ABlockType)), not SubBlock));
|
||||
inherited StartCodeFoldBlock(p+Pointer(PtrInt(ABlockType)), not SubBlock));
|
||||
end;
|
||||
|
||||
procedure TSynPasSyn.EndCodeFoldBlock(DecreaseLevel: Boolean);
|
||||
begin
|
||||
DecreaseLevel := TopCodeFoldBlockType < CountPascalCodeFoldBlockOffset;
|
||||
if FCatchNodeInfo and DecreaseLevel then begin // exclude subblocks, because they do not increase the foldlevel yet
|
||||
GrowNodeInfoList;
|
||||
InitNode(FNodeInfoList[FNodeInfoCount], -1, TopPascalCodeFoldBlockType);
|
||||
if DecreaseLevel then
|
||||
include(FNodeInfoList[FNodeInfoCount].FoldAction, sfaClose);
|
||||
inc(FNodeInfoCount);
|
||||
end;
|
||||
inherited EndCodeFoldBlock(DecreaseLevel);
|
||||
end;
|
||||
|
||||
@ -2468,9 +2369,9 @@ begin
|
||||
if TopPascalCodeFoldBlockType <> cfbtBeginEnd then
|
||||
exit;
|
||||
while TopPascalCodeFoldBlockType = cfbtBeginEnd do
|
||||
EndCodeFoldBlock;
|
||||
EndCodeFoldBlockLastLine;
|
||||
if TopPascalCodeFoldBlockType = cfbtProcedure then
|
||||
EndCodeFoldBlock; // This procedure did have a begin/end block, so it must end too
|
||||
EndCodeFoldBlockLastLine; // This procedure did have a begin/end block, so it must end too
|
||||
end;
|
||||
|
||||
procedure TSynPasSyn.EndCodeFoldBlockLastLine;
|
||||
@ -2484,12 +2385,45 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.GetFoldNodeInfo(Line, Index: Integer): TSynFoldNodeInfo;
|
||||
var
|
||||
i: LongInt;
|
||||
begin
|
||||
if FNodeInfoLine <> Line then begin
|
||||
FCatchNodeInfo := True;
|
||||
FNodeInfoCount := 0;
|
||||
SetRange(CurrentLines.Ranges[Line]);
|
||||
SetLine(CurrentLines[Line], Line);
|
||||
fStringLen := 0;
|
||||
i := LastLineFoldLevelFix(Line);
|
||||
while i < 0 do begin
|
||||
EndCodeFoldBlock;
|
||||
inc(i);
|
||||
end;
|
||||
NextToEol;
|
||||
FCatchNodeInfo := False;
|
||||
FNodeInfoLine := Line;
|
||||
end;
|
||||
|
||||
if (index < 0) or (index >= FNodeInfoCount) then
|
||||
Result := inherited GetFoldNodeInfo(Line, Index)
|
||||
else
|
||||
Result := FNodeInfoList[Index];
|
||||
end;
|
||||
|
||||
function TSynPasSyn.GetFoldNodeInfoCount(Line: Integer): Integer;
|
||||
begin
|
||||
if FNodeInfoLine <> Line then
|
||||
GetFoldNodeInfo(Line, 0);
|
||||
Result := FNodeInfoCount;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.GetRangeClass: TSynCustomHighlighterRangeClass;
|
||||
begin
|
||||
Result:=TSynPasSynRange;
|
||||
end;
|
||||
|
||||
function TSynPasSyn.GetLastLineCodeFoldLevelFix: integer;
|
||||
function TSynPasSyn.LastLineCodeFoldLevelFix: integer;
|
||||
begin
|
||||
Result := TSynPasSynRange(CodeFoldRange).LastLineCodeFoldLevelFix;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user