Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / javax / swing / text / StringContent.java
blob0a31505f3a652fbfe031a7e57f68bbadb1a754dc
1 /* StringContent.java --
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package javax.swing.text;
41 import java.io.Serializable;
42 import java.util.Iterator;
43 import java.util.Vector;
45 import javax.swing.undo.AbstractUndoableEdit;
46 import javax.swing.undo.CannotRedoException;
47 import javax.swing.undo.CannotUndoException;
48 import javax.swing.undo.UndoableEdit;
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.
55 * <p>Do not use this class for large size.</p>
57 public final class StringContent
58 implements AbstractDocument.Content, Serializable
60 /** The serialization UID (compatible with JDK1.5). */
61 private static final long serialVersionUID = 4755994433709540381L;
63 // This is package-private to avoid an accessor method.
64 char[] content;
66 private int count;
68 private Vector positions = new Vector();
70 private class InsertUndo extends AbstractUndoableEdit
72 private int start;
74 private int length;
76 private String redoContent;
78 public InsertUndo(int start, int length)
80 super();
81 this.start = start;
82 this.length = length;
85 public void undo()
87 super.undo();
88 try
90 StringContent.this.checkLocation(this.start, this.length);
91 this.redoContent = new String(StringContent.this.content, this.start,
92 this.length);
93 StringContent.this.remove(this.start, this.length);
95 catch (BadLocationException b)
97 throw new CannotUndoException();
101 public void redo()
103 super.redo();
106 StringContent.this.insertString(this.start, this.redoContent);
108 catch (BadLocationException b)
110 throw new CannotRedoException();
115 private class RemoveUndo extends AbstractUndoableEdit
117 private int start;
119 private String undoString;
121 public RemoveUndo(int start, String str)
123 super();
124 this.start = start;
125 this.undoString = str;
128 public void undo()
130 super.undo();
133 StringContent.this.insertString(this.start, this.undoString);
135 catch (BadLocationException bad)
137 throw new CannotUndoException();
141 public void redo()
143 super.redo();
146 int end = this.undoString.length();
147 StringContent.this.remove(this.start, end);
149 catch (BadLocationException bad)
151 throw new CannotRedoException();
156 private class StickyPosition implements Position
158 private int offset = -1;
160 public StickyPosition(int offset)
162 this.offset = offset;
165 // This is package-private to avoid an accessor method.
166 void setOffset(int offset)
168 this.offset = this.offset >= 0 ? offset : -1;
172 * Should be >=0.
174 public int getOffset()
176 return offset < 0 ? 0 : offset;
181 * Creates a new instance containing the string "\n".
183 public StringContent()
185 this(1);
189 * Creates a new instance containing the string "\n".
191 * @param initialLength the initial length of the underlying character
192 * array used to store the content.
194 public StringContent(int initialLength)
196 super();
197 if (initialLength < 1)
198 initialLength = 1;
199 this.content = new char[initialLength];
200 this.content[0] = '\n';
201 this.count = 1;
204 protected Vector getPositionsInRange(Vector v,
205 int offset,
206 int length)
208 Vector refPos = new Vector();
209 Iterator iter = this.positions.iterator();
210 while(iter.hasNext())
212 Position p = (Position) iter.next();
213 if ((offset <= p.getOffset())
214 && (p.getOffset() <= (offset + length)))
215 refPos.add(p);
217 return refPos;
221 * Creates a position reference for the character at the given offset. The
222 * position offset will be automatically updated when new characters are
223 * inserted into or removed from the content.
225 * @param offset the character offset.
227 * @throws BadLocationException if offset is outside the bounds of the
228 * content.
230 public Position createPosition(int offset) throws BadLocationException
232 if (offset < this.count || offset > this.count)
233 checkLocation(offset, 0);
234 StickyPosition sp = new StickyPosition(offset);
235 this.positions.add(sp);
236 return sp;
240 * Returns the length of the string content, including the '\n' character at
241 * the end.
243 * @return The length of the string content.
245 public int length()
247 return this.count;
251 * Inserts <code>str</code> at the given position and returns an
252 * {@link UndoableEdit} that enables undo/redo support.
254 * @param where the insertion point (must be less than
255 * <code>length()</code>).
256 * @param str the string to insert (<code>null</code> not permitted).
258 * @return An object that can undo the insertion.
260 public UndoableEdit insertString(int where, String str)
261 throws BadLocationException
263 checkLocation(where, 0);
264 if (where == this.count)
265 throw new BadLocationException("Invalid location", 1);
266 if (str == null)
267 throw new NullPointerException();
268 char[] insert = str.toCharArray();
269 char[] temp = new char[this.content.length + insert.length];
270 this.count += insert.length;
271 // Copy array and insert the string.
272 if (where > 0)
273 System.arraycopy(this.content, 0, temp, 0, where);
274 System.arraycopy(insert, 0, temp, where, insert.length);
275 System.arraycopy(this.content, where, temp, (where + insert.length),
276 (temp.length - where - insert.length));
277 if (this.content.length < temp.length)
278 this.content = new char[temp.length];
279 // Copy the result in the original char array.
280 System.arraycopy(temp, 0, this.content, 0, temp.length);
281 // Move all the positions.
282 Vector refPos = getPositionsInRange(this.positions, where,
283 temp.length - where);
284 Iterator iter = refPos.iterator();
285 while (iter.hasNext())
287 StickyPosition p = (StickyPosition)iter.next();
288 p.setOffset(p.getOffset() + str.length());
290 InsertUndo iundo = new InsertUndo(where, insert.length);
291 return iundo;
295 * Removes the specified range of characters and returns an
296 * {@link UndoableEdit} that enables undo/redo support.
298 * @param where the starting index.
299 * @param nitems the number of characters.
301 * @return An object that can undo the removal.
303 * @throws BadLocationException if the character range extends outside the
304 * bounds of the content OR includes the last character.
306 public UndoableEdit remove(int where, int nitems) throws BadLocationException
308 checkLocation(where, nitems + 1);
309 char[] temp = new char[(this.content.length - nitems)];
310 this.count = this.count - nitems;
311 RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where,
312 nitems));
313 // Copy array.
314 System.arraycopy(this.content, 0, temp, 0, where);
315 System.arraycopy(this.content, where + nitems, temp, where,
316 this.content.length - where - nitems);
317 this.content = new char[temp.length];
318 // Then copy the result in the original char array.
319 System.arraycopy(temp, 0, this.content, 0, this.content.length);
320 // Move all the positions.
321 Vector refPos = getPositionsInRange(this.positions, where,
322 this.content.length + nitems - where);
323 Iterator iter = refPos.iterator();
324 while (iter.hasNext())
326 StickyPosition p = (StickyPosition)iter.next();
327 int result = p.getOffset() - nitems;
328 p.setOffset(result);
329 if (result < 0)
330 this.positions.remove(p);
332 return rundo;
336 * Returns a new <code>String</code> containing the characters in the
337 * specified range.
339 * @param where the start index.
340 * @param len the number of characters.
342 * @return A string.
344 * @throws BadLocationException if the requested range of characters extends
345 * outside the bounds of the content.
347 public String getString(int where, int len) throws BadLocationException
349 checkLocation(where, len);
350 return new String(this.content, where, len);
354 * Updates <code>txt</code> to contain a direct reference to the underlying
355 * character array.
357 * @param where the index of the first character.
358 * @param len the number of characters.
359 * @param txt a carrier for the return result (<code>null</code> not
360 * permitted).
362 * @throws BadLocationException if the requested character range is not
363 * within the bounds of the content.
364 * @throws NullPointerException if <code>txt</code> is <code>null</code>.
366 public void getChars(int where, int len, Segment txt)
367 throws BadLocationException
369 checkLocation(where, len);
370 txt.array = this.content;
371 txt.offset = where;
372 txt.count = len;
377 * @specnote This method is not very well specified and the positions vector
378 * is implementation specific. The undo positions are managed
379 * differently in this implementation, this method is only here
380 * for binary compatibility.
382 protected void updateUndoPositions(Vector positions)
384 // We do nothing here.
387 /**
388 * A utility method that checks the validity of the specified character
389 * range.
391 * @param where the first character in the range.
392 * @param len the number of characters in the range.
394 * @throws BadLocationException if the specified range is not within the
395 * bounds of the content.
397 void checkLocation(int where, int len) throws BadLocationException
399 if (where < 0)
400 throw new BadLocationException("Invalid location", 1);
401 else if (where > this.count)
402 throw new BadLocationException("Invalid location", this.count);
403 else if ((where + len) > this.count)
404 throw new BadLocationException("Invalid range", this.count);