mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-01 00:23:42 +02:00
448 lines
12 KiB
ObjectPascal
448 lines
12 KiB
ObjectPascal
{-------------------------------------------------------------------------------
|
|
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.
|
|
|
|
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.
|
|
|
|
Abstract:
|
|
This is a basic synedit highlighter that does not parse text to create the
|
|
attributes, but stores a list of ranges.
|
|
|
|
-------------------------------------------------------------------------------}
|
|
unit SynHighlighterPosition;
|
|
|
|
{$I synedit.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Graphics, SynEditStrConst, SynEditTypes,
|
|
SynEditHighlighter;
|
|
|
|
const
|
|
tkNone = 0;
|
|
tkText = 1;
|
|
tkCustom = 2;
|
|
|
|
MaxColumns = 100000;
|
|
|
|
type
|
|
TtkTokenKind = integer;
|
|
|
|
TPositionToken = record
|
|
Kind: TtkTokenKind;
|
|
Column: integer;
|
|
end;
|
|
PPositionToken = ^TPositionToken;
|
|
|
|
TPositionTokens = record
|
|
Count: integer;
|
|
Tokens: array[0..MaxColumns] of TPositionToken;
|
|
end;
|
|
PPositionTokens = ^TPositionTokens;
|
|
|
|
{ TSynPositionHighlighter }
|
|
|
|
TSynPositionHighlighter = class(TSynCustomHighlighter)
|
|
private
|
|
fCopiedAttributes: TList;
|
|
fLine: string;
|
|
fLineLen: integer;
|
|
fLineNumber: Integer;
|
|
fTokenEnd: LongInt; // end of current token
|
|
fTextAttri: TSynHighlighterAttributes;
|
|
fTokenPos: Integer;
|
|
fTokenArrayPos: integer;
|
|
FTokenKind: TtkTokenKind;
|
|
fTokens: TList; // list of PPositionTokens
|
|
function GetTokens(TheLineNumber: integer): PPositionTokens;
|
|
protected
|
|
function GetIdentChars: TSynIdentChars; override;
|
|
function IsFilterStored: boolean; override; //mh 2000-10-08
|
|
function GetPositionTokensSize(ItemCount: integer): integer;
|
|
function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
|
|
override;
|
|
public
|
|
class function GetLanguageName: string; override;
|
|
public
|
|
constructor Create(TheOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function GetEol: Boolean; override;
|
|
function GetRange: Pointer; override;
|
|
function GetToken: string; override;
|
|
procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override;
|
|
function GetTokenAttribute: TSynHighlighterAttributes; override;
|
|
function GetTokenKind: integer; override;
|
|
function GetTokenPos: Integer; override;
|
|
procedure Next; override;
|
|
procedure ResetRange; override;
|
|
procedure SetLine(const NewValue: string;
|
|
LineNumber:Integer); override;
|
|
procedure SetRange(Value: Pointer); override;
|
|
function UseUserSettings(settingIndex: integer): boolean; override;
|
|
procedure EnumUserSettings(settings: TStrings); override;
|
|
property IdentChars;
|
|
public
|
|
procedure AddToken(Line, // 0 based
|
|
Col: integer; // 1 based
|
|
TokenKind: TtkTokenKind);
|
|
procedure ClearTokens(Line: integer); // 0 based
|
|
procedure ClearAllCopiedAttributes;
|
|
procedure ClearAllTokens;
|
|
procedure InsertTokens(Lines: TStringList;
|
|
Highlighter: TSynCustomHighlighter;
|
|
Line, //0 based
|
|
Col: integer // 1 based
|
|
);
|
|
function CreateTokenID(const aName: string; Foreground, BackGround: TColor;
|
|
Style: TFontStyles): TtkTokenKind;
|
|
function GetCopiedTokenID(Attr: TSynHighlighterAttributes): TtkTokenKind;
|
|
function GetCopiedAttribute(TokenID: TtkTokenKind): TSynHighlighterAttributes;
|
|
property Tokens[TheLineNumber: integer]: PPositionTokens read GetTokens;
|
|
published
|
|
property TextAttri: TSynHighlighterAttributes read fTextAttri write fTextAttri;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TSynPositionHighlighter }
|
|
|
|
function TSynPositionHighlighter.GetTokens(TheLineNumber: integer
|
|
): PPositionTokens;
|
|
begin
|
|
if (TheLineNumber>=0) and (TheLineNumber<fTokens.Count) then
|
|
Result:=PPositionTokens(fTokens[TheLineNumber])
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetIdentChars: TSynIdentChars;
|
|
begin
|
|
Result := ['_', '0'..'9', 'a'..'z', 'A'..'Z'];
|
|
end;
|
|
|
|
function TSynPositionHighlighter.IsFilterStored: boolean;
|
|
begin
|
|
Result:=true;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetPositionTokensSize(ItemCount: integer
|
|
): integer;
|
|
begin
|
|
Result:=SizeOf(integer)+SizeOf(TPositionToken)*ItemCount;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetDefaultAttribute(Index: integer
|
|
): TSynHighlighterAttributes;
|
|
begin
|
|
Result:=nil;
|
|
end;
|
|
|
|
class function TSynPositionHighlighter.GetLanguageName: string;
|
|
begin
|
|
Result:='Position based highlighter';
|
|
end;
|
|
|
|
constructor TSynPositionHighlighter.Create(TheOwner: TComponent);
|
|
begin
|
|
inherited Create(TheOwner);
|
|
fTokens:=TList.Create;
|
|
fCopiedAttributes:=TList.Create;
|
|
fTextAttri := TSynHighlighterAttributes.Create(@SYNS_AttrText, SYNS_XML_AttrText);
|
|
AddAttribute(fTextAttri);
|
|
SetAttributesOnChange(@DefHighlightChange);
|
|
|
|
fDefaultFilter := '';
|
|
end;
|
|
|
|
destructor TSynPositionHighlighter.Destroy;
|
|
begin
|
|
ClearAllTokens;
|
|
fTokens.Free;
|
|
ClearAllCopiedAttributes;
|
|
fCopiedAttributes.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetEol: Boolean;
|
|
begin
|
|
Result := fTokenKind = tkNone;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetRange: Pointer;
|
|
begin
|
|
Result := Pointer(PtrInt(fLineNumber));
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetToken: string;
|
|
var
|
|
Len: LongInt;
|
|
begin
|
|
Len := fTokenEnd - fTokenPos;
|
|
SetLength(Result{%H-},Len);
|
|
System.Move(fLine[fTokenPos],Result[1],Len);
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.GetTokenEx(out TokenStart: PChar;
|
|
out TokenLength: integer);
|
|
begin
|
|
TokenLength:=fTokenEnd-fTokenPos;
|
|
if TokenLength>0 then begin
|
|
TokenStart:=@fLine[fTokenPos];
|
|
end else begin
|
|
TokenStart:=nil;
|
|
end;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetTokenAttribute: TSynHighlighterAttributes;
|
|
var
|
|
t: TtkTokenKind;
|
|
begin
|
|
t:=GetTokenKind;
|
|
if t=tkText then
|
|
Result:=fTextAttri
|
|
else if (t<0) then
|
|
// this is a copied attribute
|
|
Result:=GetCopiedAttribute(t)
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetTokenKind: integer;
|
|
begin
|
|
Result:=fTokenKind;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetTokenPos: Integer;
|
|
begin
|
|
Result:=fTokenPos-1;
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.Next;
|
|
var
|
|
p: PPositionTokens;
|
|
begin
|
|
fTokenPos := fTokenEnd;
|
|
if fTokenEnd>fLineLen then begin
|
|
fTokenKind := tkNone;
|
|
exit;
|
|
end;
|
|
inc(fTokenArrayPos);
|
|
p:=Tokens[fLineNumber];
|
|
if (p<>nil) and (p^.Count>fTokenArrayPos) then begin
|
|
fTokenKind := p^.Tokens[fTokenArrayPos].Kind;
|
|
fTokenEnd := p^.Tokens[fTokenArrayPos].Column+1;
|
|
if fTokenEnd>fLineLen+1 then
|
|
fTokenEnd := fLineLen+1;
|
|
if fTokenEnd=fTokenPos then
|
|
Next;
|
|
end else begin
|
|
fTokenEnd := fLineLen+1;
|
|
fTokenKind := tkText;
|
|
end;
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.ResetRange;
|
|
begin
|
|
inherited ResetRange;
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.SetLine(const NewValue: string;
|
|
LineNumber: Integer);
|
|
var
|
|
p: PPositionTokens;
|
|
begin
|
|
inherited;
|
|
fLine := NewValue;
|
|
fLineLen := length(fLine);
|
|
fLineNumber := LineNumber;
|
|
fTokenArrayPos := 0;
|
|
fTokenPos := 1;
|
|
p:=Tokens[fLineNumber];
|
|
if p<>nil then begin
|
|
fTokenEnd := p^.Tokens[0].Column+1;
|
|
if fTokenEnd>fLineLen+1 then
|
|
fTokenEnd:=fLineLen+1;
|
|
FTokenKind := p^.Tokens[0].Kind;
|
|
if fTokenEnd=fTokenPos then Next;
|
|
end else begin
|
|
fTokenEnd := fLineLen+1;
|
|
FTokenKind := tkText;
|
|
end;
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.SetRange(Value: Pointer);
|
|
begin
|
|
inherited SetRange(Value);
|
|
end;
|
|
|
|
function TSynPositionHighlighter.UseUserSettings(settingIndex: integer
|
|
): boolean;
|
|
begin
|
|
Result:=inherited UseUserSettings(settingIndex);
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.EnumUserSettings(settings: TStrings);
|
|
begin
|
|
inherited EnumUserSettings(settings);
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.AddToken(Line, Col: integer;
|
|
TokenKind: TtkTokenKind);
|
|
var
|
|
p: PPositionTokens;
|
|
TokenIndex, TokenCount: integer;
|
|
begin
|
|
if Col<1 then exit;
|
|
// fill up lines
|
|
while (Line>=fTokens.Count) do fTokens.Add(nil);
|
|
// resize Token array
|
|
p:=Tokens[Line];
|
|
TokenIndex:=0;
|
|
if p<>nil then
|
|
TokenCount:=p^.Count+1
|
|
else
|
|
TokenCount:=1;
|
|
ReAllocMem(p,GetPositionTokensSize(TokenCount));
|
|
fTokens[Line]:=p;
|
|
p^.Count:=TokenCount;
|
|
// insert Token
|
|
TokenIndex:=TokenCount-1;
|
|
while (TokenIndex>0)
|
|
and (p^.Tokens[TokenIndex-1].Column>Col) do
|
|
dec(TokenIndex);
|
|
if TokenIndex<TokenCount-1 then begin
|
|
System.Move(p^.Tokens[TokenIndex],p^.Tokens[TokenIndex+1],
|
|
SizeOf(TPositionToken)*(TokenCount-TokenIndex-1));
|
|
end;
|
|
with p^.Tokens[TokenIndex] do begin
|
|
Kind:=TokenKind;
|
|
Column:=Col;
|
|
end;
|
|
DefHighlightChange(Self);
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.ClearTokens(Line: integer);
|
|
var
|
|
p: pointer;
|
|
begin
|
|
if (Line>=0) and (Line<fTokens.Count) then begin
|
|
p:=fTokens[Line];
|
|
if p<>nil then begin
|
|
FreeMem(p);
|
|
fTokens[Line]:=nil;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.ClearAllCopiedAttributes;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i:=0 to fCopiedAttributes.Count-1 do
|
|
TObject(fCopiedAttributes[i]).Free;
|
|
fCopiedAttributes.Clear;
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.ClearAllTokens;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i:=0 to fTokens.Count-1 do
|
|
ClearTokens(i);
|
|
fTokens.Clear;
|
|
end;
|
|
|
|
procedure TSynPositionHighlighter.InsertTokens(Lines: TStringList;
|
|
Highlighter: TSynCustomHighlighter; Line, Col: integer);
|
|
var
|
|
RelLine: integer;
|
|
nTokenLen: integer;
|
|
sToken: PChar;
|
|
Attr: TSynHighlighterAttributes;
|
|
TokenID: integer;
|
|
begin
|
|
if (Lines=nil) or (Lines.Count=0) or (Highlighter=nil) then exit;
|
|
RelLine:=0;
|
|
while RelLine<Lines.Count do begin
|
|
HighLighter.SetLine(Lines[RelLine], RelLine);
|
|
while not Highlighter.GetEol do begin
|
|
Attr:=Highlighter.GetTokenAttribute;
|
|
TokenID:=GetCopiedTokenID(Attr);
|
|
Highlighter.GetTokenEx(sToken,nTokenLen);
|
|
inc(Col,nTokenLen);
|
|
AddToken(Line,Col-1,TokenID);
|
|
// next Token
|
|
Highlighter.Next;
|
|
end;
|
|
// next line
|
|
inc(Line);
|
|
inc(RelLine);
|
|
Col:=1;
|
|
end;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.CreateTokenID(const aName: string;
|
|
Foreground, BackGround: TColor;
|
|
Style: TFontStyles): TtkTokenKind;
|
|
var
|
|
Attr: TSynHighlighterAttributes;
|
|
begin
|
|
Attr:=TSynHighlighterAttributes.Create(aName);
|
|
Attr.Foreground:=Foreground;
|
|
Attr.Background:=BackGround;
|
|
Attr.Style:=Style;
|
|
Result:=GetCopiedTokenID(Attr);
|
|
Attr.Free;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetCopiedTokenID(
|
|
Attr: TSynHighlighterAttributes): TtkTokenKind;
|
|
var
|
|
i: Integer;
|
|
CurAttr: TSynHighlighterAttributes;
|
|
begin
|
|
i:=fCopiedAttributes.Count-1;
|
|
while i>=0 do begin
|
|
CurAttr:=TSynHighlighterAttributes(fCopiedAttributes[i]);
|
|
if (Attr.ForeGround=CurAttr.ForeGround)
|
|
and (Attr.BackGround=CurAttr.BackGround)
|
|
and (Attr.Style=CurAttr.Style) then begin
|
|
// attribute already exists
|
|
Result:=(-i-1);
|
|
exit;
|
|
end;
|
|
dec(i);
|
|
end;
|
|
// create new attribute
|
|
CurAttr:=TSynHighlighterAttributes.Create(nil);
|
|
CurAttr.Assign(Attr);
|
|
fCopiedAttributes.Add(CurAttr);
|
|
Result:= -fCopiedAttributes.Count;
|
|
end;
|
|
|
|
function TSynPositionHighlighter.GetCopiedAttribute(TokenID: TtkTokenKind
|
|
): TSynHighlighterAttributes;
|
|
begin
|
|
if (TokenID<0) and (fCopiedAttributes.Count>=-TokenID) then
|
|
Result:=TSynHighlighterAttributes(fCopiedAttributes[-TokenID-1])
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
end.
|
|
|