PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/textarea/RangeMap.java

#
Java | 486 lines | 350 code | 42 blank | 94 comment | 102 complexity | 4f305aa5ecd706ee7f932eb263a1dfe9 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 = 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. StringBuilder buf = new StringBuilder(50);
  141. buf.append("fvmput(").append(start).append(',');
  142. buf.append(end).append(',');
  143. buf.append('{');
  144. if(put != null)
  145. {
  146. for(int i = 0; i < put.length; i++)
  147. {
  148. if(i != 0)
  149. buf.append(',');
  150. buf.append(put[i]);
  151. }
  152. }
  153. buf.append("})");
  154. Log.log(Log.DEBUG,this,buf.toString());
  155. }
  156. int putl = put == null ? 0 : put.length;
  157. int delta = putl - (end - start);
  158. if(fvmcount + delta > fvm.length)
  159. {
  160. int[] newfvm = new int[(fvm.length << 1) + 1];
  161. System.arraycopy(fvm,0,newfvm,0,fvmcount);
  162. fvm = newfvm;
  163. }
  164. if(delta != 0)
  165. {
  166. System.arraycopy(fvm,end,fvm,start + putl,
  167. fvmcount - end);
  168. }
  169. if(putl != 0)
  170. {
  171. System.arraycopy(put,0,fvm,start,put.length);
  172. }
  173. fvmcount += delta;
  174. dump();
  175. if(fvmcount == 0)
  176. throw new InternalError();
  177. } //}}}
  178. //{{{ put2() method
  179. /**
  180. * Merge previous and next entry if necessary.
  181. */
  182. void put2(int starti, int endi, int start, int end)
  183. {
  184. if(Debug.FOLD_VIS_DEBUG)
  185. {
  186. Log.log(Log.DEBUG,this,"*fvmput2(" + starti + ","
  187. + endi + "," + start + "," + end + ")");
  188. }
  189. if(starti != -1 && fvm[starti] == start)
  190. {
  191. if(endi <= fvmcount - 2 && fvm[endi + 1]
  192. == end + 1)
  193. {
  194. put(starti,endi + 2,null);
  195. }
  196. else
  197. {
  198. put(starti,endi + 1,
  199. new int[] { end + 1 });
  200. }
  201. }
  202. else
  203. {
  204. if(endi != fvmcount - 1 && fvm[endi + 1]
  205. == end + 1)
  206. {
  207. put(starti + 1,endi + 2,
  208. new int[] { start });
  209. }
  210. else
  211. {
  212. put(starti + 1,endi + 1,
  213. new int[] { start,
  214. end + 1 });
  215. }
  216. }
  217. } //}}}
  218. //{{{ next() method
  219. int next(int line)
  220. {
  221. int index = search(line);
  222. /* in collapsed range */
  223. if(index % 2 != 0)
  224. {
  225. /* beyond last visible line */
  226. if(fvmcount == index + 1)
  227. return - 1;
  228. /* start of next expanded range */
  229. else
  230. return fvm[index + 1];
  231. }
  232. /* last in expanded range */
  233. else if(line == fvm[index + 1] - 1)
  234. {
  235. /* equal to last visible line */
  236. if(fvmcount == index + 2)
  237. return -1;
  238. /* start of next expanded range */
  239. else
  240. return fvm[index + 2];
  241. }
  242. /* next in expanded range */
  243. else
  244. return line + 1;
  245. } //}}}
  246. //{{{ prev() method
  247. int prev(int line)
  248. {
  249. int index = search(line);
  250. /* before first visible line */
  251. if(index == -1)
  252. return -1;
  253. /* in collapsed range */
  254. else if(index % 2 == 1)
  255. {
  256. /* end of prev expanded range */
  257. return fvm[index] - 1;
  258. }
  259. /* first in expanded range */
  260. else if(line == fvm[index])
  261. {
  262. /* equal to first visible line */
  263. if(index == 0)
  264. return -1;
  265. /* end of prev expanded range */
  266. else
  267. return fvm[index - 1] - 1;
  268. }
  269. /* prev in expanded range */
  270. else
  271. return line - 1;
  272. } //}}}
  273. //{{{ show() method
  274. void show(int start, int end)
  275. {
  276. int starti = search(start);
  277. int endi = search(end);
  278. if(starti % 2 == 0)
  279. {
  280. if(endi % 2 == 0)
  281. put(starti + 1,endi + 1,null);
  282. else
  283. {
  284. if(endi != fvmcount - 1
  285. && fvm[endi + 1] == end + 1)
  286. put(starti + 1,endi + 2,null);
  287. else
  288. {
  289. put(starti + 1,endi,null);
  290. fvm[starti + 1] = end + 1;
  291. }
  292. }
  293. }
  294. else
  295. {
  296. if(endi % 2 == 0)
  297. {
  298. if(starti != -1 && fvm[starti] == start)
  299. put(starti,endi + 1,null);
  300. else
  301. {
  302. put(starti + 1,endi,null);
  303. fvm[starti + 1] = start;
  304. }
  305. }
  306. else
  307. put2(starti,endi,start,end);
  308. }
  309. lastfvmget = -1;
  310. } //}}}
  311. //{{{ hide() method
  312. void hide(int start, int end)
  313. {
  314. int starti = search(start);
  315. int endi = search(end);
  316. if(starti % 2 == 0)
  317. {
  318. if(endi % 2 == 0)
  319. put2(starti,endi,start,end);
  320. else
  321. {
  322. if(start == fvm[0])
  323. put(starti,endi + 1,null);
  324. else
  325. {
  326. put(starti + 1,endi,null);
  327. fvm[starti + 1] = start;
  328. }
  329. }
  330. }
  331. else
  332. {
  333. if(endi % 2 == 0)
  334. {
  335. if(end + 1 == fvm[fvmcount - 1])
  336. put(starti + 1,endi + 2,null);
  337. else
  338. {
  339. put(starti + 1,endi,null);
  340. fvm[starti + 1] = end + 1;
  341. }
  342. }
  343. else
  344. put(starti + 1,endi + 1,null);
  345. }
  346. lastfvmget = -1;
  347. } //}}}
  348. //{{{ count() method
  349. int count()
  350. {
  351. return fvmcount;
  352. } //}}}
  353. //{{{ dump() method
  354. void dump()
  355. {
  356. if(Debug.FOLD_VIS_DEBUG)
  357. {
  358. StringBuilder buf = new StringBuilder("{");
  359. for(int i = 0; i < fvmcount; i++)
  360. {
  361. if(i != 0)
  362. buf.append(',');
  363. buf.append(fvm[i]);
  364. }
  365. buf.append('}');
  366. Log.log(Log.DEBUG,this,"fvm = " + buf);
  367. }
  368. } //}}}
  369. //{{{ contentInserted() method
  370. void contentInserted(int startLine, int numLines)
  371. {
  372. if(numLines != 0)
  373. {
  374. int index = search(startLine);
  375. int start = index + 1;
  376. for(int i = start; i < fvmcount; i++)
  377. fvm[i] += numLines;
  378. lastfvmget = -1;
  379. dump();
  380. }
  381. } //}}}
  382. //{{{ preContentRemoved() method
  383. /**
  384. * @return If the anchors should be reset.
  385. */
  386. boolean preContentRemoved(int startLine, int numLines)
  387. {
  388. boolean returnValue = false;
  389. int endLine = startLine + numLines;
  390. /* update fold visibility map. */
  391. int starti = search(startLine);
  392. int endi = search(endLine);
  393. /* both have same visibility; just remove
  394. * anything in between. */
  395. if(Math.abs(starti % 2) == Math.abs(endi % 2))
  396. {
  397. if(endi - starti == fvmcount)
  398. {
  399. // we're removing from before
  400. // the first visible to after
  401. // the last visible
  402. returnValue = true;
  403. starti = 1;
  404. }
  405. else
  406. {
  407. put(starti + 1,endi + 1,null);
  408. starti++;
  409. }
  410. }
  411. /* collapse 2 */
  412. else if(starti != -1 && fvm[starti] == startLine)
  413. {
  414. if(endi - starti == fvmcount - 1)
  415. {
  416. // we're removing from
  417. // the first visible to after
  418. // the last visible
  419. returnValue = true;
  420. starti = 1;
  421. }
  422. else
  423. put(starti,endi + 1,null);
  424. }
  425. /* shift */
  426. else
  427. {
  428. put(starti + 1,endi,null);
  429. fvm[starti + 1] = startLine;
  430. starti += 2;
  431. }
  432. /* update */
  433. for(int i = starti; i < fvmcount; i++)
  434. fvm[i] -= numLines;
  435. lastfvmget = -1;
  436. dump();
  437. return returnValue;
  438. } //}}}
  439. //{{{ Private members
  440. private int[] fvm;
  441. private int fvmcount;
  442. private int lastfvmget;
  443. //}}}
  444. }