2005-05-06 Roman Kennke <roman@kennke.org>
authorRoman Kennke <roman@kennke.org>
Fri, 6 May 2005 06:03:17 +0000 (06:03 +0000)
committerMichael Koch <mkoch@gcc.gnu.org>
Fri, 6 May 2005 06:03:17 +0000 (06:03 +0000)
* javax/swing/text/PlainView.java
(drawUnselectedText): Call Utilities.drawTabbedText() with correct
offset parameter.
* javax/swing/text/Utilities.java
(drawTabbedText): Initilialize local variable pos correctly.

2005-05-06  Roman Kennke  <roman@kennke.org>

* javax/swing/text/AbstractDocument.java
(LeafElement): Made start and end package private fields for
effective reindexing.
* javax/swing/text/PlainDocument.java
(constructor): The field rootElement is always BranchElement,
so we handle it as such.
(removeUpdate): Rewritten reindexing for removeUpdate so that
the actual removal is taken into account.

2005-05-06  Roman Kennke  <roman@kennke.org>

* javax/swing/text/GapContent.java:
Removed debugging output stuff, which I accidentally left in.

2005-05-06  Roman Kennke  <roman@kennke.org>

* javax/swing/text/GapContent.java:
Implemented a real GapContent. Only the public methods have
been implemented so far and still no UndoableEdit support.

From-SVN: r99300

libjava/ChangeLog
libjava/javax/swing/text/AbstractDocument.java
libjava/javax/swing/text/GapContent.java
libjava/javax/swing/text/PlainDocument.java
libjava/javax/swing/text/PlainView.java
libjava/javax/swing/text/Utilities.java

index cdd5f060a6f747210908d2e0e9931c3b882f7dd0..e47919920eb6fe7f7c69f78253410981e6d2f7cc 100644 (file)
@@ -1,3 +1,33 @@
+2005-05-06  Roman Kennke  <roman@kennke.org>
+
+       * javax/swing/text/PlainView.java
+       (drawUnselectedText): Call Utilities.drawTabbedText() with correct
+       offset parameter.
+       * javax/swing/text/Utilities.java
+       (drawTabbedText): Initilialize local variable pos correctly.
+
+2005-05-06  Roman Kennke  <roman@kennke.org>
+
+       * javax/swing/text/AbstractDocument.java
+       (LeafElement): Made start and end package private fields for
+       effective reindexing.
+       * javax/swing/text/PlainDocument.java
+       (constructor): The field rootElement is always BranchElement,
+       so we handle it as such.
+       (removeUpdate): Rewritten reindexing for removeUpdate so that
+       the actual removal is taken into account.
+
+2005-05-06  Roman Kennke  <roman@kennke.org>
+
+       * javax/swing/text/GapContent.java:
+       Removed debugging output stuff, which I accidentally left in.
+
+2005-05-06  Roman Kennke  <roman@kennke.org>
+
+       * javax/swing/text/GapContent.java:
+       Implemented a real GapContent. Only the public methods have
+       been implemented so far and still no UndoableEdit support.
+
 2005-05-04  H.J. Lu  <hongjiu.lu@intel.com>
 
        * java/awt/BufferCapabilities.java (BufferCapabilities): Fix
