SynEdit: Folding for html

git-svn-id: trunk@24616 -
This commit is contained in:
martin 2010-04-14 02:09:43 +00:00
parent c0cdbb38c5
commit b69ccc3438
7 changed files with 568 additions and 370 deletions

1
.gitattributes vendored
View File

@ -1983,6 +1983,7 @@ components/synedit/syneditexport.pas svneol=native#text/pascal
components/synedit/syneditfoldedview.pp svneol=native#text/plain
components/synedit/synedithighlighter.pp svneol=native#text/pascal
components/synedit/synedithighlighterfoldbase.pas svneol=native#text/plain
components/synedit/synedithighlighterxmlbase.pas svneol=native#text/pascal
components/synedit/syneditkeycmds.pp svneol=native#text/pascal
components/synedit/syneditlazdsgn.lrs svneol=native#text/pascal
components/synedit/syneditlazdsgn.pas svneol=native#text/pascal

View File

@ -138,16 +138,22 @@ type
{ TSynCustomFoldHighlighter }
TSynCustomFoldHighlighter = class(TSynCustomHighlighter)
protected
// Config
FFoldConfig: Array of TSynCustomFoldConfig;
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; virtual;
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); virtual;
function GetFoldConfigCount: Integer; virtual;
function GetFoldConfigInternalCount: Integer; virtual;
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; virtual;
procedure InitFoldConfig;
procedure DestroyFoldConfig;
procedure DoFoldConfigChanged(Sender: TObject); virtual;
private
FCodeFoldRange: TSynCustomHighlighterRange;
fRanges: TSynCustomHighlighterRanges;
FRootCodeFoldBlock: TSynCustomCodeFoldBlock;
protected
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; virtual;
function GetFoldConfigCount: Integer; virtual;
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); virtual;
procedure DoFoldConfigChanged(Sender: TObject); virtual;
function GetFoldNodeInfo(Line, Index: Integer; Filter: TSynFoldActions): TSynFoldNodeInfo; virtual;
function GetFoldNodeInfoCount(Line: Integer; Filter: TSynFoldActions): Integer; virtual;
property CodeFoldRange: TSynCustomHighlighterRange read FCodeFoldRange;
@ -270,6 +276,8 @@ end;
constructor TSynCustomFoldHighlighter.Create(AOwner: TComponent);
begin
SetLength(FFoldConfig, GetFoldConfigInternalCount);
InitFoldConfig;
fRanges:=AllocateHighlighterRanges(TSynCustomHighlighterClass(ClassType));
CreateRootCodeFoldBlock;
inherited Create(AOwner);
@ -280,9 +288,11 @@ end;
destructor TSynCustomFoldHighlighter.Destroy;
begin
inherited Destroy;
DestroyFoldConfig;
FreeAndNil(FCodeFoldRange);
FreeAndNil(FRootCodeFoldBlock);
fRanges.Release;
FFoldConfig := nil;
end;
function TSynCustomFoldHighlighter.GetRange: pointer;
@ -366,7 +376,14 @@ end;
function TSynCustomFoldHighlighter.GetFoldConfig(Index: Integer): TSynCustomFoldConfig;
begin
Result := nil;
Result := FFoldConfig[Index];
end;
procedure TSynCustomFoldHighlighter.SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig);
begin
BeginUpdate;
FFoldConfig[Index].Assign(AValue);
EndUpdate;
end;
function TSynCustomFoldHighlighter.GetFoldConfigCount: Integer;
@ -374,8 +391,32 @@ begin
Result := 0;
end;
procedure TSynCustomFoldHighlighter.SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig);
function TSynCustomFoldHighlighter.GetFoldConfigInternalCount: Integer;
begin
Result := 0;
end;
function TSynCustomFoldHighlighter.GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig;
begin
Result := TSynCustomFoldConfig.Create;
Result.OnChange := @DoFoldConfigChanged;
Result.Enabled := False;
end;
procedure TSynCustomFoldHighlighter.InitFoldConfig;
var
i: Integer;
begin
for i := 0 to high(FFoldConfig) do
FFoldConfig[i] := GetFoldConfigInstance(i);
end;
procedure TSynCustomFoldHighlighter.DestroyFoldConfig;
var
i: Integer;
begin
for i := 0 to high(FFoldConfig) do
FFoldConfig[i].Free;
end;
procedure TSynCustomFoldHighlighter.DoFoldConfigChanged(Sender: TObject);

View File

