SynEdit Highlighter: Refactor; Highlighter now differs between Fold and Markup ranges; added Markup-Word-Pairs for repeat/try/case

git-svn-id: trunk@19144 -
This commit is contained in:
martin 2009-03-28 22:08:32 +00:00
parent 2c9b6bd08a
commit 8d681fd278
7 changed files with 624 additions and 414 deletions

View File

@ -312,6 +312,7 @@ type
procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS;
procedure WMVScroll(var Msg: {$IFDEF SYN_LAZARUS}TLMScroll{$ELSE}TWMScroll{$ENDIF}); message WM_VSCROLL;
private
FDividerDrawLevel: Integer;
fFirstLine: integer;
fBlockIndent: integer;
FBlockSelection: TSynEditSelection;
@ -433,6 +434,7 @@ type
procedure AquirePrimarySelection;
function GetUndoList: TSynEditUndoList;
procedure SetDividerDrawLevel(const AValue: Integer);
procedure SurrenderPrimarySelection;
procedure BookMarkOptionsChanged(Sender: TObject);
procedure ComputeCaret(X, Y: Integer);
@ -478,8 +480,6 @@ type
{$IFDEF SYN_LAZARUS}
function GetCharLen(const Line: string; CharStartPos: integer): integer;
function GetLogicalCaretXY: TPoint;
procedure SetCFDividerDrawLevel(const AValue: Integer);
function GetCFDividerDrawLevel : Integer;
procedure SetLogicalCaretXY(const NewLogCaretXY: TPoint);
procedure SetBeautifier(NewBeautifier: TSynCustomBeautifier);
{$ENDIF}
@ -619,7 +619,6 @@ type
function GetTopView : Integer;
procedure SetTopView(const AValue : Integer);
{$ENDIF}
procedure ListScanRanges(Sender: TObject);
procedure Loaded; override;
procedure MarkListChange(Sender: TObject);
{$IFDEF SYN_MBCSSUPPORT}
@ -929,10 +928,7 @@ type
{$ENDIF}
property SelectionMode: TSynSelectionMode
read GetSelectionMode write SetSelectionMode default smNormal;
{$IFDEF SYN_LAZARUS}
property CFDividerDrawLevel: Integer
read GetCFDividerDrawLevel write SetCFDividerDrawLevel;
{$ENDIF}
property CFDividerDrawLevel: Integer read FDividerDrawLevel write SetDividerDrawLevel;
property TabWidth: integer read fTabWidth write SetTabWidth default 8;
property WantTabs: boolean read fWantTabs write SetWantTabs default FALSE;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
@ -1981,16 +1977,6 @@ begin
Result:=PhysicalToLogicalPos(CaretXY);
end;
procedure TCustomSynEdit.SetCFDividerDrawLevel(const AValue: Integer);
begin
FFoldedLinesView.CFDividerDrawLevel := AValue;
end;
function TCustomSynEdit.GetCFDividerDrawLevel : Integer;
begin
Result := FFoldedLinesView.CFDividerDrawLevel;
end;
procedure TCustomSynEdit.SetLogicalCaretXY(const NewLogCaretXY: TPoint);
begin
CaretXY:=LogicalToPhysicalPos(NewLogCaretXY);
@ -2791,7 +2777,8 @@ var
colEditorBG: TColor;
// painting the background and the text
rcLine, rcToken: TRect;
CurLine: integer; // line index for the loop
CurLine: integer; // Screen-line index for the loop
CurTextIndex: Integer; // Current Index in text
CurPhysPos, CurLogIndex : Integer; // Physical Start Position of next token in current Line
TokenAccu: record
Len, MaxLen: integer;
@ -3314,6 +3301,7 @@ var
CurLine := FirstLine-1;
while CurLine<LastLine do begin
inc(CurLine);
CurTextIndex := FFoldedLinesView.TextIndex[CurLine];
FTextDrawer.FrameStartX := -1;
FTextDrawer.FrameEndX := -1;
LastFSX := -1;
@ -3340,44 +3328,22 @@ var
// Initialize highlighter with line text and range info. It is
// necessary because we probably did not scan to the end of the last
// line - the internal highlighter range might be wrong.
{$IFDEF DEBUGSYNRANGE}
if (FFoldedLinesView.Ranges[CurLine] = nil) or
(FFoldedLinesView.Ranges[CurLine] = NullRange) then begin
debugln(['>>>> SynEdit Highlight-Ranges Error <<<< ',
' AClip =', dbgs(AClip),
' FirstLine=', FirstLine,' LastLine=',Lastline,
' CurLine=',CurLine,
' FirstCol=',FirstCol, ' LastCol=',LastCol,
' CanvasRect=',dbgs(Canvas.ClipRect)]);
debugln([' Topline=', FTopLine, ' LineCount=', FLines.Count,
' FoldedTopLine=', FFoldedLinesView.TopLine,
' foldedCount=', FFoldedLinesView.Count,
' TextHeight=', FTextHeight,
' Range=', PtrInt(FFoldedLinesView.Ranges[CurLine])
]);
DrawHiLightMarkupToken(nil, PChar(Pointer(sLine)), Length(sLine));
end
else begin
{$ENDIF}
fHighlighter.StartAtLineIndex(FFoldedLinesView.ScreenLineToTextIndex(CurLine));
// Try to concatenate as many tokens as possible to minimize the count
// of ExtTextOut calls necessary. This depends on the selection state
// or the line having special colors. For spaces the foreground color
// is ignored as well.
//debugln('>>>> PaintLines Line=',dbgs(CurLine),' rect=',dbgs(rcToken));
while not fHighlighter.GetEol do begin
fHighlighter.GetTokenEx(sToken,nTokenLen);
attr := fHighlighter.GetTokenAttribute;
// Add Markup to the token and append it to the TokenAccu
// record. This will paint any chars already stored if there is
// a (visible) change in the attributes.
DrawHiLightMarkupToken(attr,sToken,nTokenLen);
// Let the highlighter scan the next token.
fHighlighter.Next;
end;
{$IFDEF DEBUGSYNRANGE}
fHighlighter.StartAtLineIndex(CurTextIndex);
// Try to concatenate as many tokens as possible to minimize the count
// of ExtTextOut calls necessary. This depends on the selection state
// or the line having special colors. For spaces the foreground color
// is ignored as well.
//debugln('>>>> PaintLines Line=',dbgs(CurLine),' rect=',dbgs(rcToken));
while not fHighlighter.GetEol do begin
fHighlighter.GetTokenEx(sToken,nTokenLen);
attr := fHighlighter.GetTokenAttribute;
// Add Markup to the token and append it to the TokenAccu
// record. This will paint any chars already stored if there is
// a (visible) change in the attributes.
DrawHiLightMarkupToken(attr,sToken,nTokenLen);
// Let the highlighter scan the next token.
fHighlighter.Next;
end;
{$ENDIF}
end;
// Draw anything that's left in the TokenAccu record. Fill to the end
// of the invalid area with the correct colors.
@ -3385,13 +3351,15 @@ var
fMarkupManager.FinishMarkupForRow(FFoldedLinesView.TextIndex[CurLine]+1);
// codefold draw splitter line
if assigned(Gutter.CodeFoldPart) and Gutter.CodeFoldPart.Visible
and (FFoldedLinesView.DrawDivider[curLine]) then
begin
ypos := rcToken.Bottom - 1;
LCLIntf.MoveToEx(dc, nRightEdge, ypos, nil);
LCLIntf.LineTo(dc, fGutterWidth - 1, ypos);
// draw splitter line
if Assigned(fHighlighter) then begin
fHighlighter.DrawDividerLevel := FDividerDrawLevel;
if (fHighlighter.DrawDivider[CurTextIndex]) then
begin
ypos := rcToken.Bottom - 1;
LCLIntf.MoveToEx(dc, nRightEdge, ypos, nil);
LCLIntf.LineTo(dc, fGutterWidth - 1, ypos);
end;
end;
end;
CurLine:=-1;
@ -4461,15 +4429,6 @@ begin
end;
{$ENDIF}
procedure TCustomSynEdit.ListScanRanges(Sender: TObject);
{$IFNDEF SYN_LAZARUS}
var
i: integer;
{$ENDIF}
begin
ScanFrom(0,FTheLinesView.Count-1);
end;
{$IFDEF SYN_MBCSSUPPORT}
type
TStringType = (stNone, stHalfNumAlpha, stHalfSymbol, stHalfKatakana,
@ -4967,6 +4926,12 @@ begin
Result := fUndoList;
end;
procedure TCustomSynEdit.SetDividerDrawLevel(const AValue: Integer);
begin
FDividerDrawLevel := AValue;
Invalidate;
end;
function TCustomSynEdit.GetLineState(ALine: Integer): TSynLineState;
begin
with TSynEditStringList(fLines) do
@ -5288,6 +5253,9 @@ begin
if Operation = opRemove then begin
if AComponent = fHighlighter then begin
fHighlighter := nil;
if assigned(FLines.Ranges) then
FLines.Ranges.Free;
FLines.Ranges := nil;
fMarkupHighCaret.Highlighter := nil;
fMarkupWordGroup.Highlighter := nil;
FFoldedLinesView.Highlighter := nil;
@ -5309,9 +5277,10 @@ end;
procedure TCustomSynEdit.RemoveHooksFromHighlighter;
begin
if Assigned(fHighlighter) then
fHighlighter.UnhookAttrChangeEvent
({$IFDEF FPC}@{$ENDIF}HighlighterAttrChanged);
if not Assigned(fHighlighter) then
exit;
fHighlighter.UnhookAttrChangeEvent({$IFDEF FPC}@{$ENDIF}HighlighterAttrChanged);
fHighlighter.DetachFromLines(FLines);
end;
procedure TCustomSynEdit.SetHighlighter(const Value: TSynCustomHighlighter);
@ -5322,6 +5291,7 @@ begin
Value.HookAttrChangeEvent(
{$IFDEF FPC}@{$ENDIF}HighlighterAttrChanged);
Value.FreeNotification(Self);
Value.AttachToLines(FLines);
end;
fHighlighter := Value;
// Ensure to free all copies in SynEit.Notification too
@ -5338,7 +5308,7 @@ begin
RecalcCharExtent;
FTheLinesView.BeginUpdate;
try
ListScanRanges(Self);
ScanFrom(0,FTheLinesView.Count-1);
finally
FTheLinesView.EndUpdate;
end;

View File

@ -180,23 +180,16 @@ type
fTextIndexList : Array of integer; (* Map each Screen line into a line in textbuffer *)
fFoldTypeList : Array of TSynEditCodeFoldType;
fOnFoldChanged : TFoldChangedEvent;
fCFDividerDrawLevel: Integer;
fLockCount : Integer;
fNeedFixFrom, fNeedFixMinEnd : Integer;
fNeedCaretCheck : Boolean;
function GetCount : integer;
function GetDrawDivider(Index : integer) : Boolean;
function GetFoldEndLevel(Index: integer): integer;
function GetFoldMinLevel(Index: integer): integer;
function GetFoldNestLevel(index : Integer): integer;
function GetLines(index : Integer) : String;
function GetDisplayNumber(index : Integer) : Integer;
function GetRange(Index : integer) : TSynEditRange;
function GetTextIndex(index : Integer) : Integer;
function GetFoldType(index : Integer) : TSynEditCodeFoldType;
function IsFolded(index : integer) : Boolean; // TextIndex
procedure PutRange(Index : integer; const AValue : TSynEditRange);
procedure SetTopLine(const ALine : integer);
function GetTopTextIndex : integer;
procedure SetTopTextIndex(const AIndex : integer);
@ -232,16 +225,10 @@ type
// Attributes for Visible-Lines-On-screen
property Lines[index : Integer] : String (* Lines on screen / 0 = TopLine *)
read GetLines; default;
property Ranges[Index: integer]: TSynEditRange
read GetRange write PutRange;
property DisplayNumber[index : Integer] : Integer (* LineNumber for display in Gutter / result is 1-based *)
read GetDisplayNumber;
property FoldType[index : Integer] : TSynEditCodeFoldType (* FoldIcon / State *)
read GetFoldType;
property FoldNestLvl[index : Integer] : integer (* FoldIcon / Deep/Level of nesting; 1 for top-lvl *)
read GetFoldNestLevel;
property DrawDivider[Index: integer]: Boolean
read GetDrawDivider;
property TextIndex[index : Integer] : Integer (* Position in SynTextBuffer / result is 0-based *)
read GetTextIndex; // maybe writable
@ -255,7 +242,6 @@ type
property Count : integer read GetCount; (* refers to visible (unfolded) lines *)
property CFDividerDrawLevel: Integer read fCFDividerDrawLevel write fCFDividerDrawLevel;
property MarkupInfoFoldedCode: TSynSelectedColor read FMarkupInfoFoldedCode;
public
procedure Lock;
@ -283,10 +269,6 @@ type
property OnFoldChanged: TFoldChangedEvent (* reports 1-based line *) {TODO: synedit expects 0 based }
read fOnFoldChanged write fOnFoldChanged;
public
// TextIndex
property FoldMinLevel[Index: integer]: integer read GetFoldMinLevel;
property FoldEndLevel[Index: integer]: integer read GetFoldEndLevel;
property HighLighter: TSynCustomHighlighter read FHighLighter
write FHighLighter;
end;
@ -1554,21 +1536,6 @@ begin
Result := fLines.Count - fFoldTree.FindLastFold.FoldedBefore;
end;
function TSynEditFoldedView.GetDrawDivider(Index : integer) : Boolean;
begin
result := (FoldType[Index] in [cfEnd])
and (FoldEndLevel[TextIndex[index]] < CFDividerDrawLevel);
end;
function TSynEditFoldedView.GetFoldNestLevel(index : Integer): integer;
begin
if (index < 0) or (index > fLinesInWindow) then exit(-1);
if (fFoldTypeList[index] = cfEnd) and (fTextIndexList[index] > 0) then
Result := FoldEndLevel[fTextIndexList[index]-1]
else
Result := FoldEndLevel[fTextIndexList[index]];
end;
(* Topline *)
procedure TSynEditFoldedView.SetTopLine(const ALine : integer);
begin
@ -1601,7 +1568,19 @@ procedure TSynEditFoldedView.CalculateMaps;
var
i, tpos, cnt : Integer;
node : TSynTextFoldAVLNode;
hl: TSynCustomFoldHighlighter;
begin
if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter))
then begin
for i := 0 to fLinesInWindow do begin
fTextIndexList[i] := fTopLine + i - 1;
fFoldTypeList[i] := cfNone;
end;
exit;
end;
FHighLighter.CurrentLines := fLines;
hl := TSynCustomFoldHighlighter(FHighLighter);
node := fFoldTree.FindFoldForFoldedLine(fTopLine, true);
// ftopline is not a folded line
// so node.FoldedBefore(next node after ftopl) does apply
@ -1617,13 +1596,13 @@ begin
if (node.IsInFold) and (tpos+1 = node.StartLine)
then fFoldTypeList[i] := cfCollapsed
else
if FoldEndLevel[tpos-1] > FoldMinLevel[tpos-1]
if (hl.FoldOpenCount(tpos - 1) > 0)
then fFoldTypeList[i] := cfExpanded
else
if (tpos > 1) and (FoldEndLevel[tpos-2] > FoldMinLevel[tpos-1])
if (tpos > 1) and (hl.FoldCloseCount(tpos - 1) > 0)
then fFoldTypeList[i] := cfEnd
else
if FoldEndLevel[tpos-1] > 0
if hl.FoldNestCount(tpos - 1) > 0
then fFoldTypeList[i] := cfContinue
else fFoldTypeList[i] := cfNone;
@ -1651,13 +1630,6 @@ begin
Result := fTextIndexList[index]+1;
end;
function TSynEditFoldedView.GetRange(Index : integer) : TSynEditRange;
begin
if (index < 0) or (index > fLinesInWindow) then
exit(fLines.Ranges[ScreenLineToTextIndex(Index)]);
Result := fLines.Ranges[fTextIndexList[index]];
end;
function TSynEditFoldedView.GetTextIndex(index : Integer) : Integer;
begin
if (index < 0) or (index > fLinesInWindow) then
@ -1676,34 +1648,8 @@ begin
Result := fFoldTree.FindFoldForLine(index+1).IsInFold;
end;
procedure TSynEditFoldedView.PutRange(Index : integer; const AValue : TSynEditRange);
begin
if (index < 0) or (index > fLinesInWindow) then exit;
fLines.Ranges[fTextIndexList[index]] := AValue;
end;
(* Folding *)
function TSynEditFoldedView.GetFoldEndLevel(Index: integer): integer;
begin
if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter))
then exit(0);
FHighLighter.CurrentLines := fLines;
Result := TSynCustomFoldHighlighter(FHighLighter).EndFoldLevel(Index) +
TSynCustomFoldHighlighter(FHighLighter).LastLineFoldLevelFix(Index + 1);
end;
function TSynEditFoldedView.GetFoldMinLevel(Index: integer): integer;
begin
if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter))
then exit(0);
FHighLighter.CurrentLines := fLines;
Result := TSynCustomFoldHighlighter(FHighLighter).EndFoldLevel(Index) +
TSynCustomFoldHighlighter(FHighLighter).LastLineFoldLevelFix(Index + 1);
Result := Min(Result,
TSynCustomFoldHighlighter(FHighLighter).MinimumFoldLevel(Index));
end;
procedure TSynEditFoldedView.FoldAtLine(AStartLine : Integer);
begin
FoldAtViewPos(AStartLine + fTopLine);
@ -1715,17 +1661,11 @@ begin
end;
function TSynEditFoldedView.LengthForFoldAtTextIndex(ALine : Integer) : Integer;
var
i, lvl, cnt : Integer;
begin
cnt := fLines.Count;
// AStartLine is 1-based // FoldEndLevel is 0-based
lvl := FoldEndLevel[ALine];
i := ALine+1;
while (i < cnt) and (FoldMinLevel[i] >= lvl) do inc(i);
// check if fold last line of block (not mixed "end begin")
if (i < cnt) and (FoldEndLevel[i] <= FoldMinLevel[i]) then inc(i);
Result := i-ALine-1;
if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter))
then exit(0);
Result := TSynCustomFoldHighlighter(FHighLighter).FoldLineLength(ALine,
TSynCustomFoldHighlighter(FHighLighter).FoldOpenCount(ALine) -1);
end;
procedure TSynEditFoldedView.FoldAtTextIndex(AStartIndex : Integer);
@ -1780,13 +1720,19 @@ end;
procedure TSynEditFoldedView.FoldAll(StartLevel : Integer = 0; IgnoreNested : Boolean = False);
var
i, l, top: Integer;
hl: TSynCustomFoldHighlighter;
begin
if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter))
then exit;
FHighLighter.CurrentLines := fLines;
hl := TSynCustomFoldHighlighter(FHighLighter);
top := TopTextIndex;
fFoldTree.Clear;
i := 0;
while i < fLines.Count do begin
if (FoldEndLevel[i] > FoldMinLevel[i])
and (FoldEndLevel[i] > StartLevel) then begin
if (hl.FoldOpenCount(i) > 0)
and (hl.FoldNestCount(i) > StartLevel) then begin
l := LengthForFoldAtTextIndex(i);
// i is 0-based
// FoldTree is 1-based AND first line remains visble
@ -1807,6 +1753,7 @@ var
line, cnt, a: Integer;
LastStart, LastCount: Integer;
node, tmpnode: TSynTextFoldAVLNode;
hl: TSynCustomFoldHighlighter;
begin
Result := false;
if fLockCount > 0 then begin
@ -1825,6 +1772,11 @@ begin
end;
If AMinEnd < node.StartLine then AMinEnd := node.StartLine;
if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter))
then exit;
FHighLighter.CurrentLines := fLines;
hl := TSynCustomFoldHighlighter(FHighLighter);
// LineCount is allowed to be -1
while node.IsInFold and (node.StartLine + node.LineCount + 1 >= AStart) do begin
tmpnode := node.Prev;
@ -1851,7 +1803,7 @@ begin
LastCount := cnt;
// look at the 0-based cfCollapsed (visible) Line
if not(FoldEndLevel[line -1] > FoldMinLevel[line - 1]) then begin
if not(hl.FoldOpenCount(line - 1) > 0) then begin
// the Fold-Begin of this node has gone
tmpnode := node.Prev;
aFoldTree.RemoveFoldForNodeAtLine(node, -1); // Don't touch any nested node
@ -1917,36 +1869,35 @@ function TSynEditFoldedView.ExpandedLineForBlockAtLine(ALine : Integer) : Intege
var
i, l : Integer;
node: TSynTextFoldAVLNode;
hl: TSynCustomFoldHighlighter;
begin
Result := -1;
i := ALine-1;
if not(assigned(FHighLighter) and (FHighLighter is TSynCustomFoldHighlighter))
then exit;
FHighLighter.CurrentLines := fLines;
hl := TSynCustomFoldHighlighter(FHighLighter);
if (i>0) and (FoldMinLevel[i] < FoldEndLevel[i-1])then begin
if FoldMinLevel[i] < FoldEndLevel[i] then begin
// this is a combined "end begin" line
node := fFoldTree.FindFoldForLine(ALine, true);
if node.IsInFold and (node.StartLine = ALine +1) then
dec(i);
if i < 0 then exit;
end else begin
// this is a "end" line
dec(i);
end;
l := FoldEndLevel[i];
end else if FoldEndLevel[i] = 0 then
exit
else begin
// check if current line is cfCollapsed
i := ALine;
if hl.FoldOpenCount(i - 1) > 0 then begin
node := fFoldTree.FindFoldForLine(ALine, true);
if node.IsInFold and (node.StartLine = ALine +1) then
dec(i);
if i < 0 then exit;
l := FoldEndLevel[i]
end;
while (i > 0) and (FoldMinLevel[i] >= l) do
dec(i)
else
exit(ALine);
end
else if hl.FoldCloseCount(i - 1) > 0 then
dec(i);
if (FoldEndLevel[i] > 0) then // TODO, check for collapsed at index = 0
if (i < 0) or (hl.FoldNestCount(i-1) = 0) then
exit;
l := 0;
while (i > 0) and (l >= 0) do begin // (FoldMinLevel[i] >= l) do
dec(i);
l := l - hl.FoldOpenCount(i);
if l >= 0 then
l := l + hl.FoldCloseCount(i);
end;
if (hl.FoldNestCount(i) > 0) then // TODO, check for collapsed at index = 0
Result := i + 1;
end;