index 29be0ad065ec61558285e67cfba039f786305518..efeb85db67f4bcf6bbd280a0bee58b49ea6ed694 100644 (file)
@@ -847,8 +847,8 @@ public abstract class AbstractDocument
   public class LeafElement extends AbstractElement
   {
     private static final long serialVersionUID = 5115368706941283802L;
-    private int start;
-    private int end;
+    int start;
+    int end;
 
     public LeafElement(Element parent, AttributeSet attributes, int start,
                        int end)
index a22aeed51a7f4e0a29464ad3db54d95e432cb9c9..111617e94a9d6e51f012604d919ef23217c83542 100644 (file)
@@ -40,8 +40,6 @@ package javax.swing.text;
 
 import java.io.Serializable;
 
-// too lazy to make a real gapcontent.
-// lets just use a stringbuffer instead.
 import javax.swing.undo.UndoableEdit;
 
 /**
@@ -53,20 +51,41 @@ import javax.swing.undo.UndoableEdit;
  * has to be shifted around when the insertion point moves (then the gap also
  * moves and one array copy is necessary) or when the gap is filled up and
  * the buffer has to be enlarged.
+ *
+ * TODO: Implement UndoableEdit support stuff
  */
 public class GapContent
   implements AbstractDocument.Content, Serializable
 {
   private static final long serialVersionUID = 8374645204155842629L;
-    
-  StringBuffer buf = new StringBuffer();
+
+  /**
+   * This is the default buffer size and the amount of bytes that
+   * a buffer is extended if it is full.
+   */
+  static final int DEFAULT_BUFSIZE = 64;
+
+  /**
+   * The text buffer.
+   */
+  char[] buffer;
+
+  /**
+   * The index of the first character of the gap.
+   */
+  int gapStart;
+
+  /**
+   * The index of the character after the last character of the gap.
+   */
+  int gapEnd;
 
   /**
    * Creates a new GapContent object.
    */
   public GapContent()
   {
-    this(10);
+    this(DEFAULT_BUFSIZE);
   }
 
   /**
@@ -76,30 +95,33 @@ public class GapContent
    */
   public GapContent(int size)
   {
-    buf.append("\n");
+    buffer = (char[]) allocateArray(size);
+    gapStart = 0;
+    gapEnd = size - 1;
+    buffer[size - 1] = '\n';
   }
 
   /**
-   * Creates and returns a mark at the specified position.
-   *
-   * @param offset the position at which to create the mark
+   * Allocates an array of the specified length that can then be used as
+   * buffer.
    *
-   * @return the create Position object for the mark
+   * @param size the size of the array to be allocated
    *
-   * @throws BadLocationException if the offset is not a valid position in
-   *         the buffer
+   * @return the allocated array
    */
-  public Position createPosition(final int offset) throws BadLocationException
+  protected Object allocateArray(int size)
   {
-    return new Position()
-      {
-       int off = offset;
+    return new char[size];
+  }
 
-       public int getOffset()
-       {
-         return off;
-       }
-      };
+  /**
+   * Returns the length of the allocated buffer array.
+   *
+   * @return the length of the allocated buffer array
+   */
+  protected int getArrayLength()
+  {
+    return buffer.length;
   }
 
   /**
@@ -109,7 +131,7 @@ public class GapContent
    */
   public int length()
   {
-    return buf.length();
+    return buffer.length - (gapEnd - gapStart);
   }
 
   /**
@@ -127,7 +149,27 @@ public class GapContent
   public UndoableEdit insertString(int where, String str)
     throws BadLocationException
   {
-    buf.insert(where, str);
+    // check arguments
+    int length = length();
+    int strLen = str.length();
+
+    if (where >= length)
+      throw new BadLocationException("the where argument cannot be greater"
+                                     + " than the content length", where);
+
+    // check if the gap is big enough to hold the string
+    if ((gapEnd - gapStart) < strLen)
+      // make room for this string and some more
+      shiftEnd(strLen + DEFAULT_BUFSIZE);
+
+    // are we at the gap boundary?
+    if (where != gapStart)
+      shiftGap(where);
+
+    // now we can simple copy the string into the gap and adjust the
+    // gap boundaries
+    System.arraycopy(str.toCharArray(), 0, buffer, gapStart, strLen);
+    gapStart += strLen;
     return null;
   }
 
@@ -146,7 +188,23 @@ public class GapContent
   public UndoableEdit remove(int where, int nitems)
     throws BadLocationException
   {
-    buf.delete(where, where + nitems);
+    // check arguments
+    int length = length();
+
+    if (where >= length)
+      throw new BadLocationException("the where argument cannot be greater"
+                                     + " than the content length", where);
+    if ((where + nitems) > length)
+      throw new BadLocationException("where + nitems cannot be greater"
+                                     + " than the content length",
+                                     where + nitems);
+
+    // check if we are at the gap boundary
+    if (where != gapStart)
+      shiftGap(where);
+
+    // now we simply have to enlarge the gap
+    gapEnd += nitems;
     return null;
   }
 
@@ -161,12 +219,18 @@ public class GapContent
    */
   public String getString(int where, int len) throws BadLocationException
   {
-    return buf.substring(where, where+len);
+    Segment seg = new Segment();
+    getChars(where, len, seg);
+    return new String(seg.array, seg.offset, seg.count);
   }
 
   /**
    * Fetches a piece of content and stores it in a {@link Segment} object.
    *
+   * If the requested piece of text spans the gap, the content is copied
+   * into a new array. If it doesn't then it is contiguous and the
+   * actual content store is returned.
+   *
    * @param where the start location of the fragment
    * @param len the length of the fragment
    * @param txt the Segment object to store the fragment in
@@ -177,11 +241,116 @@ public class GapContent
   public void getChars(int where, int len, Segment txt)
     throws BadLocationException
   {
-    txt.array = new char[len];
+    // check arguments
+    int length = length();
+    if (where >= length)
+      throw new BadLocationException("the where argument cannot be greater"
+                                     + " than the content length", where);
+    if ((where + len) > length)
+      throw new BadLocationException("len plus where cannot be greater"
+                                     + " than the content length",
+                                     len + where);
 
-    System.arraycopy(buf.toString().toCharArray(), where, txt.array, 0, len);
+    // check if requested segment is contiguous
+    if ((where < gapStart) && ((gapStart - where) < len))
+      {
+        // requested segment is not contiguous -> copy the pieces together
+        char[] copy = new char[len];
+        int lenFirst = gapStart - where; // the length of the first segment
+        System.arraycopy(buffer, where, copy, 0, lenFirst);
+        System.arraycopy(buffer, gapEnd, copy, lenFirst, len - lenFirst);
+        txt.array = copy;
+        txt.offset = 0;
+        txt.count = len;
+      }
+    else
+      {
+        // requested segment is contiguous -> we can simply return the
+        // actual content
+        txt.array = buffer;
+        if (where < gapStart)
+          txt.offset = where;
+        else
+          txt.offset = where + (gapEnd - gapStart);
+        txt.count = len;
+      }
+  }
 
-    txt.count = len;
-    txt.offset = 0;
+  /**
+   * Creates and returns a mark at the specified position.
+   *
+   * @param offset the position at which to create the mark
+   *
+   * @return the create Position object for the mark
+   *
+   * @throws BadLocationException if the offset is not a valid position in
+   *         the buffer
+   */
+  public Position createPosition(final int offset) throws BadLocationException
+  {
+    return new Position()
+      {
+       int off = offset;
+
+       public int getOffset()
+       {
+         return off;
+       }
+      };
+  }
+
+  /**
+   * Enlarges the gap. This allocates a new bigger buffer array, copy the
+   * segment before the gap as it is and the segment after the gap at
+   * the end of the new buffer array. This does change the gapEnd mark
+   * but not the gapStart mark.
+   *
+   * @param newSize the new size of the gap
+   */
+  protected void shiftEnd(int newSize)
+  {
+    char[] newBuf = (char[]) allocateArray(length() + newSize);
+    System.arraycopy(buffer, 0, newBuf, 0, gapStart);
+    System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize,
+                     buffer.length - gapEnd);
+    gapEnd = gapStart + newSize;
+    buffer = newBuf;
+  }
+
+  /**
+   * Shifts the gap to the specified position.
+   *
+   * @param newGapStart the new start position of the gap
+   */
+  protected void shiftGap(int newGapStart)
+  {
+    int newGapEnd = newGapStart + (gapEnd - gapStart);
+
+    if (newGapStart == gapStart)
+      return;
+    else if (newGapStart < gapStart)
+      {
+        System.arraycopy(buffer, newGapStart, buffer, newGapEnd,
+                         gapStart - newGapStart);
+        gapStart = newGapStart;
+        gapEnd = newGapEnd;
+      }
+    else
+      {
+        System.arraycopy(buffer, gapEnd, buffer, gapStart,
+                         newGapStart - gapStart);
+        gapStart = newGapStart;
+        gapEnd = newGapEnd;
+      }
+  }
+
+  /**
+   * Returns the allocated buffer array.
+   *
+   * @return the allocated buffer array
+   */
+  protected Object getArray()
+  {
+    return buffer;
   }
 }