@ -0,0 +1,361 @@
{-------------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: SynHighlighterXML.pas, released 2000-11-20.
The Initial Author of this file is Jeff Rafter.
All Rights Reserved.
Contributors to the SynEdit and mwEdit projects are listed in the
Contributors.txt file.
Alternatively, the contents of this file may be used under the terms of the
GNU General Public License Version 2 or later (the "GPL"), in which case
the provisions of the GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms
of the GPL and not to allow others to use your version of this file
under the MPL, indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by the GPL.
If you do not delete the provisions above, a recipient may use your version
of this file under either the MPL or the GPL.
}
(* Provides folding for Xml and Html *)
unit SynEditHighlighterXMLBase;
interface
{$I SynEdit.inc}
uses
SysUtils, Classes, math, LCLType,
SynEditTypes, SynEditTextBuffer, SynEditHighlighter, SynEditHighlighterFoldBase;
type
TSynXmlRangeInfo = record
ElementOpenList: Array of String; // List of words opened in this line (and still open at the end of line)
ElementCloseList: Array of Smallint; // include close, for open on same line
end;
{ TSynHighlighterXmlRangeList }
TSynHighlighterXmlRangeList = class(TSynHighlighterRangeList)
private
function GetXmlRangeInfo(Index: Integer): TSynXmlRangeInfo;
procedure SetXmlRangeInfo(Index: Integer; const AValue: TSynXmlRangeInfo);
protected
procedure SetCapacity(const AValue: Integer); override;
function ItemSize: Integer; override;
public
procedure Move(AFrom, ATo, ALen: Integer); override;
property XmlRangeInfo[Index: Integer]: TSynXmlRangeInfo
read GetXmlRangeInfo write SetXmlRangeInfo;
end;
TSynCustomXmlHighlighter = class(TSynCustomFoldHighlighter)
private
FXmlRangeInfo: TSynXmlRangeInfo;
FXmlRangeInfoChanged: Boolean;
FXmlRangeInfoOpenPos: integer;
FXmlRangeInfoClosePos: integer;
protected
function CreateRangeList: TSynHighlighterRangeList; override;
function UpdateRangeInfoAtLine(Index: Integer): Boolean; override; // Returns true if range changed
function StartXmlCodeFoldBlock(ABlockType: Integer): TSynCustomCodeFoldBlock;
function StartXmlNodeCodeFoldBlock(ABlockType: Integer; OpenPos: Integer;
AName: String): TSynCustomCodeFoldBlock;
procedure EndXmlCodeFoldBlock;
procedure EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
public
procedure SetLine({$IFDEF FPC}const {$ENDIF}NewValue: string; LineNumber:Integer); override;
public
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override;
// TODO: make private
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
function EndFoldLevel(ALineIndex: Integer): integer; override;
end;
implementation
const
MaxFoldNestDeep = 500;
function TSynCustomXmlHighlighter.CreateRangeList: TSynHighlighterRangeList;
begin
Result := TSynHighlighterXmlRangeList.Create;
end;
function TSynCustomXmlHighlighter.UpdateRangeInfoAtLine(Index: Integer): Boolean;
var
InfoOpenLenChanged, InfoCloseLenChanged: Boolean;
begin
Result := inherited UpdateRangeInfoAtLine(Index);
InfoOpenLenChanged := Length(FXmlRangeInfo.ElementOpenList) <> FXmlRangeInfoOpenPos;
InfoCloseLenChanged := Length(FXmlRangeInfo.ElementCloseList) <> FXmlRangeInfoClosePos;
if FXmlRangeInfoChanged or InfoOpenLenChanged or InfoCloseLenChanged then begin
Result := True;
if InfoOpenLenChanged then
SetLength(FXmlRangeInfo.ElementOpenList, FXmlRangeInfoOpenPos);
if InfoCloseLenChanged then
SetLength(FXmlRangeInfo.ElementCloseList, FXmlRangeInfoClosePos);
TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[LineIndex] := FXmlRangeInfo; // Store on this line
FXmlRangeInfoChanged := False;
end;
end;
procedure TSynCustomXmlHighlighter.SetLine({$IFDEF FPC}const {$ENDIF}NewValue: string;
LineNumber:Integer);
begin
inherited;
FXmlRangeInfo := TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[LineIndex]; // From this line, not from the previous line
FXmlRangeInfoChanged := False;
FXmlRangeInfoOpenPos := 0;
FXmlRangeInfoClosePos := 0;
end;
function TSynCustomXmlHighlighter.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
end;
function TSynCustomXmlHighlighter.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
end;
function TSynCustomXmlHighlighter.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex);
end;
function TSynCustomXmlHighlighter.FoldLineLength(ALineIndex, FoldIndex: Integer): integer;
var
i, lvl, cnt: Integer;
e, m: Integer;
begin
//atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
cnt := CurrentLines.Count;
e := EndFoldLevel(ALineIndex);
m := MinimumFoldLevel(ALineIndex);
lvl := Min(m+1+FoldIndex, e);
i := ALineIndex + 1;
while (i < cnt) and (MinimumFoldLevel(i) >= lvl) do inc(i);
// check if fold last line of block (not mixed "end begin")
// and not lastlinefix
if (i = cnt) or (EndFoldLevel(i) > MinimumFoldLevel(i)) then
dec(i);
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
Result := i - ALineIndex;
end;
function TSynCustomXmlHighlighter.MinimumFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.MinimumCodeFoldBlockLevel
else
Result := 0;
end;
function TSynCustomXmlHighlighter.EndFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize
else
Result := 0;
end;
function TSynCustomXmlHighlighter.StartXmlCodeFoldBlock(ABlockType: Integer): TSynCustomCodeFoldBlock;
var
FoldBlock: Boolean;
p: PtrInt;
begin
FoldBlock := FFoldConfig[ABlockType].Enabled;
p := 0;
if not FoldBlock then
p := PtrInt(GetFoldConfigInternalCount);
Result := StartCodeFoldBlock(p + Pointer(PtrInt(ABlockType)), FoldBlock);
end;
function TSynCustomXmlHighlighter.StartXmlNodeCodeFoldBlock(ABlockType: Integer;
OpenPos: Integer; AName: String): TSynCustomCodeFoldBlock;
var
i: Integer;
begin
If IsScanning then begin
AName := LowerCase(AName);
i := Length(FXmlRangeInfo.ElementOpenList);
if (FXmlRangeInfoOpenPos < i) then begin
if (FXmlRangeInfo.ElementOpenList[FXmlRangeInfoOpenPos] <> AName) then begin
FXmlRangeInfo.ElementOpenList[FXmlRangeInfoOpenPos] := AName;
FXmlRangeInfoChanged := true; // TODO:if this node closes on the same line, it may not be amodified ....
end;
end else begin // append - modified will be deteced by the new length
SetLength(FXmlRangeInfo.ElementOpenList, FXmlRangeInfoOpenPos + 10);
FXmlRangeInfo.ElementOpenList[FXmlRangeInfoOpenPos] := AName;
end;
end;
inc(FXmlRangeInfoOpenPos);
result := StartXmlCodeFoldBlock(ABlockType);
end;
procedure TSynCustomXmlHighlighter.EndXmlCodeFoldBlock;
var
DecreaseLevel: Boolean;
begin
DecreaseLevel := TopCodeFoldBlockType < Pointer(PtrInt(GetFoldConfigInternalCount));
EndCodeFoldBlock(DecreaseLevel);
end;
procedure TSynCustomXmlHighlighter.EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
var
cnt, i, k, lvl: Integer;
LInfo: Array of String;
begin
AName := LowerCase(AName);
cnt := 0;
If IsScanning then begin
if (AName = '') and (CodeFoldRange.CodeFoldStackSize > 0) then begin
cnt := 1;
end
else begin
cnt := 1;
i := FXmlRangeInfoOpenPos;
while i > 0 do begin
if (FXmlRangeInfo.ElementOpenList[i-1] = AName) then
break;
dec(i);
inc(cnt);
end;
if i = 0 then begin
i := LineIndex - 1;
lvl := EndFoldLevel(i);
while i >= 0 do begin
if MinimumFoldLevel(i) < lvl then begin
LInfo := TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[i].ElementOpenList;
k := length(LInfo) - Max(EndFoldLevel(i) - lvl, 0) - 1;
while (k >= 0) do begin
if (LInfo[k] = AName) then
break;
inc(cnt);
dec(k);
dec(lvl);
end;
if k >= 0 then break;
end;
dec(i);
end;
if (i < 0) or (cnt > CodeFoldRange.CodeFoldStackSize ) then cnt := 0; // never opened, do not close
end;
end;
i := Length(FXmlRangeInfo.ElementCloseList);
if (FXmlRangeInfoClosePos < i) then begin
if (FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos] <> cnt) then begin
FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos] := cnt;
FXmlRangeInfoChanged := true;
end;
end else begin // append - modified will be deteced by the new length
SetLength(FXmlRangeInfo.ElementCloseList, FXmlRangeInfoClosePos + 10);
FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos] := cnt;
end;
end
else begin
if FXmlRangeInfoClosePos < length(FXmlRangeInfo.ElementCloseList) then
cnt := FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos]
else
cnt := 0;
end;
inc(FXmlRangeInfoClosePos);
for i := 1 to cnt do begin
if FXmlRangeInfoOpenPos > 0 then
dec(FXmlRangeInfoOpenPos);
EndXmlCodeFoldBlock;
end;
end;
{ TSynHighlighterXmlRangeList }
function TSynHighlighterXmlRangeList.GetXmlRangeInfo(Index: Integer): TSynXmlRangeInfo;
begin
if (Index < 0) or (Index >= Count) then begin
Result.ElementOpenList := nil;
exit;
end;
Result := TSynXmlRangeInfo((ItemPointer[Index] + inherited ItemSize)^);
end;
procedure TSynHighlighterXmlRangeList.SetXmlRangeInfo(Index: Integer;
const AValue: TSynXmlRangeInfo);
begin
TSynXmlRangeInfo((ItemPointer[Index] + inherited ItemSize)^) := AValue;
end;
procedure TSynHighlighterXmlRangeList.SetCapacity(const AValue: Integer);
var
i: LongInt;
begin
for i := AValue to Capacity-1 do
with TSynXmlRangeInfo((ItemPointer[i] + inherited ItemSize)^) do begin
ElementOpenList := nil;
ElementCloseList := nil;
end;
inherited SetCapacity(AValue);
end;
function TSynHighlighterXmlRangeList.ItemSize: Integer;
begin
Result := inherited ItemSize + SizeOf(TSynXmlRangeInfo);
end;
procedure TSynHighlighterXmlRangeList.Move(AFrom, ATo, ALen: Integer);
var
i: LongInt;
begin
if ATo > AFrom then
for i:= Max(AFrom + ALen, ATo) to ATo + ALen - 1 do // move forward
with TSynXmlRangeInfo((ItemPointer[i] + inherited ItemSize)^) do begin
ElementOpenList := nil;
ElementCloseList := nil;
end
else
for i:= ATo to Min(ATo + ALen , AFrom) - 1 do // move backward
with TSynXmlRangeInfo((ItemPointer[i] + inherited ItemSize)^) do begin
ElementOpenList := nil;
ElementCloseList := nil;
end;
inherited Move(AFrom, ATo, ALen);
end;
end.

