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