mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-27 21:00:23 +02:00
SynEdit: Folding for html
git-svn-id: trunk@24616 -
This commit is contained in:
parent
c0cdbb38c5
commit
b69ccc3438
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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);
|
||||
|
361
components/synedit/synedithighlighterxmlbase.pas
Normal file
361
components/synedit/synedithighlighterxmlbase.pas
Normal 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.
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 }
|
||||
|
Loading…
Reference in New Issue
Block a user