View File

@ -55,7 +55,8 @@ uses
Windows, Messages, Registry,
{$ENDIF}
Classes, Controls, Graphics,
SynEditTypes, SynEditHighlighter;
SynEditTypes, SynEditHighlighter, SynEditHighlighterXMLBase,
SynEditHighlighterFoldBase;
const
MAX_ESCAPEAMPS = 151;
@ -223,10 +224,20 @@ type
TRangeState = (rsAmpersand, rsASP, rsComment, rsKey, rsParam, rsText,
rsUnKnown, rsValue);
THtmlCodeFoldBlockType = (
cfbtHtmlNode, // <foo>...</node>
cfbtHtmlComment, // <!-- -->
cfbtHtmlAsp, // <% asp %>
// internal types / not configurable
cfbtHtmlNone
);
TProcTableProc = procedure of object;
TIdentFuncTableFunc = function: TtkTokenKind of object;
TSynHTMLSyn = class(TSynCustomHighlighter)
{ TSynHTMLSyn }
TSynHTMLSyn = class(TSynCustomXmlHighlighter)
private
fAndCode: Integer;
fRange: TRangeState;
@ -407,6 +418,19 @@ type
procedure AmpersandProc;
protected
function GetIdentChars: TSynIdentChars; override;
protected
// folding
procedure CreateRootCodeFoldBlock; override;
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
function StartHtmlCodeFoldBlock(ABlockType: THtmlCodeFoldBlockType): TSynCustomCodeFoldBlock;
function StartHtmlNodeCodeFoldBlock(ABlockType: THtmlCodeFoldBlockType;
OpenPos: Integer; AName: String): TSynCustomCodeFoldBlock;
procedure EndHtmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
function TopHtmlCodeFoldBlockType(DownIndex: Integer = 0): THtmlCodeFoldBlockType;
function GetFoldConfigCount: Integer; override;
function GetFoldConfigInternalCount: Integer; override;
public
{$IFNDEF SYN_CPPB_1} class {$ENDIF} //mh 2000-07-14
function GetLanguageName: string; override;
@ -1974,6 +1998,7 @@ end;
procedure TSynHTMLSyn.SetLine(const NewValue: string; LineNumber:Integer);
begin
inherited;
fLine := PChar(NewValue);
Run := 0;
fLineNumber := LineNumber;
@ -1993,6 +2018,8 @@ begin
then begin
fRange := rsText;
Inc(Run);
if TopHtmlCodeFoldBlockType = cfbtHtmlAsp then
EndHtmlNodeCodeFoldBlock;
break;
end;
Inc(Run);
@ -2020,6 +2047,8 @@ begin
then begin
fRange := rsText;
Inc(Run);
if TopHtmlCodeFoldBlockType = cfbtHtmlComment then
EndHtmlNodeCodeFoldBlock;
break;
end;
Inc(Run);
@ -2029,20 +2058,22 @@ end;
procedure TSynHTMLSyn.BraceOpenProc;
begin
Inc(Run);
if (fLine[Run] = '!') and (fLine[Run + 1] = '-') and (fLine[Run + 2] = '-')
if (Run <= length(fLine)-2) and (fLine[Run] = '!') and (fLine[Run + 1] = '-') and (fLine[Run + 2] = '-')
then begin
fRange := rsComment;
fTokenID := tkComment;
StartHtmlCodeFoldBlock(cfbtHtmlComment);
Inc(Run, 3);
end else begin
if fLine[Run]= '%' then begin
fRange := rsASP;
fTokenID := tkASP;
Inc(Run);
end else begin
fRange := rsKey;
fTokenID := tkSymbol;
end;
end
else if fLine[Run]= '%' then begin
fRange := rsASP;
fTokenID := tkASP;
StartHtmlCodeFoldBlock(cfbtHtmlAsp);
Inc(Run);
end
else begin
fRange := rsKey;
fTokenID := tkSymbol;
end;
end;
@ -2080,6 +2111,10 @@ begin
begin
fRange := rsParam;
fTokenID := IdentKind((fLine + Run));
if fLine[Run] = '/' then
EndHtmlNodeCodeFoldBlock(Run+1, copy(fline, Run+2, fStringLen-1))
else if fLine[Run] <> '!' then
StartHtmlNodeCodeFoldBlock(cfbtHtmlNode, Run, copy(fline, Run+1, fStringLen));
Inc(Run, fStringLen);
end;
rsValue:
@ -2266,16 +2301,19 @@ end;
function TSynHTMLSyn.GetRange: Pointer;
begin
Result := Pointer(PtrInt(fRange));
CodeFoldRange.RangeType:=Pointer(PtrUInt(Integer(fRange)));
Result := inherited;
end;
procedure TSynHTMLSyn.SetRange(Value: Pointer);
begin
fRange := TRangeState(PtrUInt(Value));
inherited;
fRange := TRangeState(Integer(PtrUInt(CodeFoldRange.RangeType)));
end;
procedure TSynHTMLSyn.ReSetRange;
begin
inherited;
fRange:= rsText;
end;
@ -2284,6 +2322,53 @@ begin
Result := ['0'..'9', 'a'..'z', 'A'..'Z'];
end;
procedure TSynHTMLSyn.CreateRootCodeFoldBlock;
begin
inherited CreateRootCodeFoldBlock;
RootCodeFoldBlock.InitRootBlockType(Pointer(PtrInt(cfbtHtmlNone)));
end;
function TSynHTMLSyn.GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig;
begin
Result := inherited GetFoldConfigInstance(Index);
Result.Enabled := True;
end;
function TSynHTMLSyn.StartHtmlCodeFoldBlock(ABlockType: THtmlCodeFoldBlockType): TSynCustomCodeFoldBlock;
begin
Result := inherited StartXmlCodeFoldBlock(ord(ABlockType));
end;
function TSynHTMLSyn.StartHtmlNodeCodeFoldBlock(ABlockType: THtmlCodeFoldBlockType;
OpenPos: Integer; AName: String): TSynCustomCodeFoldBlock;
begin
if not FFoldConfig[ord(cfbtHtmlNode)].Enabled then exit;
Result := inherited StartXmlNodeCodeFoldBlock(ord(ABlockType), OpenPos, AName);
end;
procedure TSynHTMLSyn.EndHtmlNodeCodeFoldBlock(ClosePos: Integer; AName: String);
begin
if not FFoldConfig[ord(cfbtHtmlNode)].Enabled then exit;
inherited EndXmlNodeCodeFoldBlock(ClosePos, AName);
end;
function TSynHTMLSyn.TopHtmlCodeFoldBlockType(DownIndex: Integer): THtmlCodeFoldBlockType;
begin
Result := THtmlCodeFoldBlockType(PtrUInt(TopCodeFoldBlockType(DownIndex)));
end;
function TSynHTMLSyn.GetFoldConfigCount: Integer;
begin
// excluded cfbtHtmlNone;
Result := ord(high(THtmlCodeFoldBlockType)) - ord(low(THtmlCodeFoldBlockType));
end;
function TSynHTMLSyn.GetFoldConfigInternalCount: Integer;
begin
// include cfbtHtmlNone;
Result := ord(high(THtmlCodeFoldBlockType)) - ord(low(THtmlCodeFoldBlockType)) + 1;
end;
{$IFNDEF SYN_CPPB_1} class {$ENDIF} //mh 2000-07-14
function TSynHTMLSyn.GetLanguageName: string;
begin

