/[classpath]/classpath/javax/swing/text/GapContent.java
ViewVC logotype

Diff of /classpath/javax/swing/text/GapContent.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.5.2.5 by gnu_andrew, Tue Aug 2 20:12:38 2005 UTC revision 1.5.2.6 by gnu_andrew, Sun Aug 7 18:34:12 2005 UTC
# Line 46  import java.util.ListIterator; Line 46  import java.util.ListIterator;
46  import javax.swing.undo.UndoableEdit;  import javax.swing.undo.UndoableEdit;
47    
48  /**  /**
49   * This implementation of {@link AbstractDocument.Content} uses a gapped   * This implementation of {@link AbstractDocument.Content} uses a gapped buffer.
50   * buffer. This takes advantage of the fact that text area content is   * This takes advantage of the fact that text area content is mostly inserted
51   * mostly inserted sequentially. The buffer is a char array that maintains   * sequentially. The buffer is a char array that maintains a gap at the current
52   * a gap at the current insertion point. If characters a inserted at   * insertion point. If characters a inserted at gap boundaries, the cost is
53   * gap boundaries, the cost is minimal (simple array access). The array only   * minimal (simple array access). The array only has to be shifted around when
54   * has to be shifted around when the insertion point moves (then the gap also   * the insertion point moves (then the gap also moves and one array copy is
55   * moves and one array copy is necessary) or when the gap is filled up and   * necessary) or when the gap is filled up and the buffer has to be enlarged.
56   * the buffer has to be enlarged.   *
  *  
57   * TODO: Implement UndoableEdit support stuff   * TODO: Implement UndoableEdit support stuff
58   */   */
59  public class GapContent  public class GapContent
60    implements AbstractDocument.Content, Serializable      implements AbstractDocument.Content, Serializable
61  {  {
62    
63    /**    /**
64     * A {@link Position} implementation for <code>GapContent</code>.     * A {@link Position} implementation for <code>GapContent</code>.
65     */     */
66    class GapContentPosition implements Position, Comparable    class GapContentPosition
67          implements Position, Comparable
68    {    {
69    
70      /** The index within the buffer array. */      /** The index within the buffer array. */
# Line 72  public class GapContent Line 72  public class GapContent
72    
73      /**      /**
74       * Creates a new GapContentPosition object.       * Creates a new GapContentPosition object.
75       *       *
76       * @param mark the mark of this Position       * @param mark the mark of this Position
77       */       */
78      GapContentPosition(int mark)      GapContentPosition(int mark)
# Line 83  public class GapContent Line 83  public class GapContent
83      /**      /**
84       * Comparable interface implementation. This is used to store all       * Comparable interface implementation. This is used to store all
85       * positions in an ordered fashion.       * positions in an ordered fashion.
86       *       *
87       * @param o the object to be compared to this       * @param o the object to be compared to this
88       *       *
89       * @return a negative integer if this is less than <code>o</code>, zero       * @return a negative integer if this is less than <code>o</code>, zero
90       *         if both are equal or a positive integer if this is greater       *         if both are equal or a positive integer if this is greater than
91       *         than <code>o</code>       *         <code>o</code>
92       *       *
93       * @throws ClassCastException if <code>o</code> is not a GapContentPosition       * @throws ClassCastException if <code>o</code> is not a
94       *         or Integer object       *         GapContentPosition or Integer object
95       */       */
96      public int compareTo(Object o)      public int compareTo(Object o)
97      {      {
98        if (o instanceof Integer)        if (o instanceof Integer)
99          {        {
100            int otherMark = ((Integer) o).intValue();          int otherMark = ((Integer) o).intValue();
101            return mark - otherMark;          return mark - otherMark;
102          }        }
103        else        else
104          {        {
105            GapContentPosition other = (GapContentPosition) o;          GapContentPosition other = (GapContentPosition) o;
106            return mark - other.mark;          return mark - other.mark;
107          }        }
108      }      }
109    
110      /**      /**
111       * Returns the current offset of this Position within the content.       * Returns the current offset of this Position within the content.
112       *       *
113       * @return the current offset of this Position within the content.       * @return the current offset of this Position within the content.
114       */       */
115      public int getOffset()      public int getOffset()
116      {      {
117        if (mark <= gapStart)        if (mark <= gapStart)
118          return mark;          return mark;
119        else        else
120          return mark - (gapEnd - gapStart);          return mark - (gapEnd - gapStart);
121      }      }
122    }    }
123        
124    private static final long serialVersionUID = 8374645204155842629L;    private static final long serialVersionUID = 8374645204155842629L;
125    
126    /**    /**
127     * This is the default buffer size and the amount of bytes that     * This is the default buffer size and the amount of bytes that a buffer is
128     * a buffer is extended if it is full.     * extended if it is full.
129     */     */
130    static final int DEFAULT_BUFSIZE = 64;    static final int DEFAULT_BUFSIZE = 64;
131    
# Line 145  public class GapContent Line 145  public class GapContent
145    int gapEnd;    int gapEnd;
146    
147    /**    /**
148     * The positions generated by this GapContent. They are kept in an     * The positions generated by this GapContent. They are kept in an ordered
149     * ordered fashion, so they can be looked up easily.     * fashion, so they can be looked up easily.
150     */     */
151    LinkedList positions;    LinkedList positions;
152    
# Line 160  public class GapContent Line 160  public class GapContent
160    
161    /**    /**
162     * Creates a new GapContent object with a specified initial size.     * Creates a new GapContent object with a specified initial size.
163     *     *
164     * @param size the initial size of the buffer     * @param size the initial size of the buffer
165     */     */
166    public GapContent(int size)    public GapContent(int size)
# Line 175  public class GapContent Line 175  public class GapContent
175    /**    /**
176     * Allocates an array of the specified length that can then be used as     * Allocates an array of the specified length that can then be used as
177     * buffer.     * buffer.
178     *     *
179     * @param size the size of the array to be allocated     * @param size the size of the array to be allocated
180     *     *
181     * @return the allocated array     * @return the allocated array
182     */     */
183    protected Object allocateArray(int size)    protected Object allocateArray(int size)
# Line 187  public class GapContent Line 187  public class GapContent
187    
188    /**    /**
189     * Returns the length of the allocated buffer array.     * Returns the length of the allocated buffer array.
190     *     *
191     * @return the length of the allocated buffer array     * @return the length of the allocated buffer array
192     */     */
193    protected int getArrayLength()    protected int getArrayLength()
# Line 197  public class GapContent Line 197  public class GapContent
197    
198    /**    /**
199     * Returns the length of the content.     * Returns the length of the content.
200     *     *
201     * @return the length of the content     * @return the length of the content
202     */     */
203    public int length()    public int length()
# Line 207  public class GapContent Line 207  public class GapContent
207    
208    /**    /**
209     * Inserts a string at the specified position.     * Inserts a string at the specified position.
210     *     *
211     * @param where the position where the string is inserted     * @param where the position where the string is inserted
212     * @param str the string that is to be inserted     * @param str the string that is to be inserted
213     *     *
214     * @return an UndoableEdit object (currently not supported, so     * @return an UndoableEdit object (currently not supported, so
215     *         <code>null</code> is returned)     *         <code>null</code> is returned)
216     *     *
217     * @throws BadLocationException if <code>where</code> is not a valid location     * @throws BadLocationException if <code>where</code> is not a valid
218     *         in the buffer     *         location in the buffer
219     */     */
220    public UndoableEdit insertString(int where, String str)    public UndoableEdit insertString(int where, String str)
221      throws BadLocationException        throws BadLocationException
222    {    {
223      // check arguments      // check arguments
224      int length = length();      int length = length();
# Line 226  public class GapContent Line 226  public class GapContent
226    
227      if (where >= length)      if (where >= length)
228        throw new BadLocationException("the where argument cannot be greater"        throw new BadLocationException("the where argument cannot be greater"
229                                       + " than the content length", where);            + " than the content length", where);
230    
231      // check if the gap is big enough to hold the string      // check if the gap is big enough to hold the string
232      if ((gapEnd - gapStart) < strLen)      if ((gapEnd - gapStart) < strLen)
# Line 246  public class GapContent Line 246  public class GapContent
246    
247    /**    /**
248     * Removes a piece of content at th specified position.     * Removes a piece of content at th specified position.
249     *     *
250     * @param where the position where the content is to be removed     * @param where the position where the content is to be removed
251     * @param nitems number of characters to be removed     * @param nitems number of characters to be removed
252     *     *
253     * @return an UndoableEdit object (currently not supported, so     * @return an UndoableEdit object (currently not supported, so
254     *         <code>null</code> is returned)     *         <code>null</code> is returned)
255     *     *
256     * @throws BadLocationException if <code>where</code> is not a valid location     * @throws BadLocationException if <code>where</code> is not a valid
257     *         in the buffer     *         location in the buffer
258     */     */
259    public UndoableEdit remove(int where, int nitems)    public UndoableEdit remove(int where, int nitems) throws BadLocationException
     throws BadLocationException  
260    {    {
261      // check arguments      // check arguments
262      int length = length();      int length = length();
263    
264      if (where >= length)      if (where >= length)
265        throw new BadLocationException("the where argument cannot be greater"        throw new BadLocationException("the where argument cannot be greater"
266                                       + " than the content length", where);            + " than the content length", where);
267      if ((where + nitems) > length)      if ((where + nitems) > length)
268        throw new BadLocationException("where + nitems cannot be greater"        throw new BadLocationException("where + nitems cannot be greater"
269                                       + " than the content length",            + " than the content length", where + nitems);
                                      where + nitems);  
270    
271      // check if we are at the gap boundary      // check if we are at the gap boundary
272      if (where != gapStart)      if (where != gapStart)
# Line 281  public class GapContent Line 279  public class GapContent
279    
280    /**    /**
281     * Returns a piece of content as String.     * Returns a piece of content as String.
282     *     *
283     * @param where the start location of the fragment     * @param where the start location of the fragment
284     * @param len the length of the fragment     * @param len the length of the fragment
285     *     *
286     * @throws BadLocationException if <code>where</code> or     * @throws BadLocationException if <code>where</code> or
287     *         <code>where + len</code> are no valid locations in the buffer     *         <code>where + len</code> are no valid locations in the buffer
288     */     */
# Line 297  public class GapContent Line 295  public class GapContent
295    
296    /**    /**
297     * Fetches a piece of content and stores it in a {@link Segment} object.     * Fetches a piece of content and stores it in a {@link Segment} object.
298     *     *
299     * If the requested piece of text spans the gap, the content is copied     * If the requested piece of text spans the gap, the content is copied into a
300     * into a new array. If it doesn't then it is contiguous and the     * new array. If it doesn't then it is contiguous and the actual content
301     * actual content store is returned.     * store is returned.
302     *     *
303     * @param where the start location of the fragment     * @param where the start location of the fragment
304     * @param len the length of the fragment     * @param len the length of the fragment
305     * @param txt the Segment object to store the fragment in     * @param txt the Segment object to store the fragment in
306     *     *
307     * @throws BadLocationException if <code>where</code> or     * @throws BadLocationException if <code>where</code> or
308     *         <code>where + len</code> are no valid locations in the buffer     *         <code>where + len</code> are no valid locations in the buffer
309     */     */
310    public void getChars(int where, int len, Segment txt)    public void getChars(int where, int len, Segment txt)
311      throws BadLocationException        throws BadLocationException
312    {    {
313      // check arguments      // check arguments
314      int length = length();      int length = length();
315      if (where >= length)      if (where >= length)
316        throw new BadLocationException("the where argument cannot be greater"        throw new BadLocationException("the where argument cannot be greater"
317                                       + " than the content length", where);            + " than the content length", where);
318      if ((where + len) > length)      if ((where + len) > length)
319        throw new BadLocationException("len plus where cannot be greater"        throw new BadLocationException("len plus where cannot be greater"
320                                       + " than the content length",            + " than the content length", len + where);
                                      len + where);  
321    
322      // check if requested segment is contiguous      // check if requested segment is contiguous
323      if ((where < gapStart) && ((gapStart - where) < len))      if ((where < gapStart) && ((gapStart - where) < len))
324        {      {
325          // requested segment is not contiguous -> copy the pieces together        // requested segment is not contiguous -> copy the pieces together
326          char[] copy = new char[len];        char[] copy = new char[len];
327          int lenFirst = gapStart - where; // the length of the first segment        int lenFirst = gapStart - where; // the length of the first segment
328          System.arraycopy(buffer, where, copy, 0, lenFirst);        System.arraycopy(buffer, where, copy, 0, lenFirst);
329          System.arraycopy(buffer, gapEnd, copy, lenFirst, len - lenFirst);        System.arraycopy(buffer, gapEnd, copy, lenFirst, len - lenFirst);
330          txt.array = copy;        txt.array = copy;
331          txt.offset = 0;        txt.offset = 0;
332          txt.count = len;        txt.count = len;
333        }      }
334      else      else
335        {      {
336          // requested segment is contiguous -> we can simply return the        // requested segment is contiguous -> we can simply return the
337          // actual content        // actual content
338          txt.array = buffer;        txt.array = buffer;
339          if (where < gapStart)        if (where < gapStart)
340            txt.offset = where;          txt.offset = where;
341          else        else
342            txt.offset = where + (gapEnd - gapStart);          txt.offset = where + (gapEnd - gapStart);
343          txt.count = len;        txt.count = len;
344        }      }
345    }    }
346    
347    /**    /**
348     * Creates and returns a mark at the specified position.     * Creates and returns a mark at the specified position.
349     *     *
350     * @param offset the position at which to create the mark     * @param offset the position at which to create the mark
351     *     *
352     * @return the create Position object for the mark     * @return the create Position object for the mark
353     *     *
354     * @throws BadLocationException if the offset is not a valid position in     * @throws BadLocationException if the offset is not a valid position in the
355     *         the buffer     *         buffer
356     */     */
357    public Position createPosition(final int offset) throws BadLocationException    public Position createPosition(final int offset) throws BadLocationException
358    {    {
359      if (offset < 0 || offset > length())      if (offset < 0 || offset > length())
360        throw new BadLocationException("The offset was out of the bounds of this"        throw new BadLocationException("The offset was out of the bounds of this"
361                                       + " buffer", offset);            + " buffer", offset);
362    
363      // We store the actual array index in the GapContentPosition. The real      // We store the actual array index in the GapContentPosition. The real
364      // offset is then calculated in the GapContentPosition.      // offset is then calculated in the GapContentPosition.
# Line 375  public class GapContent Line 372  public class GapContent
372      if (index < 0)      if (index < 0)
373        index = -(index + 1);        index = -(index + 1);
374      positions.add(index, pos);      positions.add(index, pos);
375        
376      return pos;      return pos;
377    }    }
378    
379    /**    /**
380     * Enlarges the gap. This allocates a new bigger buffer array, copy the     * Enlarges the gap. This allocates a new bigger buffer array, copy the
381     * segment before the gap as it is and the segment after the gap at     * segment before the gap as it is and the segment after the gap at the end
382     * the end of the new buffer array. This does change the gapEnd mark     * of the new buffer array. This does change the gapEnd mark but not the
383     * but not the gapStart mark.     * gapStart mark.
384     *     *
385     * @param newSize the new size of the gap     * @param newSize the new size of the gap
386     */     */
387    protected void shiftEnd(int newSize)    protected void shiftEnd(int newSize)
# Line 392  public class GapContent Line 389  public class GapContent
389      int delta = (gapEnd - gapStart) - newSize;      int delta = (gapEnd - gapStart) - newSize;
390      char[] newBuf = (char[]) allocateArray(length() + newSize);      char[] newBuf = (char[]) allocateArray(length() + newSize);
391      System.arraycopy(buffer, 0, newBuf, 0, gapStart);      System.arraycopy(buffer, 0, newBuf, 0, gapStart);
392      System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize,      System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize, buffer.length
393                       buffer.length - gapEnd);          - gapEnd);
394      gapEnd = gapStart + newSize;      gapEnd = gapStart + newSize;
395      buffer = newBuf;      buffer = newBuf;
396    
397      // Update the marks after the gapEnd.      // Update the marks after the gapEnd.
398      int index = Collections.binarySearch(positions, new Integer(gapEnd));      int index = Collections.binarySearch(positions, new GapContentPosition(
399            gapEnd));
400      if (index < 0)      if (index < 0)
401        {      {
402          index = -(index + 1);        index = -(index + 1);
403        }      }
404      for (ListIterator i = positions.listIterator(index); i.hasNext();)      for (ListIterator i = positions.listIterator(index); i.hasNext();)
405        {      {
406          GapContentPosition p = (GapContentPosition) i.next();        GapContentPosition p = (GapContentPosition) i.next();
407          p.mark += delta;        p.mark += delta;
408        }      }
409    }    }
410    
411    /**    /**
412     * Shifts the gap to the specified position.     * Shifts the gap to the specified position.
413     *     *
414     * @param newGapStart the new start position of the gap     * @param newGapStart the new start position of the gap
415     */     */
416    protected void shiftGap(int newGapStart)    protected void shiftGap(int newGapStart)
417    {    {
418      int newGapEnd = newGapStart + (gapEnd - gapStart);      int newGapEnd = newGapStart + (gapEnd - gapStart);
419    
   
420      // Update the positions between newGapEnd and (old) gapEnd. The marks      // Update the positions between newGapEnd and (old) gapEnd. The marks
421      // must be shifted by (gapEnd - newGapEnd).      // must be shifted by (gapEnd - newGapEnd).
422      int index1 = Collections.binarySearch(positions, new Integer(gapEnd));      int index1 = Collections.binarySearch(positions, new GapContentPosition(
423      int index2 = Collections.binarySearch(positions, new Integer(newGapEnd));          gapEnd));
424      int i1 = Math.min(index1, index2);      int index2 = Collections.binarySearch(positions, new GapContentPosition(
425      int i2 = Math.max(index1, index2);          newGapEnd));
426      for (ListIterator i = positions.listIterator(i1); i.hasNext();)      if (index1 > 0 && index2 > 0)
427        {
428          int i1 = Math.min(index1, index2);
429          int i2 = Math.max(index1, index2);
430          for (ListIterator i = positions.listIterator(i1); i.hasNext();)
431        {        {
432          if (i.nextIndex() > i2)          if (i.nextIndex() > i2)
433            break;            break;
434    
435          GapContentPosition p = (GapContentPosition) i.next();          GapContentPosition p = (GapContentPosition) i.next();
436          p.mark += gapEnd - newGapEnd;          p.mark += gapEnd - newGapEnd;
437        }        }
438    
439      if (newGapStart == gapStart)        if (newGapStart == gapStart)
440        return;          return;
441      else if (newGapStart < gapStart)        else if (newGapStart < gapStart)
442        {        {
443          System.arraycopy(buffer, newGapStart, buffer, newGapEnd,          System.arraycopy(buffer, newGapStart, buffer, newGapEnd, gapStart
444                           gapStart - newGapStart);              - newGapStart);
445          gapStart = newGapStart;          gapStart = newGapStart;
446          gapEnd = newGapEnd;          gapEnd = newGapEnd;
447        }        }
448      else        else
449        {        {
450          System.arraycopy(buffer, gapEnd, buffer, gapStart,          System.arraycopy(buffer, gapEnd, buffer, gapStart, newGapStart
451                           newGapStart - gapStart);              - gapStart);
452          gapStart = newGapStart;          gapStart = newGapStart;
453          gapEnd = newGapEnd;          gapEnd = newGapEnd;
454        }        }
455        }
456    }    }
457    
458    /**    /**
459     * Returns the allocated buffer array.     * Returns the allocated buffer array.
460     *     *
461     * @return the allocated buffer array     * @return the allocated buffer array
462     */     */
463    protected Object getArray()    protected Object getArray()
# Line 465  public class GapContent Line 467  public class GapContent
467    
468    /**    /**
469     * Replaces a portion of the storage with the specified items.     * Replaces a portion of the storage with the specified items.
470     *     *
471     * @param position the position at which to remove items     * @param position the position at which to remove items
472     * @param rmSize the number of items to remove     * @param rmSize the number of items to remove
473     * @param addItems the items to add at location     * @param addItems the items to add at location
474     * @param addSize the number of items to add     * @param addSize the number of items to add
475     */     */
476    protected void replace(int position, int rmSize, Object addItems,    protected void replace(int position, int rmSize, Object addItems, int addSize)
                          int addSize)  
477    {    {
478      // Remove content      // Remove content
479      shiftGap(position);      shiftGap(position);

Legend:
Removed from v.1.5.2.5  
changed lines
  Added in v.1.5.2.6

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26