index 64e9c8ab3f43cd2ad3ccc99a64986435b4a599bc..3a44725fc1df96975a5431db881ec008116296c1 100644 (file)
@@ -47,7 +47,7 @@ public class PlainDocument extends AbstractDocument
   public static final String lineLimitAttribute = "lineLimit";
   public static final String tabSizeAttribute = "tabSize";
 
-  private Element rootElement;
+  private BranchElement rootElement;
   private int tabSize;
   
   public PlainDocument()
@@ -59,7 +59,7 @@ public class PlainDocument extends AbstractDocument
   {
     super(content);
     tabSize = 8;
-    rootElement = createDefaultRoot();
+    rootElement = (BranchElement) createDefaultRoot();
   }
 
   private void reindex()
@@ -114,9 +114,43 @@ public class PlainDocument extends AbstractDocument
 
   protected void removeUpdate(DefaultDocumentEvent event)
   {
-    reindex();
-
     super.removeUpdate(event);
+
+    int p0 = event.getOffset();
+    int p1 = event.getLength() + p0;
+    int len = event.getLength();
+
+    // check if we must collapse some elements
+    int i1 = rootElement.getElementIndex(p0);
+    int i2 = rootElement.getElementIndex(p1);
+    if (i1 != i2)
+      {
+        Element el1 = rootElement.getElement(i1);
+        Element el2 = rootElement.getElement(i2);
+        int start = el1.getStartOffset();
+        int end = el2.getEndOffset();
+        // collapse elements if the removal spans more than 1 line
+        Element newEl = createLeafElement(rootElement,
+                                          SimpleAttributeSet.EMPTY,
+                                          start, end - len);
+        rootElement.replace(start, end - start, new Element[]{ newEl });
+      }
+    else
+      {
+        // otherwise only adjust indices of the element
+        LeafElement el1 = (LeafElement) rootElement.getElement(i1);
+        el1.end -= len;
+      }
+
+    // reindex remaining elements
+    for (int i = rootElement.getElementIndex(p0) + 1;
+         i < rootElement.getElementCount(); i++)
+      {
+        LeafElement el = (LeafElement) rootElement.getElement(i);
+        el.start -= len;
+        el.end -= len;
+      }
+      
   }
 
   public Element getDefaultRootElement()
index c852c1d69b42d26fac9e5998f976907f4a807700..fb6af4eecadc9b877580561a9db98e1c975ce32b 100644 (file)
@@ -148,7 +148,7 @@ public class PlainView extends View
     g.setColor(unselectedColor);
     Segment segment = new Segment();
     getDocument().getText(p0, p1 - p0, segment);
-    return Utilities.drawTabbedText(segment, x, y, g, this, 0);
+    return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
   }
 
   public void paint(Graphics g, Shape s)
index c55f48e0a5f5dd3eaaf5750d75cbb9fc5a461f91..79047014d46382ba3d01c03868b44ed0bd044cad 100644 (file)
@@ -92,7 +92,7 @@ public class Utilities
     int ascent = metrics.getAscent();
 
     int pixelWidth = 0;
-    int pos = 0;
+    int pos = s.offset;
     int len = 0;
 
     for (int offset = s.offset; offset < (s.offset + s.count); ++offset)