View File

@ -59,6 +59,18 @@ type
{$ENDIF}
end;
{ TSynHighlighterRangeList }
TSynHighlighterRangeList = class(TSynEditStorageMem)
private
function GetRange(Index: Integer): Pointer;
procedure SetRange(Index: Integer; const AValue: Pointer);
protected
function ItemSize: Integer; override;
public
property Range[Index: Integer]: Pointer read GetRange write SetRange; default;
end;
{ TSynHighlighterAttributes }
TSynHighlighterAttributes = class(TPersistent)
@ -154,11 +166,15 @@ type
{$IFDEF SYN_LAZARUS}
FCapabilities: TSynHighlighterCapabilities;
FCurrentLines: TSynEditStrings;
FCurrentRanges: TSynHighlighterRangeList;
FDrawDividerLevel: Integer;
FLineIndex: Integer;
{$ENDIF}
fUpdateCount: integer; //mh 2001-09-13
fEnabled: Boolean;
fWordBreakChars: TSynIdentChars;
procedure SetCurrentLines(const AValue: TSynEditStrings);
procedure SetDrawDividerLevel(const AValue: Integer);
procedure SetEnabled(const Value: boolean); //DDH 2001-10-23
protected
fDefaultFilter: string;
@ -177,8 +193,12 @@ type
procedure SetAttributesOnChange(AEvent: TNotifyEvent);
procedure SetDefaultFilter(Value: string); virtual;
procedure SetSampleSource(Value: string); virtual;
function CreateRangeList: TSynHighlighterRangeList; virtual;
function UpdateRangeInfoAtLine(Index: Integer): Boolean; virtual; // Returns true if range changed
// code fold - only valid if hcCodeFolding in Capabilities
property LineIndex: Integer read FLineIndex;
property CurrentRanges: TSynHighlighterRangeList read FCurrentRanges;
function GetDrawDivider(Index: integer): Boolean; virtual;
public
procedure DefHighlightChange(Sender: TObject);
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
@ -194,6 +214,8 @@ type
procedure Assign(Source: TPersistent); override;
procedure BeginUpdate;
procedure EndUpdate;
procedure AttachToLines(Lines: TSynEditStrings);
procedure DetachFromLines(Lines: TSynEditStrings);
public
function GetEol: Boolean; virtual; abstract;
function GetRange: Pointer; virtual;
@ -206,13 +228,21 @@ type
procedure Next; virtual; abstract;
procedure NextToEol;
property DrawDivider[Index: integer]: Boolean read GetDrawDivider;
property DrawDividerLevel: Integer read FDrawDividerLevel write SetDrawDividerLevel;
public
property CurrentLines: TSynEditStrings read FCurrentLines write SetCurrentLines;
procedure StartAtLineIndex(LineNumber:Integer); virtual; // 0 based
procedure ContinueNextLine; // To be called at EOL; does not read the range
function ScanFrom(Index: integer; AtLeastTilIndex: integer = -1): integer;
procedure SetRange(Value: Pointer); virtual;
procedure ResetRange; virtual;
procedure SetLine({$IFDEF FPC}const {$ENDIF}NewValue: String;
LineNumber:Integer // 0 based
); virtual;
procedure StartAtLineIndex(LineNumber:Integer); // 0 based
procedure ContinueNextLine; // To be called at EOL; does not read the range
public
function UseUserSettings(settingIndex: integer): boolean; virtual;
procedure EnumUserSettings(Settings: TStrings); virtual;
@ -225,13 +255,6 @@ 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;
function ScanFrom(Index: integer; AtLeastTilIndex: integer = -1): integer;
(* Methds for folding *)
function MinimumCodeFoldBlockLevel: integer; virtual;
function CurrentCodeFoldBlockLevel: integer; virtual;
function LastLineCodeFoldLevelFix: integer; virtual;
public
property AttrCount: integer read GetAttribCount;
property Attribute[idx: integer]: TSynHighlighterAttributes
@ -833,6 +856,18 @@ begin
end;
end;
procedure TSynCustomHighlighter.AttachToLines(Lines: TSynEditStrings);
begin
Lines.Ranges := CreateRangeList;
end;
procedure TSynCustomHighlighter.DetachFromLines(Lines: TSynEditStrings);
begin
if assigned(Lines.Ranges) then
Lines.Ranges.Free;
Lines.Ranges := nil;
end;
procedure TSynCustomHighlighter.FreeHighlighterAttributes;
var
i: integer;
@ -1067,7 +1102,7 @@ begin
if LineNumber = 0 then
ResetRange
else
SetRange(CurrentLines.Ranges[LineNumber - 1]);
SetRange(FCurrentRanges[LineNumber - 1]);
SetLine(CurrentLines[LineNumber], LineNumber);
end;
@ -1106,11 +1141,26 @@ procedure TSynCustomHighlighter.SetSampleSource(Value: string);
begin
end;
function TSynCustomHighlighter.CreateRangeList: TSynHighlighterRangeList;
begin
Result := TSynHighlighterRangeList.Create;
end;
procedure TSynCustomHighlighter.UnhookAttrChangeEvent(ANotifyEvent: TNotifyEvent);
begin
fAttrChangeHooks.Remove(ANotifyEvent);
end;
function TSynCustomHighlighter.UpdateRangeInfoAtLine(Index: Integer): Boolean;
var
r: Pointer;
begin
r := GetRange;
Result := r <> FCurrentRanges[Index];
if Result then
FCurrentRanges[Index] := r;
end;
function TSynCustomHighlighter.ScanFrom(Index: integer; AtLeastTilIndex: integer): integer;
var
c: LongInt;
@ -1119,10 +1169,9 @@ begin
c := CurrentLines.Count;
StartAtLineIndex(Result);
NextToEol;
while (GetRange <> CurrentLines.Ranges[Result]) or
while UpdateRangeInfoAtLine(Result) or
(Result <= AtLeastTilIndex+1)
do begin
CurrentLines.Ranges[Result] := GetRange;
inc(Result);
if Result = c then
break;
@ -1131,11 +1180,6 @@ begin
end;
end;
function TSynCustomHighlighter.MinimumCodeFoldBlockLevel: integer;
begin
Result := 0;
end;
procedure TSynCustomHighlighter.SetEnabled(const Value: boolean);
begin
if fEnabled <> Value then
@ -1148,14 +1192,41 @@ begin
end;
end;
function TSynCustomHighlighter.LastLineCodeFoldLevelFix: integer;
procedure TSynCustomHighlighter.SetCurrentLines(const AValue: TSynEditStrings);
begin
Result := 0;
if AValue = FCurrentLines then
exit;
FCurrentLines := AValue;
FCurrentRanges := TSynHighlighterRangeList(AValue.Ranges);
end;
function TSynCustomHighlighter.CurrentCodeFoldBlockLevel: integer;
procedure TSynCustomHighlighter.SetDrawDividerLevel(const AValue: Integer);
begin
Result := 0;
if FDrawDividerLevel = AValue then exit;
FDrawDividerLevel := AValue;
//DefHighlightChange(Self);
end;
function TSynCustomHighlighter.GetDrawDivider(Index: integer): Boolean;
begin
result := false;
end;
{ TSynHighlighterRangeList }
function TSynHighlighterRangeList.GetRange(Index: Integer): Pointer;
begin
Result := Pointer(ItemPointer[Index]^);
end;
procedure TSynHighlighterRangeList.SetRange(Index: Integer; const AValue: Pointer);
begin
Pointer(ItemPointer[Index]^) := AValue;
end;
function TSynHighlighterRangeList.ItemSize: Integer;
begin
Result := SizeOf(Pointer);
end;
initialization

