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