/plugins/Vimage/trunk/vimage/VimageActions.java

# · Java · 380 lines · 280 code · 37 blank · 63 comment · 72 complexity · d34328d40bd70afa9ca157c23a56e77b MD5 · raw file

  1. /*
  2. Copyright (C) 2005 Ollie Rutherfurd <oliver@jedit.org>
  3. Copyright (C) 2009 Matthew Gilbert
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. */
  16. package vimage;
  17. import java.lang.Class;
  18. import java.lang.Math;
  19. import org.gjt.sp.jedit.jEdit;
  20. import org.gjt.sp.jedit.View;
  21. import org.gjt.sp.jedit.textarea.Selection;
  22. import org.gjt.sp.jedit.textarea.TextArea;
  23. import org.gjt.sp.jedit.textarea.JEditTextArea;
  24. import org.gjt.sp.jedit.Buffer;
  25. import org.gjt.sp.jedit.EditAction;
  26. import org.gjt.sp.util.Log;
  27. import org.gjt.sp.jedit.Registers;
  28. import org.gjt.sp.jedit.gui.InputHandler;
  29. import org.gjt.sp.jedit.TextUtilities;
  30. public class VimageActions
  31. {
  32. protected static int start_line;
  33. protected static void _(View view, String action)
  34. {
  35. EditAction ea = jEdit.getAction(action);
  36. if (ea == null)
  37. return;
  38. ea.invoke(view);
  39. }
  40. public static void goto_line_text_start(View view, TextArea text_area, boolean select)
  41. {
  42. int line_number = text_area.getCaretLine();
  43. String line_text = text_area.getLineText(line_number);
  44. int i = 0;
  45. while (java.lang.Character.isWhitespace(line_text.charAt(i)) && (i < line_text.length())) {
  46. ++i;
  47. }
  48. if (select) {
  49. int pos = text_area.getCaretPosition();
  50. text_area.setCaretPosition(text_area.getLineStartOffset(line_number) + i);
  51. text_area.resizeSelection(pos, text_area.getCaretPosition(), 0, false);
  52. } else {
  53. text_area.setCaretPosition(text_area.getLineStartOffset(line_number) + i);
  54. }
  55. }
  56. /**
  57. * Support for f, F, t, and T.
  58. */
  59. public static void find_char_on_line(View view, boolean forward,
  60. boolean select, int offset,
  61. String ch)
  62. {
  63. Buffer buffer = view.getBuffer();
  64. int caretLine = view.getTextArea().getCaretLine();
  65. int startOffset = view.getTextArea().getLineStartOffset(caretLine);
  66. int endOffset = view .getTextArea().getLineEndOffset(caretLine);
  67. int caret = view.getTextArea().getCaretPosition();
  68. int index = -1;
  69. String text = null;
  70. if(forward)
  71. {
  72. if(caret+1 >= buffer.getLength())
  73. {
  74. return;
  75. }
  76. int len = endOffset - (caret+1);
  77. if(endOffset >= buffer.getLength())
  78. len--;
  79. text = view.getTextArea().getText(caret+1,len);
  80. index = text.indexOf(ch);
  81. }
  82. else
  83. {
  84. text = view.getTextArea().getText(startOffset,caret-startOffset);
  85. index = text.lastIndexOf(ch);
  86. }
  87. if(index > -1)
  88. {
  89. if(forward)
  90. index = caret + index + 1;
  91. else
  92. index = startOffset + index;
  93. if(offset != 0)
  94. index += offset;
  95. if(select)
  96. {
  97. // extend selection through match char
  98. if(forward)
  99. index++;
  100. int mn = Math.min(caret, index);
  101. int mx = Math.max(caret, index);
  102. Selection s = new Selection.Range(mn,mx);
  103. if(view.getTextArea().isMultipleSelectionEnabled())
  104. view.getTextArea().addToSelection(s);
  105. else
  106. // XXX don't want to add if disjointed
  107. view.getTextArea().addToSelection(s);
  108. }
  109. view.getTextArea().moveCaretPosition(index);
  110. }
  111. }
  112. public static void goto_line(View view, TextArea text_area, int count, boolean select)
  113. {
  114. if (count == 0) {
  115. if (select)
  116. _(view, "select-document-end");
  117. else
  118. _(view, "document-end");
  119. return;
  120. }
  121. // getLineStartOffset takes 0 based line numbers, so subtract 1 from
  122. // count.
  123. int line = count - 1;
  124. if (line >= text_area.getLineCount())
  125. return;
  126. text_area.setCaretPosition(text_area.getLineStartOffset(line));
  127. if (select) {
  128. int pos = text_area.getCaretPosition();
  129. Selection sel = text_area.getSelectionAtOffset(pos);
  130. if (sel == null)
  131. text_area.resizeSelection(pos, text_area.getCaretPosition(), 0, false);
  132. else
  133. text_area.resizeSelection(sel.getStart(), text_area.getCaretPosition(), 0, false);
  134. }
  135. }
  136. public static void cut(View view, VimageInputHandler mode, TextArea text_area, char reg_name)
  137. {
  138. Selection ds = view.getTextArea().getSelectionAtOffset(view.getTextArea().getCaretPosition());
  139. if (ds == null) {
  140. return;
  141. }
  142. if (mode.isIterating()) {
  143. Registers.append(text_area, reg_name, "", true);
  144. } else {
  145. Registers.cut(text_area, reg_name);
  146. }
  147. }
  148. public static void copy(View view, VimageInputHandler mode, TextArea text_area, char reg_name)
  149. {
  150. Registers.copy(text_area, reg_name);
  151. }
  152. public static void paste(View view, TextArea text_area, char reg_name, boolean after_caret)
  153. {
  154. int pos = text_area.getCaretPosition();
  155. Selection sel = text_area.getSelectionAtOffset(pos);
  156. if (after_caret && (sel == null)) {
  157. int line_end = text_area.getLineEndOffset(text_area.getCaretLine());
  158. pos += 1;
  159. // Don't let after_caret move past the newline at the end of the
  160. // line, so take min of pos and (line_end - 1).
  161. // Ordering is important here. (line_end - 1) may be -1, so make sure the max
  162. // call comes second.
  163. pos = java.lang.Math.min(line_end - 1, pos);
  164. pos = java.lang.Math.max(0, pos);
  165. }
  166. if (sel != null) {
  167. Registers.paste(text_area, reg_name);
  168. return;
  169. }
  170. // Make a guess that anything that ends with a newline is line-wise.
  171. // eek.
  172. Registers.Register reg = Registers.getRegister(reg_name);
  173. if (reg == null)
  174. return;
  175. Buffer b = view.getBuffer();
  176. String reg_text = reg.toString();
  177. boolean linewise = reg_text.endsWith("\n");
  178. if (sel == null) {
  179. if (linewise) {
  180. if (after_caret) {
  181. pos = text_area.getLineEndOffset(text_area.getCaretLine());
  182. } else {
  183. pos = text_area.getLineStartOffset(text_area.getCaretLine());
  184. }
  185. }
  186. }
  187. pos = java.lang.Math.min(text_area.getBufferLength(), pos);
  188. pos = java.lang.Math.max(0, pos);
  189. b.insert(pos, reg_text);
  190. if (!linewise) {
  191. if (after_caret) {
  192. text_area.setCaretPosition(pos + reg_text.length());
  193. } else {
  194. text_area.setCaretPosition(pos);
  195. }
  196. }
  197. }
  198. public static void swap_case(TextArea text_area)
  199. {
  200. text_area.getBuffer().beginCompoundEdit();
  201. try {
  202. Selection[] selections = text_area.getSelection();
  203. if (selections.length == 0) {
  204. int pos = text_area.getCaretPosition();
  205. Selection.Range sel = new Selection.Range(pos, pos + 1);
  206. text_area.setSelection(sel);
  207. selections = text_area.getSelection();
  208. }
  209. for (int i = 0; i < selections.length; ++i) {
  210. Selection sel = selections[i];
  211. int start = sel.getStart();
  212. int end = sel.getEnd();
  213. String text = text_area.getText(start, end-start);
  214. StringBuffer new_text = new StringBuffer();
  215. for (int j = 0; j < text.length(); ++j) {
  216. char c = text.charAt(j);
  217. if (java.lang.Character.isUpperCase(c)) {
  218. c = java.lang.Character.toLowerCase(c);
  219. } else {
  220. c = java.lang.Character.toUpperCase(c);
  221. }
  222. new_text.append(c);
  223. }
  224. text_area.getBuffer().remove(start, end - start);
  225. text_area.getBuffer().insert(start, new_text.toString());
  226. }
  227. } catch (java.lang.Exception ex) {
  228. Log.log(Log.DEBUG, ex, ex);
  229. } finally {
  230. text_area.getBuffer().endCompoundEdit();
  231. }
  232. }
  233. public static void select_line(TextArea text_area)
  234. {
  235. start_line = text_area.getCaretLine();
  236. select_line(text_area, 0);
  237. }
  238. public static void select_line(TextArea text_area, int line_offset)
  239. {
  240. if (text_area.getBufferLength() == 0)
  241. return;
  242. int pos = text_area.getCaretPosition();
  243. int caret_line = text_area.getCaretLine();
  244. int max_line = Math.max(0, text_area.getLineCount() - 1);
  245. Selection orig = text_area.getSelectionAtOffset(pos);
  246. // If caret is at the end of the document, create at least a 1 character
  247. // selection. This fixes the case where the last line in a document is a
  248. // blank line. Without (pos - 1) then no selection will be created for
  249. // that line (jEdit doesn't do 0 width selections). We want to select
  250. // the newline of the previous line anyway.
  251. if ((orig == null) && (pos == text_area.getBufferLength())) {
  252. orig = new Selection.Range(pos - 1, pos);
  253. } else if (orig == null) {
  254. // No selection, just select the current line
  255. int line = text_area.getCaretLine();
  256. int start = text_area.getLineStartOffset(line);
  257. int end = Math.min(text_area.getLineEndOffset(line), text_area.getBufferLength());
  258. if (end == text_area.getBufferLength()) {
  259. // Add in the previous line like below.
  260. start = Math.max(0, start - 1);
  261. }
  262. Selection sel = new Selection.Range(start, end);
  263. text_area.setSelection(sel);
  264. return;
  265. }
  266. int sel_line_start = text_area.getLineOfOffset(orig.getStart());
  267. int sel_line_end = text_area.getLineOfOffset(orig.getEnd());
  268. // The following are fixups to how lines are selected. jEdit includes
  269. // If caret is at the end, then we've selected one character back, so
  270. // increment sel_line_start.
  271. if (orig.getEnd() == text_area.getBufferLength()) {
  272. sel_line_start = text_area.getLineOfOffset(Math.min(text_area.getBufferLength(),
  273. orig.getStart() + 1));
  274. if (text_area.getLineText(max_line).equals("") &&
  275. (sel_line_start < (max_line - 1)) )
  276. {
  277. sel_line_end = text_area.getLineOfOffset(Math.max(0, orig.getEnd() - 1));
  278. }
  279. }
  280. // Subtract 1 because line selections always include the newline which
  281. // extends to the next line, unless already at the end.
  282. if (orig.getEnd() != text_area.getBufferLength()) {
  283. sel_line_end = text_area.getLineOfOffset(Math.max(0, orig.getEnd() - 1));
  284. }
  285. if (sel_line_end > caret_line) {
  286. // Adjust the end line since we've moved past the caret
  287. sel_line_end += line_offset;
  288. sel_line_end = Math.min(sel_line_end, max_line);
  289. text_area.scrollTo(sel_line_end, 0, true);
  290. } else {
  291. sel_line_start += line_offset;
  292. // If at the last line, then sel_line_end == caret_line so we end up
  293. // here, we still shouldn't try to go past the last line.
  294. sel_line_start = Math.min(Math.max(sel_line_start, 0), max_line);
  295. text_area.scrollTo(sel_line_start, 0, true);
  296. }
  297. // Flip-flop start and end if line_offset has caused start and end to
  298. // flip-flop.
  299. int start = Math.min(sel_line_start, sel_line_end);
  300. int end = Math.max(sel_line_start, sel_line_end);
  301. int caret_start = text_area.getLineStartOffset(start);
  302. int caret_end = text_area.getLineEndOffset(end);
  303. caret_end = Math.min(caret_end, text_area.getBufferLength());
  304. // This is causing not to be able to re-select only the last line.
  305. // FIXME: some check.
  306. if (caret_end == text_area.getBufferLength()) {
  307. // Want to delete the last line, so delete the previous new-line
  308. // if it exists.
  309. caret_start -= 1;
  310. }
  311. caret_start = Math.max(0, caret_start);
  312. Selection sel = new Selection.Range(caret_start, caret_end);
  313. text_area.setSelection(sel);
  314. }
  315. /**
  316. * Scroll the text area relative to the caret position,
  317. * depending on the value of <code>position</code>.
  318. * @param textArea
  319. * @param select whether or not to select text
  320. * @param count new caret line, if > 0
  321. * @param position -1 = caret at top, 0 = center, 1 = bottom
  322. */
  323. public static void scroll(JEditTextArea textArea, boolean select, int position)
  324. {
  325. int firstLine = textArea.getFirstLine();
  326. int visibleLines = textArea.getVisibleLines();
  327. int caretLine = textArea.getScreenLineOfOffset(textArea.getCaretPosition());
  328. int offset = 0;
  329. if(position < 0)
  330. offset = (firstLine + caretLine) - textArea.getElectricScroll();
  331. else if(position > 0)
  332. // not sure why -2 is needed, but without it, the
  333. // caret line ends up in the electric scroll area
  334. offset = firstLine - (((visibleLines - caretLine) - textArea.getElectricScroll())-2);
  335. else
  336. offset = (firstLine + caretLine - (visibleLines / 2));
  337. textArea.setFirstLine(offset);
  338. }
  339. }