OSDN Git Service

c984bd892ee093de2a7c0f8ad53f881af869fb3c
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / text / StringContent.java
1 /* StringContent.java --
2    Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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.io.Serializable;
42 import java.util.Iterator;
43 import java.util.Vector;
44
45 import javax.swing.undo.AbstractUndoableEdit;
46 import javax.swing.undo.CannotRedoException;
47 import javax.swing.undo.CannotUndoException;
48 import javax.swing.undo.UndoableEdit;
49
50 /**
51  * An implementation of the <code>AbstractDocument.Content</code>
52  * interface useful for small documents or debugging. The character
53  * content is a simple character array. It's not really efficient.
54  * 
55  * <p>Do not use this class for large size.</p>
56  */
57 public final class StringContent implements AbstractDocument.Content, Serializable
58 {
59   private char[] content;
60
61   private int count;
62
63   private Vector positions = new Vector();
64
65   private class InsertUndo extends AbstractUndoableEdit
66   {
67     private int start;
68     
69     private int length;
70
71     private String redoContent;
72
73     public InsertUndo(int start, int length)
74     {
75       super();
76       this.start = start;
77       this.length = length;
78     }
79
80     public void undo()
81     {
82       super.undo();
83       try
84         {
85           StringContent.this.checkLocation(this.start, this.length);
86           this.redoContent = new String(StringContent.this.content, this.start, this.length);
87           StringContent.this.remove(this.start, this.length);
88         }
89       catch (BadLocationException b)
90         {
91           throw new CannotUndoException();
92         }
93     }
94     
95     public void redo()
96     {
97       super.redo();
98       try
99         {
100           StringContent.this.insertString(this.start, this.redoContent);
101         }
102       catch (BadLocationException b)
103         {
104           throw new CannotRedoException();
105         }
106     }
107   }
108
109   private class RemoveUndo extends AbstractUndoableEdit
110   {
111     private int start;
112
113     private String undoString;
114
115     public RemoveUndo(int start, String str)
116     {
117       super();
118       this.start = start;
119       this.undoString = str;
120     }
121
122     public void undo()
123     {
124       super.undo();
125       try
126         {
127           StringContent.this.insertString(this.start, this.undoString);
128         }
129       catch (BadLocationException bad)
130         {
131           throw new CannotUndoException();
132         }
133     }
134
135     public void redo()
136     {
137       super.redo();
138       try
139         {
140           int end = this.undoString.length();
141           StringContent.this.remove(this.start, end);
142         }
143       catch (BadLocationException bad)
144         {
145           throw new CannotRedoException();
146         }
147     }
148   }
149
150   private class StickyPosition implements Position
151   {
152     private int offset = -1;
153
154     public StickyPosition(int offset)
155     {
156       this.offset = offset;
157     }
158
159     private void setOffset(int offset)
160     {
161       this.offset = this.offset >= 0 ? offset : -1;
162     }
163
164     /**
165      * Should be >=0.
166      */
167     public int getOffset()
168     {
169       return offset < 0 ? 0 : offset;
170     }
171   }
172
173   public StringContent()
174   {
175     this(1);
176   }
177
178   public StringContent(int initialLength)
179   {
180     super();
181     if (initialLength < 1)
182       initialLength = 1;
183     this.content = new char[initialLength];
184     this.content[0] = '\n';
185     this.count = 1;
186   }
187
188   protected Vector getPositionsInRange(Vector v,
189                                        int offset,
190                                        int length)
191   {
192     Vector refPos = new Vector();
193     Iterator iter = this.positions.iterator();
194     while(iter.hasNext())
195       {
196         Position p = (Position)iter.next();
197         if ((offset <= p.getOffset())
198             && (p.getOffset() <= (offset + length)))
199           refPos.add(p);
200       }
201     return refPos;
202   }
203
204   public Position createPosition(int offset) throws BadLocationException
205   {
206     if (offset < this.count || offset > this.count)
207       checkLocation(offset, 0);
208     StickyPosition sp = new StickyPosition(offset);
209     this.positions.add(sp);
210     return sp;
211   }
212   
213   public int length()
214   {
215     return this.count;
216   }
217   
218   public UndoableEdit insertString(int where, String str)
219     throws BadLocationException
220   {
221     checkLocation(where, 0);
222     if (where == this.count)
223       throw new BadLocationException("Invalid location", 1);
224     if (str == null)
225       throw new NullPointerException();
226     char[] insert = str.toCharArray();
227     char[] temp = new char[this.content.length + insert.length];
228     this.count += insert.length;
229     // Copy array and insert the string.
230     if (where > 0)
231       System.arraycopy(this.content, 0, temp, 0, where);
232     System.arraycopy(insert, 0, temp, where, insert.length);
233     System.arraycopy(this.content, where, temp, (where + insert.length), (temp.length - where - insert.length));
234     if (this.content.length < temp.length)
235       this.content = new char[temp.length];
236     // Copy the result in the original char array.
237     System.arraycopy(temp, 0, this.content, 0, temp.length);
238     // Move all the positions.
239     Vector refPos = getPositionsInRange(this.positions, where, temp.length - where);
240     Iterator iter = refPos.iterator();
241     while (iter.hasNext())
242       {
243         StickyPosition p = (StickyPosition)iter.next();
244         p.setOffset(p.getOffset() + str.length());
245       }
246     InsertUndo iundo = new InsertUndo(where, insert.length);
247     return iundo;
248   }
249   
250   public UndoableEdit remove(int where, int nitems) throws BadLocationException
251   {
252     checkLocation(where, nitems);
253     char[] temp = new char[(this.content.length - nitems)];
254     this.count = this.count - nitems;
255     RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where, nitems));
256     // Copy array.
257     System.arraycopy(this.content, 0, temp, 0, where);
258     System.arraycopy(this.content, where + nitems, temp, where, this.content.length - where - nitems);
259     this.content = new char[temp.length];
260     // Then copy the result in the original char array.
261     System.arraycopy(temp, 0, this.content, 0, this.content.length);
262     // Move all the positions.
263     Vector refPos = getPositionsInRange(this.positions, where, this.content.length + nitems - where);
264     Iterator iter = refPos.iterator();
265     while (iter.hasNext())
266       {
267         StickyPosition p = (StickyPosition)iter.next();
268         int result = p.getOffset() - nitems;
269         p.setOffset(result);
270         if (result < 0)
271           this.positions.remove(p);
272       }
273     return rundo;
274   }
275   
276   public String getString(int where, int len) throws BadLocationException
277   {
278     checkLocation(where, len);
279     return new String (this.content, where, len);
280   }
281   
282   public void getChars(int where, int len, Segment txt) throws BadLocationException
283   {
284     checkLocation(where, len);
285     if (txt != null)
286       {
287         txt.array = this.content;
288         txt.offset = where;
289         txt.count = len;
290       }
291   }
292
293   private void checkLocation(int where, int len) throws BadLocationException
294   {
295     if (where < 0)
296       throw new BadLocationException("Invalid location", 1);
297     else if (where > this.count)
298       throw new BadLocationException("Invalid location", this.count);
299     else if ((where + len)>this.count)
300       throw new BadLocationException("Invalid range", this.count);
301   }
302   
303 }
304