sh_xml.pp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. {
  2. "SHEdit" - Text editor with syntax highlighting
  3. Copyright (C) 1999-2000 by Sebastian Guenther ([email protected])
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. }
  10. // viewer class for XML files
  11. {$MODE objfpc}
  12. {$H+}
  13. unit sh_xml;
  14. interface
  15. uses doc_text, shedit;
  16. type
  17. TSHXMLEdit = class(TSHTextEdit)
  18. protected
  19. procedure DoHighlighting(var flags: Byte; source, dest: PChar); override;
  20. public
  21. // Syntax highlighter style indices
  22. shTag, shTagName, shDefTagName, shArgName, shString, shReference,
  23. shInvalid, shComment, shCDATA: Integer;
  24. end;
  25. implementation
  26. uses Strings;
  27. const
  28. LF_SH_Tag = LF_SH_Multiline1;
  29. LF_SH_Comment = LF_SH_Multiline2;
  30. LF_SH_String1 = LF_SH_Multiline3; // Single quotation mark
  31. LF_SH_String2 = LF_SH_Multiline4; // Double quotation mark
  32. LF_SH_CDATA = LF_SH_Multiline5;
  33. procedure TSHXMLEdit.DoHighlighting(var flags: Byte; source, dest: PChar);
  34. var
  35. dp: Integer; {Destination postion - current offset in dest}
  36. LastSHPos: Integer; {Position of last highlighting character, or 0}
  37. procedure AddSH(sh: Byte);
  38. begin
  39. if (LastSHPos > 0) and (dp = LastSHPos + 1) then Dec(dp, 2);
  40. dest[dp] := LF_Escape; Inc(dp);
  41. LastSHPos := dp;
  42. dest[dp] := Chr(sh); Inc(dp);
  43. end;
  44. procedure PutChar;
  45. begin
  46. dest[dp] := source[0]; Inc(dp); Inc(source);
  47. end;
  48. procedure ProcessComment;
  49. begin
  50. flags := flags or LF_SH_Comment;
  51. AddSH(shComment);
  52. while source[0] <> #0 do begin
  53. if (source[0] = '-') and (source[1] = '-') and (source[2] = '>') then begin
  54. PutChar; PutChar; PutChar;
  55. flags := flags and not LF_SH_Comment;
  56. AddSH(shDefault);
  57. break;
  58. end;
  59. PutChar;
  60. end;
  61. end;
  62. procedure ProcessReference;
  63. begin
  64. AddSH(shReference);
  65. while source[0] <> #0 do begin
  66. if source[0] = ';' then begin
  67. PutChar;
  68. AddSH(shDefault);
  69. break;
  70. end else if (source[0] = '''') or (source[0] = '"') then begin
  71. AddSH(shString);
  72. break;
  73. end else
  74. PutChar;
  75. end;
  76. end;
  77. procedure ProcessString(EndChar: Char);
  78. begin
  79. while source[0] <> #0 do begin
  80. if source[0] = EndChar then begin
  81. PutChar;
  82. AddSH(shDefault);
  83. flags := flags and not (LF_SH_String1 or LF_SH_String2);
  84. break;
  85. end else if source[0] = '&' then
  86. ProcessReference
  87. else
  88. PutChar;
  89. end;
  90. end;
  91. procedure ProcessTagContd;
  92. var
  93. c: Char;
  94. begin
  95. while source[0] <> #0 do begin
  96. if (source[0] in ['/', '?']) and (source[1] = '>') then begin
  97. AddSH(shTag);
  98. PutChar;
  99. PutChar;
  100. AddSH(shDefault);
  101. flags := flags and not LF_SH_Tag;
  102. break;
  103. end else if (source[0] = '>') then begin
  104. AddSH(shTag);
  105. PutChar;
  106. AddSH(shDefault);
  107. flags := flags and not LF_SH_Tag;
  108. break;
  109. end else if (source[0] = '''') or (source[0] = '"') then begin
  110. c := source[0];
  111. if source[0] = '''' then
  112. flags := flags or LF_SH_String1
  113. else
  114. flags := flags or LF_SH_String2;
  115. AddSH(shString);
  116. PutChar;
  117. ProcessString(c);
  118. end else if source[0] in [#9, ' ', '=', '(', ')', '+', '*', '?', ','] then begin
  119. AddSH(shDefault);
  120. PutChar;
  121. end else begin
  122. AddSH(shArgName);
  123. PutChar;
  124. end;
  125. end;
  126. end;
  127. procedure ProcessTag;
  128. begin
  129. flags := flags or LF_SH_Tag;
  130. AddSH(shTag);
  131. PutChar;
  132. if source[0] = '/' then PutChar;
  133. if (source[0] = '!') or (source[0] = '?') then
  134. AddSH(shDefTagName)
  135. else
  136. AddSH(shTagName);
  137. while not (source[0] in [#0, ' ', '/', '>']) do
  138. PutChar;
  139. AddSH(shDefault);
  140. ProcessTagContd;
  141. end;
  142. procedure ProcessCDATAContd;
  143. begin
  144. AddSH(shCDATA);
  145. while source[0] <> #0 do begin
  146. if (source[0] = ']') and (source[1] = ']') and
  147. (source[2] = '>') then begin
  148. AddSH(shTag);
  149. PutChar; PutChar; PutChar;
  150. AddSH(shDefault);
  151. flags := flags and not LF_SH_CDATA;
  152. break;
  153. end;
  154. PutChar;
  155. end;
  156. end;
  157. procedure ProcessCDATA;
  158. var
  159. i: Integer;
  160. begin
  161. flags := flags or LF_SH_CDATA;
  162. AddSH(shTag);
  163. for i := 1 to 9 do PutChar;
  164. ProcessCDATAContd;
  165. end;
  166. begin
  167. dp := 0;
  168. LastSHPos := 0;
  169. if (flags and LF_SH_Comment) <> 0 then begin
  170. AddSH(shComment);
  171. ProcessComment;
  172. end;
  173. if (flags and LF_SH_String1) <> 0 then begin
  174. AddSH(shString);
  175. ProcessString('''');
  176. end;
  177. if (flags and LF_SH_String2) <> 0 then begin
  178. AddSH(shString);
  179. ProcessString('"');
  180. end;
  181. if (flags and LF_SH_Tag) <> 0 then
  182. ProcessTagContd;
  183. if (flags and LF_SH_CDATA) <> 0 then
  184. ProcessCDATAContd;
  185. while source[0] <> #0 do begin
  186. case source[0] of
  187. '<':
  188. if (source[1] = '!') and (source[2] = '-') and (source[3] = '-') then
  189. ProcessComment
  190. else if (source[1] = '!') and (source[2] = '[') and (source[3] = 'C')
  191. and (source[4] = 'D') and (source[5] = 'A') and (source[6] = 'T')
  192. and (source[7] = 'A') and (source[8] = '[') then
  193. ProcessCDATA
  194. else
  195. ProcessTag;
  196. '&': ProcessReference;
  197. else
  198. PutChar;
  199. end;
  200. end;
  201. dest[dp] := #0;
  202. end;
  203. end.