View File

@ -69,10 +69,11 @@ type
TRangeState = (rsANil, rsComment, rsUnKnown);
TLfmCodeFoldBlockType = (
cfbtLfmNone,
cfbtLfmObject, // object, inherited, inline
cfbtLfmList, // <>
cfbtLfmItem // Item
cfbtLfmItem, // Item
// internal type / no config
cfbtLfmNone
);
TProcTableProc = procedure of object;
@ -101,7 +102,6 @@ type
fSpaceAttri: TSynHighlighterAttributes;
fStringAttri: TSynHighlighterAttributes;
fSymbolAttri: TSynHighlighterAttributes;
FFoldConfig: Array [TLfmCodeFoldBlockType] of TSynCustomFoldConfig;
procedure AltProc;
procedure AsciiCharProc;
procedure BraceCloseProc;
@ -120,8 +120,6 @@ type
procedure SymbolProc;
procedure UnknownProc;
procedure MakeMethodTables;
procedure InitFoldConfig;
procedure DestroyFoldConfig;
protected
function GetIdentChars: TSynIdentChars; override;
function GetSampleSource: string; override;
@ -134,9 +132,9 @@ type
procedure EndLfmCodeFoldBlock;
function TopLfmCodeFoldBlockType(DownIndex: Integer = 0): TLfmCodeFoldBlockType;
protected
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigCount: Integer; override;
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); override;
function GetFoldConfigInternalCount: Integer; override;
public
{$IFNDEF SYN_CPPB_1} class {$ENDIF} //mh 2000-07-14
function GetLanguageName: string; override;
@ -290,29 +288,15 @@ begin
end;
end;
procedure TSynLFMSyn.InitFoldConfig;
var
i: TLfmCodeFoldBlockType;
function TSynLFMSyn.GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig;
begin
for i := low(TLfmCodeFoldBlockType) to high(TLfmCodeFoldBlockType) do begin
FFoldConfig[i] := TSynCustomFoldConfig.Create;
FFoldConfig[i].OnChange := @DoFoldConfigChanged;
FFoldConfig[i].Enabled := True;
end;
end;
procedure TSynLFMSyn.DestroyFoldConfig;
var
i: TLfmCodeFoldBlockType;
begin
for i := low(TLfmCodeFoldBlockType) to high(TLfmCodeFoldBlockType) do
FFoldConfig[i].Free;
Result := inherited GetFoldConfigInstance(Index);
Result.Enabled := True;
end;
constructor TSynLFMSyn.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
InitFoldConfig;
fCommentAttri := TSynHighlighterAttributes.Create(SYNS_AttrComment, SYNS_XML_AttrComment);
fCommentAttri.Style := [fsItalic];
AddAttribute(fCommentAttri);
@ -337,7 +321,6 @@ end;
destructor TSynLFMSyn.Destroy;
begin
DestroyFoldConfig;
inherited Destroy;
end;
@ -643,16 +626,19 @@ end;
function TSynLFMSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
end;
function TSynLFMSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
end;
function TSynLFMSyn.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
begin
If AType <> 0 then exit(0);
Result := EndFoldLevel(ALineIndex);
end;
@ -740,7 +726,7 @@ var
FoldBlock: Boolean;
p: PtrInt;
begin
FoldBlock := FFoldConfig[ABlockType].Enabled;
FoldBlock := FFoldConfig[ord(ABlockType)].Enabled;
p := 0;
if not FoldBlock then
p := PtrInt(CountLfmCodeFoldBlockOffset);
@ -760,24 +746,16 @@ begin
Result := TLfmCodeFoldBlockType(PtrUInt(TopCodeFoldBlockType(DownIndex)));
end;
function TSynLFMSyn.GetFoldConfig(Index: Integer): TSynCustomFoldConfig;
begin
// + 1 as we skip cfbtNone;
Result := FFoldConfig[TLfmCodeFoldBlockType(Index + 1)];
end;
function TSynLFMSyn.GetFoldConfigCount: Integer;
begin
// excluded cfbtNone;
// excluded cfbtLfmNone
Result := ord(high(TLfmCodeFoldBlockType)) - ord(low(TLfmCodeFoldBlockType));
end;
procedure TSynLFMSyn.SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig);
function TSynLFMSyn.GetFoldConfigInternalCount: Integer;
begin
BeginUpdate;
FFoldConfig[TLfmCodeFoldBlockType(Index + 1)].Assign(AValue);
EndUpdate;
// Todo: Since all synedits will rescan => delete all foldranges
// include cfbtLfmNone
Result := ord(high(TLfmCodeFoldBlockType)) - ord(low(TLfmCodeFoldBlockType)) + 1;
end;
{$IFNDEF SYN_CPPB_1} //mh 2000-07-14

