PageRenderTime 43ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/textarea/BufferHandler.java

#
Java | 396 lines | 273 code | 49 blank | 74 comment | 53 complexity | 601e7638a8e08e9e69f491ea57520c81 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. * BufferHandler.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2001, 2005 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.textarea;
  23. import java.util.Iterator;
  24. import org.gjt.sp.jedit.buffer.*;
  25. import org.gjt.sp.jedit.Debug;
  26. /**
  27. * Note that in this class we take great care to defer complicated
  28. * calculations to the end of the current transaction if the buffer
  29. * informs us a compound edit is in progress
  30. * (<code>isTransactionInProgress()</code>).
  31. *
  32. * This greatly speeds up replace all for example, by only doing certain
  33. * things once, particularly in <code>moveCaretPosition()</code>.
  34. *
  35. * Try doing a replace all in a large file, for example. It is very slow
  36. * in 3.2, faster in 4.0 (where the transaction optimization was
  37. * introduced) and faster still in 4.1 (where it was further improved).
  38. *
  39. * There is still work to do; see TODO.txt.
  40. */
  41. class BufferHandler implements BufferListener
  42. {
  43. private DisplayManager displayManager;
  44. private JEditTextArea textArea;
  45. private JEditBuffer buffer;
  46. boolean delayedUpdate;
  47. boolean delayedMultilineUpdate;
  48. int delayedUpdateStart;
  49. int delayedUpdateEnd;
  50. //{{{ BufferChangeHandler constructor
  51. BufferHandler(DisplayManager displayManager,
  52. JEditTextArea textArea,
  53. JEditBuffer buffer)
  54. {
  55. this.displayManager = displayManager;
  56. this.textArea = textArea;
  57. this.buffer = buffer;
  58. } //}}}
  59. //{{{ bufferLoaded() method
  60. public void bufferLoaded(JEditBuffer buffer)
  61. {
  62. displayManager.bufferLoaded();
  63. } //}}}
  64. //{{{ foldHandlerChanged() method
  65. public void foldHandlerChanged(JEditBuffer buffer)
  66. {
  67. displayManager.foldHandlerChanged();
  68. } //}}}
  69. //{{{ foldLevelChanged() method
  70. public void foldLevelChanged(JEditBuffer buffer, int start, int end)
  71. {
  72. //System.err.println("foldLevelChanged " + (start-1) + " to " + textArea.getLastPhysicalLine() + "," + end);
  73. if(textArea.getDisplayManager() == displayManager
  74. && end != 0 && !buffer.isLoading())
  75. {
  76. textArea.invalidateLineRange(start - 1,
  77. textArea.getLastPhysicalLine());
  78. }
  79. } //}}}
  80. //{{{ contentInserted() method
  81. public void contentInserted(JEditBuffer buffer, int startLine,
  82. int offset, int numLines, int length)
  83. {
  84. if(buffer.isLoading())
  85. return;
  86. displayManager.screenLineMgr.contentInserted(startLine,numLines);
  87. int endLine = startLine + numLines;
  88. if(numLines != 0)
  89. delayedMultilineUpdate = true;
  90. displayManager.folds.contentInserted(startLine,numLines);
  91. FirstLine firstLine = displayManager.firstLine;
  92. ScrollLineCount scrollLineCount = displayManager.scrollLineCount;
  93. if(textArea.getDisplayManager() == displayManager)
  94. {
  95. if(numLines != 0)
  96. {
  97. firstLine.contentInserted(startLine,numLines);
  98. scrollLineCount.contentInserted(startLine,numLines);
  99. }
  100. if(delayedUpdateEnd >= startLine)
  101. delayedUpdateEnd += numLines;
  102. delayUpdate(startLine,endLine);
  103. //{{{ resize selections if necessary
  104. Iterator iter = textArea.getSelectionIterator();
  105. while(iter.hasNext())
  106. {
  107. Selection s = (Selection)iter.next();
  108. if(s.contentInserted(buffer,startLine,offset,
  109. numLines,length))
  110. {
  111. delayUpdate(s.startLine,s.endLine);
  112. }
  113. } //}}}
  114. int caret = textArea.getCaretPosition();
  115. if(caret >= offset)
  116. {
  117. int scrollMode = (textArea.caretAutoScroll()
  118. ? JEditTextArea.ELECTRIC_SCROLL
  119. : JEditTextArea.NO_SCROLL);
  120. textArea.moveCaretPosition(
  121. caret + length,scrollMode);
  122. }
  123. else
  124. {
  125. int scrollMode = (textArea.caretAutoScroll()
  126. ? JEditTextArea.NORMAL_SCROLL
  127. : JEditTextArea.NO_SCROLL);
  128. textArea.moveCaretPosition(
  129. caret,scrollMode);
  130. }
  131. }
  132. else
  133. {
  134. firstLine.callReset = true;
  135. scrollLineCount.callReset = true;
  136. }
  137. } //}}}
  138. //{{{ preContentRemoved() method
  139. public void preContentRemoved(JEditBuffer buffer, int startLine,
  140. int offset, int numLines, int length)
  141. {
  142. if(buffer.isLoading())
  143. return;
  144. FirstLine firstLine = displayManager.firstLine;
  145. ScrollLineCount scrollLineCount = displayManager.scrollLineCount;
  146. if(textArea.getDisplayManager() == displayManager)
  147. {
  148. if(numLines != 0)
  149. {
  150. firstLine.preContentRemoved(startLine,numLines);
  151. scrollLineCount.preContentRemoved(startLine,numLines);
  152. }
  153. if(delayedUpdateEnd >= startLine)
  154. delayedUpdateEnd -= numLines;
  155. delayUpdate(startLine,startLine);
  156. }
  157. else
  158. {
  159. firstLine.callReset = true;
  160. scrollLineCount.callReset = true;
  161. }
  162. displayManager.screenLineMgr.contentRemoved(startLine,numLines);
  163. if(numLines == 0)
  164. return;
  165. delayedMultilineUpdate = true;
  166. if(displayManager.folds.preContentRemoved(startLine,numLines))
  167. {
  168. displayManager.folds.reset(buffer.getLineCount());
  169. firstLine.callReset = true;
  170. scrollLineCount.callReset = true;
  171. }
  172. if(firstLine.physicalLine
  173. > displayManager.getLastVisibleLine()
  174. || firstLine.physicalLine
  175. < displayManager.getFirstVisibleLine())
  176. {
  177. // will be handled later.
  178. // see comments at the end of
  179. // transactionComplete().
  180. }
  181. // very subtle... if we leave this for
  182. // ensurePhysicalLineIsVisible(), an
  183. // extra line will be added to the
  184. // scroll line count.
  185. else if(!displayManager.isLineVisible(
  186. firstLine.physicalLine))
  187. {
  188. firstLine.physicalLine =
  189. displayManager.getNextVisibleLine(
  190. firstLine.physicalLine);
  191. }
  192. } //}}}
  193. //{{{ contentRemoved() method
  194. public void contentRemoved(JEditBuffer buffer, int startLine,
  195. int start, int numLines, int length)
  196. {
  197. if(buffer.isLoading())
  198. return;
  199. if(textArea.getDisplayManager() == displayManager)
  200. {
  201. //{{{ resize selections if necessary
  202. Iterator iter = textArea.getSelectionIterator();
  203. while(iter.hasNext())
  204. {
  205. Selection s = (Selection)iter.next();
  206. if(s.contentRemoved(buffer,startLine,
  207. start,numLines,length))
  208. {
  209. delayUpdate(s.startLine,s.endLine);
  210. if(s.start == s.end)
  211. iter.remove();
  212. }
  213. } //}}}
  214. int caret = textArea.getCaretPosition();
  215. if(caret >= start + length)
  216. {
  217. int scrollMode = (textArea.caretAutoScroll()
  218. ? JEditTextArea.ELECTRIC_SCROLL
  219. : JEditTextArea.NO_SCROLL);
  220. textArea.moveCaretPosition(
  221. caret - length,
  222. scrollMode);
  223. }
  224. else if(caret >= start)
  225. {
  226. int scrollMode = (textArea.caretAutoScroll()
  227. ? JEditTextArea.ELECTRIC_SCROLL
  228. : JEditTextArea.NO_SCROLL);
  229. textArea.moveCaretPosition(
  230. start,scrollMode);
  231. }
  232. else
  233. {
  234. int scrollMode = (textArea.caretAutoScroll()
  235. ? JEditTextArea.NORMAL_SCROLL
  236. : JEditTextArea.NO_SCROLL);
  237. textArea.moveCaretPosition(caret,scrollMode);
  238. }
  239. }
  240. }
  241. //}}}
  242. //{{{ transactionComplete() method
  243. public void transactionComplete(JEditBuffer buffer)
  244. {
  245. if(textArea.getDisplayManager() != displayManager)
  246. {
  247. delayedUpdate = false;
  248. return;
  249. }
  250. if(delayedUpdate)
  251. doDelayedUpdate();
  252. textArea._finishCaretUpdate();
  253. delayedUpdate = false;
  254. //{{{ Debug code
  255. if(Debug.SCROLL_VERIFY)
  256. {
  257. int scrollLineCount = 0;
  258. int line = delayedUpdateStart;
  259. if(!displayManager.isLineVisible(line))
  260. line = displayManager.getNextVisibleLine(line);
  261. System.err.println(delayedUpdateStart + ":" + delayedUpdateEnd + ":" + textArea.getLineCount());
  262. while(line != -1 && line <= delayedUpdateEnd)
  263. {
  264. scrollLineCount += displayManager.getScreenLineCount(line);
  265. line = displayManager.getNextVisibleLine(line);
  266. }
  267. if(scrollLineCount != displayManager.getScrollLineCount())
  268. {
  269. throw new InternalError(scrollLineCount
  270. + " != "
  271. + displayManager.getScrollLineCount());
  272. }
  273. } //}}}
  274. } //}}}
  275. //{{{ doDelayedUpdate() method
  276. private void doDelayedUpdate()
  277. {
  278. // must update screen line counts before we call
  279. // notifyScreenLineChanges() since that calls
  280. // updateScrollBar() which needs valid info
  281. int line = delayedUpdateStart;
  282. if(!displayManager.isLineVisible(line))
  283. line = displayManager.getNextVisibleLine(line);
  284. while(line != -1 && line <= delayedUpdateEnd)
  285. {
  286. displayManager.updateScreenLineCount(line);
  287. line = displayManager.getNextVisibleLine(line);
  288. }
  289. // must be before the below call
  290. // so that the chunk cache is not
  291. // updated with an invisible first
  292. // line (see above)
  293. displayManager.notifyScreenLineChanges();
  294. if(delayedMultilineUpdate)
  295. {
  296. textArea.invalidateScreenLineRange(
  297. textArea.chunkCache
  298. .getScreenLineOfOffset(
  299. delayedUpdateStart,0),
  300. textArea.getVisibleLines());
  301. delayedMultilineUpdate = false;
  302. }
  303. else
  304. {
  305. textArea.invalidateLineRange(
  306. delayedUpdateStart,
  307. delayedUpdateEnd);
  308. }
  309. // update visible lines
  310. int visibleLines = textArea.getVisibleLines();
  311. if(visibleLines != 0)
  312. {
  313. textArea.chunkCache.getLineInfo(
  314. visibleLines - 1);
  315. }
  316. // force the fold levels to be
  317. // updated.
  318. // when painting the last line of
  319. // a buffer, Buffer.isFoldStart()
  320. // doesn't call getFoldLevel(),
  321. // hence the foldLevelChanged()
  322. // event might not be sent for the
  323. // previous line.
  324. buffer.getFoldLevel(delayedUpdateEnd);
  325. } //}}}
  326. //{{{ delayUpdate() method
  327. private void delayUpdate(int startLine, int endLine)
  328. {
  329. textArea.chunkCache.invalidateChunksFromPhys(startLine);
  330. textArea.repaintMgr.setFastScroll(false);
  331. if(!delayedUpdate)
  332. {
  333. delayedUpdateStart = startLine;
  334. delayedUpdateEnd = endLine;
  335. delayedUpdate = true;
  336. }
  337. else
  338. {
  339. delayedUpdateStart = Math.min(
  340. delayedUpdateStart,
  341. startLine);
  342. delayedUpdateEnd = Math.max(
  343. delayedUpdateEnd,
  344. endLine);
  345. }
  346. } //}}}
  347. }