View File

@ -71,7 +71,8 @@ type
TSynCustomHighlighterRange = class
private
FCodeFoldStackSize: integer;
FCodeFoldStackSize: integer; // EndLevel
FMinimumCodeFoldBlockLevel: integer;
FRangeType: Pointer;
FTop: TSynCustomCodeFoldBlock;
public
@ -79,8 +80,8 @@ type
destructor Destroy; override;
function Compare(Range: TSynCustomHighlighterRange): integer; virtual;
function Add(ABlockType: Pointer = nil; IncreaseLevel: Boolean = True):
TSynCustomCodeFoldBlock;
procedure Pop(DecreaseLevel: Boolean = True);
TSynCustomCodeFoldBlock; virtual;
procedure Pop(DecreaseLevel: Boolean = True); virtual;
procedure Clear; virtual;
procedure Assign(Src: TSynCustomHighlighterRange); virtual;
procedure WriteDebugReport;
@ -88,6 +89,8 @@ type
public
property RangeType: Pointer read FRangeType write FRangeType;
property CodeFoldStackSize: integer read FCodeFoldStackSize;
property MinimumCodeFoldBlockLevel: integer
read FMinimumCodeFoldBlockLevel write FMinimumCodeFoldBlockLevel;
property Top: TSynCustomCodeFoldBlock read FTop;
end;
TSynCustomHighlighterRangeClass = class of TSynCustomHighlighterRange;
@ -115,8 +118,6 @@ type
FCodeFoldRange: TSynCustomHighlighterRange;
fRanges: TSynCustomHighlighterRanges;
FRootCodeFoldBlock: TSynCustomCodeFoldBlock;
protected
FMinimumCodeFoldBlockLevel: integer;
protected
function GetFoldNodeInfo(Line, Index: Integer): TSynFoldNodeInfo; virtual;
function GetFoldNodeInfoCount(Line: Integer): Integer; virtual;
@ -134,14 +135,21 @@ type
destructor Destroy; override;
function GetRange: Pointer; override;
function MinimumCodeFoldBlockLevel: integer; override;
function CurrentCodeFoldBlockLevel: integer; override;
function MinimumCodeFoldBlockLevel: integer; virtual;
function CurrentCodeFoldBlockLevel: integer; virtual;
// requires CurrentLines;
function MinimumFoldLevel(Index: Integer): integer; virtual; abstract;
function EndFoldLevel(Index: Integer): integer; virtual; abstract;
function LastLineFoldLevelFix(Index: Integer): integer; virtual; abstract;
// fold-nodes that can be collapsed
// Highlighter can join several fold structures Or leave out some
function FoldOpenCount(ALineIndex: Integer): integer; virtual;
function FoldCloseCount(ALineIndex: Integer): integer; virtual;
function FoldNestCount(ALineIndex: Integer): integer; virtual;
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; virtual;
// All fold-nodes
property FoldNodeInfo[Line, Index: Integer]: TSynFoldNodeInfo read GetFoldNodeInfo;
property FoldNodeInfoCount[Line: Integer]: Integer read GetFoldNodeInfoCount;
@ -258,7 +266,7 @@ end;
function TSynCustomFoldHighlighter.MinimumCodeFoldBlockLevel: integer;
begin
Result := FMinimumCodeFoldBlockLevel;
Result := FCodeFoldRange.MinimumCodeFoldBlockLevel;
end;
procedure TSynCustomFoldHighlighter.SetRange(Value: Pointer);
@ -267,14 +275,13 @@ begin
// in case we asigned a null range
if not assigned(FCodeFoldRange.FoldRoot) then
FCodeFoldRange.FoldRoot := FRootCodeFoldBlock;
FMinimumCodeFoldBlockLevel:=FCodeFoldRange.CodeFoldStackSize;
end;
procedure TSynCustomFoldHighlighter.SetLine(const NewValue: String;
LineNumber: Integer);
begin
inherited;
FMinimumCodeFoldBlockLevel:=CodeFoldRange.CodeFoldStackSize;
FCodeFoldRange.MinimumCodeFoldBlockLevel := FCodeFoldRange.FCodeFoldStackSize;
end;
function TSynCustomFoldHighlighter.CurrentCodeFoldBlockLevel: integer;
@ -285,6 +292,26 @@ begin
Result:=0;
end;
function TSynCustomFoldHighlighter.FoldOpenCount(ALineIndex: Integer): integer;
begin
result := 0;
end;
function TSynCustomFoldHighlighter.FoldCloseCount(ALineIndex: Integer): integer;
begin
result := 0;
end;
function TSynCustomFoldHighlighter.FoldNestCount(ALineIndex: Integer): integer;
begin
Result := 0;
end;
function TSynCustomFoldHighlighter.FoldLineLength(ALineIndex, FoldIndex: Integer): integer;
begin
result := 0;
end;
function TSynCustomFoldHighlighter.GetFoldNodeInfoCount(Line: Integer): Integer;
begin
Result := 0;
@ -317,8 +344,6 @@ end;
procedure TSynCustomFoldHighlighter.EndCodeFoldBlock(DecreaseLevel: Boolean = True);
begin
CodeFoldRange.Pop(DecreaseLevel);
if FMinimumCodeFoldBlockLevel>CodeFoldRange.CodeFoldStackSize then
FMinimumCodeFoldBlockLevel:=CodeFoldRange.CodeFoldStackSize;
end;
procedure TSynCustomFoldHighlighter.CreateRootCodeFoldBlock;
@ -538,16 +563,19 @@ end;
function TSynCustomHighlighterRange.Compare(Range: TSynCustomHighlighterRange
): integer;
begin
if RangeType<Range.RangeType then
if RangeType < Range.RangeType then
Result:=1
else if RangeType>Range.RangeType then
else if RangeType > Range.RangeType then
Result:=-1
else if Pointer(FTop) < Pointer(Range.FTop) then
Result:= -1
else if Pointer(FTop) > Pointer(Range.FTop) then
Result:= 1
else
Result := 0;
Result := FMinimumCodeFoldBlockLevel - Range.FMinimumCodeFoldBlockLevel;
if Result <> 0 then
exit;
Result := FCodeFoldStackSize - Range.FCodeFoldStackSize;
end;
function TSynCustomHighlighterRange.Add(ABlockType: Pointer;
@ -568,6 +596,8 @@ begin
FTop := FTop.Parent;
if DecreaseLevel then
dec(FCodeFoldStackSize);
if FMinimumCodeFoldBlockLevel > FCodeFoldStackSize then
FMinimumCodeFoldBlockLevel := FCodeFoldStackSize;
end;
end;
@ -575,6 +605,7 @@ procedure TSynCustomHighlighterRange.Clear;
begin
FRangeType:=nil;
FCodeFoldStackSize := 0;
FMinimumCodeFoldBlockLevel := 0;
FTop:=nil;
end;
@ -583,11 +614,13 @@ begin
if (Src<>nil) and (Src<>TSynCustomHighlighterRange(NullRange)) then begin
FTop := Src.FTop;
FCodeFoldStackSize := Src.FCodeFoldStackSize;
FMinimumCodeFoldBlockLevel := Src.FMinimumCodeFoldBlockLevel;
FRangeType := Src.FRangeType;
end
else begin
FTop := nil;
FCodeFoldStackSize := 0;
FMinimumCodeFoldBlockLevel := 0;
FRangeType := nil;
end;
end;
@ -634,6 +667,7 @@ begin
// add a copy
Result:=TSynCustomHighlighterRangeClass(Range.ClassType).Create(Range);
FItems.Add(Result);
//if FItems.Count mod 32 = 0 then debugln(['FOLDRANGE Count=', FItems.Count]);
end;
//debugln('TSynCustomHighlighterRanges.GetEqual A ',dbgs(Node),' ',dbgs(Result.Compare(Range)),' ',dbgs(Result.CodeFoldStackSize));
end;

View File

@ -42,6 +42,30 @@ type
type
{ TSynEditStorageMem }
TSynEditStorageMem = class
private
FMem: PByte;
FCount, FCapacity: Integer;
function GetItemPointer(Index: Integer): Pointer;
protected
procedure SetCapacity(const AValue: Integer); virtual;
procedure SetCount(const AValue: Integer); virtual;
function ItemSize: Integer; virtual; abstract;
property Mem: PByte read FMem;
property ItemPointer[Index: Integer]: Pointer read GetItemPointer;
public
constructor Create;
destructor Destroy; override;
procedure Move(AFrom, ATo, ALen: Integer); virtual;
property Capacity: Integer read FCapacity write SetCapacity;
// Count must be maintained by owner
property Count: Integer read FCount write SetCount;
end;
{ TSynEditStrings }
TSynEditStrings = class(TStrings)
@ -49,8 +73,8 @@ type
FIsUtf8: Boolean;
function GetIsUtf8 : Boolean; virtual;
procedure SetIsUtf8(const AValue : Boolean); virtual;
function GetRange(Index: integer): TSynEditRange; virtual; abstract;
procedure PutRange(Index: integer; ARange: TSynEditRange); virtual; abstract;
function GetRange: TSynEditStorageMem; virtual; abstract;
procedure PutRange(ARange: TSynEditStorageMem); virtual; abstract;
function GetAttribute(const Owner: TClass; const Index: Integer): Pointer; virtual; abstract;
procedure SetAttribute(const Owner: TClass; const Index: Integer; const AValue: Pointer); virtual; abstract;
@ -103,7 +127,7 @@ type
property ExpandedStrings[Index: integer]: string read GetExpandedString;
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
property IsUtf8: Boolean read GetIsUtf8 write SetIsUtf8;
property Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
property Ranges: TSynEditStorageMem read GetRange write PutRange;
end;
{ TSynEditStringsLinked }
@ -115,8 +139,8 @@ type
function GetIsUtf8 : Boolean; override;
procedure SetIsUtf8(const AValue : Boolean); override;
function GetRange(Index: integer): TSynEditRange; override;
procedure PutRange(Index: integer; ARange: TSynEditRange); override;
function GetRange: TSynEditStorageMem; override;
procedure PutRange(ARange: TSynEditStorageMem); override;
function GetAttribute(const Owner: TClass; const Index: Integer): Pointer; override;
procedure SetAttribute(const Owner: TClass; const Index: Integer; const AValue: Pointer); override;
@ -451,14 +475,14 @@ begin
end;
//Ranges
function TSynEditStringsLinked.GetRange(Index: integer): TSynEditRange;
function TSynEditStringsLinked.GetRange: TSynEditStorageMem;
begin
Result:= fSynStrings.Ranges[Index];
Result:= fSynStrings.Ranges;
end;
procedure TSynEditStringsLinked.PutRange(Index: integer; ARange: TSynEditRange);
procedure TSynEditStringsLinked.PutRange(ARange: TSynEditStorageMem);
begin
fSynStrings.Ranges[Index] := ARange;
fSynStrings.Ranges := ARange;
end;
function TSynEditStringsLinked.GetAttribute(const Owner: TClass; const Index: Integer): Pointer;
@ -985,5 +1009,54 @@ begin
Result := FItems[FCount];
end;
{ TSynEditStorageMem }
function TSynEditStorageMem.GetItemPointer(Index: Integer): Pointer;
begin
Result := Pointer(FMem + Index * ItemSize);
end;
procedure TSynEditStorageMem.SetCapacity(const AValue: Integer);
begin
if FCapacity = AValue then exit;
FMem := ReallocMem(FMem, AValue * ItemSize);
if AValue > FCapacity then
FillChar((FMem+FCapacity*ItemSize)^, (AValue-FCapacity)*ItemSize, 0);
FCapacity := AValue;
end;
procedure TSynEditStorageMem.SetCount(const AValue: Integer);
begin
FCount := AValue;
end;
constructor TSynEditStorageMem.Create;
begin
FCapacity := 0;
FCount := 0;
end;
destructor TSynEditStorageMem.Destroy;
begin
SetCount(0);
SetCapacity(0);
inherited Destroy;
end;
procedure TSynEditStorageMem.Move(AFrom, ATo, ALen: Integer);
var
len: Integer;
begin
if ATo < AFrom then begin
Len := Min(ALen, AFrom-ATo);
System.Move((FMem+AFrom*ItemSize)^, (FMem+ATo*ItemSize)^, Alen*ItemSize);
FillChar((FMem+(AFrom+ALen-Len)*ItemSize)^, Len*ItemSize, 0);
end else begin
Len := Min(ALen, ATo-AFrom);
System.Move((FMem+AFrom*ItemSize)^, (FMem+ATo*ItemSize)^, Alen*ItemSize);
FillChar((FMem+AFrom*ItemSize)^, Len*ItemSize, 0);
end;
end;
end.

View File

@ -50,7 +50,6 @@ const
NullRange = TSynEditRange(-1);
type
TSynEditRangeClass = class end; // For Register
TSynEditFlagsClass = class end; // For Register
TSynEditStringFlag = (
@ -75,38 +74,36 @@ type
Procedure CallRangeNotifyEvents(Sender: TSynEditStrings; aIndex, aCount: Integer);
end;
{ TSynEditStringMemory }
TSynEditStringMemory = class
TSynEditStringMemory = class(TSynEditStorageMem)
private
FMem: ^Byte;
FCount, FCapacity: Integer;
FAttributeSize: Integer;
FRangeList: TSynEditStorageMem;
function GetAttribute(Index: Integer; Pos: Integer; Size: Word): Pointer;
function GetAttributeSize: Integer;
function GetCapacity: Integer;
function GetObject(Index: Integer): TObject;
function GetString(Index: Integer): String;
procedure SetAttribute(Index: Integer; Pos: Integer; Size: Word; const AValue: Pointer);
procedure SetAttributeSize(const AValue: Integer);
procedure SetCapacity(const AValue: Integer);
procedure SetCount(const AValue: Integer);
procedure SetCount(const AValue: Integer); override;
procedure SetObject(Index: Integer; const AValue: TObject);
procedure SetRangeList(const AValue: TSynEditStorageMem);
procedure SetString(Index: Integer; const AValue: String);
protected
function ItemSize: Integer; override;
procedure SetCapacity(const AValue: Integer); override;
public
constructor Create;
destructor Destroy; override;
procedure Move(AFrom, ATo, ALen: Integer);
procedure Move(AFrom, ATo, ALen: Integer); override;
property Strings[Index: Integer]: String read GetString write SetString; default;
property Objects[Index: Integer]: TObject read GetObject write SetObject;
property Attribute[Index: Integer; Pos: Integer; Size: Word]: Pointer
read GetAttribute write SetAttribute;
property Capacity: Integer read GetCapacity write SetCapacity;
// Count must be maintained by owner
property Count: Integer read FCount write SetCount;
property AttributeSize: Integer read GetAttributeSize write SetAttributeSize;
property RangeList: TSynEditStorageMem read FRangeList write SetRangeList;
end;
{ TSynEditStringList }
@ -144,8 +141,8 @@ type
procedure SendNotification(AReason: TSynEditNotifyReason;
ASender: TSynEditStrings; aIndex, aCount: Integer); override;
function GetRange(Index: integer): TSynEditRange; {$IFDEF SYN_LAZARUS}override;{$ENDIF}
procedure PutRange(Index: integer; ARange: TSynEditRange); {$IFDEF SYN_LAZARUS}override;{$ENDIF}
function GetRange: TSynEditStorageMem; override;
procedure PutRange(ARange: TSynEditStorageMem); override;
function GetAttribute(const Owner: TClass; const Index: Integer): Pointer; override;
procedure SetAttribute(const Owner: TClass; const Index: Integer; const AValue: Pointer); override;
function Get(Index: integer): string; override;
@ -190,7 +187,6 @@ type
public
property DosFileFormat: boolean read fDosFileFormat write fDosFileFormat;
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
property Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
property OnChange: TNotifyEvent read fOnChange write fOnChange;
property OnChanging: TNotifyEvent read fOnChanging write fOnChanging;
property OnCleared: TNotifyEvent read fOnCleared write fOnCleared;
@ -396,7 +392,6 @@ begin
FLineChangeNotificationList := TLineRangeNotificationList.Create;
inherited Create;
SetAttributeSize(0);
RegisterAttribute(TSynEditRangeClass, SizeOf(Pointer));
RegisterAttribute(TSynEditFlagsClass, SizeOf(TSynEditStringFlag));
fDosFileFormat := TRUE;
{begin} //mh 2000-10-19
@ -445,7 +440,6 @@ begin
Strings[Count-1] := AStrings[i];
Objects[Count-1] := AStrings.Objects[i];
end;
SetAttribute(TSynEditRangeClass, Count-1, NullRange);
Flags[Count-1] := [];
end;
FLineRangeNotificationList.CallRangeNotifyEvents(self, FirstAdded, Count - FirstAdded);
@ -623,12 +617,9 @@ begin
Result := nil;
end;
function TSynEditStringList.GetRange(Index: integer): TSynEditRange;
function TSynEditStringList.GetRange: TSynEditStorageMem;
begin
if (Index >= 0) and (Index < Count) then
Result := TSynEditRange(GetAttribute(TSynEditRangeClass, Index))
else
Result := nil;
Result := FList.RangeList;
end;
procedure TSynEditStringList.Grow;
@ -670,7 +661,6 @@ begin
SetCount(Count + 1);
fList[Index] := S;
FList.Objects[Index] := nil;
Ranges[Index] := NullRange;
Flags[Index] := [];
EndUpdate;
end;
@ -739,17 +729,9 @@ begin
EndUpdate;
end;
procedure TSynEditStringList.PutRange(Index: integer; ARange: TSynEditRange);
procedure TSynEditStringList.PutRange(ARange: TSynEditStorageMem);
begin
{$IFDEF SYN_LAZARUS}
// do not call BeginUpdate/EndUpdate. It would call the too generic OnChange
// events
SetAttribute(TSynEditRangeClass, Index, Pointer(PtrUInt(ARange)));
{$ELSE}
BeginUpdate;
SetAttribute(TSynEditRangeClass, Index, Pointer(PtrUInt(ARange)));
EndUpdate;
{$ENDIF}
FList.RangeList := ARange;
end;
function TSynEditStringList.GetAttribute(const Owner: TClass; const Index: Integer): Pointer;
@ -999,110 +981,111 @@ const
constructor TSynEditStringMemory.Create;
begin
inherited Create;
FCapacity := 0;
FCount := 0;
AttributeSize := 0;
end;
destructor TSynEditStringMemory.Destroy;
begin
SetCount(0);
SetCapacity(0);
inherited Destroy;
FRangeList := nil;
end;
procedure TSynEditStringMemory.Move(AFrom, ATo, ALen: Integer);
var
i, len: Integer;
Len, i: Integer;
begin
//debugln(['TSynEditStringMemory.Move(',AFrom, ',', ATo, ', ',ALen,')']);
if ATo < AFrom then begin
Len := Min(ALen, AFrom-ATo);
for i:=ATo to ATo + Len -1 do Strings[i]:='';
System.Move((FMem+AFrom*FAttributeSize)^, (FMem+ATo*FAttributeSize)^, Alen*FAttributeSize);
FillChar((FMem+(AFrom+ALen-Len)*FAttributeSize)^, Len*FAttributeSize, 0);
end else begin
Len := Min(ALen, ATo-AFrom);
for i:=ATo+Alen-Len to ATo+ALen -1 do Strings[i]:='';
System.Move((FMem+AFrom*FAttributeSize)^, (FMem+ATo*FAttributeSize)^, Alen*FAttributeSize);
FillChar((FMem+AFrom*FAttributeSize)^, Len*FAttributeSize, 0);
end;
end;
function TSynEditStringMemory.GetCapacity: Integer;
begin
Result := FCapacity;
end;
procedure TSynEditStringMemory.SetCapacity(const AValue: Integer);
begin
if FCapacity = AValue then exit;;
FMem := ReallocMem(FMem, AValue * FAttributeSize);
if AValue > FCapacity then
FillChar((FMem+FCapacity*FAttributeSize)^, (AValue-FCapacity)*FAttributeSize, 0);
FCapacity := AValue;
inherited Move(AFrom, ATo, ALen);
if assigned(FRangeList) then
FRangeList.Move(AFrom, ATo, ALen);
end;
procedure TSynEditStringMemory.SetCount(const AValue: Integer);
var
i : Integer;
begin
If FCount = AValue then exit;
for i:= AValue to FCount-1 do Strings[i]:='';
FCount := AValue;
If Count = AValue then exit;
for i:= AValue to Count-1 do Strings[i]:='';
inherited SetCount(AValue);
if assigned(FRangeList) then
FRangeList.Count := AValue;
end;
function TSynEditStringMemory.GetAttributeSize: Integer;
begin
Result := FAttributeSize - SizeOf(String) - SizeOf(TObject)
end;
procedure TSynEditStringMemory.SetAttributeSize(const AValue: Integer);
var
c: LongInt;
begin
if FAttributeSize = AValue + SizeOf(String) + SizeOf(TObject) then exit;;
c := Capacity;
Capacity := 0;
FAttributeSize := AValue + SizeOf(String) + SizeOf(TObject);
SetCapacity(FCapacity);
// Todo: Move existing records
Capacity := c;
end;
function TSynEditStringMemory.GetString(Index: Integer): String;
begin
Result := (PString(FMem + Index * FAttributeSize))^;
Result := (PString(Mem + Index * FAttributeSize))^;
end;
procedure TSynEditStringMemory.SetString(Index: Integer; const AValue: String);
begin
(PString(FMem + Index * FAttributeSize))^ := AValue;
(PString(Mem + Index * FAttributeSize))^ := AValue;
end;
function TSynEditStringMemory.ItemSize: Integer;
begin
Result := FAttributeSize;
end;
procedure TSynEditStringMemory.SetCapacity(const AValue: Integer);
begin
inherited SetCapacity(AValue);
if assigned(FRangeList) then
FRangeList.Capacity := AValue;
end;
function TSynEditStringMemory.GetObject(Index: Integer): TObject;
begin
Result := (PObject(FMem + Index * FAttributeSize + SizeOf(String)))^;
Result := (PObject(Mem + Index * FAttributeSize + SizeOf(String)))^;
end;
procedure TSynEditStringMemory.SetObject(Index: Integer; const AValue: TObject);
begin
(PObject(FMem + Index * FAttributeSize + SizeOf(String)))^ := AValue;
(PObject(Mem + Index * FAttributeSize + SizeOf(String)))^ := AValue;
end;
procedure TSynEditStringMemory.SetRangeList(const AValue: TSynEditStorageMem);
begin
FRangeList := AValue;
if FRangeList <> nil then begin
FRangeList.Capacity := Capacity;
FRangeList.Count := Count;
end;
end;
function TSynEditStringMemory.GetAttribute(Index: Integer; Pos: Integer; Size: Word): Pointer;
begin
case Size of
1 : Result := Pointer(PtrUInt((PByte(FMem + Index * FAttributeSize + AttributeOfset + Pos))^));
2 : Result := Pointer(PtrUInt((PWord(FMem + Index * FAttributeSize + AttributeOfset + Pos))^));
4 : Result := Pointer(PtrUInt((PLongWord(FMem + Index * FAttributeSize + AttributeOfset + Pos))^));
8 : Result := Pointer(PtrUInt((PQWord(FMem + Index * FAttributeSize + AttributeOfset + Pos))^));
1 : Result := Pointer(PtrUInt((PByte(Mem + Index * FAttributeSize + AttributeOfset + Pos))^));
2 : Result := Pointer(PtrUInt((PWord(Mem + Index * FAttributeSize + AttributeOfset + Pos))^));
4 : Result := Pointer(PtrUInt((PLongWord(Mem + Index * FAttributeSize + AttributeOfset + Pos))^));
8 : Result := Pointer(PtrUInt((PQWord(Mem + Index * FAttributeSize + AttributeOfset + Pos))^));
end;
end;
procedure TSynEditStringMemory.SetAttribute(Index: Integer; Pos: Integer; Size: Word; const AValue: Pointer);
begin
case Size of
1 : (PByte(FMem + Index * FAttributeSize + AttributeOfset + Pos))^ := Byte(PtrUInt(AValue));
2 : (PWord(FMem + Index * FAttributeSize + AttributeOfset + Pos))^ := Word(PtrUInt(AValue));
4 : (PLongWord(FMem + Index * FAttributeSize + AttributeOfset + Pos))^ := LongWord(PtrUInt(AValue));
8 : (PQWord(FMem + Index * FAttributeSize + AttributeOfset + Pos))^ := QWord(PtrUInt(AValue));
1 : (PByte(Mem + Index * FAttributeSize + AttributeOfset + Pos))^ := Byte(PtrUInt(AValue));
2 : (PWord(Mem + Index * FAttributeSize + AttributeOfset + Pos))^ := Word(PtrUInt(AValue));
4 : (PLongWord(Mem + Index * FAttributeSize + AttributeOfset + Pos))^ := LongWord(PtrUInt(AValue));
8 : (PQWord(Mem + Index * FAttributeSize + AttributeOfset + Pos))^ := QWord(PtrUInt(AValue));
end;
end;

View File

@ -100,7 +100,9 @@ type
cfbtUnitSection,
cfbtProgram,
cfbtUnit,
cfbtRecord
cfbtRecord,
cfbtExcept,
cfbtRepeat
);
TPascalWordTrippletRanges = set of TPascalCodeFoldBlockType;
@ -108,7 +110,9 @@ const
CountPascalCodeFoldBlockOffset: Pointer =
Pointer(PtrInt(Integer(high(TPascalCodeFoldBlockType))+1));
PascalWordTrippletRanges: TPascalWordTrippletRanges =
[cfbtBeginEnd, cfbtProcedure, cfbtClass, cfbtProgram, cfbtRecord];
[cfbtBeginEnd, cfbtProcedure, cfbtClass, cfbtProgram, cfbtRecord,
cfbtExcept, cfbtRepeat
];
type
@ -128,24 +132,27 @@ type
FMode: TPascalCompilerMode;
FBracketNestLevel : Integer;
FLastLineCodeFoldLevelFix: integer;
FMinimumCodeFoldBlockLevel: Integer;
FPasFoldEndLevel: Smallint;
FPasFoldFixLevel: Smallint;
FPasFoldMinLevel: Smallint;
public
procedure Clear; override;
function Compare(Range: TSynCustomHighlighterRange): integer; override;
procedure Assign(Src: TSynCustomHighlighterRange); override;
function Add(ABlockType: Pointer = nil; IncreaseLevel: Boolean = True):
TSynCustomCodeFoldBlock; override;
procedure Pop(DecreaseLevel: Boolean = True); override;
procedure IncBracketNestLevel;
procedure DecBracketNestLevel;
procedure DecLastLineCodeFoldLevelFix;
procedure DecLastLinePasFoldFix;
property Mode: TPascalCompilerMode read FMode write FMode;
property BracketNestLevel: integer read FBracketNestLevel write FBracketNestLevel;
// Refers To LastLine while scanning
// stored as begining of the next line, it will refer to 2nd last line
property LastLineCodeFoldLevelFix: integer
read FLastLineCodeFoldLevelFix write FLastLineCodeFoldLevelFix;
// Refers To this line while scanning
// stored as begining of the next line, it will refer to the last line
property MinimumCodeFoldBlockLevel: integer
read FMinimumCodeFoldBlockLevel write FMinimumCodeFoldBlockLevel;
property PasFoldEndLevel: Smallint read FPasFoldEndLevel write FPasFoldEndLevel;
property PasFoldFixLevel: Smallint read FPasFoldFixLevel write FPasFoldFixLevel;
property PasFoldMinLevel: Smallint read FPasFoldMinLevel write FPasFoldMinLevel;
end;
{$ENDIF}
@ -161,6 +168,7 @@ type
fAsmStart: Boolean;
FNestedComments: boolean;
FStartCodeFoldBlockLevel: integer;
FPasStartLevel: Smallint;
fRange: TRangeStates;
FAtLineStart: Boolean; // Line had only spaces or comments sofar
{$IFDEF SYN_LAZARUS}
@ -332,18 +340,27 @@ type
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;
{$IFDEF SYN_LAZARUS}
function StartPascalCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType;
SubBlock: boolean = false): TSynCustomCodeFoldBlock;
procedure EndCodeFoldBlock(DecreaseLevel: Boolean = True); override;
procedure CloseBeginEndBlocks;
function GetRangeClass: TSynCustomHighlighterRangeClass; override;
{$ENDIF}
procedure EndCodeFoldBlockLastLine;
function TopPascalCodeFoldBlockType: TPascalCodeFoldBlockType;
function GetRangeClass: TSynCustomHighlighterRangeClass; override;
property PasCodeFoldRange: TSynPasSynRange read GetPasCodeFoldRange;
function MinimumPasFoldLevel(Index: Integer): integer;
function EndPasFoldLevel(Index: Integer): integer;
function LastLinePasFoldLevelFix(Index: Integer): integer;
function LastLineFoldLevelFix(Index: Integer): integer;
function GetDrawDivider(Index: integer): Boolean; override;
public
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
function GetCapabilities: TSynHighlighterCapabilities; override;
@ -374,15 +391,14 @@ type
function UseUserSettings(settingIndex: integer): boolean; override;
procedure EnumUserSettings(settings: TStrings); override;
//code fold
function LastLineCodeFoldLevelFix: integer; override;
{$IFDEF SYN_LAZARUS}
function TopPascalCodeFoldBlockType: TPascalCodeFoldBlockType;
{$ENDIF}
// fold-nodes that can be collapsed
function FoldOpenCount(ALineIndex: Integer): integer; override;
function FoldCloseCount(ALineIndex: Integer): integer; override;
function FoldNestCount(ALineIndex: Integer): integer; override;
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; 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
@ -755,7 +771,7 @@ begin
if FCompilerMode=AValue then exit;
FCompilerMode:=AValue;
FNestedComments:=FCompilerMode in [pcmFPC,pcmObjFPC];
TSynPasSynRange(CodeFoldRange).Mode:=FCompilerMode;
PasCodeFoldRange.Mode:=FCompilerMode;
//DebugLn(['TSynPasSyn.SetCompilerMode FCompilerMode=',ord(FCompilerMode),' FNestedComments=',FNestedComments]);
end;
@ -810,13 +826,17 @@ begin
then begin
Result := tkKey;
fRange := fRange - [rsAsm];
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
{$IFDEF SYN_LAZARUS}
// there may be more than on block ending here
if TopPascalCodeFoldBlockType = cfbtRecord then begin
EndCodeFoldBlock;
end else if TopPascalCodeFoldBlockType = cfbtUnit then begin
EndCodeFoldBlock;
end else if TopPascalCodeFoldBlockType = cfbtExcept then begin
EndCodeFoldBlock;
if TopPascalCodeFoldBlockType = cfbtBeginEnd then
EndCodeFoldBlock;
end else if TopPascalCodeFoldBlockType = cfbtBeginEnd then begin
EndCodeFoldBlock;
if TopPascalCodeFoldBlockType = cfbtProcedure then
@ -910,7 +930,7 @@ begin
// if we are in an include file, we may not know the state
if (fRange * [rsImplementation, rsInterface] = []) then
Include(fRange, rsImplementation);
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
Result := tkKey;
{$IFDEF SYN_LAZARUS}
@ -942,7 +962,7 @@ begin
if KeyComp('Else') then
Result := tkKey
else if KeyComp('Var') then begin
if (TSynPasSynRange(CodeFoldRange).BracketNestLevel = 0) and
if (PasCodeFoldRange.BracketNestLevel = 0) and
(TopPascalCodeFoldBlockType in
[cfbtVarType, cfbtNone, cfbtProcedure, cfbtProgram, cfbtUnit, cfbtUnitSection]) then begin
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
@ -988,7 +1008,7 @@ function TSynPasSyn.Func54: TtkTokenKind;
begin
if KeyComp('Class') then begin
Result := tkKey;
if (rsAfterEqual in fRange) and (TSynPasSynRange(CodeFoldRange).BracketNestLevel = 0)
if (rsAfterEqual in fRange) and (PasCodeFoldRange.BracketNestLevel = 0)
then begin
fRange := fRange + [rsAtClass];
StartPascalCodeFoldBlock(cfbtClass);
@ -1001,7 +1021,7 @@ function TSynPasSyn.Func55: TtkTokenKind;
begin
if KeyComp('Object') then begin
Result := tkKey;
if (rsAfterEqual in fRange) and (TSynPasSynRange(CodeFoldRange).BracketNestLevel = 0)
if (rsAfterEqual in fRange) and (PasCodeFoldRange.BracketNestLevel = 0)
then begin
fRange := fRange + [rsAtClass];
StartPascalCodeFoldBlock(cfbtClass);
@ -1060,15 +1080,11 @@ begin
end
else if KeyComp('Array') then Result := tkKey
else if KeyComp('Try') then
{$IFDEF SYN_LAZARUS}
begin
if TopPascalCodeFoldBlockType=cfbtBeginEnd then
StartPascalCodeFoldBlock(cfbtBeginEnd,true);
Result := tkKey;
end
{$ELSE}
Result := tkKey
{$ENDIF}
else if KeyComp('Inline') then Result := tkKey else Result := tkIdentifier;
end;
@ -1091,13 +1107,17 @@ end;
function TSynPasSyn.Func65: TtkTokenKind;
begin
if KeyComp('Repeat') then Result := tkKey else Result := tkIdentifier;
if KeyComp('Repeat') then begin
Result := tkKey;
StartPascalCodeFoldBlock(cfbtRepeat, True);
end
else Result := tkIdentifier;
end;
function TSynPasSyn.Func66: TtkTokenKind;
begin
if KeyComp('Type') then begin
if (TSynPasSynRange(CodeFoldRange).BracketNestLevel = 0)
if (PasCodeFoldRange.BracketNestLevel = 0)
and (TopPascalCodeFoldBlockType in
[cfbtVarType, cfbtNone, cfbtProcedure, cfbtProgram, cfbtUnit, cfbtUnitSection])
and not(rsAfterEqual in fRange)
@ -1122,7 +1142,7 @@ begin
if KeyComp('Stdcall') then
Result := tkKey
else if KeyComp('Const') then begin
if (TSynPasSynRange(CodeFoldRange).BracketNestLevel = 0) and
if (PasCodeFoldRange.BracketNestLevel = 0) and
(TopPascalCodeFoldBlockType in
[cfbtVarType, cfbtNone, cfbtProcedure, cfbtProgram, cfbtUnit, cfbtUnitSection]) then begin
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
@ -1140,7 +1160,11 @@ end;
function TSynPasSyn.Func73: TtkTokenKind;
begin
if KeyComp('Except') then Result := tkKey else Result := tkIdentifier;
if KeyComp('Except') then begin
Result := tkKey;
StartPascalCodeFoldBlock(cfbtExcept, True);
end
else Result := tkIdentifier;
end;
function TSynPasSyn.Func75: TtkTokenKind;
@ -1153,12 +1177,20 @@ end;
function TSynPasSyn.Func76: TtkTokenKind;
begin
if KeyComp('Until') then Result := tkKey else Result := tkIdentifier;
if KeyComp('Until') then begin
Result := tkKey;
if TopPascalCodeFoldBlockType = cfbtRepeat then EndCodeFoldBlock;
end
else Result := tkIdentifier;
end;
function TSynPasSyn.Func79: TtkTokenKind;
begin
if KeyComp('Finally') then Result := tkKey else Result := tkIdentifier;
if KeyComp('Finally') then begin
Result := tkKey;
StartPascalCodeFoldBlock(cfbtExcept, True);
end
else Result := tkIdentifier;
end;
function TSynPasSyn.Func81: TtkTokenKind;
@ -1308,7 +1340,7 @@ function TSynPasSyn.Func102: TtkTokenKind;
begin
if KeyComp('Function') then begin
if not(rsAfterEqual in fRange) then begin
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
CloseBeginEndBlocks;
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
if ((rsImplementation in fRange) and
@ -1330,7 +1362,7 @@ function TSynPasSyn.Func105: TtkTokenKind;
begin
if KeyComp('Procedure') then begin
if not(rsAfterEqual in fRange) then begin
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
CloseBeginEndBlocks;
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
if ((rsImplementation in fRange) and
@ -1429,7 +1461,7 @@ end;
function TSynPasSyn.Func136: TtkTokenKind;
begin
if KeyComp('Finalization') then begin
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
CloseBeginEndBlocks;
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
if TopPascalCodeFoldBlockType=cfbtUnitSection then EndCodeFoldBlockLastLine;
@ -1454,7 +1486,7 @@ begin
begin
if not(rsAfterEqual in fRange) then
begin
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
CloseBeginEndBlocks;
if TopPascalCodeFoldBlockType = cfbtVarType then EndCodeFoldBlockLastLine;
if ((rsImplementation in fRange) and
@ -1474,7 +1506,7 @@ function TSynPasSyn.Func166: TtkTokenKind;
begin
if KeyComp('Constructor') then begin
if not(rsAfterEqual in fRange) then begin
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
CloseBeginEndBlocks;
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
if ((rsImplementation in fRange) and
@ -1485,7 +1517,7 @@ begin
Result := tkKey;
end else
if KeyComp('Implementation') then begin
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
CloseBeginEndBlocks;
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
if TopPascalCodeFoldBlockType=cfbtUnitSection then EndCodeFoldBlockLastLine;
@ -1505,7 +1537,7 @@ end;
function TSynPasSyn.Func168: TtkTokenKind;
begin
if KeyComp('Initialization') then begin
TSynPasSynRange(CodeFoldRange).BracketNestLevel := 0; // Reset in case of partial code
PasCodeFoldRange.BracketNestLevel := 0; // Reset in case of partial code
CloseBeginEndBlocks;
if TopPascalCodeFoldBlockType=cfbtVarType then EndCodeFoldBlockLastLine;
if TopPascalCodeFoldBlockType=cfbtUnitSection then EndCodeFoldBlockLastLine;
@ -1672,18 +1704,17 @@ end; { Create }
procedure TSynPasSyn.SetLine(const NewValue: string; LineNumber:Integer);
begin
//DebugLn(['TSynPasSyn.SetLine START LineNumber=',LineNumber,' Line="',NewValue,'"']);
{$IFDEF SYN_LAZARUS}
fLineStr := NewValue;
fLineLen:=length(fLineStr);
fLine:=PChar(Pointer(fLineStr));
Run := 0;
Inherited SetLine(NewValue,LineNumber);
FStartCodeFoldBlockLevel := FMinimumCodeFoldBlockLevel;
TSynPasSynRange(CodeFoldRange).LastLineCodeFoldLevelFix := 0;
{$ELSE}
fLine := PChar(NewValue);
Run := 0;
{$ENDIF}
FStartCodeFoldBlockLevel := MinimumCodeFoldBlockLevel;
PasCodeFoldRange.LastLineCodeFoldLevelFix := 0;
PasCodeFoldRange.PasFoldFixLevel := 0;
PasCodeFoldRange.PasFoldMinLevel :=
PasCodeFoldRange.PasFoldEndLevel;
FPasStartLevel := PasCodeFoldRange.PasFoldMinLevel;
FNodeInfoLine := -1;
fLineNumber := LineNumber;
FAtLineStart := True;
@ -1947,7 +1978,7 @@ begin
{$IFDEF SYN_LAZARUS}
if Run>=fLineLen then begin
fTokenID:=tkSymbol;
TSynPasSynRange(CodeFoldRange).IncBracketNestLevel;
PasCodeFoldRange.IncBracketNestLevel;
exit;
end;
{$ENDIF}
@ -1966,11 +1997,11 @@ begin
begin
inc(Run);
fTokenID := tkSymbol;
TSynPasSynRange(CodeFoldRange).IncBracketNestLevel;
PasCodeFoldRange.IncBracketNestLevel;
end;
else
fTokenID := tkSymbol;
TSynPasSynRange(CodeFoldRange).IncBracketNestLevel;
PasCodeFoldRange.IncBracketNestLevel;
end;
end;
@ -1978,7 +2009,7 @@ procedure TSynPasSyn.RoundCloseProc;
begin
inc(Run);
fTokenID := tkSymbol;
TSynPasSynRange(CodeFoldRange).DecBracketNestLevel;
PasCodeFoldRange.DecBracketNestLevel;
fRange := fRange + [rsAtClosingBracket];
end;
@ -1986,14 +2017,14 @@ procedure TSynPasSyn.SquareOpenProc;
begin
inc(Run);
fTokenID := tkSymbol;
TSynPasSynRange(CodeFoldRange).IncBracketNestLevel;
PasCodeFoldRange.IncBracketNestLevel;
end;
procedure TSynPasSyn.SquareCloseProc;
begin
inc(Run);
fTokenID := tkSymbol;
TSynPasSynRange(CodeFoldRange).DecBracketNestLevel;
PasCodeFoldRange.DecBracketNestLevel;
end;
procedure TSynPasSyn.EqualSignProc;
@ -2011,7 +2042,7 @@ begin
EndCodeFoldBlock;
if (TopPascalCodeFoldBlockType = cfbtClass) and (rsAfterClass in fRange) then
EndCodeFoldBlock;
if (rsProperty in fRange) and (TSynPasSynRange(CodeFoldRange).BracketNestLevel = 0) then
if (rsProperty in fRange) and (PasCodeFoldRange.BracketNestLevel = 0) then
fRange := fRange - [rsProperty];
end;
@ -2110,7 +2141,7 @@ begin
fRange := fRange + [rsAfterClass] - [rsAtClass];
fProcTable[fLine[Run]];
if not (FTokenID in [tkSpace, tkComment, tkDirective]) then begin
if (TSynPasSynRange(CodeFoldRange).BracketNestLevel = 0) and
if (PasCodeFoldRange.BracketNestLevel = 0) and
not(rsAtClosingBracket in fRange) then
fRange := fRange - [rsAfterClass];
fRange := fRange - [rsAfterEqual, rsAtClosingBracket];
@ -2214,41 +2245,29 @@ end;
function TSynPasSyn.GetRange: Pointer;
begin
{$IFDEF SYN_LAZARUS}
// For speed reasons, we work with fRange instead of CodeFoldRange.RangeType
// -> update now
CodeFoldRange.RangeType:=Pointer(PtrUInt(Integer(fRange)));
PasCodeFoldRange.MinimumCodeFoldBlockLevel := MinimumCodeFoldBlockLevel;
// return a fixed copy of the current CodeFoldRange instance
Result := inherited GetRange;
{$ELSE}
Result := Pointer(PtrInt(fRange));
{$ENDIF}
end;
procedure TSynPasSyn.SetRange(Value: Pointer);
begin
{$IFDEF SYN_LAZARUS}
//DebugLn(['TSynPasSyn.SetRange START']);
inherited SetRange(Value);
CompilerMode := TSynPasSynRange(CodeFoldRange).Mode;
CompilerMode := PasCodeFoldRange.Mode;
fRange := TRangeStates(Integer(PtrUInt(CodeFoldRange.RangeType)));
{$ELSE}
fRange := TRangeStates(PtrUInt(Value));
{$ENDIF}
FNodeInfoLine := -1;
FStartCodeFoldBlockLevel := FMinimumCodeFoldBlockLevel;
end;
procedure TSynPasSyn.ResetRange;
begin
fRange := [];
FStartCodeFoldBlockLevel:=0;
FMinimumCodeFoldBlockLevel := 0;
{$IFDEF SYN_LAZARUS}
FPasStartLevel := 0;
Inherited ResetRange;
CompilerMode:=pcmDelphi;
{$ENDIF}
end;
procedure TSynPasSyn.EnumUserSettings(settings: TStrings);
@ -2275,7 +2294,6 @@ begin
end;
end;
{$IFDEF SYN_LAZARUS}
function TSynPasSyn.TopPascalCodeFoldBlockType: TPascalCodeFoldBlockType;
var
p: Pointer;
@ -2286,41 +2304,117 @@ begin
Result := TPascalCodeFoldBlockType(PtrUInt(p));
end;
function TSynPasSyn.MinimumFoldLevel(Index: Integer): integer;
function TSynPasSyn.FoldOpenCount(ALineIndex: Integer): integer;
begin
Result := EndPasFoldLevel(ALineIndex) - MinimumPasFoldLevel(ALineIndex);
end;
function TSynPasSyn.FoldCloseCount(ALineIndex: Integer): integer;
begin
Result := EndPasFoldLevel(ALineIndex - 1) - MinimumPasFoldLevel(ALineIndex);
end;
function TSynPasSyn.FoldNestCount(ALineIndex: Integer): integer;
begin
Result := EndPasFoldLevel(ALineIndex);
end;
function TSynPasSyn.FoldLineLength(ALineIndex, FoldIndex: Integer): integer;
var
r: Pointer;
i, lvl, cnt : Integer;
e, m: Integer;
begin
cnt := CurrentLines.Count;
e := EndPasFoldLevel(ALineIndex);
m := MinimumPasFoldLevel(ALineIndex);
lvl := Min(m+1+FoldIndex, e);
i := ALineIndex + 1;
while (i < cnt) and (MinimumPasFoldLevel(i) >= lvl) do inc(i);
// check if fold last line of block (not mixed "end begin")
// and not lastlinefix
if (i < cnt) and (EndPasFoldLevel(i) > MinimumPasFoldLevel(i)) then
dec(i);
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
Result := i - ALineIndex;
end;
function TSynPasSyn.MinimumPasFoldLevel(Index: Integer): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := CurrentLines.Ranges[Index];
if (r <> nil) and (r <> NullRange) then
Result := TSynPasSynRange(r).MinimumCodeFoldBlockLevel
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := Min(r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1),
r.PasFoldMinLevel)
else
Result := 0;
end;
function TSynPasSyn.EndPasFoldLevel(Index: Integer): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.PasFoldEndLevel + LastLinePasFoldLevelFix(Index + 1)
else
Result := 0;
end;
function TSynPasSyn.LastLinePasFoldLevelFix(Index: Integer): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.PasFoldFixLevel
else
Result := 0;
end;
function TSynPasSyn.MinimumFoldLevel(Index: Integer): integer;
var
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := Min(r.CodeFoldStackSize + LastLineFoldLevelFix(Index + 1),
r.MinimumCodeFoldBlockLevel)
else
Result := 0;
end;
function TSynPasSyn.EndFoldLevel(Index: Integer): integer;
var
r: Pointer;
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := CurrentLines.Ranges[Index];
if (r <> nil) and (r <> NullRange) then
Result := TSynPasSynRange(r).CodeFoldStackSize
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize + LastLineFoldLevelFix(Index + 1)
else
Result := 0;
end;
function TSynPasSyn.LastLineFoldLevelFix(Index: Integer): integer;
var
r: Pointer;
r: TSynPasSynRange;
begin
if (Index < 0) or (Index >= CurrentLines.Count) then
exit(0);
r := CurrentLines.Ranges[Index];
if (r <> nil) and (r <> NullRange) then
Result := TSynPasSynRange(r).LastLineCodeFoldLevelFix
r := TSynPasSynRange(CurrentRanges[Index]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.LastLineCodeFoldLevelFix
else
Result := 0;
end;
@ -2347,10 +2441,10 @@ var
p: PtrInt;
begin
p := 0;
if FCatchNodeInfo and not SubBlock then begin // exclude subblocks, because they do not increase the foldlevel yet
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
GrowNodeInfoList;
InitNode(FNodeInfoList[FNodeInfoCount], +1, ABlockType);
if not SubBlock then
// if not SubBlock then
include(FNodeInfoList[FNodeInfoCount].FoldAction, sfaOpen);
inc(FNodeInfoCount);
end;
@ -2363,10 +2457,10 @@ 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
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
GrowNodeInfoList;
InitNode(FNodeInfoList[FNodeInfoCount], -1, TopPascalCodeFoldBlockType);
if DecreaseLevel then
// if DecreaseLevel then
include(FNodeInfoList[FNodeInfoCount].FoldAction, sfaClose);
inc(FNodeInfoCount);
end;
@ -2375,9 +2469,9 @@ end;
procedure TSynPasSyn.CloseBeginEndBlocks;
begin
if TopPascalCodeFoldBlockType <> cfbtBeginEnd then
if not(TopPascalCodeFoldBlockType in [cfbtBeginEnd, cfbtExcept, cfbtRepeat]) then
exit;
while TopPascalCodeFoldBlockType = cfbtBeginEnd do
while TopPascalCodeFoldBlockType in [cfbtBeginEnd, cfbtExcept, cfbtRepeat] do
EndCodeFoldBlockLastLine;
if TopPascalCodeFoldBlockType = cfbtProcedure then
EndCodeFoldBlockLastLine; // This procedure did have a begin/end block, so it must end too
@ -2390,13 +2484,19 @@ begin
i := FNodeInfoCount;
EndCodeFoldBlock;
if FAtLineStart then begin
// If we are not at linestate, new folds could have been opened => handle as normal close
// If we are not at linestart, new folds could have been opened => handle as normal close
if (CurrentCodeFoldBlockLevel < FStartCodeFoldBlockLevel) and
(FStartCodeFoldBlockLevel > 0)
then begin
TSynPasSynRange(CodeFoldRange).DecLastLineCodeFoldLevelFix;
PasCodeFoldRange.DecLastLineCodeFoldLevelFix;
dec(FStartCodeFoldBlockLevel);
end
end;
if (PasCodeFoldRange.PasFoldEndLevel < FPasStartLevel) and
(FPasStartLevel > 0)
then begin
PasCodeFoldRange.DecLastLinePasFoldFix;
dec(FPasStartLevel);
end;
end
else if FNodeInfoCount > i then begin
exclude(FNodeInfoList[FNodeInfoCount - 1].FoldAction, sfaMarkup); // not markup able
@ -2404,6 +2504,13 @@ begin
end;
end;
function TSynPasSyn.GetDrawDivider(Index: integer): Boolean;
begin
result := (EndFoldLevel(Index) < DrawDividerLevel) and
(EndFoldLevel(Index - 1) >= DrawDividerLevel) and
(MinimumFoldLevel(Index) = EndFoldLevel(Index)); // not amixed line
end;
function TSynPasSyn.GetFoldNodeInfo(Line, Index: Integer): TSynFoldNodeInfo;
var
i: LongInt;
@ -2441,13 +2548,6 @@ begin
Result:=TSynPasSynRange;
end;
function TSynPasSyn.LastLineCodeFoldLevelFix: integer;
begin
Result := TSynPasSynRange(CodeFoldRange).LastLineCodeFoldLevelFix;
end;
{$endif}
function TSynPasSyn.UseUserSettings(settingIndex: integer): boolean;
// Possible parameter values:
// index into TStrings returned by EnumUserSettings
@ -2651,7 +2751,6 @@ begin
CompilerMode:=pcmObjFPC;
end;
{$IFDEF SYN_LAZARUS}
{ TSynPasSynRange }
procedure TSynPasSynRange.Clear;
@ -2659,7 +2758,9 @@ begin
inherited Clear;
FBracketNestLevel := 0;
FLastLineCodeFoldLevelFix := 0;
FMinimumCodeFoldBlockLevel := 0;
FPasFoldEndLevel := 0;
FPasFoldFixLevel := 0;
FPasFoldMinLevel := 0;
end;
function TSynPasSynRange.Compare(Range: TSynCustomHighlighterRange): integer;
@ -2671,9 +2772,13 @@ begin
if Result<>0 then exit;
Result := FBracketNestLevel - TSynPasSynRange(Range).FBracketNestLevel;
if Result<>0 then exit;
Result := FMinimumCodeFoldBlockLevel - TSynPasSynRange(Range).FMinimumCodeFoldBlockLevel;
if Result<>0 then exit;
Result := FLastLineCodeFoldLevelFix - TSynPasSynRange(Range).FLastLineCodeFoldLevelFix;
if Result<>0 then exit;
Result := FPasFoldEndLevel - TSynPasSynRange(Range).FPasFoldEndLevel;
if Result<>0 then exit;
Result := FPasFoldMinLevel - TSynPasSynRange(Range).FPasFoldMinLevel;
if Result<>0 then exit;
Result := FPasFoldFixLevel - TSynPasSynRange(Range).FPasFoldFixLevel;
end;
procedure TSynPasSynRange.Assign(Src: TSynCustomHighlighterRange);
@ -2682,11 +2787,31 @@ begin
inherited Assign(Src);
FMode:=TSynPasSynRange(Src).FMode;
FBracketNestLevel:=TSynPasSynRange(Src).FBracketNestLevel;
FMinimumCodeFoldBlockLevel := TSynPasSynRange(Src).FMinimumCodeFoldBlockLevel;
FLastLineCodeFoldLevelFix := TSynPasSynRange(Src).FLastLineCodeFoldLevelFix;
FPasFoldEndLevel := TSynPasSynRange(Src).FPasFoldEndLevel;
FPasFoldMinLevel := TSynPasSynRange(Src).FPasFoldMinLevel;
FPasFoldFixLevel := TSynPasSynRange(Src).FPasFoldFixLevel;
end;
end;
function TSynPasSynRange.Add(ABlockType: Pointer; IncreaseLevel: Boolean): TSynCustomCodeFoldBlock;
begin
if IncreaseLevel then
inc(FPasFoldEndLevel);
Result := inherited Add(ABlockType, True);
end;
procedure TSynPasSynRange.Pop(DecreaseLevel: Boolean);
begin
if assigned(Top.Parent) then begin
if DecreaseLevel then
dec(FPasFoldEndLevel);
if FPasFoldMinLevel > FPasFoldEndLevel then
FPasFoldMinLevel := FPasFoldEndLevel;
end;
inherited Pop(True);
end;
procedure TSynPasSynRange.IncBracketNestLevel;
begin
inc(FBracketNestLevel);
@ -2702,7 +2827,10 @@ begin
dec(FLastLineCodeFoldLevelFix)
end;
{$ENDIF}
procedure TSynPasSynRange.DecLastLinePasFoldFix;
begin
dec(FPasFoldFixLevel);
end;
initialization
MakeIdentTable;