OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / text / DefaultEditorKit.java
1 /* DefaultEditorKit.java --
2    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.swing.text;
40
41 import java.awt.Toolkit;
42 import java.awt.event.ActionEvent;
43
44 import java.io.BufferedReader;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.io.InputStreamReader;
48 import java.io.OutputStream;
49 import java.io.OutputStreamWriter;
50 import java.io.Reader;
51 import java.io.Writer;
52
53 import javax.swing.Action;
54 import javax.swing.SwingConstants;
55
56 /**
57  * The default implementation of {@link EditorKit}. This <code>EditorKit</code>
58  * a plain text <code>Document</code> and several commands that together
59  * make up a basic editor, like cut / copy + paste.
60  *
61  * @author original author unknown
62  * @author Roman Kennke (roman@kennke.org)
63  * @author Robert Schuster (robertschuster@fsfe.org)
64  */
65 public class DefaultEditorKit extends EditorKit
66 {
67   static class SelectionPreviousWordAction
68       extends TextAction
69   {
70     SelectionPreviousWordAction()
71     {
72       super(selectionPreviousWordAction);
73     }
74
75     public void actionPerformed(ActionEvent event)
76     {
77       try
78         {
79           JTextComponent t = getTextComponent(event);
80       
81           if (t != null)
82             {
83               int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
84       
85               Caret c = t.getCaret();
86               c.moveDot(offs);
87               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
88             }
89         }
90       catch(BadLocationException ble)
91         {
92           // Can't happen.
93         }
94     }
95   }
96
97   static class SelectionNextWordAction
98       extends TextAction
99   {
100     SelectionNextWordAction()
101     {
102       super(selectionNextWordAction);
103     }
104
105     public void actionPerformed(ActionEvent event)
106     {
107       try
108         {
109           JTextComponent t = getTextComponent(event);
110       
111           if (t != null)
112             {
113               int offs = Utilities.getNextWord(t, t.getCaretPosition());
114       
115               Caret c = t.getCaret();
116               c.moveDot(offs);
117               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
118             }
119         }
120       catch(BadLocationException ble)
121         {
122           // Can't happen.
123         }
124     }
125   }
126
127   static class SelectionBeginWordAction extends TextAction
128   {
129     SelectionBeginWordAction()
130     {
131       super(selectionBeginWordAction);
132     }
133   
134     public void actionPerformed(ActionEvent event)
135     {
136       try
137         {
138           JTextComponent t = getTextComponent(event);
139       
140           if (t != null)
141             {
142               int offs = Utilities.getWordStart(t, t.getCaretPosition());
143       
144               Caret c = t.getCaret();
145               c.moveDot(offs);
146               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
147             }
148         }
149       catch(BadLocationException ble)
150         {
151           // Can't happen.
152         }
153     }
154   }
155   
156   static class SelectionEndWordAction extends TextAction
157   {
158     SelectionEndWordAction()
159     {
160       super(selectionEndWordAction);
161     }
162   
163     public void actionPerformed(ActionEvent event)
164     {
165       try
166         {
167           JTextComponent t = getTextComponent(event);
168       
169           if (t != null)
170             {
171               int offs = Utilities.getWordEnd(t, t.getCaretPosition());
172       
173               Caret c = t.getCaret();
174               c.moveDot(offs);
175               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
176             }
177         }
178       catch(BadLocationException ble)
179         {
180           // Can't happen.
181         }
182     }
183   }
184   
185   static class BeginWordAction extends TextAction
186   {
187     BeginWordAction()
188     {
189       super(beginWordAction);
190     }
191   
192     public void actionPerformed(ActionEvent event)
193     {
194       try
195         {
196           JTextComponent t = getTextComponent(event);
197       
198           if (t != null)
199             {
200               int offs = Utilities.getWordStart(t, t.getCaretPosition());
201       
202               Caret c = t.getCaret();
203               c.setDot(offs);
204               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
205             }
206         }
207       catch(BadLocationException ble)
208         {
209           // Can't happen.
210         }
211     }
212   }
213   
214   static class EndWordAction extends TextAction
215   {
216     EndWordAction()
217     {
218       super(endWordAction);
219     }
220   
221     public void actionPerformed(ActionEvent event)
222     {
223       try
224         {
225           JTextComponent t = getTextComponent(event);
226       
227           if (t != null)
228             {
229               int offs = Utilities.getWordEnd(t, t.getCaretPosition());
230       
231               Caret c = t.getCaret();
232               c.setDot(offs);
233               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
234             }
235         }
236       catch(BadLocationException ble)
237         {
238           // Can't happen.
239         }
240     }
241   }
242
243   static class PreviousWordAction
244       extends TextAction
245   {
246     PreviousWordAction()
247     {
248       super(previousWordAction);
249     }
250
251     public void actionPerformed(ActionEvent event)
252     {
253       try
254         {
255           JTextComponent t = getTextComponent(event);
256       
257           if (t != null)
258             {
259               int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
260       
261               Caret c = t.getCaret();
262               c.setDot(offs);
263               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
264             }
265         }
266       catch(BadLocationException ble)
267         {
268           // Can't happen.
269         }
270     }
271   }
272
273   static class NextWordAction
274       extends TextAction
275   {
276     NextWordAction()
277     {
278       super(nextWordAction);
279     }
280
281     public void actionPerformed(ActionEvent event)
282     {
283       try
284         {
285           JTextComponent t = getTextComponent(event);
286       
287           if (t != null)
288             {
289               int offs = Utilities.getNextWord(t, t.getCaretPosition());
290       
291               Caret c = t.getCaret();
292               c.setDot(offs);
293               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
294             }
295         }
296       catch(BadLocationException ble)
297         {
298           // Can't happen.
299         }
300     }
301   }
302
303   static class SelectAllAction
304       extends TextAction
305   {
306     SelectAllAction()
307     {
308       super(selectAllAction);
309     }
310
311     public void actionPerformed(ActionEvent event)
312     {
313       JTextComponent t = getTextComponent(event);
314       if (t != null)
315         {
316           int offs = t.getDocument().getLength();
317           Caret c = t.getCaret();
318           c.setDot(0);
319           c.moveDot(offs);
320           try
321             {   
322               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
323             }
324           catch(BadLocationException ble)
325             {
326               // Can't happen.
327             }
328         }
329     }
330   }
331
332   static class SelectionBeginAction
333       extends TextAction
334   {
335     SelectionBeginAction()
336     {
337       super(selectionBeginAction);
338     }
339
340     public void actionPerformed(ActionEvent event)
341     {
342       JTextComponent t = getTextComponent(event);
343       if (t != null)
344         {
345           Caret c = t.getCaret();
346           c.moveDot(0);
347           try
348             {   
349               c.setMagicCaretPosition(t.modelToView(0).getLocation());
350             }
351           catch(BadLocationException ble)
352             {
353               // Can't happen.
354             }
355         }
356     }
357   }
358
359   static class SelectionEndAction
360       extends TextAction
361   {
362     SelectionEndAction()
363     {
364       super(selectionEndAction);
365     }
366
367     public void actionPerformed(ActionEvent event)
368     {
369       JTextComponent t = getTextComponent(event);
370       if (t != null)
371         {
372           int offs = t.getDocument().getLength();
373           Caret c = t.getCaret();
374           c.moveDot(offs);
375           try
376             {   
377               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
378             }
379           catch(BadLocationException ble)
380             {
381               // Can't happen.
382             }
383         }
384     }
385   }
386   
387   static class SelectionBeginLineAction
388     extends TextAction
389   {
390     
391     SelectionBeginLineAction()
392     {
393       super(selectionBeginLineAction);
394     }
395
396     public void actionPerformed(ActionEvent event)
397     {
398       JTextComponent t = getTextComponent(event);
399       if (t != null)
400         {
401           Caret c = t.getCaret();
402           try
403             {
404               int offs = Utilities.getRowStart(t, c.getDot());
405               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
406             }
407           catch(BadLocationException ble)
408             {
409               // Can't happen.
410             }
411         }
412     }
413   }
414
415   static class SelectionEndLineAction
416       extends TextAction
417   {
418     SelectionEndLineAction()
419     {
420       super(selectionEndLineAction);
421     }
422
423     public void actionPerformed(ActionEvent event)
424     {
425       JTextComponent t = getTextComponent(event);
426       if (t != null)
427         {
428           Caret c = t.getCaret();
429           try
430             {
431               int offs = Utilities.getRowEnd(t, c.getDot());
432               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
433             }
434           catch(BadLocationException ble)
435             {
436               // Can't happen.
437             }
438         }
439     }
440   }
441   
442   static class SelectLineAction extends TextAction
443   {
444     SelectLineAction()
445     {
446       super(selectLineAction);
447     }
448   
449     public void actionPerformed(ActionEvent event)
450     {
451       JTextComponent t = getTextComponent(event);
452       if (t != null)
453         {
454           Caret c = t.getCaret();
455           try
456             {
457               int offs1 = Utilities.getRowStart(t, c.getDot());
458               int offs2 = Utilities.getRowEnd(t, c.getDot());
459               c.setDot(offs2);
460               c.moveDot(offs1);
461               c.setMagicCaretPosition(t.modelToView(offs2).getLocation());
462             }
463           catch(BadLocationException ble)
464             {
465               // Can't happen.
466             }
467         }
468     }
469   }
470   
471   static class SelectWordAction extends TextAction
472   {
473     SelectWordAction()
474     {
475       super(selectWordAction);
476     }
477   
478     public void actionPerformed(ActionEvent event)
479     {
480       JTextComponent t = getTextComponent(event);
481       if (t != null)
482         {
483           Caret c = t.getCaret();
484           int dot = c.getDot();
485           try
486             {
487               int wordStart = Utilities.getWordStart(t, dot);
488
489               if (dot == wordStart)
490                 {
491                   // Current cursor position is on the first character in a word.
492                   c.setDot(wordStart);
493                   c.moveDot(Utilities.getWordEnd(t, wordStart));
494                 }
495               else
496                 {
497                   // Current cursor position is not on the first character
498                   // in a word. 
499                   int nextWord = Utilities.getNextWord(t, dot);
500                   int previousWord = Utilities.getPreviousWord(t, dot);
501                   int previousWordEnd = Utilities.getWordEnd(t, previousWord);
502                   
503                   // Cursor position is in the space between two words. In such a
504                   // situation just select the space.
505                   if (dot >= previousWordEnd && dot <= nextWord)
506                     {
507                       c.setDot(previousWordEnd);
508                       c.moveDot(nextWord);
509                     }
510                   else
511                     {
512                       // Cursor position is inside a word. Just select it then.
513                       c.setDot(previousWord);
514                       c.moveDot(previousWordEnd);
515                     }
516                 }
517
518               // If the position was updated change the magic caret position
519               // as well.
520               if (c.getDot() != dot)
521                 c.setMagicCaretPosition(t.modelToView(c.getDot()).getLocation());
522             }
523           catch(BadLocationException ble)
524             {
525               // Can't happen.
526             }
527         }
528     }
529   }
530
531   static class SelectionDownAction
532       extends TextAction.VerticalMovementAction
533   {
534     SelectionDownAction()
535     {
536       super(selectionDownAction, SwingConstants.SOUTH);
537     }
538
539     protected void actionPerformedImpl(Caret c, int offs)
540     {
541       c.moveDot(offs);
542     }
543     
544   }
545
546   static class SelectionUpAction
547   extends TextAction.VerticalMovementAction
548   {
549     SelectionUpAction()
550     {
551       super(selectionUpAction, SwingConstants.NORTH);
552     }
553
554     protected void actionPerformedImpl(Caret c, int offs)
555     {
556       c.moveDot(offs);
557     }
558
559   }
560
561   static class SelectionForwardAction
562       extends TextAction.HorizontalMovementAction
563   {
564     SelectionForwardAction()
565     {
566       super(selectionForwardAction, SwingConstants.EAST);
567     }
568
569     protected void actionPerformedImpl(Caret c, int offs)
570     {
571       c.moveDot(offs);
572     }
573   }
574
575   static class SelectionBackwardAction
576       extends TextAction.HorizontalMovementAction
577   {
578     SelectionBackwardAction()
579     {
580       super(selectionBackwardAction, SwingConstants.WEST);
581     }
582
583     protected void actionPerformedImpl(Caret c, int offs)
584     {
585       c.moveDot(offs);
586     }
587   }
588
589   static class DownAction
590       extends TextAction.VerticalMovementAction
591   {
592     DownAction()
593     {
594       super(downAction, SwingConstants.SOUTH);
595     }
596
597     protected void actionPerformedImpl(Caret c, int offs)
598     {
599       c.setDot(offs);
600     }
601   }
602
603   static class UpAction
604       extends TextAction.VerticalMovementAction
605   {
606     UpAction()
607     {
608       super(upAction, SwingConstants.NORTH);
609     }
610
611     protected void actionPerformedImpl(Caret c, int offs)
612     {
613       c.setDot(offs);
614     }
615     
616   }
617
618   static class ForwardAction
619       extends TextAction.HorizontalMovementAction
620   {
621     ForwardAction()
622     {
623       super(forwardAction, SwingConstants.EAST);
624     }
625
626     protected void actionPerformedImpl(Caret c, int offs)
627     {
628       c.setDot(offs);
629     }
630     
631   }
632
633   static class BackwardAction
634       extends TextAction.HorizontalMovementAction
635   {
636     BackwardAction()
637     {
638       super(backwardAction, SwingConstants.WEST);
639     }
640
641     protected void actionPerformedImpl(Caret c, int offs)
642     {
643       c.setDot(offs);
644     }
645     
646   }
647
648   static class DeletePrevCharAction
649       extends TextAction
650   {
651     DeletePrevCharAction()
652     {
653       super(deletePrevCharAction);
654     }
655
656     public void actionPerformed(ActionEvent event)
657     {
658       JTextComponent t = getTextComponent(event);
659       if (t != null)
660         {
661           try
662             {
663               int pos = t.getSelectionStart();
664               int len = t.getSelectionEnd() - pos;
665               
666               if (len > 0)
667                   t.getDocument().remove(pos, len);
668               else if (pos > 0)
669                 {
670                   pos--;
671                   t.getDocument().remove(pos, 1);
672                   Caret c = t.getCaret();
673                   c.setDot(pos);
674                   c.setMagicCaretPosition(t.modelToView(pos).getLocation());
675                 }
676             }
677           catch (BadLocationException e)
678             {
679               // FIXME: we're not authorized to throw this.. swallow it?
680             }
681         }
682     }
683   }
684
685   static class DeleteNextCharAction
686       extends TextAction
687   {
688     DeleteNextCharAction()
689     {
690       super(deleteNextCharAction);
691     }
692
693     public void actionPerformed(ActionEvent event)
694     {
695       JTextComponent t = getTextComponent(event);
696       if (t != null)
697         {
698           try
699             {
700               int pos = t.getSelectionStart();
701               int len = t.getSelectionEnd() - pos;
702               
703               if (len > 0)
704                   t.getDocument().remove(pos, len);
705               else if (pos < t.getDocument().getLength())
706                   t.getDocument().remove(pos, 1);
707     
708               Caret c = t.getCaret();
709               c.setDot(pos);
710               c.setMagicCaretPosition(t.modelToView(pos).getLocation());
711             }
712           catch (BadLocationException e)
713             {
714               // FIXME: we're not authorized to throw this.. swallow it?
715             }
716         }
717     }
718   }
719
720   static class EndLineAction
721       extends TextAction
722   {
723     EndLineAction()
724     {
725       super(endLineAction);
726     }
727
728     public void actionPerformed(ActionEvent event)
729     {
730       JTextComponent t = getTextComponent(event);
731       if (t != null)
732         {
733           try
734             {
735               int offs = Utilities.getRowEnd(t, t.getCaretPosition());
736               if (offs > -1)
737                 {
738                   Caret c = t.getCaret();
739                   c.setDot(offs);
740                   c.setMagicCaretPosition(t.modelToView(offs).getLocation());
741                 }
742             }
743           catch (BadLocationException ble)
744             {
745               // Nothing to do here
746             }
747         }
748     }
749   }
750
751   static class BeginLineAction
752       extends TextAction
753   {
754     BeginLineAction()
755     {
756       super(beginLineAction);
757     }
758
759     public void actionPerformed(ActionEvent event)
760     {
761       JTextComponent t = getTextComponent(event);
762       if (t != null)
763         {
764           try
765             {
766               int offs = Utilities.getRowStart(t, t.getCaretPosition());
767               if (offs > -1)
768                 {
769                   Caret c = t.getCaret();
770                   c.setDot(offs);
771                   c.setMagicCaretPosition(t.modelToView(offs).getLocation());
772                 }
773             }
774           catch (BadLocationException ble)
775             {
776               // Do nothing here.
777             }
778         }
779     }
780   }
781
782   static class BeginAction extends TextAction
783   {
784     
785     BeginAction()
786     {
787       super(beginAction);
788     }
789
790     public void actionPerformed(ActionEvent event)
791     {
792       JTextComponent t = getTextComponent(event);
793       if (t != null)
794         {
795           Caret c = t.getCaret();
796           c.setDot(0);
797           try
798             {
799               c.setMagicCaretPosition(t.modelToView(0).getLocation());
800             }
801           catch(BadLocationException ble)
802             {
803               // Can't happen.
804             }
805         }
806     }
807   }
808
809   static class EndAction extends TextAction
810   {
811       
812     EndAction()
813     {
814       super(endAction);
815     }
816
817     public void actionPerformed(ActionEvent event)
818     {
819       JTextComponent t = getTextComponent(event);
820       if (t != null)
821         {
822           int offs = t.getDocument().getLength();
823           Caret c = t.getCaret();
824           c.setDot(offs);
825           try
826             {   
827               c.setMagicCaretPosition(t.modelToView(offs).getLocation());
828             }
829           catch(BadLocationException ble)
830             {
831               // Can't happen.
832             }
833         }
834     }
835   }
836   
837   /**
838    * Creates a beep on the PC speaker.
839    *
840    * @see Toolkit#beep()
841    */
842   public static class BeepAction extends TextAction
843   {
844     /**
845      * Creates a new <code>BeepAction</code>.
846      */
847     public BeepAction()
848     {
849       super(beepAction);
850     }
851
852     /**
853      * Performs the <code>Action</code>.
854      *
855      * @param event the action event describing the user action
856      */
857     public void actionPerformed(ActionEvent event)
858     {
859       Toolkit.getDefaultToolkit().beep();
860     }
861   }
862
863   /**
864    * Copies the selected content into the system clipboard.
865    *
866    * @see Toolkit#getSystemClipboard()
867    * @see CutAction
868    * @see PasteAction
869    */
870   public static class CopyAction extends TextAction
871   {
872
873     /**
874      * Create a new <code>CopyAction</code>.
875      */
876     public CopyAction()
877     {
878       super(copyAction);
879     }
880
881     /**
882      * Performs the <code>Action</code>.
883      *
884      * @param event the action event describing the user action
885      */
886     public void actionPerformed(ActionEvent event)
887     {
888       JTextComponent target = getTextComponent(event);
889       if (target != null)
890         target.copy();
891     }
892   }
893
894
895   /**
896    * Copies the selected content into the system clipboard and deletes the
897    * selection.
898    *
899    * @see Toolkit#getSystemClipboard()
900    * @see CopyAction
901    * @see PasteAction
902    */
903   public static class CutAction extends TextAction
904   {
905
906     /**
907      * Create a new <code>CutAction</code>.
908      */
909     public CutAction()
910     {
911       super(cutAction);
912     }
913
914     /**
915      * Performs the <code>Action</code>.
916      *
917      * @param event the action event describing the user action
918      */
919     public void actionPerformed(ActionEvent event)
920     {
921       JTextComponent target = getTextComponent(event);
922       if (target != null)
923         target.cut();
924     }
925   }
926
927   /**
928    * Copies content from the system clipboard into the editor.
929    *
930    * @see Toolkit#getSystemClipboard()
931    * @see CopyAction
932    * @see CutAction
933    */
934   public static class PasteAction extends TextAction
935   {
936
937     /**
938      * Create a new <code>PasteAction</code>.
939      */
940     public PasteAction()
941     {
942       super(pasteAction);
943     }
944
945     /**
946      * Performs the <code>Action</code>.
947      *
948      * @param event the action event describing the user action
949      */
950     public void actionPerformed(ActionEvent event)
951     {
952       JTextComponent target = getTextComponent(event);
953       if (target != null)
954         target.paste();
955     }
956   }
957
958   /**
959    * This action is executed as default action when a KEY_TYPED
960    * event is received and no keymap entry exists for that. The purpose
961    * of this action is to filter out a couple of characters. This includes
962    * the control characters and characters with the ALT-modifier.
963    * 
964    * If an event does not get filtered, it is inserted into the document
965    * of the text component. If there is some text selected in the text
966    * component, this text will be replaced.
967    */
968   public static class DefaultKeyTypedAction 
969     extends TextAction
970   {
971
972     /**
973      * Creates a new <code>DefaultKeyTypedAction</code>.
974      */
975     public DefaultKeyTypedAction()
976     {
977       super(defaultKeyTypedAction);
978     }
979
980     /**
981      * Performs the <code>Action</code>.
982      *
983      * @param event the action event describing the user action
984      */
985     public void actionPerformed(ActionEvent event)
986     {
987       // first we filter the following events:
988       // - control characters
989       // - key events with the ALT modifier
990       JTextComponent target = getTextComponent(event);
991       if ((target != null) && (event != null))
992         {
993           if ((target.isEditable()) && (target.isEnabled()))
994             {
995               String content = event.getActionCommand();
996               int mod = event.getModifiers();
997               if ((content != null) && (content.length() > 0)
998                   && (mod & ActionEvent.ALT_MASK) == 0
999                   && (mod & ActionEvent.CTRL_MASK) == 0)
1000                 {
1001                   char c = content.charAt(0);
1002                   if ((c >= 0x20) && (c != 0x7F))
1003                     {
1004                       target.replaceSelection(content);
1005                     }
1006                 }
1007             }
1008         }
1009     }    
1010   }
1011
1012   /**
1013    * This action inserts a newline character into the document
1014    * of the text component. This is typically triggered by hitting
1015    * ENTER on the keyboard.
1016    */
1017   public static class InsertBreakAction extends TextAction
1018   {
1019
1020     /**
1021      * Creates a new <code>InsertBreakAction</code>.
1022      */
1023     public InsertBreakAction()
1024     {
1025       super(insertBreakAction);
1026     }
1027
1028     /**
1029      * Performs the <code>Action</code>.
1030      *
1031      * @param event the action event describing the user action
1032      */
1033     public void actionPerformed(ActionEvent event)
1034     {
1035       JTextComponent t = getTextComponent(event);
1036       if (t != null)
1037         t.replaceSelection("\n");
1038     }
1039   }
1040
1041   /**
1042    * Places content into the associated editor. If there currently is a
1043    * selection, this selection is replaced.
1044    */
1045   // FIXME: Figure out what this Action is supposed to do. Obviously text
1046   // that is entered by the user is inserted through DefaultKeyTypedAction.
1047   public static class InsertContentAction extends TextAction
1048   {
1049
1050     /**
1051      * Creates a new <code>InsertContentAction</code>.
1052      */
1053     public InsertContentAction()
1054     {
1055       super(insertContentAction);
1056     }
1057
1058     /**
1059      * Performs the <code>Action</code>.
1060      *
1061      * @param event the action event describing the user action
1062      */
1063     public void actionPerformed(ActionEvent event)
1064     {
1065       // FIXME: Figure out what this Action is supposed to do. Obviously text
1066       // that is entered by the user is inserted through DefaultKeyTypedAction.
1067     }
1068   }
1069
1070   /**
1071    * Inserts a TAB character into the text editor.
1072    */
1073   public static class InsertTabAction extends TextAction
1074   {
1075
1076     /**
1077      * Creates a new <code>TabAction</code>.
1078      */
1079     public InsertTabAction()
1080     {
1081       super(insertTabAction);
1082     }
1083
1084     /**
1085      * Performs the <code>Action</code>.
1086      *
1087      * @param event the action event describing the user action
1088      */
1089     public void actionPerformed(ActionEvent event)
1090     {
1091       JTextComponent t = getTextComponent(event);
1092       if (t != null)
1093         t.replaceSelection("\t");
1094     }
1095   }
1096
1097   /**
1098    * The serial version of DefaultEditorKit.
1099    */
1100   private static final long serialVersionUID = 9017245433028523428L;
1101
1102   /**
1103    * The name of the <code>Action</code> that moves the caret one character
1104    * backwards.
1105    *
1106    * @see #getActions()
1107    */
1108   public static final String backwardAction = "caret-backward";
1109
1110   /**
1111    * The name of the <code>Action</code> that creates a beep in the speaker.
1112    *
1113    * @see #getActions()
1114    */
1115   public static final String beepAction = "beep";
1116
1117   /**
1118    * The name of the <code>Action</code> that moves the caret to the beginning
1119    * of the <code>Document</code>.
1120    *
1121    * @see #getActions()
1122    */
1123   public static final String beginAction = "caret-begin";
1124
1125   /**
1126    * The name of the <code>Action</code> that moves the caret to the beginning
1127    * of the current line.
1128    *
1129    * @see #getActions()
1130    */
1131   public static final String beginLineAction = "caret-begin-line";
1132
1133   /**
1134    * The name of the <code>Action</code> that moves the caret to the beginning
1135    * of the current paragraph.
1136    *
1137    * @see #getActions()
1138    */
1139   public static final String beginParagraphAction = "caret-begin-paragraph";
1140
1141   /**
1142    * The name of the <code>Action</code> that moves the caret to the beginning
1143    * of the current word.
1144    *
1145    * @see #getActions()
1146    */
1147   public static final String beginWordAction = "caret-begin-word";
1148
1149   /**
1150    * The name of the <code>Action</code> that copies the selected content
1151    * into the system clipboard.
1152    *
1153    * @see #getActions()
1154    */
1155   public static final String copyAction = "copy-to-clipboard";
1156
1157   /**
1158    * The name of the <code>Action</code> that copies the selected content
1159    * into the system clipboard and removes the selection.
1160    *
1161    * @see #getActions()
1162    */
1163   public static final String cutAction = "cut-to-clipboard";
1164
1165   /**
1166    * The name of the <code>Action</code> that is performed by default if
1167    * a key is typed and there is no keymap entry.
1168    *
1169    * @see #getActions()
1170    */
1171   public static final String defaultKeyTypedAction = "default-typed";
1172
1173   /**
1174    * The name of the <code>Action</code> that deletes the character that
1175    * follows the current caret position.
1176    *
1177    * @see #getActions()
1178    */
1179   public static final String deleteNextCharAction = "delete-next";
1180
1181   /**
1182    * The name of the <code>Action</code> that deletes the character that
1183    * precedes the current caret position.
1184    *
1185    * @see #getActions()
1186    */
1187   public static final String deletePrevCharAction = "delete-previous";
1188
1189   /**
1190    * The name of the <code>Action</code> that moves the caret one line down.
1191    *
1192    * @see #getActions()
1193    */
1194   public static final String downAction = "caret-down";
1195
1196   /**
1197    * The name of the <code>Action</code> that moves the caret to the end
1198    * of the <code>Document</code>.
1199    *
1200    * @see #getActions()
1201    */
1202   public static final String endAction = "caret-end";
1203
1204   /**
1205    * The name of the <code>Action</code> that moves the caret to the end
1206    * of the current line.
1207    *
1208    * @see #getActions()
1209    */
1210   public static final String endLineAction = "caret-end-line";
1211
1212   /**
1213    * When a document is read and an CRLF is encountered, then we add a property
1214    * with this name and a value of &quot;\r\n&quot;.
1215    */
1216   public static final String EndOfLineStringProperty = "__EndOfLine__";
1217
1218   /**
1219    * The name of the <code>Action</code> that moves the caret to the end
1220    * of the current paragraph.
1221    *
1222    * @see #getActions()
1223    */
1224   public static final String endParagraphAction = "caret-end-paragraph";
1225
1226   /**
1227    * The name of the <code>Action</code> that moves the caret to the end
1228    * of the current word.
1229    *
1230    * @see #getActions()
1231    */
1232   public static final String endWordAction = "caret-end-word";
1233
1234   /**
1235    * The name of the <code>Action</code> that moves the caret one character
1236    * forward.
1237    *
1238    * @see #getActions()
1239    */
1240   public static final String forwardAction = "caret-forward";
1241
1242   /**
1243    * The name of the <code>Action</code> that inserts a line break.
1244    *
1245    * @see #getActions()
1246    */
1247   public static final String insertBreakAction = "insert-break";
1248
1249   /**
1250    * The name of the <code>Action</code> that inserts some content.
1251    *
1252    * @see #getActions()
1253    */
1254   public static final String insertContentAction = "insert-content";
1255
1256   /**
1257    * The name of the <code>Action</code> that inserts a TAB.
1258    *
1259    * @see #getActions()
1260    */
1261   public static final String insertTabAction = "insert-tab";
1262
1263   /**
1264    * The name of the <code>Action</code> that moves the caret to the beginning
1265    * of the next word.
1266    *
1267    * @see #getActions()
1268    */
1269   public static final String nextWordAction = "caret-next-word";
1270
1271   /**
1272    * The name of the <code>Action</code> that moves the caret one page down.
1273    *
1274    * @see #getActions()
1275    */
1276   public static final String pageDownAction = "page-down";
1277
1278   /**
1279    * The name of the <code>Action</code> that moves the caret one page up.
1280    *
1281    * @see #getActions()
1282    */
1283   public static final String pageUpAction = "page-up";
1284
1285   /**
1286    * The name of the <code>Action</code> that copies content from the system
1287    * clipboard into the document.
1288    *
1289    * @see #getActions()
1290    */
1291   public static final String pasteAction = "paste-from-clipboard";
1292
1293   /**
1294    * The name of the <code>Action</code> that moves the caret to the beginning
1295    * of the previous word.
1296    *
1297    * @see #getActions()
1298    */
1299   public static final String previousWordAction = "caret-previous-word";
1300
1301   /**
1302    * The name of the <code>Action</code> that sets the editor in read only
1303    * mode.
1304    *
1305    * @see #getActions()
1306    */
1307   public static final String readOnlyAction = "set-read-only";
1308
1309   /**
1310    * The name of the <code>Action</code> that selects the whole document.
1311    *
1312    * @see #getActions()
1313    */
1314   public static final String selectAllAction = "select-all";
1315
1316   /**
1317    * The name of the <code>Action</code> that moves the caret one character
1318    * backwards, possibly extending the current selection.
1319    *
1320    * @see #getActions()
1321    */
1322   public static final String selectionBackwardAction = "selection-backward";
1323
1324   /**
1325    * The name of the <code>Action</code> that moves the caret to the beginning
1326    * of the document, possibly extending the current selection.
1327    *
1328    * @see #getActions()
1329    */
1330   public static final String selectionBeginAction = "selection-begin";
1331
1332   /**
1333    * The name of the <code>Action</code> that moves the caret to the beginning
1334    * of the current line, possibly extending the current selection.
1335    *
1336    * @see #getActions()
1337    */
1338   public static final String selectionBeginLineAction = "selection-begin-line";
1339
1340   /**
1341    * The name of the <code>Action</code> that moves the caret to the beginning
1342    * of the current paragraph, possibly extending the current selection.
1343    *
1344    * @see #getActions()
1345    */
1346   public static final String selectionBeginParagraphAction =
1347     "selection-begin-paragraph";
1348
1349   /**
1350    * The name of the <code>Action</code> that moves the caret to the beginning
1351    * of the current word, possibly extending the current selection.
1352    *
1353    * @see #getActions()
1354    */
1355   public static final String selectionBeginWordAction = "selection-begin-word";
1356
1357   /**
1358    * The name of the <code>Action</code> that moves the caret one line down,
1359    * possibly extending the current selection.
1360    *
1361    * @see #getActions()
1362    */
1363   public static final String selectionDownAction = "selection-down";
1364
1365   /**
1366    * The name of the <code>Action</code> that moves the caret to the end
1367    * of the document, possibly extending the current selection.
1368    *
1369    * @see #getActions()
1370    */
1371   public static final String selectionEndAction = "selection-end";
1372
1373   /**
1374    * The name of the <code>Action</code> that moves the caret to the end
1375    * of the current line, possibly extending the current selection.
1376    *
1377    * @see #getActions()
1378    */
1379   public static final String selectionEndLineAction = "selection-end-line";
1380
1381   /**
1382    * The name of the <code>Action</code> that moves the caret to the end
1383    * of the current paragraph, possibly extending the current selection.
1384    *
1385    * @see #getActions()
1386    */
1387   public static final String selectionEndParagraphAction =
1388     "selection-end-paragraph";
1389
1390   /**
1391    * The name of the <code>Action</code> that moves the caret to the end
1392    * of the current word, possibly extending the current selection.
1393    *
1394    * @see #getActions()
1395    */
1396   public static final String selectionEndWordAction = "selection-end-word";
1397
1398   /**
1399    * The name of the <code>Action</code> that moves the caret one character
1400    * forwards, possibly extending the current selection.
1401    *
1402    * @see #getActions()
1403    */
1404   public static final String selectionForwardAction = "selection-forward";
1405
1406   /**
1407    * The name of the <code>Action</code> that moves the caret to the beginning
1408    * of the next word, possibly extending the current selection.
1409    *
1410    * @see #getActions()
1411    */
1412   public static final String selectionNextWordAction = "selection-next-word";
1413
1414   /**
1415    * The name of the <code>Action</code> that moves the caret to the beginning
1416    * of the previous word, possibly extending the current selection.
1417    *
1418    * @see #getActions()
1419    */
1420   public static final String selectionPreviousWordAction =
1421     "selection-previous-word";
1422
1423   /**
1424    * The name of the <code>Action</code> that moves the caret one line up,
1425    * possibly extending the current selection.
1426    *
1427    * @see #getActions()
1428    */
1429   public static final String selectionUpAction = "selection-up";
1430
1431   /**
1432    * The name of the <code>Action</code> that selects the line around the
1433    * caret.
1434    *
1435    * @see #getActions()
1436    */
1437   public static final String selectLineAction = "select-line";
1438
1439   /**
1440    * The name of the <code>Action</code> that selects the paragraph around the
1441    * caret.
1442    *
1443    * @see #getActions()
1444    */
1445   public static final String selectParagraphAction = "select-paragraph";
1446
1447   /**
1448    * The name of the <code>Action</code> that selects the word around the
1449    * caret.
1450    *
1451    * @see #getActions()
1452    */
1453   public static final String selectWordAction = "select-word";
1454
1455   /**
1456    * The name of the <code>Action</code> that moves the caret one line up.
1457    *
1458    * @see #getActions()
1459    */
1460   public static final String upAction = "caret-up";
1461
1462   /**
1463    * The name of the <code>Action</code> that sets the editor in read-write
1464    * mode.
1465    *
1466    * @see #getActions()
1467    */
1468   public static final String writableAction = "set-writable";
1469
1470   /**
1471    * Creates a new <code>DefaultEditorKit</code>.
1472    */
1473   public DefaultEditorKit()
1474   {
1475     // Nothing to do here.
1476   }
1477
1478   /**
1479    * The <code>Action</code>s that are supported by the
1480    * <code>DefaultEditorKit</code>.
1481    */
1482   private static Action[] defaultActions = 
1483   new Action[] {
1484     // These classes are public because they are so in the RI.            
1485     new BeepAction(),
1486     new CopyAction(),
1487     new CutAction(),
1488     new DefaultKeyTypedAction(),
1489     new InsertBreakAction(),
1490     new InsertContentAction(),
1491     new InsertTabAction(),
1492     new PasteAction(),
1493     
1494     // These are (package-)private inner classes.
1495     new DeleteNextCharAction(),
1496     new DeletePrevCharAction(),
1497
1498     new BeginLineAction(),
1499     new SelectionBeginLineAction(),
1500     
1501     new EndLineAction(),
1502     new SelectionEndLineAction(),
1503     
1504     new BackwardAction(),
1505     new SelectionBackwardAction(),
1506
1507     new ForwardAction(),
1508     new SelectionForwardAction(),
1509     
1510     new UpAction(),
1511     new SelectionUpAction(),
1512
1513     new DownAction(),
1514     new SelectionDownAction(),
1515     
1516     new NextWordAction(),
1517     new SelectionNextWordAction(),
1518
1519     new PreviousWordAction(),
1520     new SelectionPreviousWordAction(),
1521
1522     new BeginAction(),
1523     new SelectionBeginAction(),
1524     
1525     new EndAction(),
1526     new SelectionEndAction(),
1527     
1528     new BeginWordAction(),
1529     new SelectionBeginWordAction(),
1530     
1531     new EndWordAction(),
1532     new SelectionEndWordAction(),
1533     
1534     new SelectAllAction(),
1535     new SelectLineAction(),
1536     new SelectWordAction()
1537   };
1538
1539   /**
1540    * Creates the <code>Caret</code> for this <code>EditorKit</code>. This
1541    * returns a {@link DefaultCaret} in this case.
1542    *
1543    * @return the <code>Caret</code> for this <code>EditorKit</code>
1544    */
1545   public Caret createCaret()
1546   {
1547     return new DefaultCaret();
1548   }
1549
1550   /**
1551    * Creates the default {@link Document} that this <code>EditorKit</code>
1552    * supports. This is a {@link PlainDocument} in this case.
1553    *
1554    * @return the default {@link Document} that this <code>EditorKit</code>
1555    *         supports
1556    */
1557   public Document createDefaultDocument()
1558   {
1559     return new PlainDocument();
1560   }
1561
1562   /**
1563    * Returns the <code>Action</code>s supported by this <code>EditorKit</code>.
1564    *
1565    * @return the <code>Action</code>s supported by this <code>EditorKit</code>
1566    */
1567   public Action[] getActions()
1568   {
1569     return defaultActions;
1570   }
1571
1572   /**
1573    * Returns the content type that this <code>EditorKit</code> supports.
1574    * The <code>DefaultEditorKit</code> supports the content type
1575    * <code>text/plain</code>.
1576    *
1577    * @return the content type that this <code>EditorKit</code> supports
1578    */
1579   public String getContentType()
1580   {
1581     return "text/plain";
1582   }
1583
1584   /**
1585    * Returns a {@link ViewFactory} that is able to create {@link View}s for
1586    * the <code>Element</code>s that are used in this <code>EditorKit</code>'s
1587    * model. This returns null which lets the UI of the text component supply
1588    * <code>View</code>s.
1589    *
1590    * @return a {@link ViewFactory} that is able to create {@link View}s for
1591    *         the <code>Element</code>s that are used in this
1592    *         <code>EditorKit</code>'s model
1593    */
1594   public ViewFactory getViewFactory()
1595   {
1596     return null;
1597   }
1598
1599   /**
1600    * Reads a document of the supported content type from an {@link InputStream}
1601    * into the actual {@link Document} object.
1602    *
1603    * @param in the stream from which to read the document
1604    * @param document the document model into which the content is read
1605    * @param offset the offset inside to document where the content is inserted
1606    *
1607    * @throws BadLocationException if <code>offset</code> is an invalid location
1608    *         inside <code>document</code>
1609    * @throws IOException if something goes wrong while reading from
1610    *        <code>in</code>
1611    */
1612   public void read(InputStream in, Document document, int offset)
1613     throws BadLocationException, IOException
1614   {
1615     read(new InputStreamReader(in), document, offset);
1616   }
1617
1618   /**
1619    * Reads a document of the supported content type from a {@link Reader}
1620    * into the actual {@link Document} object.
1621    *
1622    * @param in the reader from which to read the document
1623    * @param document the document model into which the content is read
1624    * @param offset the offset inside to document where the content is inserted
1625    *
1626    * @throws BadLocationException if <code>offset</code> is an invalid location
1627    *         inside <code>document</code>
1628    * @throws IOException if something goes wrong while reading from
1629    *        <code>in</code>
1630    */
1631   public void read(Reader in, Document document, int offset)
1632     throws BadLocationException, IOException
1633   {
1634     BufferedReader reader = new BufferedReader(in);
1635
1636     String line;
1637     StringBuffer content = new StringBuffer();
1638
1639     while ((line = reader.readLine()) != null)
1640       {
1641         content.append(line);
1642         content.append("\n");
1643       }
1644     
1645     document.insertString(offset, content.substring(0, content.length() - 1),
1646                           SimpleAttributeSet.EMPTY);
1647   }
1648
1649   /**
1650    * Writes the <code>Document</code> (or a fragment of the
1651    * <code>Document</code>) to an {@link OutputStream} in the
1652    * supported content type format.
1653    *
1654    * @param out the stream to write to
1655    * @param document the document that should be written out
1656    * @param offset the beginning offset from where to write
1657    * @param len the length of the fragment to write
1658    *
1659    * @throws BadLocationException if <code>offset</code> or
1660    *         <code>offset + len</code>is an invalid location inside
1661    *         <code>document</code>
1662    * @throws IOException if something goes wrong while writing to
1663    *        <code>out</code>
1664    */
1665   public void write(OutputStream out, Document document, int offset, int len)
1666     throws BadLocationException, IOException
1667   {
1668     write(new OutputStreamWriter(out), document, offset, len);
1669   }
1670
1671   /**
1672    * Writes the <code>Document</code> (or a fragment of the
1673    * <code>Document</code>) to a {@link Writer} in the
1674    * supported content type format.
1675    *
1676    * @param out the writer to write to
1677    * @param document the document that should be written out
1678    * @param offset the beginning offset from where to write
1679    * @param len the length of the fragment to write
1680    *
1681    * @throws BadLocationException if <code>offset</code> is an 
1682    * invalid location inside <code>document</code>.
1683    * @throws IOException if something goes wrong while writing to
1684    *        <code>out</code>
1685    */
1686   public void write(Writer out, Document document, int offset, int len)
1687       throws BadLocationException, IOException
1688   {
1689     // Throw a BLE if offset is invalid
1690     if (offset < 0 || offset > document.getLength())
1691       throw new BadLocationException("Tried to write to invalid location",
1692                                      offset);
1693
1694     // If they gave an overly large len, just adjust it
1695     if (offset + len > document.getLength())
1696       len = document.getLength() - offset;
1697
1698     out.write(document.getText(offset, len));
1699   }
1700 }