1
2
3
4
5
6
7
8
9
10 package org.syntax.jedit;
11
12 import java.awt.Component;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.KeyAdapter;
16 import java.awt.event.KeyEvent;
17 import java.util.Enumeration;
18 import java.util.EventObject;
19 import java.util.Hashtable;
20
21 import javax.swing.AbstractAction;
22 import javax.swing.Action;
23 import javax.swing.JPopupMenu;
24 import javax.swing.KeyStroke;
25 import javax.swing.text.BadLocationException;
26
27 /***
28 * An input handler converts the user's key strokes into concrete actions.
29 * It also takes care of macro recording and action repetition.<p>
30 *
31 * This class provides all the necessary support code for an input
32 * handler, but doesn't actually do any key binding logic. It is up
33 * to the implementations of this class to do so.
34 *
35 * @author Slava Pestov
36 * @version $Id$
37 * @see org.syntax.jedit.DefaultInputHandler
38 *
39 * 08/12/2002 Clipboard actions (Oliver Henning)
40 */
41 public abstract class InputHandler extends KeyAdapter
42 {
43 /***
44 * If this client property is set to Boolean.TRUE on the text area,
45 * the home/end keys will support 'smart' BRIEF-like behaviour
46 * (one press = start/end of line, two presses = start/end of
47 * viewscreen, three presses = start/end of document). By default,
48 * this property is not set.
49 */
50 public static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd";
51
52 public static final ActionListener BACKSPACE = new backspace();
53 public static final ActionListener BACKSPACE_WORD = new backspace_word();
54 public static final ActionListener DELETE = new delete();
55 public static final ActionListener DELETE_WORD = new delete_word();
56 public static final ActionListener END = new end(false);
57 public static final ActionListener DOCUMENT_END = new document_end(false);
58 public static final ActionListener SELECT_ALL = new select_all();
59 public static final ActionListener SELECT_END = new end(true);
60 public static final ActionListener SELECT_DOC_END = new document_end(true);
61 public static final ActionListener INSERT_BREAK = new insert_break();
62 public static final ActionListener INSERT_TAB = new insert_tab();
63 public static final ActionListener HOME = new home(false);
64 public static final ActionListener DOCUMENT_HOME = new document_home(false);
65 public static final ActionListener SELECT_HOME = new home(true);
66 public static final ActionListener SELECT_DOC_HOME = new document_home(true);
67 public static final ActionListener NEXT_CHAR = new next_char(false);
68 public static final ActionListener NEXT_LINE = new next_line(false);
69 public static final ActionListener NEXT_PAGE = new next_page(false);
70 public static final ActionListener NEXT_WORD = new next_word(false);
71 public static final ActionListener SELECT_NEXT_CHAR = new next_char(true);
72 public static final ActionListener SELECT_NEXT_LINE = new next_line(true);
73 public static final ActionListener SELECT_NEXT_PAGE = new next_page(true);
74 public static final ActionListener SELECT_NEXT_WORD = new next_word(true);
75 public static final ActionListener OVERWRITE = new overwrite();
76 public static final ActionListener PREV_CHAR = new prev_char(false);
77 public static final ActionListener PREV_LINE = new prev_line(false);
78 public static final ActionListener PREV_PAGE = new prev_page(false);
79 public static final ActionListener PREV_WORD = new prev_word(false);
80 public static final ActionListener SELECT_PREV_CHAR = new prev_char(true);
81 public static final ActionListener SELECT_PREV_LINE = new prev_line(true);
82 public static final ActionListener SELECT_PREV_PAGE = new prev_page(true);
83 public static final ActionListener SELECT_PREV_WORD = new prev_word(true);
84 public static final ActionListener REPEAT = new repeat();
85 public static final ActionListener TOGGLE_RECT = new toggle_rect();
86
87 public static final Action CLIP_COPY = new clip_copy();
88 public static final Action CLIP_PASTE = new clip_paste();
89 public static final Action CLIP_CUT = new clip_cut();
90
91
92 public static final ActionListener INSERT_CHAR = new insert_char();
93
94 private static Hashtable<String,ActionListener> actions;
95
96 static
97 {
98 actions = new Hashtable<String,ActionListener>();
99 actions.put("backspace",BACKSPACE);
100 actions.put("backspace-word",BACKSPACE_WORD);
101 actions.put("delete",DELETE);
102 actions.put("delete-word",DELETE_WORD);
103 actions.put("end",END);
104 actions.put("select-all",SELECT_ALL);
105 actions.put("select-end",SELECT_END);
106 actions.put("document-end",DOCUMENT_END);
107 actions.put("select-doc-end",SELECT_DOC_END);
108 actions.put("insert-break",INSERT_BREAK);
109 actions.put("insert-tab",INSERT_TAB);
110 actions.put("home",HOME);
111 actions.put("select-home",SELECT_HOME);
112 actions.put("document-home",DOCUMENT_HOME);
113 actions.put("select-doc-home",SELECT_DOC_HOME);
114 actions.put("next-char",NEXT_CHAR);
115 actions.put("next-line",NEXT_LINE);
116 actions.put("next-page",NEXT_PAGE);
117 actions.put("next-word",NEXT_WORD);
118 actions.put("select-next-char",SELECT_NEXT_CHAR);
119 actions.put("select-next-line",SELECT_NEXT_LINE);
120 actions.put("select-next-page",SELECT_NEXT_PAGE);
121 actions.put("select-next-word",SELECT_NEXT_WORD);
122 actions.put("overwrite",OVERWRITE);
123 actions.put("prev-char",PREV_CHAR);
124 actions.put("prev-line",PREV_LINE);
125 actions.put("prev-page",PREV_PAGE);
126 actions.put("prev-word",PREV_WORD);
127 actions.put("select-prev-char",SELECT_PREV_CHAR);
128 actions.put("select-prev-line",SELECT_PREV_LINE);
129 actions.put("select-prev-page",SELECT_PREV_PAGE);
130 actions.put("select-prev-word",SELECT_PREV_WORD);
131 actions.put("repeat",REPEAT);
132 actions.put("toggle-rect",TOGGLE_RECT);
133 actions.put("insert-char",INSERT_CHAR);
134 actions.put("clipboard-copy",CLIP_COPY);
135 actions.put("clipboard-paste",CLIP_PASTE);
136 actions.put("clipboard-cut",CLIP_CUT);
137 }
138
139 /***
140 * Returns a named text area action.
141 * @param name The action name
142 */
143 public static ActionListener getAction(String name)
144 {
145 return (ActionListener)actions.get(name);
146 }
147
148 /***
149 * Returns the name of the specified text area action.
150 * @param listener The action
151 */
152 public static String getActionName(ActionListener listener)
153 {
154 Enumeration _enum = getActions();
155 while(_enum.hasMoreElements())
156 {
157 String name = (String)_enum.nextElement();
158 ActionListener _listener = getAction(name);
159 if(_listener == listener)
160 return name;
161 }
162 return null;
163 }
164
165 /***
166 * Returns an enumeration of all available actions.
167 */
168 public static Enumeration getActions()
169 {
170 return actions.keys();
171 }
172
173 /***
174 * Adds the default key bindings to this input handler.
175 * This should not be called in the constructor of this
176 * input handler, because applications might load the
177 * key bindings from a file, etc.
178 */
179 public abstract void addDefaultKeyBindings();
180
181 /***
182 * Adds a key binding to this input handler.
183 * @param keyBinding The key binding (the format of this is
184 * input-handler specific)
185 * @param action The action
186 */
187 public abstract void addKeyBinding(String keyBinding, ActionListener action);
188
189 /***
190 * Removes a key binding from this input handler.
191 * @param keyBinding The key binding
192 */
193 public abstract void removeKeyBinding(String keyBinding);
194
195 /***
196 * Removes all key bindings from this input handler.
197 */
198 public abstract void removeAllKeyBindings();
199
200 /***
201 * Grabs the next key typed event and invokes the specified
202 * action with the key as a the action command.
203 * @param action The action
204 */
205 public void grabNextKeyStroke(ActionListener listener)
206 {
207 grabAction = listener;
208 }
209
210 /***
211 * Returns if repeating is enabled. When repeating is enabled,
212 * actions will be executed multiple times. This is usually
213 * invoked with a special key stroke in the input handler.
214 */
215 public boolean isRepeatEnabled()
216 {
217 return repeat;
218 }
219
220 /***
221 * Enables repeating. When repeating is enabled, actions will be
222 * executed multiple times. Once repeating is enabled, the input
223 * handler should read a number from the keyboard.
224 */
225 public void setRepeatEnabled(boolean repeat)
226 {
227 this.repeat = repeat;
228 }
229
230 /***
231 * Returns the number of times the next action will be repeated.
232 */
233 public int getRepeatCount()
234 {
235 return (repeat ? Math.max(1,repeatCount) : 1);
236 }
237
238 /***
239 * Sets the number of times the next action will be repeated.
240 * @param repeatCount The repeat count
241 */
242 public void setRepeatCount(int repeatCount)
243 {
244 this.repeatCount = repeatCount;
245 }
246
247 /***
248 * Returns the macro recorder. If this is non-null, all executed
249 * actions should be forwarded to the recorder.
250 */
251 public InputHandler.MacroRecorder getMacroRecorder()
252 {
253 return recorder;
254 }
255
256 /***
257 * Sets the macro recorder. If this is non-null, all executed
258 * actions should be forwarded to the recorder.
259 * @param recorder The macro recorder
260 */
261 public void setMacroRecorder(InputHandler.MacroRecorder recorder)
262 {
263 this.recorder = recorder;
264 }
265
266 /***
267 * Returns a copy of this input handler that shares the same
268 * key bindings. Setting key bindings in the copy will also
269 * set them in the original.
270 */
271 public abstract InputHandler copy();
272
273 /***
274 * Executes the specified action, repeating and recording it as
275 * necessary.
276 * @param listener The action listener
277 * @param source The event source
278 * @param actionCommand The action command
279 */
280 public void executeAction(ActionListener listener, Object source,
281 String actionCommand)
282 {
283
284 ActionEvent evt = new ActionEvent(source,
285 ActionEvent.ACTION_PERFORMED,
286 actionCommand);
287
288
289
290 if(listener instanceof Wrapper)
291 {
292 listener.actionPerformed(evt);
293 return;
294 }
295
296
297 boolean _repeat = repeat;
298 int _repeatCount = getRepeatCount();
299
300
301 if(listener instanceof InputHandler.NonRepeatable)
302 listener.actionPerformed(evt);
303 else
304 {
305 for(int i = 0; i < Math.max(1,repeatCount); i++)
306 listener.actionPerformed(evt);
307 }
308
309
310
311 if(grabAction == null)
312 {
313 if(recorder != null)
314 {
315 if(!(listener instanceof InputHandler.NonRecordable))
316 {
317 if(_repeatCount != 1)
318 recorder.actionPerformed(REPEAT,String.valueOf(_repeatCount));
319
320 recorder.actionPerformed(listener,actionCommand);
321 }
322 }
323
324
325
326 if(_repeat)
327 {
328 repeat = false;
329 repeatCount = 0;
330 }
331 }
332 }
333
334 /***
335 * Returns the text area that fired the specified event.
336 * @param evt The event
337 */
338 public static JEditTextArea getTextArea(EventObject evt)
339 {
340 if(evt != null)
341 {
342 Object o = evt.getSource();
343 if(o instanceof Component)
344 {
345
346 Component c = (Component)o;
347 for(;;)
348 {
349 if(c instanceof JEditTextArea)
350 return (JEditTextArea)c;
351 else if(c == null)
352 break;
353 if(c instanceof JPopupMenu)
354 c = ((JPopupMenu)c)
355 .getInvoker();
356 else
357 c = c.getParent();
358 }
359 }
360 }
361
362
363 System.err.println("BUG: getTextArea() returning null");
364 System.err.println("Report this to Slava Pestov <sp@gjt.org>");
365 return null;
366 }
367
368
369
370 /***
371 * If a key is being grabbed, this method should be called with
372 * the appropriate key event. It executes the grab action with
373 * the typed character as the parameter.
374 */
375 protected void handleGrabAction(KeyEvent evt)
376 {
377
378
379 ActionListener _grabAction = grabAction;
380 grabAction = null;
381 executeAction(_grabAction,evt.getSource(),
382 String.valueOf(evt.getKeyChar()));
383 }
384
385
386 protected ActionListener grabAction;
387 protected boolean repeat;
388 protected int repeatCount;
389 protected InputHandler.MacroRecorder recorder;
390
391 /***
392 * If an action implements this interface, it should not be repeated.
393 * Instead, it will handle the repetition itself.
394 */
395 public interface NonRepeatable {}
396
397 /***
398 * If an action implements this interface, it should not be recorded
399 * by the macro recorder. Instead, it will do its own recording.
400 */
401 public interface NonRecordable {}
402
403 /***
404 * For use by EditAction.Wrapper only.
405 * @since jEdit 2.2final
406 */
407 public interface Wrapper {}
408
409 /***
410 * Macro recorder.
411 */
412 public interface MacroRecorder
413 {
414 void actionPerformed(ActionListener listener,
415 String actionCommand);
416 }
417
418 public static class backspace implements ActionListener
419 {
420 public void actionPerformed(ActionEvent evt)
421 {
422 JEditTextArea textArea = getTextArea(evt);
423
424 if(!textArea.isEditable())
425 {
426 textArea.getToolkit().beep();
427 return;
428 }
429
430 if(textArea.getSelectionStart()
431 != textArea.getSelectionEnd())
432 {
433 textArea.setSelectedText("");
434 }
435 else
436 {
437 int caret = textArea.getCaretPosition();
438 if(caret == 0)
439 {
440 textArea.getToolkit().beep();
441 return;
442 }
443 try
444 {
445 textArea.getDocument().remove(caret - 1,1);
446 }
447 catch(BadLocationException bl)
448 {
449 bl.printStackTrace();
450 }
451 }
452 }
453 }
454
455 public static class backspace_word implements ActionListener
456 {
457 public void actionPerformed(ActionEvent evt)
458 {
459 JEditTextArea textArea = getTextArea(evt);
460 int start = textArea.getSelectionStart();
461 if(start != textArea.getSelectionEnd())
462 {
463 textArea.setSelectedText("");
464 }
465
466 int line = textArea.getCaretLine();
467 int lineStart = textArea.getLineStartOffset(line);
468 int caret = start - lineStart;
469
470 String lineText = textArea.getLineText(textArea
471 .getCaretLine());
472
473 if(caret == 0)
474 {
475 if(lineStart == 0)
476 {
477 textArea.getToolkit().beep();
478 return;
479 }
480 caret--;
481 }
482 else
483 {
484 String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
485 caret = TextUtilities.findWordStart(lineText,caret,noWordSep);
486 }
487
488 try
489 {
490 textArea.getDocument().remove(
491 caret + lineStart,
492 start - (caret + lineStart));
493 }
494 catch(BadLocationException bl)
495 {
496 bl.printStackTrace();
497 }
498 }
499 }
500
501 public static class delete implements ActionListener
502 {
503 public void actionPerformed(ActionEvent evt)
504 {
505 JEditTextArea textArea = getTextArea(evt);
506
507 if(!textArea.isEditable())
508 {
509 textArea.getToolkit().beep();
510 return;
511 }
512
513 if(textArea.getSelectionStart()
514 != textArea.getSelectionEnd())
515 {
516 textArea.setSelectedText("");
517 }
518 else
519 {
520 int caret = textArea.getCaretPosition();
521 if(caret == textArea.getDocumentLength())
522 {
523 textArea.getToolkit().beep();
524 return;
525 }
526 try
527 {
528 textArea.getDocument().remove(caret,1);
529 }
530 catch(BadLocationException bl)
531 {
532 bl.printStackTrace();
533 }
534 }
535 }
536 }
537
538 public static class delete_word implements ActionListener
539 {
540 public void actionPerformed(ActionEvent evt)
541 {
542 JEditTextArea textArea = getTextArea(evt);
543 int start = textArea.getSelectionStart();
544 if(start != textArea.getSelectionEnd())
545 {
546 textArea.setSelectedText("");
547 }
548
549 int line = textArea.getCaretLine();
550 int lineStart = textArea.getLineStartOffset(line);
551 int caret = start - lineStart;
552
553 String lineText = textArea.getLineText(textArea
554 .getCaretLine());
555
556 if(caret == lineText.length())
557 {
558 if(lineStart + caret == textArea.getDocumentLength())
559 {
560 textArea.getToolkit().beep();
561 return;
562 }
563 caret++;
564 }
565 else
566 {
567 String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
568 caret = TextUtilities.findWordEnd(lineText,caret,noWordSep);
569 }
570
571 try
572 {
573 textArea.getDocument().remove(start,
574 (caret + lineStart) - start);
575 }
576 catch(BadLocationException bl)
577 {
578 bl.printStackTrace();
579 }
580 }
581 }
582
583 public static class end implements ActionListener
584 {
585 private boolean select;
586
587 public end(boolean select)
588 {
589 this.select = select;
590 }
591
592 public void actionPerformed(ActionEvent evt)
593 {
594 JEditTextArea textArea = getTextArea(evt);
595
596 int caret = textArea.getCaretPosition();
597
598 int lastOfLine = textArea.getLineEndOffset(
599 textArea.getCaretLine()) - 1;
600 int lastVisibleLine = textArea.getFirstLine()
601 + textArea.getVisibleLines();
602 if(lastVisibleLine >= textArea.getLineCount())
603 {
604 lastVisibleLine = Math.min(textArea.getLineCount() - 1,
605 lastVisibleLine);
606 }
607 else
608 lastVisibleLine -= (textArea.getElectricScroll() + 1);
609
610 int lastVisible = textArea.getLineEndOffset(lastVisibleLine) - 1;
611 int lastDocument = textArea.getDocumentLength();
612
613 if(caret == lastDocument)
614 {
615 textArea.getToolkit().beep();
616 return;
617 }
618 else if(!Boolean.TRUE.equals(textArea.getClientProperty(
619 SMART_HOME_END_PROPERTY)))
620 caret = lastOfLine;
621 else if(caret == lastVisible)
622 caret = lastDocument;
623 else if(caret == lastOfLine)
624 caret = lastVisible;
625 else
626 caret = lastOfLine;
627
628 if(select)
629 textArea.select(textArea.getMarkPosition(),caret);
630 else
631 textArea.setCaretPosition(caret);
632 }
633 }
634
635 public static class select_all implements ActionListener {
636 public void actionPerformed(ActionEvent evt)
637 {
638 JEditTextArea textArea = getTextArea(evt);
639 textArea.selectAll();
640 }
641 }
642
643 public static class document_end implements ActionListener
644 {
645 private boolean select;
646
647 public document_end(boolean select)
648 {
649 this.select = select;
650 }
651
652 public void actionPerformed(ActionEvent evt)
653 {
654 JEditTextArea textArea = getTextArea(evt);
655 if(select)
656 textArea.select(textArea.getMarkPosition(),
657 textArea.getDocumentLength());
658 else
659 textArea.setCaretPosition(textArea
660 .getDocumentLength());
661 }
662 }
663
664 public static class home implements ActionListener
665 {
666 private boolean select;
667
668 public home(boolean select)
669 {
670 this.select = select;
671 }
672
673 public void actionPerformed(ActionEvent evt)
674 {
675 JEditTextArea textArea = getTextArea(evt);
676
677 int caret = textArea.getCaretPosition();
678
679 int firstLine = textArea.getFirstLine();
680
681 int firstOfLine = textArea.getLineStartOffset(
682 textArea.getCaretLine());
683 int firstVisibleLine = (firstLine == 0 ? 0 :
684 firstLine + textArea.getElectricScroll());
685 int firstVisible = textArea.getLineStartOffset(
686 firstVisibleLine);
687
688 if(caret == 0)
689 {
690 textArea.getToolkit().beep();
691 return;
692 }
693 else if(!Boolean.TRUE.equals(textArea.getClientProperty(
694 SMART_HOME_END_PROPERTY)))
695 caret = firstOfLine;
696 else if(caret == firstVisible)
697 caret = 0;
698 else if(caret == firstOfLine)
699 caret = firstVisible;
700 else
701 caret = firstOfLine;
702
703 if(select)
704 textArea.select(textArea.getMarkPosition(),caret);
705 else
706 textArea.setCaretPosition(caret);
707 }
708 }
709
710 public static class document_home implements ActionListener
711 {
712 private boolean select;
713
714 public document_home(boolean select)
715 {
716 this.select = select;
717 }
718
719 public void actionPerformed(ActionEvent evt)
720 {
721 JEditTextArea textArea = getTextArea(evt);
722 if(select)
723 textArea.select(textArea.getMarkPosition(),0);
724 else
725 textArea.setCaretPosition(0);
726 }
727 }
728
729 public static class insert_break implements ActionListener
730 {
731 public void actionPerformed(ActionEvent evt)
732 {
733 JEditTextArea textArea = getTextArea(evt);
734
735 if(!textArea.isEditable())
736 {
737 textArea.getToolkit().beep();
738 return;
739 }
740
741 textArea.setSelectedText("\n");
742 }
743 }
744
745 public static class insert_tab implements ActionListener
746 {
747 public void actionPerformed(ActionEvent evt)
748 {
749 JEditTextArea textArea = getTextArea(evt);
750
751 if(!textArea.isEditable())
752 {
753 textArea.getToolkit().beep();
754 return;
755 }
756
757 textArea.overwriteSetSelectedText("\t");
758 }
759 }
760
761 public static class next_char implements ActionListener
762 {
763 private boolean select;
764
765 public next_char(boolean select)
766 {
767 this.select = select;
768 }
769
770 public void actionPerformed(ActionEvent evt)
771 {
772 JEditTextArea textArea = getTextArea(evt);
773 int caret = textArea.getCaretPosition();
774 if(caret == textArea.getDocumentLength())
775 {
776 textArea.getToolkit().beep();
777 return;
778 }
779
780 if(select)
781 textArea.select(textArea.getMarkPosition(),
782 caret + 1);
783 else
784 textArea.setCaretPosition(caret + 1);
785 }
786 }
787
788 public static class next_line implements ActionListener
789 {
790 private boolean select;
791
792 public next_line(boolean select)
793 {
794 this.select = select;
795 }
796
797 public void actionPerformed(ActionEvent evt)
798 {
799 JEditTextArea textArea = getTextArea(evt);
800 int caret = textArea.getCaretPosition();
801 int line = textArea.getCaretLine();
802
803 if(line == textArea.getLineCount() - 1)
804 {
805 textArea.getToolkit().beep();
806 return;
807 }
808
809 int magic = textArea.getMagicCaretPosition();
810 if(magic == -1)
811 {
812 magic = textArea.offsetToX(line,
813 caret - textArea.getLineStartOffset(line));
814 }
815
816 caret = textArea.getLineStartOffset(line + 1)
817 + textArea.xToOffset(line + 1,magic);
818 if(select)
819 textArea.select(textArea.getMarkPosition(),caret);
820 else
821 textArea.setCaretPosition(caret);
822 textArea.setMagicCaretPosition(magic);
823 }
824 }
825
826 public static class next_page implements ActionListener
827 {
828 private boolean select;
829
830 public next_page(boolean select)
831 {
832 this.select = select;
833 }
834
835 public void actionPerformed(ActionEvent evt)
836 {
837 JEditTextArea textArea = getTextArea(evt);
838 int lineCount = textArea.getLineCount();
839 int firstLine = textArea.getFirstLine();
840 int visibleLines = textArea.getVisibleLines();
841 int line = textArea.getCaretLine();
842
843 firstLine += visibleLines;
844
845 if(firstLine + visibleLines >= lineCount - 1)
846 firstLine = lineCount - visibleLines;
847
848 textArea.setFirstLine(firstLine);
849
850 int caret = textArea.getLineStartOffset(
851 Math.min(textArea.getLineCount() - 1,
852 line + visibleLines));
853 if(select)
854 textArea.select(textArea.getMarkPosition(),caret);
855 else
856 textArea.setCaretPosition(caret);
857 }
858 }
859
860 public static class next_word implements ActionListener
861 {
862 private boolean select;
863
864 public next_word(boolean select)
865 {
866 this.select = select;
867 }
868
869 public void actionPerformed(ActionEvent evt)
870 {
871 JEditTextArea textArea = getTextArea(evt);
872 int caret = textArea.getCaretPosition();
873 int line = textArea.getCaretLine();
874 int lineStart = textArea.getLineStartOffset(line);
875 caret -= lineStart;
876
877 String lineText = textArea.getLineText(textArea
878 .getCaretLine());
879
880 if(caret == lineText.length())
881 {
882 if(lineStart + caret == textArea.getDocumentLength())
883 {
884 textArea.getToolkit().beep();
885 return;
886 }
887 caret++;
888 }
889 else
890 {
891 String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
892 caret = TextUtilities.findWordEnd(lineText,caret,noWordSep);
893 }
894
895 if(select)
896 textArea.select(textArea.getMarkPosition(),
897 lineStart + caret);
898 else
899 textArea.setCaretPosition(lineStart + caret);
900 }
901 }
902
903 public static class overwrite implements ActionListener
904 {
905 public void actionPerformed(ActionEvent evt)
906 {
907 JEditTextArea textArea = getTextArea(evt);
908 textArea.setOverwriteEnabled(
909 !textArea.isOverwriteEnabled());
910 }
911 }
912
913 public static class prev_char implements ActionListener
914 {
915 private boolean select;
916
917 public prev_char(boolean select)
918 {
919 this.select = select;
920 }
921
922 public void actionPerformed(ActionEvent evt)
923 {
924 JEditTextArea textArea = getTextArea(evt);
925 int caret = textArea.getCaretPosition();
926 if(caret == 0)
927 {
928 textArea.getToolkit().beep();
929 return;
930 }
931
932 if(select)
933 textArea.select(textArea.getMarkPosition(),
934 caret - 1);
935 else
936 textArea.setCaretPosition(caret - 1);
937 }
938 }
939
940 public static class prev_line implements ActionListener
941 {
942 private boolean select;
943
944 public prev_line(boolean select)
945 {
946 this.select = select;
947 }
948
949 public void actionPerformed(ActionEvent evt)
950 {
951 JEditTextArea textArea = getTextArea(evt);
952 int caret = textArea.getCaretPosition();
953 int line = textArea.getCaretLine();
954
955 if(line == 0)
956 {
957 textArea.getToolkit().beep();
958 return;
959 }
960
961 int magic = textArea.getMagicCaretPosition();
962 if(magic == -1)
963 {
964 magic = textArea.offsetToX(line,
965 caret - textArea.getLineStartOffset(line));
966 }
967
968 caret = textArea.getLineStartOffset(line - 1)
969 + textArea.xToOffset(line - 1,magic);
970 if(select)
971 textArea.select(textArea.getMarkPosition(),caret);
972 else
973 textArea.setCaretPosition(caret);
974 textArea.setMagicCaretPosition(magic);
975 }
976 }
977
978 public static class prev_page implements ActionListener
979 {
980 private boolean select;
981
982 public prev_page(boolean select)
983 {
984 this.select = select;
985 }
986
987 public void actionPerformed(ActionEvent evt)
988 {
989 JEditTextArea textArea = getTextArea(evt);
990 int firstLine = textArea.getFirstLine();
991 int visibleLines = textArea.getVisibleLines();
992 int line = textArea.getCaretLine();
993
994 if(firstLine < visibleLines)
995 firstLine = visibleLines;
996
997 textArea.setFirstLine(firstLine - visibleLines);
998
999 int caret = textArea.getLineStartOffset(
1000 Math.max(0,line - visibleLines));
1001 if(select)
1002 textArea.select(textArea.getMarkPosition(),caret);
1003 else
1004 textArea.setCaretPosition(caret);
1005 }
1006 }
1007
1008 public static class prev_word implements ActionListener
1009 {
1010 private boolean select;
1011
1012 public prev_word(boolean select)
1013 {
1014 this.select = select;
1015 }
1016
1017 public void actionPerformed(ActionEvent evt)
1018 {
1019 JEditTextArea textArea = getTextArea(evt);
1020 int caret = textArea.getCaretPosition();
1021 int line = textArea.getCaretLine();
1022 int lineStart = textArea.getLineStartOffset(line);
1023 caret -= lineStart;
1024
1025 String lineText = textArea.getLineText(textArea
1026 .getCaretLine());
1027
1028 if(caret == 0)
1029 {
1030 if(lineStart == 0)
1031 {
1032 textArea.getToolkit().beep();
1033 return;
1034 }
1035 caret--;
1036 }
1037 else
1038 {
1039 String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
1040 caret = TextUtilities.findWordStart(lineText,caret,noWordSep);
1041 }
1042
1043 if(select)
1044 textArea.select(textArea.getMarkPosition(),
1045 lineStart + caret);
1046 else
1047 textArea.setCaretPosition(lineStart + caret);
1048 }
1049 }
1050
1051 public static class repeat implements ActionListener,
1052 InputHandler.NonRecordable
1053 {
1054 public void actionPerformed(ActionEvent evt)
1055 {
1056 JEditTextArea textArea = getTextArea(evt);
1057 textArea.getInputHandler().setRepeatEnabled(true);
1058 String actionCommand = evt.getActionCommand();
1059 if(actionCommand != null)
1060 {
1061 textArea.getInputHandler().setRepeatCount(
1062 Integer.parseInt(actionCommand));
1063 }
1064 }
1065 }
1066
1067 public static class toggle_rect implements ActionListener
1068 {
1069 public void actionPerformed(ActionEvent evt)
1070 {
1071 JEditTextArea textArea = getTextArea(evt);
1072 textArea.setSelectionRectangular(
1073 !textArea.isSelectionRectangular());
1074 }
1075 }
1076
1077 public static class insert_char implements ActionListener,
1078 InputHandler.NonRepeatable
1079 {
1080 public void actionPerformed(ActionEvent evt)
1081 {
1082 JEditTextArea textArea = getTextArea(evt);
1083 String str = evt.getActionCommand();
1084 int repeatCount = textArea.getInputHandler().getRepeatCount();
1085
1086 if(textArea.isEditable())
1087 {
1088 StringBuffer buf = new StringBuffer();
1089 for(int i = 0; i < repeatCount; i++)
1090 buf.append(str);
1091 textArea.overwriteSetSelectedText(buf.toString());
1092 }
1093 else
1094 {
1095 textArea.getToolkit().beep();
1096 }
1097 }
1098 }
1099
1100 public static class clip_copy extends AbstractAction {
1101
1102 public clip_copy()
1103 {
1104 super( "Copy" );
1105 putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( KeyEvent.VK_C, KeyEvent.CTRL_MASK ));
1106 }
1107
1108 public void actionPerformed(ActionEvent evt)
1109 {
1110 JEditTextArea textArea = getTextArea(evt);
1111 textArea.copy();
1112 }
1113 }
1114
1115 public static class clip_paste extends AbstractAction {
1116
1117 public clip_paste()
1118 {
1119 super( "Paste" );
1120 putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( KeyEvent.VK_V, KeyEvent.CTRL_MASK ));
1121 }
1122
1123 public void actionPerformed(ActionEvent evt)
1124 {
1125 JEditTextArea textArea = getTextArea(evt);
1126 textArea.paste();
1127 }
1128 }
1129
1130 public static class clip_cut extends AbstractAction {
1131
1132 public clip_cut()
1133 {
1134 super( "Cut" );
1135 putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( KeyEvent.VK_X, KeyEvent.CTRL_MASK ));
1136 }
1137
1138 public void actionPerformed(ActionEvent evt)
1139 {
1140 JEditTextArea textArea = getTextArea(evt);
1141 textArea.cut();
1142 }
1143 }
1144 }