PageRenderTime 29ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/textarea/Selection.java

#
Java | 508 lines | 330 code | 63 blank | 115 comment | 58 complexity | 0d1f8688193c9316243538ce6564abd6 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. * Selection.java - Selected text
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2001, 2002 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. //{{{ Imports
  24. import javax.swing.text.Segment;
  25. import java.util.ArrayList;
  26. import org.gjt.sp.jedit.Buffer;
  27. import org.gjt.sp.jedit.MiscUtilities;
  28. //}}}
  29. /**
  30. * An interface representing a portion of the current selection.
  31. * @author Slava Pestov
  32. * @version $Id: Selection.java 4249 2002-06-14 06:07:18Z spestov $
  33. * @since jEdit 3.2pre1
  34. */
  35. public abstract class Selection implements Cloneable
  36. {
  37. //{{{ getStart() method
  38. /**
  39. * Returns the start offset of this selection.
  40. */
  41. public int getStart()
  42. {
  43. return start;
  44. } //}}}
  45. //{{{ getEnd() method
  46. /**
  47. * Returns the end offset of this selection.
  48. */
  49. public int getEnd()
  50. {
  51. return end;
  52. } //}}}
  53. //{{{ getStart() method
  54. /**
  55. * Returns the start offset of this selection on the specified
  56. * line.
  57. * @param buffer The buffer
  58. * @param line The line number
  59. * @since jEdit 4.1pre1
  60. */
  61. public abstract int getStart(Buffer buffer, int line);
  62. //}}}
  63. //{{{ getEnd() method
  64. /**
  65. * Returns the end offset of this selection on the specified
  66. * line.
  67. * @param buffer The buffer
  68. * @param line The line number
  69. * @since jEdit 4.1pre1
  70. */
  71. public abstract int getEnd(Buffer buffer, int line);
  72. //}}}
  73. //{{{ getStartLine() method
  74. /**
  75. * Returns the starting line number of this selection.
  76. */
  77. public int getStartLine()
  78. {
  79. return startLine;
  80. } //}}}
  81. //{{{ getEndLine() method
  82. /**
  83. * Returns the ending line number of this selection.
  84. */
  85. public int getEndLine()
  86. {
  87. return endLine;
  88. } //}}}
  89. //{{{ overlaps() method
  90. /**
  91. * Returns if this selection and the specified selection overlap.
  92. * @param s The other selection
  93. * @since jEdit 4.1pre1
  94. */
  95. public boolean overlaps(Selection s)
  96. {
  97. if((start >= s.start && start <= s.end)
  98. || (end >= s.start && end <= s.end))
  99. return true;
  100. else
  101. return false;
  102. } //}}}
  103. //{{{ toString() method
  104. public String toString()
  105. {
  106. return getClass().getName() + "[start=" + start
  107. + ",end=" + end + ",startLine=" + startLine
  108. + ",endLine=" + endLine + "]";
  109. } //}}}
  110. //{{{ clone() method
  111. public Object clone()
  112. {
  113. try
  114. {
  115. return super.clone();
  116. }
  117. catch(CloneNotSupportedException e)
  118. {
  119. throw new InternalError("I just drank a whole "
  120. + "bottle of cough syrup and I feel "
  121. + "funny!");
  122. }
  123. } //}}}
  124. //{{{ Package-private members
  125. int start, end;
  126. int startLine, endLine;
  127. //{{{ Selection constructor
  128. Selection()
  129. {
  130. } //}}}
  131. //{{{ Range constructor
  132. Selection(Selection sel)
  133. {
  134. this.start = sel.start;
  135. this.end = sel.end;
  136. } //}}}
  137. //{{{ Selection constructor
  138. Selection(int start, int end)
  139. {
  140. this.start = start;
  141. this.end = end;
  142. } //}}}
  143. // should the next two be public, maybe?
  144. abstract void getText(Buffer buffer, StringBuffer buf);
  145. abstract int setText(Buffer buffer, String text);
  146. //}}}
  147. //{{{ Range class
  148. /**
  149. * An ordinary range selection.
  150. * @since jEdit 3.2pre1
  151. */
  152. public static class Range extends Selection
  153. {
  154. //{{{ Range constructor
  155. public Range()
  156. {
  157. } //}}}
  158. //{{{ Range constructor
  159. public Range(Selection sel)
  160. {
  161. super(sel);
  162. } //}}}
  163. //{{{ Range constructor
  164. public Range(int start, int end)
  165. {
  166. super(start,end);
  167. } //}}}
  168. //{{{ getStart() method
  169. public int getStart(Buffer buffer, int line)
  170. {
  171. if(line == startLine)
  172. return start;
  173. else
  174. return buffer.getLineStartOffset(line);
  175. } //}}}
  176. //{{{ getEnd() method
  177. public int getEnd(Buffer buffer, int line)
  178. {
  179. if(line == endLine)
  180. return end;
  181. else
  182. return buffer.getLineEndOffset(line) - 1;
  183. } //}}}
  184. //{{{ getText() method
  185. void getText(Buffer buffer, StringBuffer buf)
  186. {
  187. buf.append(buffer.getText(start,end - start));
  188. } //}}}
  189. //{{{ setText() method
  190. int setText(Buffer buffer, String text)
  191. {
  192. buffer.remove(start,end - start);
  193. if(text != null && text.length() != 0)
  194. {
  195. buffer.insert(start,text);
  196. return start + text.length();
  197. }
  198. else
  199. return start;
  200. } //}}}
  201. } //}}}
  202. //{{{ Rect class
  203. /**
  204. * A rectangular selection.
  205. * @since jEdit 3.2pre1
  206. */
  207. // this class is not very fast...
  208. public static class Rect extends Selection
  209. {
  210. //{{{ Rect constructor
  211. public Rect()
  212. {
  213. super();
  214. } //}}}
  215. //{{{ Rect constructor
  216. public Rect(Selection sel)
  217. {
  218. super(sel);
  219. } //}}}
  220. //{{{ Rect constructor
  221. public Rect(int start, int end)
  222. {
  223. super(start,end);
  224. } //}}}
  225. //{{{ Rect constructor
  226. public Rect(int startLine, int start, int endLine, int end)
  227. {
  228. this.startLine = startLine;
  229. this.start = start;
  230. this.endLine = endLine;
  231. this.end = end;
  232. } //}}}
  233. //{{{ Rect constructor
  234. public Rect(Buffer buffer, int startLine, int startColumn,
  235. int endLine, int endColumn)
  236. {
  237. this.startLine = startLine;
  238. this.endLine = endLine;
  239. int[] width = new int[1];
  240. int startOffset = buffer.getOffsetOfVirtualColumn(startLine,
  241. startColumn,width);
  242. if(startOffset == -1)
  243. {
  244. extraStartVirt = startColumn - width[0];
  245. startOffset = buffer.getLineEndOffset(startLine) - 1;
  246. }
  247. else
  248. startOffset += buffer.getLineStartOffset(startLine);
  249. int endOffset = buffer.getOffsetOfVirtualColumn(endLine,
  250. endColumn,width);
  251. if(endOffset == -1)
  252. {
  253. extraEndVirt = endColumn - width[0];
  254. endOffset = buffer.getLineEndOffset(endLine) - 1;
  255. }
  256. else
  257. endOffset += buffer.getLineStartOffset(endLine);
  258. } //}}}
  259. //{{{ getStartColumn() method
  260. public int getStartColumn(Buffer buffer)
  261. {
  262. int virtColStart = buffer.getVirtualWidth(startLine,
  263. start - buffer.getLineStartOffset(startLine)) + extraStartVirt;
  264. int virtColEnd = buffer.getVirtualWidth(endLine,
  265. end - buffer.getLineStartOffset(endLine)) + extraEndVirt;
  266. return Math.min(virtColStart,virtColEnd);
  267. } //}}}
  268. //{{{ getEndColumn() method
  269. public int getEndColumn(Buffer buffer)
  270. {
  271. int virtColStart = buffer.getVirtualWidth(startLine,
  272. start - buffer.getLineStartOffset(startLine)) + extraStartVirt;
  273. int virtColEnd = buffer.getVirtualWidth(endLine,
  274. end - buffer.getLineStartOffset(endLine)) + extraEndVirt;
  275. return Math.max(virtColStart,virtColEnd);
  276. } //}}}
  277. //{{{ getStart() method
  278. public int getStart(Buffer buffer, int line)
  279. {
  280. return getColumnOnOtherLine(buffer,startLine,line,
  281. getStartColumn(buffer));
  282. } //}}}
  283. //{{{ getEnd() method
  284. public int getEnd(Buffer buffer, int line)
  285. {
  286. return getColumnOnOtherLine(buffer,startLine,line,
  287. getEndColumn(buffer));
  288. } //}}}
  289. //{{{ Package-private members
  290. int extraStartVirt;
  291. int extraEndVirt;
  292. //{{{ getText() method
  293. void getText(Buffer buffer, StringBuffer buf)
  294. {
  295. int start = getStartColumn(buffer);
  296. int end = getEndColumn(buffer);
  297. for(int i = startLine; i <= endLine; i++)
  298. {
  299. int lineStart = buffer.getLineStartOffset(i);
  300. int lineLen = buffer.getLineLength(i);
  301. int rectStart = buffer.getOffsetOfVirtualColumn(
  302. i,start,null);
  303. if(rectStart == -1)
  304. rectStart = lineLen;
  305. int rectEnd = buffer.getOffsetOfVirtualColumn(
  306. i,end,null);
  307. if(rectEnd == -1)
  308. rectEnd = lineLen;
  309. buf.append(buffer.getText(lineStart + rectStart,
  310. rectEnd - rectStart));
  311. if(i != endLine)
  312. buf.append('\n');
  313. }
  314. } //}}}
  315. //{{{ setText() method
  316. int setText(Buffer buffer, String text)
  317. {
  318. int startColumn = getStartColumn(buffer);
  319. int endColumn = getEndColumn(buffer);
  320. int[] total = new int[1];
  321. int tabSize = buffer.getTabSize();
  322. int maxWidth = 0;
  323. int totalLines = 0;
  324. ArrayList lines = new ArrayList();
  325. //{{{ Split the text into lines
  326. if(text != null)
  327. {
  328. int lastNewline = 0;
  329. int currentWidth = startColumn;
  330. for(int i = 0; i < text.length(); i++)
  331. {
  332. char ch = text.charAt(i);
  333. if(ch == '\n')
  334. {
  335. totalLines++;
  336. lines.add(text.substring(
  337. lastNewline,i));
  338. lastNewline = i + 1;
  339. maxWidth = Math.max(maxWidth,currentWidth);
  340. lines.add(new Integer(currentWidth));
  341. currentWidth = startColumn;
  342. }
  343. else if(ch == '\t')
  344. currentWidth += tabSize - (currentWidth % tabSize);
  345. else
  346. currentWidth++;
  347. }
  348. if(lastNewline != text.length())
  349. {
  350. totalLines++;
  351. lines.add(text.substring(lastNewline));
  352. lines.add(new Integer(currentWidth));
  353. maxWidth = Math.max(maxWidth,currentWidth);
  354. }
  355. } //}}}
  356. //{{{ Insert the lines into the buffer
  357. int endOffset = 0;
  358. int lastLine = Math.max(startLine + totalLines - 1,endLine);
  359. for(int i = startLine; i <= lastLine; i++)
  360. {
  361. if(i == buffer.getLineCount())
  362. buffer.insert(buffer.getLength(),"\n");
  363. int lineStart = buffer.getLineStartOffset(i);
  364. int lineLen = buffer.getLineLength(i);
  365. int rectStart = buffer.getOffsetOfVirtualColumn(
  366. i,startColumn,total);
  367. int startWhitespace;
  368. if(rectStart == -1)
  369. {
  370. startWhitespace = (startColumn - total[0]);
  371. rectStart = lineLen;
  372. }
  373. else
  374. startWhitespace = 0;
  375. int rectEnd = buffer.getOffsetOfVirtualColumn(
  376. i,endColumn,null);
  377. if(rectEnd == -1)
  378. rectEnd = lineLen;
  379. buffer.remove(rectStart + lineStart,rectEnd - rectStart);
  380. int index = 2 * (i - startLine);
  381. int endWhitespace;
  382. if(rectEnd == lineLen)
  383. endWhitespace = 0;
  384. else if(i - startLine >= totalLines)
  385. endWhitespace = maxWidth - startColumn;
  386. else
  387. {
  388. endWhitespace = maxWidth
  389. - ((Integer)lines.get(index+1))
  390. .intValue();
  391. }
  392. String str = (i - startLine >= totalLines
  393. ? "" : (String)lines.get(index));
  394. if(startWhitespace != 0)
  395. {
  396. buffer.insert(rectStart + lineStart,
  397. MiscUtilities.createWhiteSpace(startWhitespace,0));
  398. }
  399. buffer.insert(rectStart + lineStart + startWhitespace,str);
  400. if(endWhitespace != 0)
  401. {
  402. buffer.insert(rectStart + lineStart
  403. + startWhitespace + str.length(),
  404. MiscUtilities.createWhiteSpace(endWhitespace,0));
  405. }
  406. endOffset = rectStart + lineStart
  407. + startWhitespace
  408. + endWhitespace
  409. + str.length();
  410. } //}}}
  411. //{{{ Move the caret down a line
  412. if(text == null || text.length() == 0)
  413. return end;
  414. if(lastLine != buffer.getLineCount() - 1)
  415. {
  416. int offset = buffer.getOffsetOfVirtualColumn(
  417. lastLine + 1,startColumn,null);
  418. if(offset == -1)
  419. {
  420. buffer.insertAtColumn(lastLine + 1,startColumn,"");
  421. return buffer.getLineEndOffset(lastLine + 1) - 1;
  422. }
  423. else
  424. return buffer.getLineStartOffset(lastLine + 1) + offset;
  425. }
  426. else
  427. return endOffset;
  428. //}}}
  429. } //}}}
  430. //}}}
  431. //{{{ Private members
  432. //{{{ getColumnOnOtherLine() method
  433. private int getColumnOnOtherLine(Buffer buffer, int line1,
  434. int line2, int col)
  435. {
  436. int returnValue = buffer.getOffsetOfVirtualColumn(
  437. line2,col,null);
  438. if(returnValue == -1)
  439. return buffer.getLineEndOffset(line2) - 1;
  440. else
  441. return buffer.getLineStartOffset(line2) + returnValue;
  442. } //}}}
  443. //}}}
  444. } //}}}
  445. }