View File

@ -90,7 +90,6 @@ type
type
{$IFDEF SYN_LAZARUS}
TPascalCodeFoldBlockType = (
cfbtNone,
cfbtBeginEnd, // Nested
cfbtTopBeginEnd, // Begin of Procedure
cfbtNestedComment,
@ -110,7 +109,9 @@ type
cfbtAsm,
cfbtCase,
cfbtIfDef, // {$IfDef} directive, ths is not counted in the Range-Node
cfbtRegion // {%Region} user folds, not counted in the Range-Node
cfbtRegion, // {%Region} user folds, not counted in the Range-Node
// Internal type / not configurable
cfbtNone
);
TPascalCodeFoldBlockTypes = set of TPascalCodeFoldBlockType;
@ -271,7 +272,6 @@ type
FNodeInfoLine, FNodeInfoCount: Integer;
FNodeInfoList: Array of TSynFoldNodeInfo;
FDividerDrawConfig: Array [TSynPasDividerDrawLocation] of TSynDividerDrawConfig;
FFoldConfig: Array [TPascalCodeFoldBlockType] of TSynCustomFoldConfig;
procedure GrowNodeInfoList;
function GetPasCodeFoldRange: TSynPasSynRange;
procedure SetCompilerMode(const AValue: TPascalCompilerMode);
@ -408,8 +408,6 @@ type
ABlockType: TPascalCodeFoldBlockType; aActions: TSynFoldActions);
procedure CreateDividerDrawConfig;
procedure DestroyDividerDrawConfig;
procedure InitFoldConfig;
procedure DestroyFoldConfig;
protected
function GetIdentChars: TSynIdentChars; override;
function IsFilterStored: boolean; override; //mh 2000-10-08
@ -444,9 +442,9 @@ type
function GetDividerDrawConfig(Index: Integer): TSynDividerDrawConfig; override;
function GetDividerDrawConfigCount: Integer; override;
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigCount: Integer; override;
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); override;
function GetFoldConfigInternalCount: Integer; override;
public
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
function GetCapabilities: TSynHighlighterCapabilities; override;
@ -2020,7 +2018,6 @@ constructor TSynPasSyn.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
CreateDividerDrawConfig;
InitFoldConfig;
fD4syntax := true;
fAsmAttri := TSynHighlighterAttributes.Create(SYNS_AttrAssembler, SYNS_XML_AttrAssembler);
AddAttribute(fAsmAttri);
@ -2059,7 +2056,6 @@ end; { Create }
destructor TSynPasSyn.Destroy;
begin
DestroyDividerDrawConfig;
DestroyFoldConfig;
inherited Destroy;
end;
@ -3060,7 +3056,7 @@ end;
procedure TSynPasSyn.StartCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType);
begin
if not FFoldConfig[ABlockType].Enabled then exit;
if not FFoldConfig[ord(ABlockType)].Enabled then exit;
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
GrowNodeInfoList;
InitNode(FNodeInfoList[FNodeInfoCount], +1, ABlockType, [sfaOpen, sfaFold]);
@ -3076,7 +3072,7 @@ end;
procedure TSynPasSyn.EndCustomCodeFoldBlock(ABlockType: TPascalCodeFoldBlockType);
begin
if not FFoldConfig[ABlockType].Enabled then exit;
if not FFoldConfig[ord(ABlockType)].Enabled then exit;
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
GrowNodeInfoList;
InitNode(FNodeInfoList[FNodeInfoCount], -1, ABlockType, [sfaClose, sfaFold]);
@ -3108,7 +3104,7 @@ var
FoldBlock: Boolean;
act: TSynFoldActions;
begin
FoldBlock := FFoldConfig[ABlockType].Enabled;
FoldBlock := FFoldConfig[ord(ABlockType)].Enabled;
p := 0;
if FCatchNodeInfo then begin // exclude subblocks, because they do not increase the foldlevel yet
GrowNodeInfoList;
@ -3360,26 +3356,14 @@ begin
FreeAndNil(FDividerDrawConfig[i]);
end;
procedure TSynPasSyn.InitFoldConfig;
var
i: TPascalCodeFoldBlockType;
function TSynPasSyn.GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig;
begin
for i := low(TPascalCodeFoldBlockType) to high(TPascalCodeFoldBlockType) do begin
FFoldConfig[i] := TSynCustomFoldConfig.Create;
FFoldConfig[i].OnChange := @DoFoldConfigChanged;
FFoldConfig[i].Enabled := i in [cfbtBeginEnd, cfbtTopBeginEnd, cfbtNestedComment,
cfbtProcedure, cfbtUses, cfbtLocalVarType, cfbtClass,
cfbtClassSection, cfbtRecord, cfbtRepeat, cfbtCase,
cfbtAsm, cfbtRegion];
end;
end;
procedure TSynPasSyn.DestroyFoldConfig;
var
i: TPascalCodeFoldBlockType;
begin
for i := low(TPascalCodeFoldBlockType) to high(TPascalCodeFoldBlockType) do
FFoldConfig[i].Free;
Result := inherited GetFoldConfigInstance(Index);
Result.Enabled := TPascalCodeFoldBlockType(Index) in
[cfbtBeginEnd, cfbtTopBeginEnd, cfbtNestedComment,
cfbtProcedure, cfbtUses, cfbtLocalVarType, cfbtClass,
cfbtClassSection, cfbtRecord, cfbtRepeat, cfbtCase,
cfbtAsm, cfbtRegion];
end;
function TSynPasSyn.CreateRangeList: TSynHighlighterRangeList;
@ -3401,12 +3385,6 @@ begin
TSynHighlighterPasRangeList(CurrentRanges).PasRangeInfo[Index] := FSynPasRangeInfo;
end;
function TSynPasSyn.GetFoldConfig(Index: Integer): TSynCustomFoldConfig;
begin
// + 1 as we skip cfbtNone;
Result := FFoldConfig[TPascalCodeFoldBlockType(Index + 1)];
end;
function TSynPasSyn.GetFoldConfigCount: Integer;
begin
// excluded cfbtNone;
@ -3414,12 +3392,12 @@ begin
ord(low(TPascalCodeFoldBlockType));
end;
procedure TSynPasSyn.SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig);
function TSynPasSyn.GetFoldConfigInternalCount: Integer;
begin
BeginUpdate;
FFoldConfig[TPascalCodeFoldBlockType(Index + 1)].Assign(AValue);
EndUpdate;
// Todo: Since all synedits will rescan => delete all foldranges
// include cfbtNone;
Result := ord(high(TPascalCodeFoldBlockType)) -
ord(low(TPascalCodeFoldBlockType))
+ 1;
end;
function TSynPasSyn.GetDividerDrawConfig(Index: Integer): TSynDividerDrawConfig;

