PageRenderTime 68ms CodeModel.GetById 42ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/branches/jedit43_nostrings/org/gjt/sp/jedit/textarea/RangeMap.java

#
Java | 484 lines | 348 code | 42 blank | 94 comment | 102 complexity | 9546c07c1982497242f1c1200ae9a0ce 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. * RangeMap.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 org.gjt.sp.jedit.Debug;
  24. import org.gjt.sp.util.Log;
  25. /**
  26. * The fold visibility map.
  27. *
  28. * All lines from fvm[2*n] to fvm[2*n+1]-1 inclusive are visible.
  29. * All lines from position fvm[2*n+1] to fvm[2*n+2]-1 inclusive are
  30. * invisible.
  31. *
  32. * Examples:
  33. * ---------
  34. * All lines visible: { 0, buffer.getLineCount() }
  35. * Narrow from a to b: { a, b + 1 }
  36. * Collapsed fold from a to b: { 0, a + 1, b, buffer.getLineCount() }
  37. *
  38. * Note: length is always even.
  39. */
  40. class RangeMap
  41. {
  42. //{{{ RangeMap constructor
  43. RangeMap()
  44. {
  45. fvm = new int[2];
  46. lastfvmget = -1;
  47. } //}}}
  48. //{{{ RangeMap constructor
  49. RangeMap(RangeMap copy)
  50. {
  51. this.fvm = (int[])copy.fvm.clone();
  52. this.fvmcount = copy.fvmcount;
  53. } //}}}
  54. //{{{ reset() method
  55. void reset(int lines)
  56. {
  57. lastfvmget = -1;
  58. fvmcount = 2;
  59. fvm[0] = 0;
  60. fvm[1] = lines;
  61. } //}}}
  62. //{{{ first() method
  63. int first()
  64. {
  65. return fvm[0];
  66. } //}}}
  67. //{{{ last() method
  68. int last()
  69. {
  70. return fvm[fvmcount - 1] - 1;
  71. } //}}}
  72. //{{{ lookup() method
  73. int lookup(int index)
  74. {
  75. return fvm[index];
  76. } //}}}
  77. //{{{ search() method
  78. /**
  79. * Returns the fold visibility map index for the given line.
  80. */
  81. int search(int line)
  82. {
  83. if(line < fvm[0])
  84. return -1;
  85. if(line >= fvm[fvmcount - 1])
  86. return fvmcount - 1;
  87. if(lastfvmget != -1)
  88. {
  89. if(line >= fvm[lastfvmget])
  90. {
  91. if(lastfvmget == fvmcount - 1
  92. || line < fvm[lastfvmget + 1])
  93. {
  94. return lastfvmget;
  95. }
  96. }
  97. }
  98. int start = 0;
  99. int end = fvmcount - 1;
  100. loop: for(;;)
  101. {
  102. switch(end - start)
  103. {
  104. case 0:
  105. lastfvmget = start;
  106. break loop;
  107. case 1:
  108. int value = fvm[end];
  109. if(value <= line)
  110. lastfvmget = end;
  111. else
  112. lastfvmget = start;
  113. break loop;
  114. default:
  115. int pivot = (end + start) / 2;
  116. value = fvm[pivot];
  117. if(value == line)
  118. {
  119. lastfvmget = pivot;
  120. break loop;
  121. }
  122. else if(value < line)
  123. start = pivot;
  124. else
  125. end = pivot - 1;
  126. break;
  127. }
  128. }
  129. return lastfvmget;
  130. } //}}}
  131. //{{{ put() method
  132. /**
  133. * Replaces from <code>start</code> to <code>end-1</code> inclusive with
  134. * <code>put</code>. Update <code>fvmcount</code>.
  135. */
  136. void put(int start, int end, int[] put)
  137. {
  138. if(Debug.FOLD_VIS_DEBUG)
  139. {
  140. StringBuffer buf = new StringBuffer("{");
  141. if(put != null)
  142. {
  143. for(int i = 0; i < put.length; i++)
  144. {
  145. if(i != 0)
  146. buf.append(',');
  147. buf.append(put[i]);
  148. }
  149. }
  150. buf.append("}");
  151. Log.log(Log.DEBUG,this,"fvmput(" + start + ","
  152. + end + "," + buf + ")");
  153. }
  154. int putl = (put == null ? 0 : put.length);
  155. int delta = putl - (end - start);
  156. if(fvmcount + delta > fvm.length)
  157. {
  158. int[] newfvm = new int[fvm.length * 2 + 1];
  159. System.arraycopy(fvm,0,newfvm,0,fvmcount);
  160. fvm = newfvm;
  161. }
  162. if(delta != 0)
  163. {
  164. System.arraycopy(fvm,end,fvm,start + putl,
  165. fvmcount - end);
  166. }
  167. if(putl != 0)
  168. {
  169. System.arraycopy(put,0,fvm,start,put.length);
  170. }
  171. fvmcount += delta;
  172. dump();
  173. if(fvmcount == 0)
  174. throw new InternalError();
  175. } //}}}
  176. //{{{ put2() method
  177. /**
  178. * Merge previous and next entry if necessary.
  179. */
  180. void put2(int starti, int endi, int start, int end)
  181. {
  182. if(Debug.FOLD_VIS_DEBUG)
  183. {
  184. Log.log(Log.DEBUG,this,"*fvmput2(" + starti + ","
  185. + endi + "," + start + "," + end + ")");
  186. }
  187. if(starti != -1 && fvm[starti] == start)
  188. {
  189. if(endi <= fvmcount - 2 && fvm[endi + 1]
  190. == end + 1)
  191. {
  192. put(starti,endi + 2,null);
  193. }
  194. else
  195. {
  196. put(starti,endi + 1,
  197. new int[] { end + 1 });
  198. }
  199. }
  200. else
  201. {
  202. if(endi != fvmcount - 1 && fvm[endi + 1]
  203. == end + 1)
  204. {
  205. put(starti + 1,endi + 2,
  206. new int[] { start });
  207. }
  208. else
  209. {
  210. put(starti + 1,endi + 1,
  211. new int[] { start,
  212. end + 1 });
  213. }
  214. }
  215. } //}}}
  216. //{{{ next() method
  217. int next(int line)
  218. {
  219. int index = search(line);
  220. /* in collapsed range */
  221. if(index % 2 != 0)
  222. {
  223. /* beyond last visible line */
  224. if(fvmcount == index + 1)
  225. return - 1;
  226. /* start of next expanded range */
  227. else
  228. return fvm[index + 1];
  229. }
  230. /* last in expanded range */
  231. else if(line == fvm[index + 1] - 1)
  232. {
  233. /* equal to last visible line */
  234. if(fvmcount == index + 2)
  235. return -1;
  236. /* start of next expanded range */
  237. else
  238. return fvm[index + 2];
  239. }
  240. /* next in expanded range */
  241. else
  242. return line + 1;
  243. } //}}}
  244. //{{{ prev() method
  245. int prev(int line)
  246. {
  247. int index = search(line);
  248. /* before first visible line */
  249. if(index == -1)
  250. return -1;
  251. /* in collapsed range */
  252. else if(index % 2 == 1)
  253. {
  254. /* end of prev expanded range */
  255. return fvm[index] - 1;
  256. }
  257. /* first in expanded range */
  258. else if(line == fvm[index])
  259. {
  260. /* equal to first visible line */
  261. if(index == 0)
  262. return -1;
  263. /* end of prev expanded range */
  264. else
  265. return fvm[index - 1] - 1;
  266. }
  267. /* prev in expanded range */
  268. else
  269. return line - 1;
  270. } //}}}
  271. //{{{ show() method
  272. void show(int start, int end)
  273. {
  274. int starti = search(start);
  275. int endi = search(end);
  276. if(starti % 2 == 0)
  277. {
  278. if(endi % 2 == 0)
  279. put(starti + 1,endi + 1,null);
  280. else
  281. {
  282. if(endi != fvmcount - 1
  283. && fvm[endi + 1] == end + 1)
  284. put(starti + 1,endi + 2,null);
  285. else
  286. {
  287. put(starti + 1,endi,null);
  288. fvm[starti + 1] = end + 1;
  289. }
  290. }
  291. }
  292. else
  293. {
  294. if(endi % 2 == 0)
  295. {
  296. if(starti != -1 && fvm[starti] == start)
  297. put(starti,endi + 1,null);
  298. else
  299. {
  300. put(starti + 1,endi,null);
  301. fvm[starti + 1] = start;
  302. }
  303. }
  304. else
  305. put2(starti,endi,start,end);
  306. }
  307. lastfvmget = -1;
  308. } //}}}
  309. //{{{ hide() method
  310. void hide(int start, int end)
  311. {
  312. int starti = search(start);
  313. int endi = search(end);
  314. if(starti % 2 == 0)
  315. {
  316. if(endi % 2 == 0)
  317. put2(starti,endi,start,end);
  318. else
  319. {
  320. if(start == fvm[0])
  321. put(starti,endi + 1,null);
  322. else
  323. {
  324. put(starti + 1,endi,null);
  325. fvm[starti + 1] = start;
  326. }
  327. }
  328. }
  329. else
  330. {
  331. if(endi % 2 == 0)
  332. {
  333. if(end + 1 == fvm[fvmcount - 1])
  334. put(starti + 1,endi + 2,null);
  335. else
  336. {
  337. put(starti + 1,endi,null);
  338. fvm[starti + 1] = end + 1;
  339. }
  340. }
  341. else
  342. put(starti + 1,endi + 1,null);
  343. }
  344. lastfvmget = -1;
  345. } //}}}
  346. //{{{ count() method
  347. int count()
  348. {
  349. return fvmcount;
  350. } //}}}
  351. //{{{ dump() method
  352. void dump()
  353. {
  354. if(Debug.FOLD_VIS_DEBUG)
  355. {
  356. StringBuffer buf = new StringBuffer("{");
  357. for(int i = 0; i < fvmcount; i++)
  358. {
  359. if(i != 0)
  360. buf.append(',');
  361. buf.append(fvm[i]);
  362. }
  363. buf.append("}");
  364. Log.log(Log.DEBUG,this,"fvm = " + buf);
  365. }
  366. } //}}}
  367. //{{{ contentInserted() method
  368. void contentInserted(int startLine, int numLines)
  369. {
  370. if(numLines != 0)
  371. {
  372. int index = search(startLine);
  373. int start = index + 1;
  374. for(int i = start; i < fvmcount; i++)
  375. fvm[i] += numLines;
  376. lastfvmget = -1;
  377. dump();
  378. }
  379. } //}}}
  380. //{{{ preContentRemoved() method
  381. /**
  382. * @return If the anchors should be reset.
  383. */
  384. boolean preContentRemoved(int startLine, int numLines)
  385. {
  386. boolean returnValue = false;
  387. int endLine = startLine + numLines;
  388. /* update fold visibility map. */
  389. int starti = search(startLine);
  390. int endi = search(endLine);
  391. /* both have same visibility; just remove
  392. * anything in between. */
  393. if(Math.abs(starti % 2) == Math.abs(endi % 2))
  394. {
  395. if(endi - starti == fvmcount)
  396. {
  397. // we're removing from before
  398. // the first visible to after
  399. // the last visible
  400. returnValue = true;
  401. starti = 1;
  402. }
  403. else
  404. {
  405. put(starti + 1,endi + 1,null);
  406. starti++;
  407. }
  408. }
  409. /* collapse 2 */
  410. else if(starti != -1 && fvm[starti] == startLine)
  411. {
  412. if(endi - starti == fvmcount - 1)
  413. {
  414. // we're removing from
  415. // the first visible to after
  416. // the last visible
  417. returnValue = true;
  418. starti = 1;
  419. }
  420. else
  421. put(starti,endi + 1,null);
  422. }
  423. /* shift */
  424. else
  425. {
  426. put(starti + 1,endi,null);
  427. fvm[starti + 1] = startLine;
  428. starti += 2;
  429. }
  430. /* update */
  431. for(int i = starti; i < fvmcount; i++)
  432. fvm[i] -= numLines;
  433. lastfvmget = -1;
  434. dump();
  435. return returnValue;
  436. } //}}}
  437. //{{{ Private members
  438. private int[] fvm;
  439. private int fvmcount;
  440. private int lastfvmget;
  441. //}}}
  442. }