PageRenderTime 33ms CodeModel.GetById 15ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 1ms

/components/synedit/synhighlighterposition.pas

http://github.com/graemeg/lazarus
Pascal | 439 lines | 368 code | 44 blank | 27 comment | 30 complexity | 85fea378a38a83db58391e2df2e983a0 MD5 | raw file
  1{-------------------------------------------------------------------------------
  2The contents of this file are subject to the Mozilla Public License
  3Version 1.1 (the "License"); you may not use this file except in compliance
  4with the License. You may obtain a copy of the License at
  5http://www.mozilla.org/MPL/
  6Software distributed under the License is distributed on an "AS IS" basis,
  7WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  8the specific language governing rights and limitations under the License.
  9
 10
 11$Id$
 12
 13This is a basic synedit highlighter that does not parse text to create the
 14attributes, but stores a list of ranges.
 15
 16-------------------------------------------------------------------------------}
 17unit SynHighlighterPosition;
 18
 19{$I synedit.inc}
 20
 21interface
 22
 23uses
 24  Classes, SysUtils, Graphics, SynEditStrConst, SynEditTypes,
 25  SynEditHighlighter;
 26
 27const
 28  tkNone   = 0;
 29  tkText   = 1;
 30  tkCustom = 2;
 31  
 32  MaxColumns = 100000;
 33
 34type
 35  TtkTokenKind = integer;
 36
 37  TPositionToken = record
 38    Kind: TtkTokenKind;
 39    Column: integer;
 40  end;
 41  PPositionToken = ^TPositionToken;
 42
 43  TPositionTokens = record
 44    Count: integer;
 45    Tokens: array[0..MaxColumns] of TPositionToken;
 46  end;
 47  PPositionTokens = ^TPositionTokens;
 48
 49  { TSynPositionHighlighter }
 50
 51  TSynPositionHighlighter = class(TSynCustomHighlighter)
 52  private
 53    fCopiedAttributes: TList;
 54    fLine: string;
 55    fLineLen: integer;
 56    fLineNumber: Integer;
 57    fTokenEnd: LongInt; // end of current token
 58    fTextAttri: TSynHighlighterAttributes;
 59    fTokenPos: Integer;
 60    fTokenArrayPos: integer;
 61    FTokenKind: TtkTokenKind;
 62    fTokens: TList; // list of PPositionTokens
 63    function GetTokens(TheLineNumber: integer): PPositionTokens;
 64  protected
 65    function GetIdentChars: TSynIdentChars; override;
 66    function IsFilterStored: boolean; override;                                 //mh 2000-10-08
 67    function GetPositionTokensSize(ItemCount: integer): integer;
 68    function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes;
 69      override;
 70  public
 71    class function GetLanguageName: string; override;
 72  public
 73    constructor Create(TheOwner: TComponent); override;
 74    destructor Destroy; override;
 75    function GetEol: Boolean; override;
 76    function GetRange: Pointer; override;
 77    function GetToken: string; override;
 78    procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override;
 79    function GetTokenAttribute: TSynHighlighterAttributes; override;
 80    function GetTokenKind: integer; override;
 81    function GetTokenPos: Integer; override;
 82    procedure Next; override;
 83    procedure ResetRange; override;
 84    procedure SetLine(const NewValue: string;
 85      LineNumber:Integer); override;
 86    procedure SetRange(Value: Pointer); override;
 87    function UseUserSettings(settingIndex: integer): boolean; override;
 88    procedure EnumUserSettings(settings: TStrings); override;
 89    property IdentChars;
 90  public
 91    procedure AddToken(Line, // 0 based
 92                       Col: integer; // 1 based
 93                       TokenKind: TtkTokenKind);
 94    procedure ClearTokens(Line: integer); // 0 based
 95    procedure ClearAllCopiedAttributes;
 96    procedure ClearAllTokens;
 97    procedure InsertTokens(Lines: TStringList;
 98      Highlighter: TSynCustomHighlighter;
 99      Line, //0 based
100      Col: integer // 1 based
101      );
102    function CreateTokenID(const aName: string; Foreground, BackGround: TColor;
103                           Style: TFontStyles): TtkTokenKind;
104    function GetCopiedTokenID(Attr: TSynHighlighterAttributes): TtkTokenKind;
105    function GetCopiedAttribute(TokenID: TtkTokenKind): TSynHighlighterAttributes;
106    property Tokens[TheLineNumber: integer]: PPositionTokens read GetTokens;
107  published
108    property TextAttri: TSynHighlighterAttributes read fTextAttri write fTextAttri;
109  end;
110
111implementation
112
113{ TSynPositionHighlighter }
114
115function TSynPositionHighlighter.GetTokens(TheLineNumber: integer
116  ): PPositionTokens;
117begin
118  if (TheLineNumber>=0) and (TheLineNumber<fTokens.Count) then
119    Result:=PPositionTokens(fTokens[TheLineNumber])
120  else
121    Result:=nil;
122end;
123
124function TSynPositionHighlighter.GetIdentChars: TSynIdentChars;
125begin
126  Result := ['_', '0'..'9', 'a'..'z', 'A'..'Z'];
127end;
128
129function TSynPositionHighlighter.IsFilterStored: boolean;
130begin
131  Result:=true;
132end;
133
134function TSynPositionHighlighter.GetPositionTokensSize(ItemCount: integer
135  ): integer;
136begin
137  Result:=SizeOf(integer)+SizeOf(TPositionToken)*ItemCount;
138end;
139
140function TSynPositionHighlighter.GetDefaultAttribute(Index: integer
141  ): TSynHighlighterAttributes;
142begin
143  Result:=nil;
144end;
145
146class function TSynPositionHighlighter.GetLanguageName: string;
147begin
148  Result:='Position based highlighter';
149end;
150
151constructor TSynPositionHighlighter.Create(TheOwner: TComponent);
152begin
153  inherited Create(TheOwner);
154  fTokens:=TList.Create;
155  fCopiedAttributes:=TList.Create;
156  fTextAttri := TSynHighlighterAttributes.Create(@SYNS_AttrText, SYNS_XML_AttrText);
157  AddAttribute(fTextAttri);
158  SetAttributesOnChange(@DefHighlightChange);
159
160  fDefaultFilter := '';
161end;
162
163destructor TSynPositionHighlighter.Destroy;
164begin
165  ClearAllTokens;
166  fTokens.Free;
167  ClearAllCopiedAttributes;
168  fCopiedAttributes.Free;
169  inherited Destroy;
170end;
171
172function TSynPositionHighlighter.GetEol: Boolean;
173begin
174  Result := fTokenKind = tkNone;
175end;
176
177function TSynPositionHighlighter.GetRange: Pointer;
178begin
179  Result := Pointer(PtrInt(fLineNumber));
180end;
181
182function TSynPositionHighlighter.GetToken: string;
183var
184  Len: LongInt;
185begin
186  Len := fTokenEnd - fTokenPos;
187  SetLength(Result,Len);
188  System.Move(fLine[fTokenPos],Result[1],Len);
189end;
190
191procedure TSynPositionHighlighter.GetTokenEx(out TokenStart: PChar;
192  out TokenLength: integer);
193begin
194  TokenLength:=fTokenEnd-fTokenPos;
195  if TokenLength>0 then begin
196    TokenStart:=@fLine[fTokenPos];
197  end else begin
198    TokenStart:=nil;
199  end;
200end;
201
202function TSynPositionHighlighter.GetTokenAttribute: TSynHighlighterAttributes;
203var
204  t: TtkTokenKind;
205begin
206  t:=GetTokenKind;
207  if t=tkText then
208    Result:=fTextAttri
209  else if (t<0) then
210    // this is a copied attribute
211    Result:=GetCopiedAttribute(t)
212  else
213    Result:=nil;
214end;
215
216function TSynPositionHighlighter.GetTokenKind: integer;
217begin
218  Result:=fTokenKind;
219end;
220
221function TSynPositionHighlighter.GetTokenPos: Integer;
222begin
223  Result:=fTokenPos-1;
224end;
225
226procedure TSynPositionHighlighter.Next;
227var
228  p: PPositionTokens;
229begin
230  fTokenPos := fTokenEnd;
231  if fTokenEnd>fLineLen then begin
232    fTokenKind := tkNone;
233    exit;
234  end;
235  inc(fTokenArrayPos);
236  p:=Tokens[fLineNumber];
237  if (p<>nil) and (p^.Count>fTokenArrayPos) then begin
238    fTokenKind := p^.Tokens[fTokenArrayPos].Kind;
239    fTokenEnd := p^.Tokens[fTokenArrayPos].Column+1;
240    if fTokenEnd>fLineLen+1 then
241      fTokenEnd := fLineLen+1;
242    if fTokenEnd=fTokenPos then
243      Next;
244  end else begin
245    fTokenEnd := fLineLen+1;
246    fTokenKind := tkText;
247  end;
248end;
249
250procedure TSynPositionHighlighter.ResetRange;
251begin
252  inherited ResetRange;
253end;
254
255procedure TSynPositionHighlighter.SetLine(const NewValue: string;
256  LineNumber: Integer);
257var
258  p: PPositionTokens;
259begin
260  inherited;
261  fLine := NewValue;
262  fLineLen := length(fLine);
263  fLineNumber := LineNumber;
264  fTokenArrayPos := 0;
265  fTokenPos := 1;
266  p:=Tokens[fLineNumber];
267  if p<>nil then begin
268    fTokenEnd := p^.Tokens[0].Column+1;
269    if fTokenEnd>fLineLen+1 then
270      fTokenEnd:=fLineLen+1;
271    FTokenKind := p^.Tokens[0].Kind;
272    if fTokenEnd=fTokenPos then Next;
273  end else begin
274    fTokenEnd := fLineLen+1;
275    FTokenKind := tkText;
276  end;
277end;
278
279procedure TSynPositionHighlighter.SetRange(Value: Pointer);
280begin
281  inherited SetRange(Value);
282end;
283
284function TSynPositionHighlighter.UseUserSettings(settingIndex: integer
285  ): boolean;
286begin
287  Result:=inherited UseUserSettings(settingIndex);
288end;
289
290procedure TSynPositionHighlighter.EnumUserSettings(settings: TStrings);
291begin
292  inherited EnumUserSettings(settings);
293end;
294
295procedure TSynPositionHighlighter.AddToken(Line, Col: integer;
296  TokenKind: TtkTokenKind);
297var
298  p: PPositionTokens;
299  TokenIndex, TokenCount: integer;
300begin
301  if Col<1 then exit;
302  // fill up lines
303  while (Line>=fTokens.Count) do fTokens.Add(nil);
304  // resize Token array
305  p:=Tokens[Line];
306  TokenIndex:=0;
307  if p<>nil then
308    TokenCount:=p^.Count+1
309  else
310    TokenCount:=1;
311  ReAllocMem(p,GetPositionTokensSize(TokenCount));
312  fTokens[Line]:=p;
313  p^.Count:=TokenCount;
314  // insert Token
315  TokenIndex:=TokenCount-1;
316  while (TokenIndex>0)
317  and (p^.Tokens[TokenIndex-1].Column>Col) do
318    dec(TokenIndex);
319  if TokenIndex<TokenCount-1 then begin
320    System.Move(p^.Tokens[TokenIndex],p^.Tokens[TokenIndex+1],
321      SizeOf(TPositionToken)*(TokenCount-TokenIndex-1));
322  end;
323  with p^.Tokens[TokenIndex] do begin
324    Kind:=TokenKind;
325    Column:=Col;
326  end;
327  DefHighlightChange(Self);
328end;
329
330procedure TSynPositionHighlighter.ClearTokens(Line: integer);
331var
332  p: pointer;
333begin
334  if (Line>=0) and (Line<fTokens.Count) then begin
335    p:=fTokens[Line];
336    if p<>nil then begin
337      FreeMem(p);
338      fTokens[Line]:=nil;
339    end;
340  end;
341end;
342
343procedure TSynPositionHighlighter.ClearAllCopiedAttributes;
344var
345  i: Integer;
346begin
347  for i:=0 to fCopiedAttributes.Count-1 do
348    TObject(fCopiedAttributes[i]).Free;
349  fCopiedAttributes.Clear;
350end;
351
352procedure TSynPositionHighlighter.ClearAllTokens;
353var
354  i: Integer;
355begin
356  for i:=0 to fTokens.Count-1 do
357    ClearTokens(i);
358  fTokens.Clear;
359end;
360
361procedure TSynPositionHighlighter.InsertTokens(Lines: TStringList;
362  Highlighter: TSynCustomHighlighter; Line, Col: integer);
363var
364  RelLine: integer;
365  nTokenLen: integer;
366  sToken: PChar;
367  Attr: TSynHighlighterAttributes;
368  TokenID: integer;
369begin
370  if (Lines=nil) or (Lines.Count=0) or (Highlighter=nil) then exit;
371  RelLine:=0;
372  while RelLine<Lines.Count do begin
373    HighLighter.SetLine(Lines[RelLine], RelLine);
374    while not Highlighter.GetEol do begin
375      Attr:=Highlighter.GetTokenAttribute;
376      TokenID:=GetCopiedTokenID(Attr);
377      Highlighter.GetTokenEx(sToken,nTokenLen);
378      inc(Col,nTokenLen);
379      AddToken(Line,Col-1,TokenID);
380      // next Token
381      Highlighter.Next;
382    end;
383    // next line
384    inc(Line);
385    inc(RelLine);
386    Col:=1;
387  end;
388end;
389
390function TSynPositionHighlighter.CreateTokenID(const aName: string;
391  Foreground, BackGround: TColor;
392  Style: TFontStyles): TtkTokenKind;
393var
394  Attr: TSynHighlighterAttributes;
395begin
396  Attr:=TSynHighlighterAttributes.Create(aName);
397  Attr.Foreground:=Foreground;
398  Attr.Background:=BackGround;
399  Attr.Style:=Style;
400  Result:=GetCopiedTokenID(Attr);
401  Attr.Free;
402end;
403
404function TSynPositionHighlighter.GetCopiedTokenID(
405  Attr: TSynHighlighterAttributes): TtkTokenKind;
406var
407  i: Integer;
408  CurAttr: TSynHighlighterAttributes;
409begin
410  i:=fCopiedAttributes.Count-1;
411  while i>=0 do begin
412    CurAttr:=TSynHighlighterAttributes(fCopiedAttributes[i]);
413    if (Attr.ForeGround=CurAttr.ForeGround)
414    and (Attr.BackGround=CurAttr.BackGround)
415    and (Attr.Style=CurAttr.Style) then begin
416      // attribute already exists
417      Result:=(-i-1);
418      exit;
419    end;
420    dec(i);
421  end;
422  // create new attribute
423  CurAttr:=TSynHighlighterAttributes.Create(nil);
424  CurAttr.Assign(Attr);
425  fCopiedAttributes.Add(CurAttr);
426  Result:= -fCopiedAttributes.Count;
427end;
428
429function TSynPositionHighlighter.GetCopiedAttribute(TokenID: TtkTokenKind
430  ): TSynHighlighterAttributes;
431begin
432  if (TokenID<0) and (fCopiedAttributes.Count>=-TokenID) then
433    Result:=TSynHighlighterAttributes(fCopiedAttributes[-TokenID-1])
434  else
435    Result:=nil;
436end;
437
438end.
439