View File

@ -60,14 +60,10 @@ uses
{$IFDEF SYN_CLX}
Qt, QControls, QGraphics,
{$ELSE}
{$IFDEF SYN_LAZARUS}
LCLIntf, LCLType,
{$ELSE}
Windows, Messages, Registry,
Graphics,
{$ENDIF}
Controls, Graphics,
{$ENDIF}
SynEditTypes, SynEditTextBuffer, SynEditHighlighter, SynEditHighlighterFoldBase;
SynEditTypes, SynEditTextBuffer, SynEditHighlighter,
SynEditHighlighterFoldBase, SynEditHighlighterXMLBase;
type
TtkTokenKind = (tkAposAttrValue, tkAposEntityRef, tkAttribute, tkCDATA,
@ -97,25 +93,17 @@ type
);
TXmlCodeFoldBlockType = (
cfbtXmlNone,
cfbtXmlNode, // <foo>...</node>
cfbtXmlComment, // <!-- -->
cfbtXmlCData, // <![CDATA[ ]]>
cfbtXmlDocType, // <!DOCTYPE
cfbtXmlProcess // <?
cfbtXmlProcess, // <?
// internal types / not configurable
cfbtXmlNone
);
const
CountXmlCodeFoldBlockOffset: Pointer =
Pointer(PtrInt(Integer(high(TXmlCodeFoldBlockType))+1));
type
TSynXmlRangeInfo = record
ElementOpenList: Array of String; // List of words opened in this line (and still open at the end of line)
ElementCloseList: Array of Smallint; // include close, for open on same line
end;
{ TSynHighlighterXmlRangeList }
TSynHighlighterXmlRangeList = class(TSynHighlighterRangeList)
@ -135,13 +123,9 @@ type
{ TSynXMLSyn }
TSynXMLSyn = class(TSynCustomFoldHighlighter)
TSynXMLSyn = class(TSynCustomXmlHighlighter)
private
fRange: TRangeState;
FXmlRangeInfo: TSynXmlRangeInfo;
FXmlRangeInfoChanged: Boolean;
FXmlRangeInfoOpenPos: integer;
FXmlRangeInfoClosePos: integer;
fLine: PChar;
Run: Longint;
fTokenPos: Integer;
@ -162,7 +146,6 @@ type
fSymbolAttri: TSynHighlighterAttributes;
fProcTable: array[#0..#255] of TProcTableProc;
FWantBracesParsed: Boolean;
FFoldConfig: Array [TXmlCodeFoldBlockType] of TSynCustomFoldConfig;
procedure NullProc;
procedure CarriageReturnProc;
procedure LineFeedProc;
@ -185,33 +168,27 @@ type
procedure EntityRefProc;
procedure QEntityRefProc;
procedure AEntityRefProc;
procedure InitFoldConfig;
procedure DestroyFoldConfig;
protected
function UpdateRangeInfoAtLine(Index: Integer): Boolean; override; // Returns true if range changed
function GetIdentChars: TSynIdentChars; override;
function GetSampleSource : String; override;
protected
// folding
procedure CreateRootCodeFoldBlock; override;
function CreateRangeList: TSynHighlighterRangeList; override;
function StartXmlCodeFoldBlock(ABlockType: TXmlCodeFoldBlockType): TSynCustomCodeFoldBlock;
function StartXmlNodeCodeFoldBlock(ABlockType: TXmlCodeFoldBlockType;
OpenPos: Integer; AName: String): TSynCustomCodeFoldBlock;
procedure EndXmlCodeFoldBlock;
procedure EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
function TopXmlCodeFoldBlockType(DownIndex: Integer = 0): TXmlCodeFoldBlockType;
protected
function GetFoldConfig(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig; override;
function GetFoldConfigCount: Integer; override;
procedure SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig); override;
function GetFoldConfigInternalCount: Integer; override;
public
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
function GetLanguageName: string; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
override;
function GetEol: Boolean; override;
@ -229,15 +206,6 @@ type
procedure SetRange(Value: Pointer); override;
procedure ReSetRange; override;
property IdentChars;
public
// folding
function FoldOpenCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldCloseCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldNestCount(ALineIndex: Integer; AType: Integer = 0): integer; override;
function FoldLineLength(ALineIndex, FoldIndex: Integer): integer; override;
// TODO: make private
function MinimumFoldLevel(ALineIndex: Integer): integer; override;
function EndFoldLevel(ALineIndex: Integer): integer; override;
published
property ElementAttri: TSynHighlighterAttributes read fElementAttri
write fElementAttri;
@ -281,7 +249,6 @@ const
constructor TSynXMLSyn.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
InitFoldConfig;
fElementAttri:= TSynHighlighterAttributes.Create(SYNS_AttrElementName, SYNS_XML_AttrElementName);
fTextAttri:= TSynHighlighterAttributes.Create(SYNS_AttrText, SYNS_XML_AttrText);
@ -355,12 +322,6 @@ begin
fDefaultFilter := SYNS_FilterXML;
end;
destructor TSynXMLSyn.Destroy;
begin
DestroyFoldConfig;
inherited Destroy;
end;
procedure TSynXMLSyn.MakeMethodTables;
var
i: Char;
@ -401,11 +362,6 @@ procedure TSynXMLSyn.SetLine({$IFDEF FPC}const {$ENDIF}NewValue: string;
LineNumber:Integer);
begin
inherited;
FXmlRangeInfo := TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[LineIndex]; // From this line, not from the previous line
FXmlRangeInfoChanged := False;
FXmlRangeInfoOpenPos := 0;
FXmlRangeInfoClosePos := 0;
fLine := PChar(NewValue);
Run := 0;
fLineNumber := LineNumber;
@ -812,41 +768,10 @@ begin
fRange := rsAPosAttrValue;
end;
procedure TSynXMLSyn.InitFoldConfig;
var
i: TXmlCodeFoldBlockType;
function TSynXMLSyn.GetFoldConfigInstance(Index: Integer): TSynCustomFoldConfig;
begin
for i := low(TXmlCodeFoldBlockType) to high(TXmlCodeFoldBlockType) do begin
FFoldConfig[i] := TSynCustomFoldConfig.Create;
FFoldConfig[i].OnChange := @DoFoldConfigChanged;
FFoldConfig[i].Enabled := True;
end;
end;
procedure TSynXMLSyn.DestroyFoldConfig;
var
i: TXmlCodeFoldBlockType;
begin
for i := low(TXmlCodeFoldBlockType) to high(TXmlCodeFoldBlockType) do
FFoldConfig[i].Free;
end;
function TSynXMLSyn.UpdateRangeInfoAtLine(Index: Integer): Boolean;
var
InfoOpenLenChanged, InfoCloseLenChanged: Boolean;
begin
Result := inherited UpdateRangeInfoAtLine(Index);
InfoOpenLenChanged := Length(FXmlRangeInfo.ElementOpenList) <> FXmlRangeInfoOpenPos;
InfoCloseLenChanged := Length(FXmlRangeInfo.ElementCloseList) <> FXmlRangeInfoClosePos;
if FXmlRangeInfoChanged or InfoOpenLenChanged or InfoCloseLenChanged then begin
Result := True;
if InfoOpenLenChanged then
SetLength(FXmlRangeInfo.ElementOpenList, FXmlRangeInfoOpenPos);
if InfoCloseLenChanged then
SetLength(FXmlRangeInfo.ElementCloseList, FXmlRangeInfoClosePos);
TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[LineIndex] := FXmlRangeInfo; // Store on this line
FXmlRangeInfoChanged := False;
end;
Result := inherited GetFoldConfigInstance(Index);
Result.Enabled := True;
end;
procedure TSynXMLSyn.IdentProc;
@ -1029,67 +954,6 @@ begin
fRange:= rsText;
end;
function TSynXMLSyn.FoldOpenCount(ALineIndex: Integer; AType: Integer): integer;
begin
Result := EndFoldLevel(ALineIndex) - MinimumFoldLevel(ALineIndex);
end;
function TSynXMLSyn.FoldCloseCount(ALineIndex: Integer; AType: Integer): integer;
begin
Result := EndFoldLevel(ALineIndex - 1) - MinimumFoldLevel(ALineIndex);
end;
function TSynXMLSyn.FoldNestCount(ALineIndex: Integer; AType: Integer): integer;
begin
Result := EndFoldLevel(ALineIndex);
end;
function TSynXMLSyn.FoldLineLength(ALineIndex, FoldIndex: Integer): integer;
var
i, lvl, cnt: Integer;
e, m: Integer;
begin
//atype := FoldTypeAtNodeIndex(ALineIndex, FoldIndex);
cnt := CurrentLines.Count;
e := EndFoldLevel(ALineIndex);
m := MinimumFoldLevel(ALineIndex);
lvl := Min(m+1+FoldIndex, e);
i := ALineIndex + 1;
while (i < cnt) and (MinimumFoldLevel(i) >= lvl) do inc(i);
// check if fold last line of block (not mixed "end begin")
// and not lastlinefix
if (i = cnt) or (EndFoldLevel(i) > MinimumFoldLevel(i)) then
dec(i);
// Amount of lines, that will become invisible (excludes the cfCollapsed line)
Result := i - ALineIndex;
end;
function TSynXMLSyn.MinimumFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.MinimumCodeFoldBlockLevel
else
Result := 0;
end;
function TSynXMLSyn.EndFoldLevel(ALineIndex: Integer): integer;
var
r: TSynCustomHighlighterRange;
begin
if (ALineIndex < 0) or (ALineIndex >= CurrentLines.Count) then
exit(0);
r := TSynCustomHighlighterRange(CurrentRanges[ALineIndex]);
if (r <> nil) and (Pointer(r) <> NullRange) then
Result := r.CodeFoldStackSize
else
Result := 0;
end;
function TSynXMLSyn.GetIdentChars: TSynIdentChars;
begin
Result := ['0'..'9', 'a'..'z', 'A'..'Z', '_', '.', '-'] + TSynSpecialChars;
@ -1118,124 +982,22 @@ begin
RootCodeFoldBlock.InitRootBlockType(Pointer(PtrInt(cfbtXmlNone)));
end;
function TSynXMLSyn.CreateRangeList: TSynHighlighterRangeList;
begin
Result := TSynHighlighterXmlRangeList.Create;
end;
function TSynXMLSyn.StartXmlCodeFoldBlock(ABlockType: TXmlCodeFoldBlockType): TSynCustomCodeFoldBlock;
var
FoldBlock: Boolean;
p: PtrInt;
begin
FoldBlock := FFoldConfig[ABlockType].Enabled;
p := 0;
if not FoldBlock then
p := PtrInt(CountXmlCodeFoldBlockOffset);
Result := StartCodeFoldBlock(p + Pointer(PtrInt(ABlockType)), FoldBlock);
Result := inherited StartXmlCodeFoldBlock(ord(ABlockType));
end;
function TSynXMLSyn.StartXmlNodeCodeFoldBlock(ABlockType: TXmlCodeFoldBlockType;
OpenPos: Integer; AName: String): TSynCustomCodeFoldBlock;
var
i: Integer;
begin
if not FFoldConfig[cfbtXmlNode].Enabled then exit;
If IsScanning then begin
AName := LowerCase(AName);
i := Length(FXmlRangeInfo.ElementOpenList);
if (FXmlRangeInfoOpenPos < i) then begin
if (FXmlRangeInfo.ElementOpenList[FXmlRangeInfoOpenPos] <> AName) then begin
FXmlRangeInfo.ElementOpenList[FXmlRangeInfoOpenPos] := AName;
FXmlRangeInfoChanged := true; // TODO:if this node closes on the same line, it may not be amodified ....
end;
end else begin // append - modified will be deteced by the new length
SetLength(FXmlRangeInfo.ElementOpenList, FXmlRangeInfoOpenPos + 10);
FXmlRangeInfo.ElementOpenList[FXmlRangeInfoOpenPos] := AName;
end;
end;
inc(FXmlRangeInfoOpenPos);
result := StartXmlCodeFoldBlock(ABlockType);
if not FFoldConfig[ord(cfbtXmlNode)].Enabled then exit;
Result := inherited StartXmlNodeCodeFoldBlock(ord(ABlockType), OpenPos, AName);
end;
procedure TSynXMLSyn.EndXmlCodeFoldBlock;
var
DecreaseLevel: Boolean;
procedure TSynXMLSyn.EndXmlNodeCodeFoldBlock(ClosePos: Integer; AName: String);
begin
DecreaseLevel := TopCodeFoldBlockType < CountXmlCodeFoldBlockOffset;
EndCodeFoldBlock(DecreaseLevel);
end;
procedure TSynXMLSyn.EndXmlNodeCodeFoldBlock(ClosePos: Integer = -1; AName: String = '');
var
cnt, i, k, lvl: Integer;
LInfo: Array of String;
begin
if not FFoldConfig[cfbtXmlNode].Enabled then exit;
AName := LowerCase(AName);
cnt := 0;
If IsScanning then begin
if (AName = '') and (CodeFoldRange.CodeFoldStackSize > 0) then begin
cnt := 1;
end
else begin
cnt := 1;
i := FXmlRangeInfoOpenPos;
while i > 0 do begin
if (FXmlRangeInfo.ElementOpenList[i-1] = AName) then
break;
dec(i);
inc(cnt);
end;
if i = 0 then begin
i := LineIndex - 1;
lvl := EndFoldLevel(i);
while i >= 0 do begin
if MinimumFoldLevel(i) < lvl then begin
LInfo := TSynHighlighterXmlRangeList(CurrentRanges).XmlRangeInfo[i].ElementOpenList;
k := length(LInfo) - Max(EndFoldLevel(i) - lvl, 0) - 1;
while (k >= 0) do begin
if (LInfo[k] = AName) then
break;
inc(cnt);
dec(k);
dec(lvl);
end;
if k >= 0 then break;
end;
dec(i);
end;
if (i < 0) or (cnt > CodeFoldRange.CodeFoldStackSize ) then cnt := 0; // never opened, do not close
end;
end;
i := Length(FXmlRangeInfo.ElementCloseList);
if (FXmlRangeInfoClosePos < i) then begin
if (FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos] <> cnt) then begin
FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos] := cnt;
FXmlRangeInfoChanged := true;
end;
end else begin // append - modified will be deteced by the new length
SetLength(FXmlRangeInfo.ElementCloseList, FXmlRangeInfoClosePos + 10);
FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos] := cnt;
end;
end
else begin
if FXmlRangeInfoClosePos < length(FXmlRangeInfo.ElementCloseList) then
cnt := FXmlRangeInfo.ElementCloseList[FXmlRangeInfoClosePos]
else
cnt := 0;
end;
inc(FXmlRangeInfoClosePos);
for i := 1 to cnt do begin
if FXmlRangeInfoOpenPos > 0 then
dec(FXmlRangeInfoOpenPos);
EndXmlCodeFoldBlock;
end;
if not FFoldConfig[ord(cfbtXmlNode)].Enabled then exit;
inherited EndXmlNodeCodeFoldBlock(ClosePos, AName);
end;
function TSynXMLSyn.TopXmlCodeFoldBlockType(DownIndex: Integer): TXmlCodeFoldBlockType;
@ -1243,24 +1005,16 @@ begin
Result := TXmlCodeFoldBlockType(PtrUInt(TopCodeFoldBlockType(DownIndex)));
end;
function TSynXMLSyn.GetFoldConfig(Index: Integer): TSynCustomFoldConfig;
begin
// + 1 as we skip cfbtNone;
Result := FFoldConfig[TXmlCodeFoldBlockType(Index + 1)];
end;
function TSynXMLSyn.GetFoldConfigCount: Integer;
begin
// excluded cfbtNone;
// excluded cfbtXmlNone
Result := ord(high(TXmlCodeFoldBlockType)) - ord(low(TXmlCodeFoldBlockType));
end;
procedure TSynXMLSyn.SetFoldConfig(Index: Integer; const AValue: TSynCustomFoldConfig);
function TSynXMLSyn.GetFoldConfigInternalCount: Integer;
begin
BeginUpdate;
FFoldConfig[TXmlCodeFoldBlockType(Index + 1)].Assign(AValue);
EndUpdate;
// Todo: Since all synedits will rescan => delete all foldranges
// excluded cfbtXmlNone;
Result := ord(high(TXmlCodeFoldBlockType)) - ord(low(TXmlCodeFoldBlockType)) + 1;
end;
{ TSynHighlighterXmlRangeList }