PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/syntax/DisplayTokenHandler.java

#
Java | 234 lines | 146 code | 34 blank | 54 comment | 33 complexity | af5330082b09a59e1709c9b01caeee59 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * DisplayTokenHandler.java - converts tokens to chunks
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2003 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package org.gjt.sp.jedit.syntax;
  23. //{{{ Imports
  24. import javax.swing.text.*;
  25. import java.awt.font.*;
  26. import java.util.List;
  27. import org.gjt.sp.jedit.syntax.*;
  28. //}}}
  29. /**
  30. * Creates {@link Chunk} objects that can be painted on screen.
  31. */
  32. public class DisplayTokenHandler extends DefaultTokenHandler
  33. {
  34. // don't have chunks longer than 100 characters to avoid slowing things down
  35. public static final int MAX_CHUNK_LEN = 100;
  36. //{{{ init() method
  37. public void init(SyntaxStyle[] styles,
  38. FontRenderContext fontRenderContext,
  39. TabExpander expander, List out,
  40. float wrapMargin)
  41. {
  42. super.init();
  43. x = 0.0f;
  44. this.styles = styles;
  45. this.fontRenderContext = fontRenderContext;
  46. this.expander = expander;
  47. // SILLY: allow for anti-aliased characters' "fuzz"
  48. if(wrapMargin != 0.0f)
  49. this.wrapMargin = wrapMargin += 2.0f;
  50. else
  51. this.wrapMargin = 0.0f;
  52. this.out = out;
  53. seenNonWhitespace = false;
  54. endX = endOfWhitespace = 0.0f;
  55. end = null;
  56. } //}}}
  57. //{{{ getChunkList() method
  58. /**
  59. * Returns the list of chunks.
  60. * @since jEdit 4.1pre7
  61. */
  62. public List getChunkList()
  63. {
  64. return out;
  65. } //}}}
  66. //{{{ handleToken() method
  67. /**
  68. * Called by the token marker when a syntax token has been parsed.
  69. * @param seg The segment containing the text
  70. * @param id The token type (one of the constants in the
  71. * {@link Token} class).
  72. * @param offset The start offset of the token
  73. * @param length The number of characters in the token
  74. * @param context The line context
  75. * @since jEdit 4.2pre3
  76. */
  77. public void handleToken(Segment seg, byte id, int offset, int length,
  78. TokenMarker.LineContext context)
  79. {
  80. if(id == Token.END)
  81. {
  82. if(firstToken != null)
  83. out.add(merge((Chunk)firstToken,seg));
  84. return;
  85. }
  86. for(int splitOffset = 0; splitOffset < length; splitOffset += MAX_CHUNK_LEN)
  87. {
  88. int splitLength = Math.min(length - splitOffset,MAX_CHUNK_LEN);
  89. Chunk chunk = createChunk(id,offset + splitOffset,splitLength,context);
  90. addToken(chunk,context);
  91. if(wrapMargin != 0.0f)
  92. {
  93. initChunk(chunk,seg);
  94. x += chunk.width;
  95. if(Character.isWhitespace(seg.array[
  96. seg.offset + chunk.offset]))
  97. {
  98. if(seenNonWhitespace)
  99. {
  100. end = lastToken;
  101. endX = x;
  102. }
  103. else
  104. endOfWhitespace = x;
  105. }
  106. else
  107. {
  108. if(x > wrapMargin
  109. && end != null
  110. && seenNonWhitespace)
  111. {
  112. Chunk nextLine = new Chunk(endOfWhitespace,
  113. end.offset + end.length,
  114. getParserRuleSet(context));
  115. initChunk(nextLine,seg);
  116. nextLine.next = end.next;
  117. end.next = null;
  118. if(firstToken != null)
  119. out.add(merge((Chunk)firstToken,seg));
  120. firstToken = nextLine;
  121. x = x - endX + endOfWhitespace;
  122. end = null;
  123. endX = x;
  124. }
  125. seenNonWhitespace = true;
  126. }
  127. }
  128. }
  129. } //}}}
  130. //{{{ Private members
  131. //{{{ Instance variables
  132. private SyntaxStyle[] styles;
  133. private FontRenderContext fontRenderContext;
  134. private TabExpander expander;
  135. private float x;
  136. private List out;
  137. private float wrapMargin;
  138. private float endX;
  139. private Token end;
  140. private boolean seenNonWhitespace;
  141. private float endOfWhitespace;
  142. //}}}
  143. //{{{ createChunk() method
  144. private Chunk createChunk(byte id, int offset, int length,
  145. TokenMarker.LineContext context)
  146. {
  147. return new Chunk(id,offset,length,
  148. getParserRuleSet(context),styles,
  149. context.rules.getDefault());
  150. } //}}}
  151. //{{{ initChunk() method
  152. protected void initChunk(Chunk chunk, Segment seg)
  153. {
  154. chunk.init(seg,expander,x,fontRenderContext);
  155. } //}}}
  156. //{{{ merge() method
  157. private Chunk merge(Chunk first, Segment seg)
  158. {
  159. if(first == null)
  160. return null;
  161. Chunk chunk = first;
  162. while(chunk.next != null)
  163. {
  164. Chunk next = (Chunk)chunk.next;
  165. if(canMerge(chunk,next,seg))
  166. {
  167. // in case already initialized; un-initialize it
  168. chunk.initialized = false;
  169. chunk.length += next.length;
  170. chunk.width += next.width;
  171. chunk.next = next.next;
  172. }
  173. else
  174. {
  175. if(!chunk.initialized)
  176. {
  177. initChunk(chunk,seg);
  178. if(wrapMargin == 0.0f)
  179. x += chunk.width;
  180. }
  181. chunk = next;
  182. }
  183. }
  184. if(!chunk.initialized)
  185. initChunk(chunk,seg);
  186. return first;
  187. } //}}}
  188. //{{{ canMerge() method
  189. private boolean canMerge(Chunk c1, Chunk c2, Segment seg)
  190. {
  191. if(!c1.accessable || !c2.accessable)
  192. return false;
  193. char ch1 = seg.array[seg.offset + c1.offset];
  194. char ch2 = seg.array[seg.offset + c2.offset];
  195. return ((c1.style == c2.style)
  196. && ch1 != '\t' && ch2 != '\t'
  197. && (c1.length + c2.length <= MAX_CHUNK_LEN));
  198. } //}}}
  199. //}}}
  200. }