[llvm-commits] [llvm-gcc-4.2] r43913 [54/80] - in /llvm-gcc-4.2/trunk: boehm-gc/ boehm-gc/Mac_files/ boehm-gc/cord/ boehm-gc/doc/ boehm-gc/include/ boehm-gc/include/private/ boehm-gc/tests/ libffi/ libffi/include/ libffi/src/ libffi/src/alpha/ libffi/src/arm/ libffi/src/cris/ libffi/src/frv/ libffi/src/ia64/ libffi/src/m32r/ libffi/src/m68k/ libffi/src/mips/ libffi/src/pa/ libffi/src/powerpc/ libffi/src/s390/ libffi/src/sh/ libffi/src/sh64/ libffi/src/sparc/ libffi/src/x86/ libffi/testsuite/ libffi/testsuite/config/ li...

Bill Wendling isanbard at gmail.com
Thu Nov 8 14:57:11 PST 2007


Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,671 @@
+/* DefaultTableColumnModel.java --
+   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Vector;
+
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.event.TableColumnModelListener;
+
+/**
+ * A model that stores information about the columns used in a {@link JTable}.
+ * 
+ * @see JTable#setColumnModel(TableColumnModel)
+ * 
+ * @author	Andrew Selkirk
+ */
+public class DefaultTableColumnModel
+  implements TableColumnModel, PropertyChangeListener, ListSelectionListener,
+             Serializable
+{
+  private static final long serialVersionUID = 6580012493508960512L;
+
+  /**
+   * Storage for the table columns.
+   */
+  protected Vector tableColumns;
+
+  /**
+   * A selection model that keeps track of column selections.
+   */
+  protected ListSelectionModel selectionModel;
+
+  /**
+   * The space between the columns (the default value is <code>1</code>).
+   */
+  protected int columnMargin;
+
+  /**
+   * Storage for the listeners registered with the model.
+   */
+  protected EventListenerList listenerList = new EventListenerList();
+
+  /**
+   * A change event used when notifying listeners of a change to the 
+   * <code>columnMargin</code> field.  This single event is reused for all
+   * notifications (it is lazily instantiated within the 
+   * {@link #fireColumnMarginChanged()} method).
+   */
+  protected transient ChangeEvent changeEvent;
+
+  /**
+   * A flag that indicates whether or not columns can be selected. 
+   */
+  protected boolean columnSelectionAllowed;
+
+  /**
+   * The total width of all the columns in this model.
+   */
+  protected int totalColumnWidth;
+
+  /**
+   * Creates a new table column model with zero columns.  A default column 
+   * selection model is created by calling {@link #createSelectionModel()}.
+   * The default value for <code>columnMargin</code> is <code>1</code> and
+   * the default value for <code>columnSelectionAllowed</code> is 
+   * <code>false</code>.
+   */
+  public DefaultTableColumnModel()
+  {
+    tableColumns = new Vector();
+    selectionModel = createSelectionModel();
+    selectionModel.addListSelectionListener(this);
+    columnMargin = 1;
+    columnSelectionAllowed = false;
+  }
+
+  /**
+   * Adds a column to the model then calls 
+   * {@link #fireColumnAdded(TableColumnModelEvent)} to notify the registered
+   * listeners.  The model registers itself with the column as a
+   * {@link PropertyChangeListener} so that changes to the column width will
+   * invalidate the cached {@link #totalColumnWidth} value.
+   *
+   * @param column  the column (<code>null</code> not permitted).
+   * 
+   * @throws IllegalArgumentException if <code>column</code> is 
+   *     <code>null</code>.
+   * 
+   * @see #removeColumn(TableColumn)
+   */
+  public void addColumn(TableColumn column)
+  {
+    if (column == null)
+      throw new IllegalArgumentException("Null 'col' argument.");
+    tableColumns.add(column);
+    column.addPropertyChangeListener(this);
+    invalidateWidthCache();
+    fireColumnAdded(new TableColumnModelEvent(this, 0, 
+                                              tableColumns.size() - 1));
+  }
+
+  /**
+   * Removes a column from the model then calls
+   * {@link #fireColumnRemoved(TableColumnModelEvent)} to notify the registered
+   * listeners.  If the specified column does not belong to the model, or is 
+   * <code>null</code>, this method does nothing.
+   *
+   * @param column the column to be removed (<code>null</code> permitted).
+   * 
+   * @see #addColumn(TableColumn)
+   */
+  public void removeColumn(TableColumn column)
+  {
+    int index = this.tableColumns.indexOf(column);
+    if (index < 0)
+      return;
+    tableColumns.remove(column);
+    fireColumnRemoved(new TableColumnModelEvent(this, index, 0));    
+    column.removePropertyChangeListener(this);
+    invalidateWidthCache();
+  }
+
+  /**
+   * Moves the column at index i to the position specified by index j, then 
+   * calls {@link #fireColumnMoved(TableColumnModelEvent)} to notify registered
+   * listeners.
+   *
+   * @param i index of the column that will be moved.
+   * @param j index of the column's new location.
+   * 
+   * @throws IllegalArgumentException if <code>i</code> or <code>j</code> are
+   *     outside the range <code>0</code> to <code>N-1</code>, where 
+   *     <code>N</code> is the column count.
+   */
+  public void moveColumn(int i, int j)
+  {
+    int columnCount = getColumnCount();
+    if (i < 0 || i >= columnCount)
+      throw new IllegalArgumentException("Index 'i' out of range.");
+    if (j < 0 || j >= columnCount)
+      throw new IllegalArgumentException("Index 'j' out of range.");
+    Object column = tableColumns.remove(i);
+    tableColumns.add(j, column);
+    fireColumnMoved(new TableColumnModelEvent(this, i, j));
+  }
+
+  /**
+   * Sets the column margin then calls {@link #fireColumnMarginChanged()} to
+   * notify the registered listeners.
+   * 
+   * @param margin  the column margin.
+   * 
+   * @see #getColumnMargin()
+   */
+  public void setColumnMargin(int margin)
+  {
+    columnMargin = margin;
+    fireColumnMarginChanged();
+  }
+
+  /**
+   * Returns the number of columns in the model.
+   * 
+   * @return The column count.
+   */
+  public int getColumnCount()
+  {
+    return tableColumns.size();
+  }
+
+  /**
+   * Returns an enumeration of the columns in the model.
+   * 
+   * @return An enumeration of the columns in the model.
+   */
+  public Enumeration getColumns()
+  {
+    return tableColumns.elements();
+  }
+
+  /**
+   * Returns the index of the {@link TableColumn} with the given identifier.
+   *
+   * @param identifier  the identifier (<code>null</code> not permitted).
+   * 
+   * @return The index of the {@link TableColumn} with the given identifier.
+   * 
+   * @throws IllegalArgumentException if <code>identifier</code> is 
+   *         <code>null</code> or there is no column with that identifier.
+   */
+  public int getColumnIndex(Object identifier)
+  {
+    if (identifier == null)
+      throw new IllegalArgumentException("Null identifier.");
+    int columnCount = tableColumns.size();
+    for (int i = 0; i < columnCount; i++) 
+    {
+      TableColumn tc = (TableColumn) tableColumns.get(i);
+      if (identifier.equals(tc.getIdentifier()))
+        return i;
+    }
+    throw new IllegalArgumentException("No TableColumn with that identifier.");
+  }
+
+  /**
+   * Returns the column at the specified index.
+   * 
+   * @param columnIndex  the column index (in the range from <code>0</code> to 
+   *     <code>N-1</code>, where <code>N</code> is the number of columns in 
+   *     the model).
+   * 
+   * @return The column at the specified index.
+   * 
+   * @throws ArrayIndexOutOfBoundsException if <code>i</code> is not within
+   *     the specified range.
+   */
+  public TableColumn getColumn(int columnIndex)
+  {
+    return (TableColumn) tableColumns.get(columnIndex);
+  }
+
+  /**
+   * Returns the column margin.
+   * 
+   * @return The column margin.
+   * 
+   * @see #setColumnMargin(int)
+   */
+  public int getColumnMargin()
+  {
+    return columnMargin;
+  }
+
+  /**
+   * Returns the index of the column that contains the specified x-coordinate.
+   * This method assumes that:
+   * <ul>
+   * <li>column zero begins at position zero;</li>
+   * <li>all columns appear in order;</li>
+   * <li>individual column widths are taken into account, but the column margin
+   *     is ignored.</li>
+   * </ul>
+   * If no column contains the specified position, this method returns 
+   * <code>-1</code>.
+   * 
+   * @param x  the x-position.
+   * 
+   * @return The column index, or <code>-1</code>.
+   */
+  public int getColumnIndexAtX(int x)
+  {    
+    for (int i = 0; i < tableColumns.size(); ++i)
+      {
+        int w = ((TableColumn) tableColumns.get(i)).getWidth();
+        if (0 <= x && x < w)
+          return i;
+        else
+          x -= w;
+      }
+    return -1;
+  }
+
+  /**
+   * Returns total width of all the columns in the model, ignoring the
+   * {@link #columnMargin}.
+   *
+   * @return The total width of all the columns.
+   */
+  public int getTotalColumnWidth()
+  {
+    if (totalColumnWidth == -1)
+      recalcWidthCache();
+    return totalColumnWidth;
+  }
+
+  /**
+   * Sets the selection model that will be used to keep track of the selected 
+   * columns.
+   *
+   * @param model  the selection model (<code>null</code> not permitted).
+   * 
+   * @throws IllegalArgumentException if <code>model</code> is 
+   *     <code>null</code>.
+   *     
+   * @see #getSelectionModel()
+   */
+  public void setSelectionModel(ListSelectionModel model)
+  {
+    if (model == null)
+      throw new IllegalArgumentException();
+    
+    selectionModel.removeListSelectionListener(this);
+    selectionModel = model;
+    selectionModel.addListSelectionListener(this);
+  }
+
+  /**
+   * Returns the selection model used to track table column selections.
+   * 
+   * @return The selection model.
+   * 
+   * @see #setSelectionModel(ListSelectionModel)
+   */
+  public ListSelectionModel getSelectionModel()
+  {
+    return selectionModel;
+  }
+
+  /**
+   * Sets the flag that indicates whether or not column selection is allowed.
+   *
+   * @param flag  the new flag value.
+   * 
+   * @see #getColumnSelectionAllowed()
+   */
+  public void setColumnSelectionAllowed(boolean flag)
+  {
+    columnSelectionAllowed = flag;
+  }
+
+  /**
+   * Returns <code>true</code> if column selection is allowed, and 
+   * <code>false</code> if column selection is not allowed.
+   *
+   * @return A boolean.
+   * 
+   * @see #setColumnSelectionAllowed(boolean)
+   */
+  public boolean getColumnSelectionAllowed()
+  {
+    return columnSelectionAllowed;
+  }
+
+  /**
+   * Returns an array containing the indices of the selected columns.
+   *
+   * @return An array containing the indices of the selected columns.
+   */
+  public int[] getSelectedColumns()
+  {
+    // FIXME: Implementation of this method was taken from private method 
+    // JTable.getSelections(), which is used in various places in JTable
+    // including selected row calculations and cannot be simply removed.
+    // This design should be improved to illuminate duplication of code.
+    
+    ListSelectionModel lsm = this.selectionModel;    
+    int sz = getSelectedColumnCount();
+    int [] ret = new int[sz];
+
+    int lo = lsm.getMinSelectionIndex();
+    int hi = lsm.getMaxSelectionIndex();
+    int j = 0;
+    java.util.ArrayList ls = new java.util.ArrayList();
+    if (lo != -1 && hi != -1)
+      {
+        switch (lsm.getSelectionMode())
+          {
+          case ListSelectionModel.SINGLE_SELECTION:
+            ret[0] = lo;
+            break;      
+      
+          case ListSelectionModel.SINGLE_INTERVAL_SELECTION:            
+            for (int i = lo; i <= hi; ++i)
+              ret[j++] = i;
+            break;
+            
+          case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
+            for (int i = lo; i <= hi; ++i)
+              if (lsm.isSelectedIndex(i))        
+                ret[j++] = i;
+            break;
+          }
+      }
+    return ret;
+  }
+
+  /**
+   * Returns the number of selected columns in the model.
+   * 
+   * @return The selected column count.
+   * 
+   * @see #getSelectionModel()
+   */
+  public int getSelectedColumnCount()
+  {
+    // FIXME: Implementation of this method was taken from private method 
+    // JTable.countSelections(), which is used in various places in JTable
+    // including selected row calculations and cannot be simply removed.
+    // This design should be improved to illuminate duplication of code.
+   
+    ListSelectionModel lsm = this.selectionModel;
+    int lo = lsm.getMinSelectionIndex();
+    int hi = lsm.getMaxSelectionIndex();
+    int sum = 0;
+    
+    if (lo != -1 && hi != -1)
+      {
+        switch (lsm.getSelectionMode())
+          {
+          case ListSelectionModel.SINGLE_SELECTION:
+            sum = 1;
+            break;
+            
+          case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
+            sum = hi - lo + 1;
+            break;
+            
+          case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
+            for (int i = lo; i <= hi; ++i)
+              if (lsm.isSelectedIndex(i))        
+                ++sum;
+            break;
+          }
+      }
+     
+     return sum;
+  }
+
+  /**
+   * Registers a listener with the model, so that it will receive
+   * {@link TableColumnModelEvent} notifications.
+   *
+   * @param listener the listener (<code>null</code> ignored).
+   */
+  public void addColumnModelListener(TableColumnModelListener listener)
+  {
+    listenerList.add(TableColumnModelListener.class, listener);
+  }
+
+  /**
+   * Deregisters a listener so that it no longer receives notification of 
+   * changes to this model.
+   *
+   * @param listener  the listener to remove
+   */
+  public void removeColumnModelListener(TableColumnModelListener listener)
+  {
+    listenerList.remove(TableColumnModelListener.class, listener);
+  }
+
+  /**
+   * Returns an array containing the listeners that are registered with the
+   * model.  If there are no listeners, an empty array is returned.
+   * 
+   * @return An array containing the listeners that are registered with the
+   *     model.
+   *     
+   * @see #addColumnModelListener(TableColumnModelListener)
+   * @since 1.4
+   */
+  public TableColumnModelListener[] getColumnModelListeners()
+  {
+    return (TableColumnModelListener[])
+      listenerList.getListeners(TableColumnModelListener.class);
+  }	  
+
+  /**
+   * Sends the specified {@link TableColumnModelEvent} to all registered 
+   * listeners, to indicate that a column has been added to the model.  The
+   * event's <code>toIndex</code> attribute should contain the index of the
+   * added column.  
+   * 
+   * @param e  the event.
+   * 
+   * @see #addColumn(TableColumn)
+   */
+  protected void fireColumnAdded(TableColumnModelEvent e)
+  {    
+    TableColumnModelListener[] listeners = getColumnModelListeners();
+
+    for (int i = 0; i < listeners.length; i++)
+      listeners[i].columnAdded(e);        
+  }
+
+  /**
+   * Sends the specified {@link TableColumnModelEvent} to all registered 
+   * listeners, to indicate that a column has been removed from the model.  The
+   * event's <code>fromIndex</code> attribute should contain the index of the
+   * removed column.  
+   * 
+   * @param e  the event.
+   * 
+   * @see #removeColumn(TableColumn)
+   */
+  protected void fireColumnRemoved(TableColumnModelEvent e)
+  {
+    TableColumnModelListener[] listeners = getColumnModelListeners();
+
+    for (int i = 0; i < listeners.length; i++)
+      listeners[i].columnRemoved(e);        
+  }
+
+  /**
+   * Sends the specified {@link TableColumnModelEvent} to all registered 
+   * listeners, to indicate that a column in the model has been moved.  The
+   * event's <code>fromIndex</code> attribute should contain the old column
+   * index, and the <code>toIndex</code> attribute should contain the new
+   * column index.  
+   * 
+   * @param e  the event.
+   * 
+   * @see #moveColumn(int, int)
+   */
+  protected void fireColumnMoved(TableColumnModelEvent e)
+  {
+    TableColumnModelListener[] listeners = getColumnModelListeners();
+
+    for (int i = 0; i < listeners.length; i++)
+      listeners[i].columnMoved(e);        
+  }
+
+  /**
+   * Sends the specified {@link ListSelectionEvent} to all registered listeners,
+   * to indicate that the column selections have changed.
+   *
+   * @param e  the event.
+   * 
+   * @see #valueChanged(ListSelectionEvent)
+   */
+  protected void fireColumnSelectionChanged(ListSelectionEvent e)
+  {
+    EventListener [] listeners = getListeners(TableColumnModelListener.class);
+    for (int i = 0; i < listeners.length; ++i)
+      ((TableColumnModelListener) listeners[i]).columnSelectionChanged(e);
+  }
+
+  /**
+   * Sends a {@link ChangeEvent} to the model's registered listeners to 
+   * indicate that the column margin was changed.  
+   * 
+   * @see #setColumnMargin(int)
+   */
+  protected void fireColumnMarginChanged()
+  {
+    EventListener[] listeners = getListeners(TableColumnModelListener.class);
+    if (changeEvent == null && listeners.length > 0)
+      changeEvent = new ChangeEvent(this);
+    for (int i = 0; i < listeners.length; ++i)
+      ((TableColumnModelListener) listeners[i]).columnMarginChanged(changeEvent);
+  }
+
+  /**
+   * Returns an array containing the listeners (of the specified type) that 
+   * are registered with this model.
+   * 
+   * @param listenerType  the listener type (must indicate a subclass of 
+   *     {@link EventListener}, <code>null</code> not permitted).
+   *
+   * @return An array containing the listeners (of the specified type) that 
+   *     are registered with this model.
+   */
+  public EventListener[] getListeners(Class listenerType)
+  {
+    return listenerList.getListeners(listenerType);
+  }
+
+  /**
+   * Receives notification of property changes for the columns in the model.
+   * If the <code>width</code> property for any column changes, we invalidate
+   * the {@link #totalColumnWidth} value here. 
+   *
+   * @param event  the event.
+   */
+  public void propertyChange(PropertyChangeEvent event)
+  {
+    if (event.getPropertyName().equals("width"))
+	  invalidateWidthCache(); 
+  }
+
+  /**
+   * Receives notification of the change to the list selection model, and 
+   * responds by calling 
+   * {@link #fireColumnSelectionChanged(ListSelectionEvent)}.
+   * 
+   * @param e  the list selection event.
+   * 
+   * @see #getSelectionModel()
+   */
+  public void valueChanged(ListSelectionEvent e)
+  {
+    fireColumnSelectionChanged(e);
+  }
+
+  /**
+   * Creates a default selection model to track the currently selected 
+   * column(s).  This method is called by the constructor and returns a new
+   * instance of {@link DefaultListSelectionModel}.
+   *
+   * @return A new default column selection model.
+   */
+  protected ListSelectionModel createSelectionModel()
+  {    
+    return new DefaultListSelectionModel();
+  }
+
+  /**
+   * Recalculates the total width of the columns, if the cached value is
+   * <code>-1</code>.  Otherwise this method does nothing.
+   * 
+   * @see #getTotalColumnWidth()
+   */
+  protected void recalcWidthCache()
+  {
+    if (totalColumnWidth == -1)
+      {
+        totalColumnWidth = 0;
+        for (int i = 0; i < tableColumns.size(); ++i)
+          {
+            totalColumnWidth += ((TableColumn) tableColumns.get(i)).getWidth();
+          }
+      }
+  }
+
+  /**
+   * Sets the {@link #totalColumnWidth} field to <code>-1</code>.
+   * 
+   * @see #recalcWidthCache()
+   */
+  private void invalidateWidthCache()
+  {
+    totalColumnWidth = -1;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,634 @@
+/* DefaultTableModel.java --
+   Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.io.Serializable;
+import java.util.Vector;
+
+import javax.swing.event.TableModelEvent;
+
+/**
+ * A two dimensional data structure used to store <code>Object</code> 
+ * instances, usually for display in a <code>JTable</code> component.
+ * 
+ * @author	Andrew Selkirk
+ */
+public class DefaultTableModel extends AbstractTableModel
+  implements Serializable
+{
+  static final long serialVersionUID = 6680042567037222321L;
+
+  /**
+   * Storage for the rows in the table (each row is itself 
+   * a <code>Vector</code>).
+   */
+  protected Vector dataVector;
+
+  /**
+   * Storage for the column identifiers.
+   */
+  protected Vector columnIdentifiers;
+
+  /**
+   * Creates an empty table with zero rows and zero columns.
+   */
+  public DefaultTableModel() 
+  {
+    this(0, 0);
+  }
+  
+  /**
+   * Creates a new table with the specified number of rows and columns.
+   * All cells in the table are initially empty (set to <code>null</code>).
+   * 
+   * @param numRows  the number of rows.
+   * @param numColumns  the number of columns.
+   */
+  public DefaultTableModel(int numRows, int numColumns) 
+  {
+    Vector defaultNames = new Vector(numColumns);
+    Vector data = new Vector(numRows);
+    for (int i = 0; i < numColumns; i++) 
+      {
+        defaultNames.add(super.getColumnName(i));
+      }          
+    for (int r = 0; r < numRows; r++) 
+      {
+        Vector tmp = new Vector(numColumns);
+        tmp.setSize(numColumns);
+        data.add(tmp);
+      }
+    setDataVector(data, defaultNames);
+  }
+  
+  /**
+   * Creates a new table with the specified column names and number of
+   * rows.  The number of columns is determined by the number of column
+   * names supplied.
+   *   
+   * @param columnNames the column names.
+   * @param numRows the number of rows.
+   */
+  public DefaultTableModel(Vector columnNames, int numRows) 
+  {
+    if (numRows < 0)
+      throw new IllegalArgumentException("numRows < 0");
+    Vector data = new Vector();
+    int numColumns = 0;
+
+    if (columnNames != null)
+      numColumns = columnNames.size();
+    
+    while (0 < numRows--) 
+      {
+        Vector rowData = new Vector();
+        rowData.setSize(numColumns);
+        data.add(rowData);
+      }
+    setDataVector(data, columnNames);
+  }
+
+  /**
+   * Creates a new table with the specified column names and row count.
+   * 
+   * @param columnNames the column names.
+   * @param numRows the number of rows.
+   */
+  public DefaultTableModel(Object[] columnNames, int numRows) 
+  {
+    this(convertToVector(columnNames), numRows);
+  }
+  
+  /**
+   * Creates a new table with the specified data values and column names.
+   * 
+   * @param data the data values.
+   * @param columnNames the column names.
+   */
+  public DefaultTableModel(Vector data, Vector columnNames) 
+  {
+    setDataVector(data, columnNames);
+  }
+
+  /**
+   * Creates a new table with the specified data values and column names.
+   * 
+   * @param data the data values.
+   * @param columnNames the column names.
+   */
+  public DefaultTableModel(Object[][] data, Object[] columnNames) 
+  {
+    this(convertToVector(data), convertToVector(columnNames));
+  }
+
+  /**
+   * Returns the vector containing the row data for the table.
+   * 
+   * @return The data vector.
+   */
+  public Vector getDataVector() 
+  {
+    return dataVector;
+  }
+
+  /**
+   * Sets the data and column identifiers for the table.  The data vector
+   * contains a <code>Vector</code> for each row in the table - if the
+   * number of objects in each row does not match the number of column
+   * names specified, the row data is truncated or expanded (by adding
+   * <code>null</code> values) as required.
+   * 
+   * @param data the data for the table (a vector of row vectors).
+   * @param columnNames the column names.
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   */
+  public void setDataVector(Vector data, Vector columnNames) 
+  {
+    if (data == null)
+      dataVector = new Vector();
+    else
+      dataVector = data;
+    setColumnIdentifiers(columnNames);
+  }
+
+  /**
+   * Sets the data and column identifiers for the table.
+   * 
+   * @param data the data for the table.
+   * @param columnNames the column names.
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   */
+  public void setDataVector(Object[][] data, Object[] columnNames) 
+  {
+    setDataVector(convertToVector(data), 
+                  convertToVector(columnNames));
+  }
+  
+  /**
+   * Sends the specified <code>event</code> to all registered listeners.
+   * This method is equivalent to 
+   * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}.
+   * 
+   * @param event the event.
+   */
+  public void newDataAvailable(TableModelEvent event) 
+  {
+    fireTableChanged(event);
+  }
+
+  /**
+   * Sends the specified <code>event</code> to all registered listeners.
+   * This method is equivalent to 
+   * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}.
+   * 
+   * @param event the event.
+   */
+  public void newRowsAdded(TableModelEvent event) 
+  {
+    fireTableChanged(event);
+  }
+
+  /**
+   * Sends the specified <code>event</code> to all registered listeners.
+   * This method is equivalent to 
+   * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}.
+   * 
+   * @param event the event.
+   */
+  public void rowsRemoved(TableModelEvent event) 
+  {
+    fireTableChanged(event);
+  }
+
+  /**
+   * Sets the column identifiers, updates the data rows (truncating
+   * or padding each row with <code>null</code> values) to match the 
+   * number of columns, and sends a {@link TableModelEvent} to all
+   * registered listeners.
+   * 
+   * @param columnIdentifiers the column identifiers.
+   */
+  public void setColumnIdentifiers(Vector columnIdentifiers) 
+  {
+    this.columnIdentifiers = columnIdentifiers;
+    setColumnCount(columnIdentifiers == null ? 0 : columnIdentifiers.size());
+  }
+  
+  /**
+   * Sets the column identifiers, updates the data rows (truncating
+   * or padding each row with <code>null</code> values) to match the 
+   * number of columns, and sends a {@link TableModelEvent} to all
+   * registered listeners.
+   * 
+   * @param columnIdentifiers the column identifiers.
+   */
+  public void setColumnIdentifiers(Object[] columnIdentifiers) 
+  {
+    setColumnIdentifiers(convertToVector(columnIdentifiers));
+  }
+
+  /**
+   * This method is obsolete, use {@link #setRowCount(int)} instead.
+   * 
+   * @param numRows the number of rows.
+   */
+  public void setNumRows(int numRows) 
+  {
+    setRowCount(numRows);
+  }
+
+  /**
+   * Sets the number of rows in the table.  If <code>rowCount</code> is less
+   * than the current number of rows in the table, rows are discarded.
+   * If <code>rowCount</code> is greater than the current number of rows in
+   * the table, new (empty) rows are added.
+   * 
+   * @param rowCount the row count.
+   */
+  public void setRowCount(int rowCount) 
+  {
+    int existingRowCount = dataVector.size();
+    if (rowCount < existingRowCount) 
+    {
+      dataVector.setSize(rowCount);
+      fireTableRowsDeleted(rowCount, existingRowCount - 1);      
+    }
+    else 
+    {
+      int rowsToAdd = rowCount - existingRowCount;
+      addExtraRows(rowsToAdd, columnIdentifiers.size());
+      fireTableRowsInserted(existingRowCount, rowCount - 1);
+    }
+  }
+
+  /**
+   * Sets the number of columns in the table.  Existing rows are truncated
+   * or padded with <code>null</code> values to match the new column count.
+   * A {@link TableModelEvent} is sent to all registered listeners.
+   * 
+   * @param columnCount the column count.
+   */
+  public void setColumnCount(int columnCount) 
+  {
+    for (int i = 0; i < dataVector.size(); ++i)
+      {
+        ((Vector) dataVector.get(i)).setSize(columnCount);
+      }
+    if (columnIdentifiers != null)  
+      columnIdentifiers.setSize(columnCount);
+    fireTableStructureChanged();
+  }
+
+  /**
+   * Adds a column with the specified name to the table.  All cell values
+   * for the column are initially set to <code>null</code>.
+   * 
+   * @param columnName the column name (<code>null</code> permitted).
+   */
+  public void addColumn(Object columnName) 
+  {
+    addColumn(columnName, (Object[]) null);
+  }
+
+  /**
+   * Adds a column with the specified name and data values to the table.  
+   * 
+   * @param columnName the column name (<code>null</code> permitted).
+   * @param columnData the column data.
+   */
+  public void addColumn(Object columnName, Vector columnData) 
+  {
+    Object[] dataArray = null;
+    if (columnData != null) 
+    {
+      int rowCount = dataVector.size();
+      if (columnData.size() < rowCount)
+        columnData.setSize(rowCount);
+      dataArray = columnData.toArray();
+    }
+    addColumn(columnName, dataArray);
+  }
+
+  /**
+   * Adds a column with the specified name and data values to the table.
+   * 
+   * @param columnName the column name (<code>null</code> permitted).
+   * @param columnData the column data.
+   */
+  public void addColumn(Object columnName, Object[] columnData) 
+  {
+    if (columnData != null)
+    {
+      // check columnData array for cases where the number of items
+      // doesn't match the number of rows in the existing table
+      if (columnData.length > dataVector.size()) 
+      {
+        int rowsToAdd = columnData.length - dataVector.size();
+        addExtraRows(rowsToAdd, columnIdentifiers.size());
+      }
+      else if (columnData.length < dataVector.size())
+      {
+        Object[] tmp = new Object[dataVector.size()];
+        System.arraycopy(columnData, 0, tmp, 0, columnData.length);
+        columnData = tmp;
+      }
+    }
+    for (int i = 0; i < dataVector.size(); ++i)
+      {
+        ((Vector) dataVector.get(i)).add(columnData == null ? null : columnData[i]);
+      }
+    columnIdentifiers.add(columnName);
+    fireTableStructureChanged();
+  }
+
+  /**
+   * Adds a new row containing the specified data to the table and sends a
+   * {@link TableModelEvent} to all registered listeners.
+   * 
+   * @param rowData the row data (<code>null</code> permitted).
+   */
+  public void addRow(Vector rowData) 
+  {
+    int rowIndex = dataVector.size();
+    dataVector.add(rowData);
+    newRowsAdded(new TableModelEvent(
+      this, rowIndex, rowIndex, -1, TableModelEvent.INSERT)
+    );
+  }
+
+  /**
+   * Adds a new row containing the specified data to the table and sends a
+   * {@link TableModelEvent} to all registered listeners.
+   * 
+   * @param rowData the row data (<code>null</code> permitted).
+   */
+  public void addRow(Object[] rowData) 
+  {
+    addRow(convertToVector(rowData));
+  }
+
+  /**
+   * Inserts a new row into the table.
+   * 
+   * @param row the row index.
+   * @param rowData the row data.
+   */
+  public void insertRow(int row, Vector rowData) 
+  {
+    dataVector.add(row, rowData);
+    fireTableRowsInserted(row, row);
+  }
+
+  /**
+   * Inserts a new row into the table.
+   * 
+   * @param row the row index.
+   * @param rowData the row data.
+   */
+  public void insertRow(int row, Object[] rowData) 
+  {
+    insertRow(row, convertToVector(rowData));
+  }
+
+  /**
+   * Moves the rows from <code>startIndex</code> to <code>endIndex</code>
+   * (inclusive) to the specified row.
+   * 
+   * @param startIndex the start row.
+   * @param endIndex the end row.
+   * @param toIndex the row to move to.
+   */
+  public void moveRow(int startIndex, int endIndex, int toIndex) 
+  {
+    Vector removed = new Vector();
+    for (int i = endIndex; i >= startIndex; i--)
+    {
+      removed.add(this.dataVector.remove(i));
+    }
+    for (int i = 0; i <= endIndex - startIndex; i++) 
+    {
+      dataVector.insertElementAt(removed.get(i), toIndex);  
+    }
+    int firstRow = Math.min(startIndex, toIndex);
+    int lastRow = Math.max(endIndex, toIndex + (endIndex - startIndex));
+    fireTableRowsUpdated(firstRow, lastRow);
+  }
+
+  /**
+   * Removes a row from the table and sends a {@link TableModelEvent} to
+   * all registered listeners.
+   * 
+   * @param row the row index.
+   */
+  public void removeRow(int row) 
+  {
+    dataVector.remove(row);
+    fireTableRowsDeleted(row, row);
+  }
+
+  /**
+   * Returns the number of rows in the model.
+   * 
+   * @return The row count.
+   */
+  public int getRowCount() 
+  {
+    return dataVector.size();
+  }
+
+  /**
+   * Returns the number of columns in the model.
+   * 
+   * @return The column count.
+   */
+  public int getColumnCount() 
+  {
+    return columnIdentifiers == null ? 0 : columnIdentifiers.size();
+  }
+
+  /**
+   * Get the name of the column. If the column has the column identifier set,
+   * the return value is the result of the .toString() method call on that
+   * identifier. If the identifier is not explicitly set, the returned value
+   * is calculated by {@link AbstractTableModel#getColumnName(int)}.
+   * 
+   * @param column the column index.
+   * 
+   * @return The column name.
+   */
+  public String getColumnName(int column)
+  {
+    String result = "";
+    if (columnIdentifiers == null) 
+      result = super.getColumnName(column);
+    else 
+    {
+      if (column < getColumnCount())
+      {
+        checkSize();
+        Object id = columnIdentifiers.get(column);
+        if (id != null) 
+          result = id.toString();
+        else
+          result = super.getColumnName(column);
+      }
+      else
+        result = super.getColumnName(column);
+    }
+    return result;
+  }
+
+  /**
+   * Returns <code>true</code> if the specified cell can be modified, and
+   * <code>false</code> otherwise.  For this implementation, the method
+   * always returns <code>true</code>.
+   * 
+   * @param row the row index.
+   * @param column the column index.
+   * 
+   * @return <code>true</code> in all cases.
+   */
+  public boolean isCellEditable(int row, int column) 
+  {
+    return true;
+  }
+
+  /**
+   * Returns the value at the specified cell in the table.
+   * 
+   * @param row the row index.
+   * @param column the column index.
+   * 
+   * @return The value (<code>Object</code>, possibly <code>null</code>) at 
+   *         the specified cell in the table.
+   */
+  public Object getValueAt(int row, int column) 
+  {
+    return ((Vector) dataVector.get(row)).get(column);
+  }
+
+  /**
+   * Sets the value for the specified cell in the table and sends a 
+   * {@link TableModelEvent} to all registered listeners.
+   * 
+   * @param value the value (<code>Object</code>, <code>null</code> permitted).
+   * @param row the row index.
+   * @param column the column index.
+   */
+  public void setValueAt(Object value, int row, int column) 
+  {
+    ((Vector) dataVector.get(row)).set(column, value);
+    fireTableCellUpdated(row, column);
+  }
+
+  /**
+   * Converts the data array to a <code>Vector</code>.
+   * 
+   * @param data the data array (<code>null</code> permitted).
+   * 
+   * @return A vector (or <code>null</code> if the data array 
+   *         is <code>null</code>).
+   */
+  protected static Vector convertToVector(Object[] data) 
+  {
+    if (data == null)
+      return null;
+    Vector vector = new Vector(data.length);
+    for (int i = 0; i < data.length; i++) 
+      vector.add(data[i]);
+    return vector;          
+  }
+  
+  /**
+   * Converts the data array to a <code>Vector</code> of rows.
+   * 
+   * @param data the data array (<code>null</code> permitted).
+   * 
+   * @return A vector (or <code>null</code> if the data array 
+   *         is <code>null</code>.
+   */
+  protected static Vector convertToVector(Object[][] data) 
+  {
+    if (data == null)
+      return null;
+    Vector vector = new Vector(data.length);
+    for (int i = 0; i < data.length; i++)
+      vector.add(convertToVector(data[i]));
+    return vector;
+  }
+
+  /**
+   * This method adds some rows to <code>dataVector</code>.
+   *
+   * @param rowsToAdd number of rows to add
+   * @param nbColumns size of the added rows
+   */
+  private void addExtraRows(int rowsToAdd, int nbColumns)
+  {
+    for (int i = 0; i < rowsToAdd; i++) 
+      {
+        Vector tmp = new Vector();
+        tmp.setSize(columnIdentifiers.size());
+        dataVector.add(tmp);
+      } 
+  }
+
+  /**
+   * Checks the real columns/rows sizes against the ones returned by
+   * <code>getColumnCount()</code> and <code>getRowCount()</code>.
+   * If the supposed one are bigger, then we grow <code>columIdentifiers</code>
+   * and <code>dataVector</code> to their expected size.
+   */
+  private void checkSize()
+  {
+    int columnCount = getColumnCount();
+    int rowCount = getRowCount();
+    
+    if (columnCount > columnIdentifiers.size())
+      columnIdentifiers.setSize(columnCount);
+           
+    if (rowCount > dataVector.size())
+      {
+        int rowsToAdd = rowCount - dataVector.size();
+        addExtraRows(rowsToAdd, columnCount);
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1055 @@
+/* JTableHeader.java --
+   Copyright (C) 2003, 2004, 2005, 2006,  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.FocusListener;
+import java.beans.PropertyChangeListener;
+import java.util.Locale;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
+import javax.accessibility.AccessibleValue;
+import javax.swing.JComponent;
+import javax.swing.JTable;
+import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.event.TableColumnModelListener;
+import javax.swing.plaf.TableHeaderUI;
+
+/**
+ * Represents the table header. The header displays the column header values,
+ * is always visible event if the rest of the table scrolls up and down and
+ * supports column reordering and resizing with mouse.
+ */
+public class JTableHeader extends JComponent
+  implements TableColumnModelListener, Accessible
+{
+  protected class AccessibleJTableHeader extends AccessibleJComponent
+  {
+    protected class AccessibleJTableHeaderEntry extends AccessibleContext
+      implements Accessible, AccessibleComponent
+    {
+      
+      private int columnIndex;
+      
+      private JTableHeader parent;
+      
+      private JTable table;
+      
+      public AccessibleJTableHeaderEntry(int c, JTableHeader p, JTable t)
+      {
+        columnIndex = c;
+        parent = p;
+        table = t;
+      }
+      
+      /**
+       * Returns the column header renderer.
+       * 
+       * @return The column header renderer.
+       */
+      Component getColumnHeaderRenderer()
+      {
+        TableColumn tc = parent.getColumnModel().getColumn(columnIndex);
+        TableCellRenderer r = tc.getHeaderRenderer();
+        if (r == null)
+          r = parent.getDefaultRenderer();
+        return r.getTableCellRendererComponent(table, tc.headerValue, 
+            false, false, -1, columnIndex);
+      }
+      
+      /**
+       * Returns the accessible context for the column header renderer, or 
+       * <code>null</code>.
+       * 
+       * @return The accessible context.
+       */
+      AccessibleContext getAccessibleColumnHeaderRenderer()
+      {
+        Component c = getColumnHeaderRenderer();
+        if (c instanceof Accessible)
+          return c.getAccessibleContext();
+        return null;
+      }
+      
+      /**
+       * @see #removeFocusListener(FocusListener)
+       */
+      public void addFocusListener(FocusListener l)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          c.addFocusListener(l);
+      }
+      
+      /**
+       * @see #removePropertyChangeListener(PropertyChangeListener)
+       */
+      public void addPropertyChangeListener(PropertyChangeListener l)
+      {
+        // add the listener to the accessible context for the header
+        // renderer...
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          ac.addPropertyChangeListener(l);
+      }
+      
+      public boolean contains(Point p)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.contains(p);
+        else 
+          return false;
+      }
+      
+      public AccessibleAction getAccessibleAction()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac instanceof AccessibleAction)
+          return (AccessibleAction) ac;
+        else 
+          return null;
+      }
+      
+      public Accessible getAccessibleAt(Point p)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getAccessibleAt(p);
+        else
+          return null;
+      }
+      
+      /**
+       * Returns <code>null</code> as the header entry has no accessible
+       * children.
+       * 
+       * @return <code>null</code>.
+       */
+      public Accessible getAccessibleChild(int i)
+      {
+        return null;
+      }
+      
+      /**
+       * Returns the number of accessible children, zero in this case.
+       * 
+       * @return 0
+       */
+      public int getAccessibleChildrenCount()
+      {
+        return 0;
+      }
+      
+      /**
+       * Returns the accessible component for this header entry.
+       * 
+       * @return <code>this</code>.
+       */
+      public AccessibleComponent getAccessibleComponent()
+      {
+        return this;
+      }
+      
+      /**
+       * Returns the accessible context for this header entry.
+       * 
+       * @return <code>this</code>.
+       */
+      public AccessibleContext getAccessibleContext()
+      {
+        return this;
+      }
+      
+      /**
+       * Returns the accessible description.
+       * 
+       * @return The accessible description.
+       * 
+       * @see #setAccessibleDescription(String)
+       */
+      public String getAccessibleDescription()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          return ac.getAccessibleDescription();
+        return accessibleDescription;
+      }
+      
+      /**
+       * Returns the index of this header entry.
+       * 
+       * @return The index of this header entry.
+       */
+      public int getAccessibleIndexInParent()
+      {
+        return columnIndex;
+      }
+      
+      /**
+       * Returns the accessible name.
+       * 
+       * @return The accessible name.
+       * 
+       * @see #setAccessibleName(String)
+       */
+      public String getAccessibleName()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          return ac.getAccessibleName();
+        return accessibleName;
+      }
+      
+      /**
+       * Returns the accessible role for the header entry.
+       * 
+       * @return The accessible role.
+       */
+      public AccessibleRole getAccessibleRole()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          return ac.getAccessibleRole();
+        else
+          return null;
+      }
+      
+      public AccessibleSelection getAccessibleSelection()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac instanceof AccessibleValue)
+          return (AccessibleSelection) ac;
+        else 
+          return null;
+      }
+      
+      public AccessibleStateSet getAccessibleStateSet()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          return ac.getAccessibleStateSet();
+        else 
+          return null;
+      }
+      
+      public AccessibleText getAccessibleText()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          return ac.getAccessibleText();
+        else 
+          return null;
+      }
+      
+      public AccessibleValue getAccessibleValue()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac instanceof AccessibleValue)
+          return (AccessibleValue) ac;
+        else 
+          return null;
+      }
+      
+      public Color getBackground()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getBackground();
+        else
+          return null;
+      }
+      
+      public Rectangle getBounds()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getBounds();
+        else
+          return null;
+      }
+      
+      public Cursor getCursor()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getCursor();
+        else
+          return null;
+      }
+      
+      public Font getFont()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getFont();
+        else
+          return null;
+      }
+      
+      public FontMetrics getFontMetrics(Font f)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getFontMetrics(f);
+        else
+          return null;
+      }
+      
+      public Color getForeground()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getForeground();
+        else
+          return null;
+      }
+      
+      public Locale getLocale()
+      {
+        Component c = getColumnHeaderRenderer();
+        if (c != null)
+          return c.getLocale();
+        return null;
+      }
+      
+      public Point getLocation()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getLocation();
+        else
+          return null;
+      }
+      
+      public Point getLocationOnScreen()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getLocationOnScreen();
+        else
+          return null;
+      }
+      
+      public Dimension getSize()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.getSize();
+        else
+          return null;
+      }
+      
+      public boolean isEnabled()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.isEnabled();
+        else
+          return false;
+      }
+      
+      public boolean isFocusTraversable()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.isFocusTraversable();
+        else
+          return false;
+      }
+      
+      public boolean isShowing()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.isShowing();
+        else
+          return false;
+      }
+      
+      public boolean isVisible()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          return c.isVisible();
+        else
+          return false;
+      }
+      
+      /**
+       * @see #addFocusListener(FocusListener)
+       */
+      public void removeFocusListener(FocusListener l)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          c.removeFocusListener(l);
+      }
+      
+      /**
+       * @see #addPropertyChangeListener(PropertyChangeListener)
+       */
+      public void removePropertyChangeListener(PropertyChangeListener l)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          ac.removePropertyChangeListener(l);
+      }
+      
+      /**
+       * @see #addFocusListener(FocusListener)
+       */
+      public void requestFocus()
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent c = ac.getAccessibleComponent();
+        if (c != null)
+          c.requestFocus();
+      }
+      
+      /**
+       * @see #getAccessibleDescription()
+       */
+      public void setAccessibleDescription(String s)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          ac.setAccessibleDescription(s);
+        else
+          accessibleDescription = s;
+      }
+      
+      /**
+       * @see #getAccessibleName()
+       */
+      public void setAccessibleName(String s)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        if (ac != null)
+          ac.setAccessibleName(s);
+      }
+      
+      public void setBackground(Color c)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setBackground(c);
+      }
+      
+      public void setBounds(Rectangle r)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setBounds(r);
+      }
+      
+      public void setCursor(Cursor c)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setCursor(c);
+      }
+      
+      public void setEnabled(boolean b)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setEnabled(b);
+      }
+      
+      public void setFont(Font f)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setFont(f);
+      }
+      
+      public void setForeground(Color c)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setForeground(c);
+      }
+      
+      public void setLocation(Point p)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setLocation(p);
+      }
+      
+      public void setSize(Dimension d)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setSize(d);
+      }
+      
+      public void setVisible(boolean b)
+      {
+        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+        AccessibleComponent comp = ac.getAccessibleComponent();
+        if (comp != null)
+          comp.setVisible(b);
+      }
+    };
+    
+    public AccessibleRole getAccessibleRole()
+    {
+      return AccessibleRole.PANEL;
+    }
+    
+    public int getAccessibleChildrenCount()
+    {
+      return table.getColumnCount();
+    }
+    
+    public Accessible getAccessibleChild(int i)
+    {
+      return new AccessibleJTableHeaderEntry(i, JTableHeader.this, table);
+    }
+    
+    public Accessible getAccessibleAt(Point p)
+    {
+      return getAccessibleChild(columnAtPoint(p));
+    }
+  }
+  
+  /**
+   * Use serialVersionUid for interoperability.
+   */
+  private static final long serialVersionUID = 5144633983372967710L;
+
+  /**
+   * The columnModel property.
+   */
+  protected TableColumnModel columnModel;
+
+  /**
+   * The draggedColumn property.
+   */
+  protected TableColumn draggedColumn;
+
+  /**
+   * The draggedDistance property.
+   */
+  protected int draggedDistance;
+
+  /**
+   * The opaque property.
+   */
+  boolean opaque;
+
+  /**
+   * The reorderingAllowed property.
+   */
+  protected boolean reorderingAllowed;
+
+  /**
+   * The resizingAllowed property.
+   */
+  protected boolean resizingAllowed = true;
+
+  /**
+   * The resizingColumn property.
+   */
+  protected TableColumn resizingColumn;
+
+  /**
+   * The table property.
+   */
+  protected JTable table;
+
+  /**
+   * The updateTableInRealTime property.
+   */
+  protected boolean updateTableInRealTime;
+
+  TableCellRenderer cellRenderer; 
+
+  /**
+   * Creates a new default instance.
+   */
+  public JTableHeader()
+  {
+    this(null);
+  }
+
+  /**
+   * Creates a new header.  If <code>cm</code> is <code>null</code>, a new
+   * table column model is created by calling 
+   * {@link #createDefaultColumnModel()}.
+   * 
+   * @param cm  the table column model (<code>null</code> permitted).
+   */
+  public JTableHeader(TableColumnModel cm)
+  {
+    columnModel = cm == null ? createDefaultColumnModel() : cm; 
+    initializeLocalVars();
+    updateUI();
+  }
+
+  /**
+   * Creates a default table column model.
+   * 
+   * @return A default table column model.
+   */
+  protected TableColumnModel createDefaultColumnModel()
+  {
+    return new DefaultTableColumnModel();
+  }
+
+  /**
+   * Get the value of the {@link #accessibleContext} property.
+   *
+   * @return The current value of the property
+   */
+  public AccessibleContext getAccessibleContext()
+  {
+    return accessibleContext;
+  }
+
+  /**
+   * Get the value of the {@link #columnModel} property.
+   *
+   * @return The current value of the property
+   */
+  public TableColumnModel getColumnModel()
+  {
+    return columnModel;
+  }
+
+  /**
+   * Get the column that is currently being dragged. This is used when
+   * handling the column reordering with mouse.
+   *
+   * @return the column being dragged, null if none.
+   */
+  public TableColumn getDraggedColumn()
+  {
+    return draggedColumn;
+  }
+
+  /**
+   * Get the value of the {@link #draggedDistance} property.
+   *
+   * @return The current value of the property
+   */
+  public int getDraggedDistance()
+  {
+    return draggedDistance;
+  }
+
+  /**
+   * Check if it is possible to reorder the table columns by dragging column
+   * header with mouse. The table reordering is enabled by default, but can be
+   * disabled with {@link #setReorderingAllowed(boolean)}.
+   *
+   * @return true if reordering is allowed, false otherwise.
+   */ 
+  public boolean getReorderingAllowed()
+  {
+    return reorderingAllowed;
+  }
+
+  /**
+   * Check if it is possible to resize the table columns by dragging the column
+   * boundary in the table header with mouse. The resizing is enabled
+   * by default, but can be disabled with {@link #setResizingAllowed(boolean)}.
+   *
+   * @return true if resizing is allowed, false otherwise.
+   */ 
+  public boolean getResizingAllowed()
+  {
+    return resizingAllowed;
+  }
+
+  /**
+   * Get the column that is currently being resized. This is used when
+   * handling the column resizing with mouse.
+   *
+   * @return the column being currently resized, null if none.
+   */
+  public TableColumn getResizingColumn()
+  {
+    return resizingColumn;
+  }
+
+  /**
+   * Get the table, having this header.
+   *
+   * @return the table, having this header.
+   */
+  public JTable getTable()
+  {
+    return table;
+  }
+
+  /**
+   * Get the value of the {@link #updateTableInRealTime} property.
+   *
+   * @return The current value of the property
+   */
+  public boolean getUpdateTableInRealTime()
+  {
+    return updateTableInRealTime;
+  }
+
+  /**
+   * Get the value of the {@link #opaque} property.
+   *
+   * @return The current value of the property
+   */
+  public boolean isOpaque()
+  {
+    return opaque;
+  }
+
+  /**
+   * Set the value of the {@link #columnModel} property.
+   *
+   * @param c The new value of the property
+   */ 
+  public void setColumnModel(TableColumnModel c)
+  {
+    columnModel.removeColumnModelListener(this);
+    columnModel = c;
+    columnModel.addColumnModelListener(this);
+  }
+
+  /**
+   * Set the column that is currently being dragged. This is used when
+   * dragging the column with mouse. Setting to null will stop the 
+   * dragging session immediately.
+   *
+   * @param draggingIt the column being currently dragged, null if none.
+   */ 
+  public void setDraggedColumn(TableColumn draggingIt)
+  {
+    draggedColumn = draggingIt;
+  }
+
+  /**
+   * Set the value of the {@link #draggedDistance} property.
+   *
+   * @param d The new value of the property
+   */ 
+  public void setDraggedDistance(int d)
+  {
+    draggedDistance = d;
+  }
+
+  /**
+   * Set the value of the {@link #opaque} property.
+   *
+   * @param o The new value of the property
+   */ 
+  public void setOpaque(boolean o)
+  {
+    opaque = o;
+  }
+
+  /**
+   * Set the table ability to reorder columns by dragging column header
+   * with mouse. The table reordering is enabled by default, but can be
+   * disabled with this method.
+   *
+   * @param allowed true if reordering is allowed, false otherwise.
+   */ 
+  public void setReorderingAllowed(boolean allowed)
+  {
+    reorderingAllowed = allowed;
+  }
+
+  /**
+   * Set the table ability to resize columns by dragging the column
+   * boundary in the table header with mouse. The resizing is enabled
+   * by default, but can be disabled using this method.
+   *
+   * @param allowed true if resizing is allowed, false otherwise.
+   */ 
+  public void setResizingAllowed(boolean allowed)
+  {
+    resizingAllowed = allowed;
+  }
+
+  /**
+   * The the column that is currently being resized. This property is used
+   * when handling table resizing with mouse. Setting to null would stop
+   * the resizing session immediately.
+   *
+   * @param resizingIt the column being currently resized
+   */ 
+  public void setResizingColumn(TableColumn resizingIt)
+  {
+    resizingColumn = resizingIt;
+  }
+
+  /**
+   * Set the value of the {@link #table} property.
+   *
+   * @param t The new value of the property
+   */ 
+  public void setTable(JTable t)
+  {
+    table = t;
+  }
+
+  /**
+   * Set the value of the {@link #updateTableInRealTime} property.
+   *
+   * @param u The new value of the property
+   */ 
+  public void setUpdateTableInRealTime(boolean u)
+  {
+    updateTableInRealTime = u;
+  }
+
+  /**
+   * Creates a default renderer.
+   * 
+   * @return A default renderer.
+   */
+  protected TableCellRenderer createDefaultRenderer()
+  {
+    return new DefaultTableCellRenderer();
+  }
+  
+  /**
+   * Returns the default table cell renderer.
+   * 
+   * @return The default table cell renderer.
+   */
+  public TableCellRenderer getDefaultRenderer()
+  {
+    return cellRenderer;
+  }
+
+  /**
+   * Sets the default table cell renderer.
+   * 
+   * @param cellRenderer  the renderer.
+   */
+  public void setDefaultRenderer(TableCellRenderer cellRenderer)
+  {
+    this.cellRenderer = cellRenderer;
+  }
+  
+  /**
+   * Get the rectangle, occupied by the header of the given column.
+   * 
+   * @param column the column, for that the header area is requested.
+   * 
+   * @return the column header area.
+   */
+  public Rectangle getHeaderRect(int column)
+  {
+    Rectangle r = getTable().getCellRect(-1, column, false);
+    r.height = getHeight();
+    return r;
+  }
+
+  protected String paramString()
+  {
+    return "JTableHeader";
+  }
+
+  // UI support
+
+  public String getUIClassID()
+  {
+    return "TableHeaderUI";
+  }
+
+  public TableHeaderUI getUI()
+  {
+    return (TableHeaderUI) ui;
+  }
+
+  public void setUI(TableHeaderUI u)
+  {
+    super.setUI(u);
+  }
+
+  public void updateUI()
+  {
+    setUI((TableHeaderUI) UIManager.getUI(this));
+  }
+
+  /**
+   * Returns the index of the column at the specified point.
+   * 
+   * @param point  the point.
+   * 
+   * @return The column index, or -1.
+   */
+  public int columnAtPoint(Point point)
+  {
+    if (getBounds().contains(point))
+      return columnModel.getColumnIndexAtX(point.x);
+    
+    return -1;
+  }
+
+  /**
+   * Receives notification when a column is added to the column model.
+   *
+   * @param event the table column model event
+   */
+  public void columnAdded(TableColumnModelEvent event)
+  {
+    // TODO: What else to do here (if anything)?
+    resizeAndRepaint();
+  }
+
+  /**
+   * Receives notification when a column margin changes in the column model.
+   *
+   * @param event the table column model event
+   */
+  public void columnMarginChanged(ChangeEvent event)
+  {
+    // TODO: What else to do here (if anything)?
+    resizeAndRepaint();
+  }
+
+  /**
+   * Receives notification when a column is moved within the column model.
+   *
+   * @param event the table column model event
+   */
+  public void columnMoved(TableColumnModelEvent event)
+  {
+    // TODO: What else to do here (if anything)?
+    resizeAndRepaint();
+  }
+
+  /**
+   * Receives notification when a column is removed from the column model.
+   *
+   * @param event the table column model event
+   */
+  public void columnRemoved(TableColumnModelEvent event)
+  {
+    // TODO: What else to do here (if anything)?
+    resizeAndRepaint();
+  }
+
+  /**
+   * Receives notification when the column selection has changed.
+   *
+   * @param event the table column model event
+   */
+  public void columnSelectionChanged(ListSelectionEvent event)
+  {
+    // TODO: What else to do here (if anything)?
+    resizeAndRepaint();
+  }
+
+  /**
+   * Validates the layout of this table header and repaints it. This is
+   * equivalent to <code>revalidate()</code> followed by
+   * <code>repaint()</code>.
+   */
+  public void resizeAndRepaint()
+  {
+    revalidate();
+    repaint();
+  }
+
+  /**
+   * Initializes the fields and properties of this class with default values.
+   * This is called by the constructors.
+   */
+  protected void initializeLocalVars()
+  {
+    accessibleContext = new AccessibleJTableHeader();
+    draggedColumn = null;
+    draggedDistance = 0;
+    opaque = true;
+    reorderingAllowed = true;
+    resizingAllowed = true;
+    resizingColumn = null;
+    table = null;
+    updateTableInRealTime = true;
+    cellRenderer = createDefaultRenderer();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,65 @@
+/* TableCellEditor.java --
+   Copyright (C) 2002, 2004  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Component;
+
+import javax.swing.CellEditor;
+import javax.swing.JTable;
+
+/**
+ * TableCellEditor public interface
+ * @author Andrew Selkirk
+ */
+public interface TableCellEditor extends CellEditor 
+{
+
+  /**
+   * Get table cell editor component
+   * @param table JTable
+   * @param value Value of cell
+   * @param isSelected Cell selected
+   * @param row Row of cell
+   * @param column Column of cell
+   * @return Component
+   */
+  Component getTableCellEditorComponent(JTable table, Object value, 
+      boolean isSelected, int row, int column);
+
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,66 @@
+/* TableCellRenderer.java --
+   Copyright (C) 2002, 2004  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Component;
+
+import javax.swing.JTable;
+
+/**
+ * TableCellRenderer public interface
+ * @author Andrew Selkirk
+ */
+public interface TableCellRenderer 
+{
+
+  /**
+   * Get table cell renderer component
+   * @param table JTable
+   * @param value Value of cell
+   * @param isSelected Cell selected
+   * @param hasFocus Cell has focus
+   * @param row Row of cell
+   * @param column Column of cell
+   * @return Component
+   */
+  Component getTableCellRendererComponent(JTable table, Object value, 
+      boolean isSelected, boolean hasFocus, int row, int column);
+
+
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,693 @@
+/* TableColumn.java --
+   Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.Serializable;
+
+import javax.swing.event.SwingPropertyChangeSupport;
+
+/**
+ * Represents the attributes of a column in a table, including the column index,
+ * width, minimum width, preferred width and maximum width.
+ * 
+ * @author	Andrew Selkirk
+ */
+public class TableColumn
+  implements Serializable
+{
+  static final long serialVersionUID = -6113660025878112608L;
+
+  /**
+   * The name for the <code>columnWidth</code> property (this field is
+   * obsolete and no longer used).  Note also that the typo in the value 
+   * string is deliberate, to match the specification.
+   */
+  public static final String COLUMN_WIDTH_PROPERTY = "columWidth";
+
+  /**
+   * The name for the <code>headerValue</code> property.
+   */
+  public static final String HEADER_VALUE_PROPERTY = "headerValue";
+
+  /**
+   * The name for the <code>headerRenderer</code> property.
+   */
+  public static final String HEADER_RENDERER_PROPERTY = "headerRenderer";
+
+  /**
+   * The name for the <code>cellRenderer</code> property.
+   */
+  public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
+
+  /**
+   * The index of the corresponding column in the table model.
+   */
+  protected int modelIndex;
+
+  /**
+   * The identifier for the column.
+   */
+  protected Object identifier;
+
+  /**
+   * The current width for the column.
+   */
+  protected int width;
+
+  /**
+   * The minimum width for the column.
+   */
+  protected int minWidth = 15;
+
+  /**
+   * The preferred width for the column.
+   */
+  private int preferredWidth;
+
+  /**
+   * The maximum width for the column.
+   */
+  protected int maxWidth = Integer.MAX_VALUE;
+
+  /**
+   * The renderer for the column header.
+   */
+  protected TableCellRenderer headerRenderer;
+
+  /**
+   * The value for the column header.
+   */
+  protected Object headerValue;
+
+  /**
+   * The renderer for the regular cells in this column.
+   */
+  protected TableCellRenderer cellRenderer;
+
+  /**
+   * An editor for the regular cells in this column.
+   */
+  protected TableCellEditor cellEditor;
+
+  /**
+   * A flag that determines whether or not the column is resizable (the default
+   * is <code>true</code>).
+   */
+  protected boolean isResizable = true;
+
+  /**
+   * resizedPostingDisableCount
+   *
+   * @deprecated 1.3
+   */
+  protected transient int resizedPostingDisableCount;
+
+  /**
+   * A storage and notification mechanism for property change listeners.
+   */
+  private SwingPropertyChangeSupport changeSupport =
+    new SwingPropertyChangeSupport(this);
+
+  /**
+   * Creates a new <code>TableColumn</code> that maps to column 0 in the
+   * related table model.  The default width is <code>75</code> units.
+   */
+  public TableColumn()
+  {
+    this(0, 75, null, null);
+  }
+
+  /**
+   * Creates a new <code>TableColumn</code> that maps to the specified column 
+   * in the related table model.  The default width is <code>75</code> units.
+   * 
+   * @param modelIndex the index of the column in the model
+   */
+  public TableColumn(int modelIndex)
+  {
+    this(modelIndex, 75, null, null);
+  }
+
+  /**
+   * Creates a new <code>TableColumn</code> that maps to the specified column 
+   * in the related table model, and has the specified <code>width</code>.
+   * 
+   * @param modelIndex the index of the column in the model
+   * @param width the width
+   */
+  public TableColumn(int modelIndex, int width)
+  {
+    this(modelIndex, width, null, null);
+  }
+
+  /**
+   * Creates a new <code>TableColumn</code> that maps to the specified column 
+   * in the related table model, and has the specified <code>width</code>,
+   * <code>cellRenderer</code> and <code>cellEditor</code>.
+   * 
+   * @param modelIndex the index of the column in the model
+   * @param width the width
+   * @param cellRenderer the cell renderer (<code>null</code> permitted).
+   * @param cellEditor the cell editor (<code>null</code> permitted).
+   */
+  public TableColumn(int modelIndex, int width,
+                     TableCellRenderer cellRenderer, TableCellEditor cellEditor)
+  {
+    this.modelIndex = modelIndex;
+    this.width = width;
+    this.preferredWidth = width;
+    this.cellRenderer = cellRenderer;
+    this.cellEditor = cellEditor;
+    this.headerValue = null;
+    this.identifier = null;
+  }
+
+  /**
+   * Sets the index of the column in the related {@link TableModel} that this
+   * <code>TableColumn</code> maps to, and sends a {@link PropertyChangeEvent}
+   * (with the property name 'modelIndex') to all registered listeners.
+   * 
+   * @param modelIndex the column index in the model.
+   * 
+   * @see #getModelIndex()
+   */
+  public void setModelIndex(int modelIndex)
+  {
+    if (this.modelIndex != modelIndex)
+      {
+        int oldValue = this.modelIndex;
+        this.modelIndex = modelIndex;
+        changeSupport.firePropertyChange("modelIndex", oldValue, modelIndex);
+      }
+  }
+
+  /**
+   * Returns the index of the column in the related {@link TableModel} that
+   * this <code>TableColumn</code> maps to.
+   * 
+   * @return the model index.
+   * 
+   * @see #setModelIndex(int)
+   */
+  public int getModelIndex()
+  {
+    return modelIndex;
+  }
+
+  /**
+   * Sets the identifier for the column and sends a {@link PropertyChangeEvent}
+   * (with the property name 'identifier') to all registered listeners.
+   * 
+   * @param identifier the identifier (<code>null</code> permitted).
+   * 
+   * @see #getIdentifier()
+   */
+  public void setIdentifier(Object identifier)
+  {
+    if (this.identifier != identifier)
+      {       
+        Object oldValue = this.identifier;
+        this.identifier = identifier;
+        changeSupport.firePropertyChange("identifier", oldValue, identifier);
+      }
+  }
+
+  /**
+   * Returns the identifier for the column, or {@link #getHeaderValue()} if the 
+   * identifier is <code>null</code>.
+   * 
+   * @return The identifier (or {@link #getHeaderValue()} if the identifier is 
+   *         <code>null</code>).
+   */
+  public Object getIdentifier()
+  {
+    if (identifier == null)
+      return getHeaderValue();
+    return identifier;
+  }
+
+  /**
+   * Sets the header value and sends a {@link PropertyChangeEvent} (with the 
+   * property name {@link #HEADER_VALUE_PROPERTY}) to all registered listeners.
+   * 
+   * @param headerValue the value of the header (<code>null</code> permitted).
+   * 
+   * @see #getHeaderValue()
+   */
+  public void setHeaderValue(Object headerValue)
+  {
+    if (this.headerValue == headerValue)
+      return;
+    
+    Object oldValue = this.headerValue;
+    this.headerValue = headerValue;
+    changeSupport.firePropertyChange(HEADER_VALUE_PROPERTY, oldValue, 
+                                     headerValue);
+  }
+
+  /**
+   * Returns the header value.
+   * 
+   * @return the value of the header.
+   * 
+   * @see #getHeaderValue()
+   */
+  public Object getHeaderValue()
+  {
+    return headerValue;
+  }
+
+  /**
+   * Sets the renderer for the column header and sends a 
+   * {@link PropertyChangeEvent} (with the property name 
+   * {@link #HEADER_RENDERER_PROPERTY}) to all registered listeners.
+   * 
+   * @param renderer the header renderer (<code>null</code> permitted).
+   * 
+   * @see #getHeaderRenderer()
+   */
+  public void setHeaderRenderer(TableCellRenderer renderer)
+  {
+    if (headerRenderer == renderer)
+      return;
+    
+    TableCellRenderer oldRenderer = headerRenderer;
+    headerRenderer = renderer;
+    changeSupport.firePropertyChange(HEADER_RENDERER_PROPERTY, oldRenderer, 
+                                     headerRenderer);
+  }
+
+  /**
+   * Returns the renderer for the column header.
+   * 
+   * @return The renderer for the column header (possibly <code>null</code>).
+   * 
+   * @see #setHeaderRenderer(TableCellRenderer)
+   */
+  public TableCellRenderer getHeaderRenderer()
+  {
+    return headerRenderer;
+  }
+
+  /**
+   * Sets the renderer for cells in this column and sends a 
+   * {@link PropertyChangeEvent} (with the property name 
+   * {@link #CELL_RENDERER_PROPERTY}) to all registered listeners.
+   * 
+   * @param renderer the cell renderer (<code>null</code> permitted).
+   * 
+   * @see #getCellRenderer()
+   */
+  public void setCellRenderer(TableCellRenderer renderer)
+  {
+    if (cellRenderer == renderer)
+      return;
+    
+    TableCellRenderer oldRenderer = cellRenderer;
+    cellRenderer = renderer;
+    changeSupport.firePropertyChange(CELL_RENDERER_PROPERTY, oldRenderer, 
+                                     cellRenderer);
+  }
+
+  /**
+   * Returns the renderer for the table cells in this column.
+   * 
+   * @return The cell renderer (possibly <code>null</code>).
+   * 
+   * @see #setCellRenderer(TableCellRenderer)
+   */
+  public TableCellRenderer getCellRenderer()
+  {
+    return cellRenderer;
+  }
+
+  /**
+   * Sets the cell editor for the column and sends a {@link PropertyChangeEvent}
+   * (with the property name 'cellEditor') to all registered listeners.
+   * 
+   * @param cellEditor the cell editor (<code>null</code> permitted).
+   * 
+   * @see #getCellEditor()
+   */
+  public void setCellEditor(TableCellEditor cellEditor)
+  {
+    if (this.cellEditor != cellEditor)
+      {
+        TableCellEditor oldValue = this.cellEditor;
+        this.cellEditor = cellEditor;
+        changeSupport.firePropertyChange("cellEditor", oldValue, cellEditor);
+      }
+  }
+
+  /**
+   * Returns the cell editor for the column (the default value is 
+   * <code>null</code>).
+   * 
+   * @return The cell editor (possibly <code>null</code>).
+   * 
+   * @see #setCellEditor(TableCellEditor)
+   */
+  public TableCellEditor getCellEditor()
+  {
+    return cellEditor;
+  }
+
+  /**
+   * Sets the width for the column and sends a {@link PropertyChangeEvent} 
+   * (with the property name 'width') to all registered listeners.  If the new
+   * width falls outside the range getMinWidth() to getMaxWidth() it is 
+   * adjusted to the appropriate boundary value.
+   * 
+   * @param newWidth the width.
+   * 
+   * @see #getWidth()
+   */
+  public void setWidth(int newWidth)
+  {
+    int	oldWidth = width;
+
+    if (newWidth < minWidth)
+      width = minWidth;
+    else if (newWidth > maxWidth)
+      width = maxWidth;
+    else
+      width = newWidth;
+
+    if (width == oldWidth)
+      return;
+
+    // We do have a constant field COLUMN_WIDTH_PROPERTY,
+    // however, tests show that the actual fired property name is 'width'
+    // and even Sun's API docs say that this constant field is obsolete and
+    // not used.
+    changeSupport.firePropertyChange("width", oldWidth, width);
+  }
+
+  /**
+   * Returns the width for the column (the default value is <code>75</code>).
+   * 
+   * @return The width.
+   *
+   * @see #setWidth(int)
+   */
+  public int getWidth()
+  {
+    return width;
+  }
+
+  /**
+   * Sets the preferred width for the column and sends a 
+   * {@link PropertyChangeEvent} (with the property name 'preferredWidth') to 
+   * all registered listeners.  If necessary, the supplied value will be 
+   * adjusted to fit in the range {@link #getMinWidth()} to 
+   * {@link #getMaxWidth()}.
+   * 
+   * @param preferredWidth  the preferred width.
+   * 
+   * @see #getPreferredWidth()
+   */
+  public void setPreferredWidth(int preferredWidth)
+  {
+    int oldPrefWidth = this.preferredWidth;
+
+    if (preferredWidth < minWidth)
+      this.preferredWidth = minWidth;
+    else if (preferredWidth > maxWidth)
+      this.preferredWidth = maxWidth;
+    else
+      this.preferredWidth = preferredWidth;
+
+    changeSupport.firePropertyChange("preferredWidth", oldPrefWidth, 
+                                     this.preferredWidth);
+  }
+
+  /**
+   * Returns the preferred width for the column (the default value is 
+   * <code>75</code>).
+   * 
+   * @return The preferred width.
+   * 
+   * @see #setPreferredWidth(int)
+   */
+  public int getPreferredWidth()
+  {
+    return preferredWidth;
+  }
+
+  /**
+   * Sets the minimum width for the column and sends a 
+   * {@link PropertyChangeEvent} (with the property name 'minWidth') to all
+   * registered listeners.  If the current <code>width</code> and/or 
+   * <code>preferredWidth</code> are less than the new minimum width, they are
+   * adjusted accordingly.
+   * 
+   * @param minWidth  the minimum width (negative values are treated as 0).
+   * 
+   * @see #getMinWidth()
+   */
+  public void setMinWidth(int minWidth)
+  {
+    if (minWidth < 0)
+      minWidth = 0;
+    if (this.minWidth != minWidth)
+      {
+        if (width < minWidth)
+          setWidth(minWidth);
+        if (preferredWidth < minWidth)
+          setPreferredWidth(minWidth);
+        int oldValue = this.minWidth;
+        this.minWidth = minWidth;
+        changeSupport.firePropertyChange("minWidth", oldValue, minWidth);
+      }
+  }
+
+  /**
+   * Returns the <code>TableColumn</code>'s minimum width (the default value
+   * is <code>15</code>).
+   * 
+   * @return The minimum width.
+   * 
+   * @see #setMinWidth(int)
+   */
+  public int getMinWidth()
+  {
+    return minWidth;
+  }
+
+  /**
+   * Sets the maximum width for the column and sends a 
+   * {@link PropertyChangeEvent} (with the property name 'maxWidth') to all
+   * registered listeners.  If the current <code>width</code> and/or 
+   * <code>preferredWidth</code> are greater than the new maximum width, they 
+   * are adjusted accordingly.
+   * 
+   * @param maxWidth the maximum width.
+   * 
+   * @see #getMaxWidth()
+   */
+  public void setMaxWidth(int maxWidth)
+  {
+    if (this.maxWidth != maxWidth)
+      {
+        if (width > maxWidth)
+          setWidth(maxWidth);
+        if (preferredWidth > maxWidth)
+          setPreferredWidth(maxWidth);
+        int oldValue = this.maxWidth;
+        this.maxWidth = maxWidth;
+        changeSupport.firePropertyChange("maxWidth", oldValue, maxWidth);
+       }
+  }
+
+  /**
+   * Returns the maximum width for the column (the default value is
+   * {@link Integer#MAX_VALUE}).
+   * 
+   * @return The maximum width for the column.
+   * 
+   * @see #setMaxWidth(int)
+   */
+  public int getMaxWidth()
+  {
+    return maxWidth;
+  }
+
+  /**
+   * Sets the flag that controls whether or not the column is resizable, and
+   * sends a {@link PropertyChangeEvent} (with the property name 'isResizable')
+   * to all registered listeners.
+   * 
+   * @param isResizable <code>true</code> if this column is resizable,
+   * <code>false</code> otherwise.
+   * 
+   * @see #getResizable()
+   */
+  public void setResizable(boolean isResizable)
+  {
+    if (this.isResizable != isResizable)
+      {
+        this.isResizable = isResizable;
+        changeSupport.firePropertyChange("isResizable", !this.isResizable, 
+            isResizable);
+      }
+  }
+
+  /**
+   * Returns the flag that controls whether or not the column is resizable.
+   * 
+   * @return <code>true</code> if this column is resizable,
+   * <code>false</code> otherwise.
+   * 
+   * @see #setResizable(boolean)
+   */
+  public boolean getResizable()
+  {
+    return isResizable;
+  }
+
+  /**
+   * Sets the minimum, maximum, preferred and current width to match the
+   * minimum, maximum and preferred width of the header renderer component.
+   * If there is no header renderer component, this method does nothing.
+   */
+  public void sizeWidthToFit()
+  {
+    if (headerRenderer == null)
+      return;
+    Component c = headerRenderer.getTableCellRendererComponent(null, 
+        getHeaderValue(), false, false, 0, 0);
+    Dimension min = c.getMinimumSize();
+    Dimension max = c.getMaximumSize();
+    Dimension pref = c.getPreferredSize();
+    setMinWidth(min.width);
+    setMaxWidth(max.width);
+    setPreferredWidth(pref.width);
+    setWidth(pref.width);
+  }
+
+  /**
+   * This method is empty, unused and deprecated.
+   * @deprecated 1.3
+   */
+  public void disableResizedPosting()
+  {
+    // Does nothing
+  }
+
+  /**
+   * This method is empty, unused and deprecated.
+   * @deprecated 1.3
+   */
+  public void enableResizedPosting()
+  {
+    // Does nothing
+  }
+
+  /**
+   * Adds a listener so that it receives {@link PropertyChangeEvent} 
+   * notifications from this column.  The properties defined by the column are:
+   * <ul>
+   * <li><code>width</code> - see {@link #setWidth(int)};</li>
+   * <li><code>preferredWidth</code> - see {@link #setPreferredWidth(int)};</li>
+   * <li><code>minWidth</code> - see {@link #setMinWidth(int)};</li> 
+   * <li><code>maxWidth</code> - see {@link #setMaxWidth(int)};</li>
+   * <li><code>modelIndex</code> - see {@link #setModelIndex(int)};</li>
+   * <li><code>isResizable</code> - see {@link #setResizable(boolean)};</li>
+   * <li><code>cellRenderer</code> - see 
+   *   {@link #setCellRenderer(TableCellRenderer)};</li>
+   * <li><code>cellEditor</code> - see 
+   *   {@link #setCellEditor(TableCellEditor)};</li>
+   * <li><code>headerRenderer</code> - see 
+   *   {@link #setHeaderRenderer(TableCellRenderer)};</li>
+   * <li><code>headerValue</code> - see {@link #setHeaderValue(Object)};</li>
+   * <li><code>identifier</code> - see {@link #setIdentifier(Object)}.</li>
+   * </ul>
+   * 
+   * @param listener the listener to add (<code>null</code> is ignored).
+   * 
+   * @see #removePropertyChangeListener(PropertyChangeListener)
+   */
+  public synchronized void addPropertyChangeListener(
+      PropertyChangeListener listener)
+  {
+    changeSupport.addPropertyChangeListener(listener);
+  }
+
+  /**
+   * Removes a listener so that it no longer receives 
+   * {@link PropertyChangeEvent} notifications from this column.  If 
+   * <code>listener</code> is not registered with the column, or is 
+   * <code>null</code>, this method does nothing.
+   * 
+   * @param listener the listener to remove (<code>null</code> is ignored).
+   */
+  public synchronized void removePropertyChangeListener(
+      PropertyChangeListener listener)
+  {
+    changeSupport.removePropertyChangeListener(listener);
+  }
+
+  /**
+   * Returns the property change listeners for this <code>TableColumn</code>.
+   * An empty array is returned if there are currently no listeners registered.
+   * 
+   * @return The property change listeners registered with this column.
+   * 
+   * @since 1.4
+   */
+  public PropertyChangeListener[] getPropertyChangeListeners()
+  {
+    return changeSupport.getPropertyChangeListeners();
+  }
+
+  /**
+   * Creates and returns a default renderer for the column header (in this case,
+   * a new instance of {@link DefaultTableCellRenderer}).
+   * 
+   * @return A default renderer for the column header.
+   */
+  protected TableCellRenderer createDefaultHeaderRenderer()
+  {
+    return new DefaultTableCellRenderer();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,232 @@
+/* TableColumnModel.java --
+   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.util.Enumeration;
+
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.event.TableColumnModelListener;
+
+/**
+ * The interface used by {@link JTable} to access the columns in the table
+ * view.
+ * 
+ * @author Andrew Selkirk
+ */
+public interface TableColumnModel
+{
+  /**
+   * Adds a column to the model.
+   * 
+   * @param column  the new column (<code>null</code> not permitted).
+   * 
+   * @throws IllegalArgumentException if <code>column</code> is 
+   *         <code>null</code>.
+   */
+  void addColumn(TableColumn column);
+
+  /**
+   * Removes a column from the model.  If <code>column</code> is not defined
+   * in the model, this method does nothing.
+   * 
+   * @param column TableColumn
+   */
+  void removeColumn(TableColumn column);
+
+  /**
+   * Moves a column.
+   * 
+   * @param columnIndex Index of column to move
+   * @param newIndex New index of column
+   */
+  void moveColumn(int columnIndex, int newIndex);
+
+  /**
+   * Sets the column margin and sends a {@link ChangeEvent} to all registered
+   * {@link TableColumnModelListener}s registered with the model.
+   * 
+   * @param margin  the column margin.
+   * 
+   * @see #getColumnMargin()
+   */
+  void setColumnMargin(int margin);
+
+  /**
+   * Returns the number of columns in the model.
+   * 
+   * @return The column count.
+   */
+  int getColumnCount();
+
+  /**
+   * Returns an enumeration of the columns in the model.
+   * 
+   * @return An enumeration of the columns in the model.
+   */
+  Enumeration getColumns();
+
+  /**
+   * Returns the index of the {@link TableColumn} with the given identifier.
+   *
+   * @param identifier  the identifier (<code>null</code> not permitted).
+   * 
+   * @return The index of the {@link TableColumn} with the given identifier.
+   * 
+   * @throws IllegalArgumentException if <code>identifier</code> is 
+   *         <code>null</code> or there is no column with that identifier.
+   */
+  int getColumnIndex(Object identifier);
+
+  /**
+   * Returns the <code>TableColumn</code> at the specified index.
+   * 
+   * @param columnIndex  the column index.
+   * 
+   * @return The table column.
+   */
+  TableColumn getColumn(int columnIndex);
+
+  /**
+   * Returns the column margin.
+   * 
+   * @return The column margin.
+   * 
+   * @see #setColumnMargin(int)
+   */
+  int getColumnMargin();
+
+  /**
+   * Returns the index of the column that contains the specified x-coordinate,
+   * assuming that:
+   * <ul>
+   * <li>column zero begins at position zero;</li>
+   * <li>all columns appear in order;</li>
+   * <li>individual column widths are taken into account, but the column margin
+   *     is ignored.</li>
+   * </ul>
+   * If no column contains the specified position, this method returns 
+   * <code>-1</code>.
+   * 
+   * @param xPosition  the x-position.
+   * 
+   * @return The column index, or <code>-1</code>.
+   */
+  int getColumnIndexAtX(int xPosition);
+
+  /**
+   * Returns total width of all the columns in the model, ignoring the
+   * column margin (see {@link #getColumnMargin()}).
+   *
+   * @return The total width of all the columns.
+   */
+  int getTotalColumnWidth();
+
+  /**
+   * Sets the flag that indicates whether or not column selection is allowed.
+   *
+   * @param allowed  the new flag value.
+   * 
+   * @see #getColumnSelectionAllowed()
+   */
+  void setColumnSelectionAllowed(boolean allowed);
+
+  /**
+   * Returns <code>true</code> if column selection is allowed, and 
+   * <code>false</code> if column selection is not allowed.
+   *
+   * @return A boolean.
+   * 
+   * @see #setColumnSelectionAllowed(boolean)
+   */
+  boolean getColumnSelectionAllowed();
+
+  /**
+   * getSelectedColumns
+   * @return Selected columns
+   */
+  int[] getSelectedColumns();
+
+  /**
+   * Returns the number of selected columns in the model.
+   * 
+   * @return The selected column count.
+   * 
+   * @see #getSelectionModel()
+   */
+  int getSelectedColumnCount();
+
+  /**
+   * Sets the selection model that will be used to keep track of the selected 
+   * columns.
+   *
+   * @param model  the selection model (<code>null</code> not permitted).
+   * 
+   * @throws IllegalArgumentException if <code>model</code> is 
+   *     <code>null</code>.
+   */
+  void setSelectionModel(ListSelectionModel model);
+
+  /**
+   * Returns the selection model used to track table column selections.
+   * 
+   * @return The selection model.
+   * 
+   * @see #setSelectionModel(ListSelectionModel)
+   */
+  ListSelectionModel getSelectionModel();
+
+  /**
+   * Registers a listener with the model, so that it will receive
+   * {@link TableColumnModelEvent} notifications.
+   *
+   * @param listener the listener (<code>null</code> ignored).
+   */
+  void addColumnModelListener(TableColumnModelListener listener);
+
+  /**
+   * Deregisters a listener, so that it will no longer receive 
+   * {@link TableColumnModelEvent} notifications.
+   * 
+   * @param listener  the listener.
+   */
+  void removeColumnModelListener(TableColumnModelListener listener);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,134 @@
+/* TableModel.java --
+   Copyright (C) 2002, 2005, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.table;
+
+import javax.swing.event.TableModelListener;
+
+/**
+ * A <code>TableModel</code> is a two dimensional data structure that 
+ * can store arbitrary <code>Object</code> instances, usually for the
+ * purpose of display in a {@link javax.swing.JTable} component.  Individual 
+ * objects can be accessed by specifying the row index and column index for 
+ * the object.  Each column in the model has a name associated with it.
+ * <p>
+ * The {@link DefaultTableModel} class provides one implementation of
+ * this interface.
+ * 
+ * @author Andrew Selkirk
+ */
+public interface TableModel
+{
+  /**
+   * Returns the number of rows in the model.
+   * 
+   * @return The row count.
+   */
+  int getRowCount();
+
+  /**
+   * Returns the number of columns in the model.
+   * 
+   * @return The column count
+   */
+  int getColumnCount();
+
+  /**
+   * Returns the name of a column in the model.
+   * 
+   * @param columnIndex the column index.
+   * 
+   * @return The column name.
+   */
+  String getColumnName(int columnIndex);
+
+  /**
+   * Returns the <code>Class</code> for all <code>Object</code> instances
+   * in the specified column.  
+   * 
+   * @param columnIndex the column index.
+   * 
+   * @return The class.
+   */
+  Class getColumnClass(int columnIndex);
+
+  /**
+   * Returns <code>true</code> if the cell is editable, and <code>false</code>
+   * otherwise.
+   * 
+   * @param rowIndex the row index.
+   * @param columnIndex the column index.
+   * 
+   * @return <code>true</code> if editable, <code>false</code> otherwise.
+   */
+  boolean isCellEditable(int rowIndex, int columnIndex);
+
+  /**
+   * Returns the value (<code>Object</code>) at a particular cell in the
+   * table.
+   * 
+   * @param rowIndex the row index.
+   * @param columnIndex the column index.
+   * 
+   * @return The value at the specified cell.
+   */
+  Object getValueAt(int rowIndex, int columnIndex);
+
+  /**
+   * Sets the value at a particular cell in the table.  
+   * 
+   * @param aValue the value (<code>null</code> permitted).
+   * @param rowIndex the row index.
+   * @param columnIndex the column index.
+   */
+  void setValueAt(Object aValue, int rowIndex, int columnIndex);
+
+  /**
+   * Adds a listener to the model.  The listener will receive notification
+   * of updates to the model.
+   * 
+   * @param listener the listener.
+   */
+  void addTableModelListener(TableModelListener listener);
+
+  /**
+   * Removes a listener from the model.
+   * 
+   * @param listener the listener.
+   */
+  void removeTableModelListener(TableModelListener listener);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html Thu Nov  8 16:56:19 2007
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in javax.swing.table package.
+   Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - javax.swing.table</title></head>
+
+<body>
+<p>Interfaces and classes that support the {@link javax.swing.JTable} 
+component.</p>
+
+</body>
+</html>

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,2369 @@
+/* AbstractDocument.java --
+   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.event.UndoableEditListener;
+import javax.swing.text.DocumentFilter;
+import javax.swing.tree.TreeNode;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CompoundEdit;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * An abstract base implementation for the {@link Document} interface.
+ * This class provides some common functionality for all <code>Element</code>s,
+ * most notably it implements a locking mechanism to make document modification
+ * thread-safe.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public abstract class AbstractDocument implements Document, Serializable
+{
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 6842927725919637215L;
+
+  /**
+   * Standard error message to indicate a bad location.
+   */
+  protected static final String BAD_LOCATION = "document location failure";
+
+  /**
+   * Standard name for unidirectional <code>Element</code>s.
+   */
+  public static final String BidiElementName = "bidi level";
+
+  /**
+   * Standard name for content <code>Element</code>s. These are usually
+   * {@link LeafElement}s.
+   */
+  public static final String ContentElementName = "content";
+
+  /**
+   * Standard name for paragraph <code>Element</code>s. These are usually
+   * {@link BranchElement}s.
+   */
+  public static final String ParagraphElementName = "paragraph";
+
+  /**
+   * Standard name for section <code>Element</code>s. These are usually
+   * {@link DefaultStyledDocument.SectionElement}s.
+   */
+  public static final String SectionElementName = "section";
+
+  /**
+   * Attribute key for storing the element name.
+   */
+  public static final String ElementNameAttribute = "$ename";
+
+  /**
+   * The actual content model of this <code>Document</code>.
+   */
+  Content content;
+
+  /**
+   * The AttributeContext for this <code>Document</code>.
+   */
+  AttributeContext context;
+
+  /**
+   * The currently installed <code>DocumentFilter</code>.
+   */
+  DocumentFilter documentFilter;
+
+  /**
+   * The documents properties.
+   */
+  Dictionary properties;
+
+  /**
+   * Manages event listeners for this <code>Document</code>.
+   */
+  protected EventListenerList listenerList = new EventListenerList();
+  
+  /**
+   * Stores the current writer thread.  Used for locking.
+   */ 
+  private Thread currentWriter = null;
+  
+  /**
+   * The number of readers.  Used for locking.
+   */
+  private int numReaders = 0;
+  
+  /**
+   * Tells if there are one or more writers waiting.
+   */
+  private int numWritersWaiting = 0;  
+
+  /**
+   * A condition variable that readers and writers wait on.
+   */
+  private Object documentCV = new Object();
+
+  /** An instance of a DocumentFilter.FilterBypass which allows calling
+   * the insert, remove and replace method without checking for an installed
+   * document filter.
+   */
+  private DocumentFilter.FilterBypass bypass;
+
+  /**
+   * The bidi root element.
+   */
+  private Element bidiRoot;
+
+  /**
+   * Creates a new <code>AbstractDocument</code> with the specified
+   * {@link Content} model.
+   *
+   * @param doc the <code>Content</code> model to be used in this
+   *        <code>Document<code>
+   *
+   * @see GapContent
+   * @see StringContent
+   */
+  protected AbstractDocument(Content doc)
+  {
+    this(doc, StyleContext.getDefaultStyleContext());
+  }
+
+  /**
+   * Creates a new <code>AbstractDocument</code> with the specified
+   * {@link Content} model and {@link AttributeContext}.
+   *
+   * @param doc the <code>Content</code> model to be used in this
+   *        <code>Document<code>
+   * @param ctx the <code>AttributeContext</code> to use
+   *
+   * @see GapContent
+   * @see StringContent
+   */
+  protected AbstractDocument(Content doc, AttributeContext ctx)
+  {
+    content = doc;
+    context = ctx;
+
+    // FIXME: This is determined using a Mauve test. Make the document
+    // actually use this.
+    putProperty("i18n", Boolean.FALSE);
+
+    // FIXME: Fully implement bidi.
+    bidiRoot = new BranchElement(null, null);
+  }
+  
+  /** Returns the DocumentFilter.FilterBypass instance for this
+   * document and create it if it does not exist yet.
+   *  
+   * @return This document's DocumentFilter.FilterBypass instance.
+   */
+  private DocumentFilter.FilterBypass getBypass()
+  {
+    if (bypass == null)
+      bypass = new Bypass();
+    
+    return bypass;
+  }
+
+  /**
+   * Returns the paragraph {@link Element} that holds the specified position.
+   *
+   * @param pos the position for which to get the paragraph element
+   *
+   * @return the paragraph {@link Element} that holds the specified position
+   */
+  public abstract Element getParagraphElement(int pos);
+
+  /**
+   * Returns the default root {@link Element} of this <code>Document</code>.
+   * Usual <code>Document</code>s only have one root element and return this.
+   * However, there may be <code>Document</code> implementations that
+   * support multiple root elements, they have to return a default root element
+   * here.
+   *
+   * @return the default root {@link Element} of this <code>Document</code>
+   */
+  public abstract Element getDefaultRootElement();
+
+  /**
+   * Creates and returns a branch element with the specified
+   * <code>parent</code> and <code>attributes</code>. Note that the new
+   * <code>Element</code> is linked to the parent <code>Element</code>
+   * through {@link Element#getParentElement}, but it is not yet added
+   * to the parent <code>Element</code> as child.
+   *
+   * @param parent the parent <code>Element</code> for the new branch element
+   * @param attributes the text attributes to be installed in the new element
+   *
+   * @return the new branch <code>Element</code>
+   *
+   * @see BranchElement
+   */
+  protected Element createBranchElement(Element parent,
+					AttributeSet attributes)
+  {
+    return new BranchElement(parent, attributes);
+  }
+
+  /**
+   * Creates and returns a leaf element with the specified
+   * <code>parent</code> and <code>attributes</code>. Note that the new
+   * <code>Element</code> is linked to the parent <code>Element</code>
+   * through {@link Element#getParentElement}, but it is not yet added
+   * to the parent <code>Element</code> as child.
+   *
+   * @param parent the parent <code>Element</code> for the new branch element
+   * @param attributes the text attributes to be installed in the new element
+   *
+   * @return the new branch <code>Element</code>
+   *
+   * @see LeafElement
+   */
+  protected Element createLeafElement(Element parent, AttributeSet attributes,
+				      int start, int end)
+  {
+    return new LeafElement(parent, attributes, start, end);
+  }
+
+  /**
+   * Creates a {@link Position} that keeps track of the location at the
+   * specified <code>offset</code>.
+   *
+   * @param offset the location in the document to keep track by the new
+   *        <code>Position</code>
+   *
+   * @return the newly created <code>Position</code>
+   *
+   * @throws BadLocationException if <code>offset</code> is not a valid
+   *         location in the documents content model
+   */
+  public Position createPosition(final int offset) throws BadLocationException
+  {
+    return content.createPosition(offset);
+  }
+
+  /**
+   * Notifies all registered listeners when the document model changes.
+   *
+   * @param event the <code>DocumentEvent</code> to be fired
+   */
+  protected void fireChangedUpdate(DocumentEvent event)
+  {
+    DocumentListener[] listeners = getDocumentListeners();
+
+    for (int index = 0; index < listeners.length; ++index)
+      listeners[index].changedUpdate(event);
+  }
+
+  /**
+   * Notifies all registered listeners when content is inserted in the document
+   * model.
+   *
+   * @param event the <code>DocumentEvent</code> to be fired
+   */
+  protected void fireInsertUpdate(DocumentEvent event)
+  {
+    DocumentListener[] listeners = getDocumentListeners();
+
+    for (int index = 0; index < listeners.length; ++index)
+      listeners[index].insertUpdate(event);
+  }
+
+  /**
+   * Notifies all registered listeners when content is removed from the
+   * document model.
+   *
+   * @param event the <code>DocumentEvent</code> to be fired
+   */
+  protected void fireRemoveUpdate(DocumentEvent event)
+  {
+    DocumentListener[] listeners = getDocumentListeners();
+
+    for (int index = 0; index < listeners.length; ++index)
+      listeners[index].removeUpdate(event);
+  }
+
+  /**
+   * Notifies all registered listeners when an <code>UndoableEdit</code> has
+   * been performed on this <code>Document</code>.
+   *
+   * @param event the <code>UndoableEditEvent</code> to be fired
+   */
+  protected void fireUndoableEditUpdate(UndoableEditEvent event)
+  {
+    UndoableEditListener[] listeners = getUndoableEditListeners();
+
+    for (int index = 0; index < listeners.length; ++index)
+      listeners[index].undoableEditHappened(event);
+  }
+
+  /**
+   * Returns the asynchronous loading priority. Returns <code>-1</code> if this
+   * document should not be loaded asynchronously.
+   *
+   * @return the asynchronous loading priority
+   */
+  public int getAsynchronousLoadPriority()
+  {
+    return 0;
+  }
+
+  /**
+   * Returns the {@link AttributeContext} used in this <code>Document</code>.
+   *
+   * @return the {@link AttributeContext} used in this <code>Document</code>
+   */
+  protected final AttributeContext getAttributeContext()
+  {
+    return context;
+  }
+
+  /**
+   * Returns the root element for bidirectional content.
+   *
+   * @return the root element for bidirectional content
+   */
+  public Element getBidiRootElement()
+  {
+    return bidiRoot;
+  }
+
+  /**
+   * Returns the {@link Content} model for this <code>Document</code>
+   *
+   * @return the {@link Content} model for this <code>Document</code>
+   *
+   * @see GapContent
+   * @see StringContent
+   */
+  protected final Content getContent()
+  {
+    return content;
+  }
+
+  /**
+   * Returns the thread that currently modifies this <code>Document</code>
+   * if there is one, otherwise <code>null</code>. This can be used to
+   * distinguish between a method call that is part of an ongoing modification
+   * or if it is a separate modification for which a new lock must be aquired.
+   *
+   * @return the thread that currently modifies this <code>Document</code>
+   *         if there is one, otherwise <code>null</code>
+   */
+  protected final Thread getCurrentWriter()
+  {
+    return currentWriter;
+  }
+
+  /**
+   * Returns the properties of this <code>Document</code>.
+   *
+   * @return the properties of this <code>Document</code>
+   */
+  public Dictionary getDocumentProperties()
+  {
+    // FIXME: make me thread-safe
+    if (properties == null)
+      properties = new Hashtable();
+
+    return properties;
+  }
+
+  /**
+   * Returns a {@link Position} which will always mark the end of the
+   * <code>Document</code>.
+   *
+   * @return a {@link Position} which will always mark the end of the
+   *         <code>Document</code>
+   */
+  public final Position getEndPosition()
+  {
+    // FIXME: Properly implement this by calling Content.createPosition().
+    return new Position() 
+      {        
+        public int getOffset() 
+        { 
+          return getLength(); 
+        } 
+      };
+  }
+
+  /**
+   * Returns the length of this <code>Document</code>'s content.
+   *
+   * @return the length of this <code>Document</code>'s content
+   */
+  public int getLength()
+  {
+    // We return Content.getLength() -1 here because there is always an
+    // implicit \n at the end of the Content which does count in Content
+    // but not in Document.
+    return content.length() - 1;
+  }
+
+  /**
+   * Returns all registered listeners of a given listener type.
+   *
+   * @param listenerType the type of the listeners to be queried
+   *
+   * @return all registered listeners of the specified type
+   */
+  public EventListener[] getListeners(Class listenerType)
+  {
+    return listenerList.getListeners(listenerType);
+  }
+
+  /**
+   * Returns a property from this <code>Document</code>'s property list.
+   *
+   * @param key the key of the property to be fetched
+   *
+   * @return the property for <code>key</code> or <code>null</code> if there
+   *         is no such property stored
+   */
+  public final Object getProperty(Object key)
+  {
+    // FIXME: make me thread-safe
+    Object value = null;
+    if (properties != null)
+      value = properties.get(key);
+
+    return value;
+  }
+
+  /**
+   * Returns all root elements of this <code>Document</code>. By default
+   * this just returns the single root element returned by
+   * {@link #getDefaultRootElement()}. <code>Document</code> implementations
+   * that support multiple roots must override this method and return all roots
+   * here.
+   *
+   * @return all root elements of this <code>Document</code>
+   */
+  public Element[] getRootElements()
+  {
+    Element[] elements = new Element[2];
+    elements[0] = getDefaultRootElement();
+    elements[1] = getBidiRootElement();
+    return elements;
+  }
+
+  /**
+   * Returns a {@link Position} which will always mark the beginning of the
+   * <code>Document</code>.
+   *
+   * @return a {@link Position} which will always mark the beginning of the
+   *         <code>Document</code>
+   */
+  public final Position getStartPosition()
+  {
+    // FIXME: Properly implement this using Content.createPosition().
+    return new Position() 
+      {        
+        public int getOffset() 
+        { 
+          return 0; 
+        } 
+      };
+  }
+
+  /**
+   * Returns a piece of this <code>Document</code>'s content.
+   *
+   * @param offset the start offset of the content
+   * @param length the length of the content
+   *
+   * @return the piece of content specified by <code>offset</code> and
+   *         <code>length</code>
+   *
+   * @throws BadLocationException if <code>offset</code> or <code>offset +
+   *         length</code> are invalid locations with this
+   *         <code>Document</code>
+   */
+  public String getText(int offset, int length) throws BadLocationException
+  {
+    return content.getString(offset, length);
+  }
+
+  /**
+   * Fetches a piece of this <code>Document</code>'s content and stores
+   * it in the given {@link Segment}.
+   *
+   * @param offset the start offset of the content
+   * @param length the length of the content
+   * @param segment the <code>Segment</code> to store the content in
+   *
+   * @throws BadLocationException if <code>offset</code> or <code>offset +
+   *         length</code> are invalid locations with this
+   *         <code>Document</code>
+   */
+  public void getText(int offset, int length, Segment segment)
+    throws BadLocationException
+  {
+    content.getChars(offset, length, segment);
+  }
+
+  /**
+   * Inserts a String into this <code>Document</code> at the specified
+   * position and assigning the specified attributes to it.
+   * 
+   * <p>If a {@link DocumentFilter} is installed in this document, the
+   * corresponding method of the filter object is called.</p>
+   * 
+   * <p>The method has no effect when <code>text</code> is <code>null</code>
+   * or has a length of zero.</p>
+   * 
+   *
+   * @param offset the location at which the string should be inserted
+   * @param text the content to be inserted
+   * @param attributes the text attributes to be assigned to that string
+   *
+   * @throws BadLocationException if <code>offset</code> is not a valid
+   *         location in this <code>Document</code>
+   */
+  public void insertString(int offset, String text, AttributeSet attributes)
+    throws BadLocationException
+  {
+    // Bail out if we have a bogus insertion (Behavior observed in RI).
+    if (text == null || text.length() == 0)
+      return;
+    
+    if (documentFilter == null)
+      insertStringImpl(offset, text, attributes);
+    else
+      documentFilter.insertString(getBypass(), offset, text, attributes);
+  }
+
+  void insertStringImpl(int offset, String text, AttributeSet attributes)
+    throws BadLocationException
+  {
+    // Just return when no text to insert was given.
+    if (text == null || text.length() == 0)
+      return;
+    DefaultDocumentEvent event =
+      new DefaultDocumentEvent(offset, text.length(),
+			       DocumentEvent.EventType.INSERT);
+
+    try
+      {
+        writeLock();
+        UndoableEdit undo = content.insertString(offset, text);
+        if (undo != null)
+          event.addEdit(undo);
+
+        insertUpdate(event, attributes);
+
+        fireInsertUpdate(event);
+        if (undo != null)
+          fireUndoableEditUpdate(new UndoableEditEvent(this, undo));
+      }
+    finally
+      {
+        writeUnlock();
+      }
+  }
+
+  /**
+   * Called to indicate that text has been inserted into this
+   * <code>Document</code>. The default implementation does nothing.
+   * This method is executed within a write lock.
+   *
+   * @param chng the <code>DefaultDocumentEvent</code> describing the change
+   * @param attr the attributes of the changed content
+   */
+  protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr)
+  {
+    // Do nothing here. Subclasses may want to override this.
+  }
+
+  /**
+   * Called after some content has been removed from this
+   * <code>Document</code>. The default implementation does nothing.
+   * This method is executed within a write lock.
+   *
+   * @param chng the <code>DefaultDocumentEvent</code> describing the change
+   */
+  protected void postRemoveUpdate(DefaultDocumentEvent chng)
+  {
+    // Do nothing here. Subclasses may want to override this.
+  }
+
+  /**
+   * Stores a property in this <code>Document</code>'s property list.
+   *
+   * @param key the key of the property to be stored
+   * @param value the value of the property to be stored
+   */
+  public final void putProperty(Object key, Object value)
+  {
+    // FIXME: make me thread-safe
+    if (properties == null)
+      properties = new Hashtable();
+
+    properties.put(key, value);
+  }
+
+  /**
+   * Blocks until a read lock can be obtained.  Must block if there is
+   * currently a writer modifying the <code>Document</code>.
+   */
+  public final void readLock()
+  {
+    if (currentWriter != null && currentWriter.equals(Thread.currentThread()))
+      return;
+    synchronized (documentCV)
+      {
+        while (currentWriter != null || numWritersWaiting > 0)
+          {
+            try
+              {
+                documentCV.wait();
+              }
+            catch (InterruptedException ie)
+              {
+                throw new Error("interrupted trying to get a readLock");
+              }
+          }
+          numReaders++;
+      }
+  }
+
+  /**
+   * Releases the read lock. If this was the only reader on this
+   * <code>Document</code>, writing may begin now.
+   */
+  public final void readUnlock()
+  {
+    // Note we could have a problem here if readUnlock was called without a
+    // prior call to readLock but the specs simply warn users to ensure that
+    // balance by using a finally block:
+    // readLock()
+    // try
+    // { 
+    //   doSomethingHere 
+    // }
+    // finally
+    // {
+    //   readUnlock();
+    // }
+    
+    // All that the JDK seems to check for is that you don't call unlock
+    // more times than you've previously called lock, but it doesn't make
+    // sure that the threads calling unlock were the same ones that called lock
+
+    // If the current thread holds the write lock, and attempted to also obtain
+    // a readLock, then numReaders hasn't been incremented and we don't need
+    // to unlock it here.
+    if (currentWriter == Thread.currentThread())
+      return;
+
+    // FIXME: the reference implementation throws a 
+    // javax.swing.text.StateInvariantError here
+    if (numReaders == 0)
+      throw new IllegalStateException("document lock failure");
+    
+    synchronized (documentCV)
+    {
+      // If currentWriter is not null, the application code probably had a 
+      // writeLock and then tried to obtain a readLock, in which case 
+      // numReaders wasn't incremented
+      if (currentWriter == null)
+        {
+          numReaders --;
+          if (numReaders == 0 && numWritersWaiting != 0)
+            documentCV.notify();
+        }
+    }
+  }
+
+  /**
+   * Removes a piece of content from this <code>Document</code>.
+   * 
+   * <p>If a {@link DocumentFilter} is installed in this document, the
+   * corresponding method of the filter object is called. The
+   * <code>DocumentFilter</code> is called even if <code>length</code>
+   * is zero. This is different from {@link #replace}.</p>
+   * 
+   * <p>Note: When <code>length</code> is zero or below the call is not
+   * forwarded to the underlying {@link AbstractDocument.Content} instance
+   * of this document and no exception is thrown.</p>
+   * 
+   * @param offset the start offset of the fragment to be removed
+   * @param length the length of the fragment to be removed
+   *
+   * @throws BadLocationException if <code>offset</code> or
+   *         <code>offset + length</code> or invalid locations within this
+   *         document
+   */
+  public void remove(int offset, int length) throws BadLocationException
+  {
+    if (documentFilter == null)
+      removeImpl(offset, length);
+    else
+      documentFilter.remove(getBypass(), offset, length);
+  }
+  
+  void removeImpl(int offset, int length) throws BadLocationException
+  {
+    // The RI silently ignores all requests that have a negative length.
+    // Don't ask my why, but that's how it is.
+    if (length > 0)
+      {
+        if (offset < 0 || offset > getLength())
+          throw new BadLocationException("Invalid remove position", offset);
+
+        if (offset + length > getLength())
+          throw new BadLocationException("Invalid remove length", offset);
+
+        DefaultDocumentEvent event =
+          new DefaultDocumentEvent(offset, length,
+                                   DocumentEvent.EventType.REMOVE);
+    
+        try
+        {
+          writeLock();
+        
+          // The order of the operations below is critical!        
+          removeUpdate(event);
+          UndoableEdit temp = content.remove(offset, length);
+        
+          postRemoveUpdate(event);
+          fireRemoveUpdate(event);
+        }
+        finally
+          {
+            writeUnlock();
+          }
+      }
+  }
+
+  /**
+   * Replaces a piece of content in this <code>Document</code> with
+   * another piece of content.
+   * 
+   * <p>If a {@link DocumentFilter} is installed in this document, the
+   * corresponding method of the filter object is called.</p>
+   * 
+   * <p>The method has no effect if <code>length</code> is zero (and
+   * only zero) and, at the same time, <code>text</code> is
+   * <code>null</code> or has zero length.</p>
+   *
+   * @param offset the start offset of the fragment to be removed
+   * @param length the length of the fragment to be removed
+   * @param text the text to replace the content with
+   * @param attributes the text attributes to assign to the new content
+   *
+   * @throws BadLocationException if <code>offset</code> or
+   *         <code>offset + length</code> or invalid locations within this
+   *         document
+   *
+   * @since 1.4
+   */
+  public void replace(int offset, int length, String text,
+                      AttributeSet attributes)
+    throws BadLocationException
+  {
+    // Bail out if we have a bogus replacement (Behavior observed in RI).
+    if (length == 0 
+        && (text == null || text.length() == 0))
+      return;
+    
+    if (documentFilter == null)
+      {
+        // It is important to call the methods which again do the checks
+        // of the arguments and the DocumentFilter because subclasses may
+        // have overridden these methods and provide crucial behavior
+        // which would be skipped if we call the non-checking variants.
+        // An example for this is PlainDocument where insertString can
+        // provide a filtering of newlines.
+        remove(offset, length);
+        insertString(offset, text, attributes);
+      }
+    else
+      documentFilter.replace(getBypass(), offset, length, text, attributes);
+    
+  }
+  
+  void replaceImpl(int offset, int length, String text,
+		      AttributeSet attributes)
+    throws BadLocationException
+  {
+    removeImpl(offset, length);
+    insertStringImpl(offset, text, attributes);
+  }
+
+  /**
+   * Adds a <code>DocumentListener</code> object to this document.
+   *
+   * @param listener the listener to add
+   */
+  public void addDocumentListener(DocumentListener listener)
+  {
+    listenerList.add(DocumentListener.class, listener);
+  }
+
+  /**
+   * Removes a <code>DocumentListener</code> object from this document.
+   *
+   * @param listener the listener to remove
+   */
+  public void removeDocumentListener(DocumentListener listener)
+  {
+    listenerList.remove(DocumentListener.class, listener);
+  }
+
+  /**
+   * Returns all registered <code>DocumentListener</code>s.
+   *
+   * @return all registered <code>DocumentListener</code>s
+   */
+  public DocumentListener[] getDocumentListeners()
+  {
+    return (DocumentListener[]) getListeners(DocumentListener.class);
+  }
+
+  /**
+   * Adds an {@link UndoableEditListener} to this <code>Document</code>.
+   *
+   * @param listener the listener to add
+   */
+  public void addUndoableEditListener(UndoableEditListener listener)
+  {
+    listenerList.add(UndoableEditListener.class, listener);
+  }
+
+  /**
+   * Removes an {@link UndoableEditListener} from this <code>Document</code>.
+   *
+   * @param listener the listener to remove
+   */
+  public void removeUndoableEditListener(UndoableEditListener listener)
+  {
+    listenerList.remove(UndoableEditListener.class, listener);
+  }
+
+  /**
+   * Returns all registered {@link UndoableEditListener}s.
+   *
+   * @return all registered {@link UndoableEditListener}s
+   */
+  public UndoableEditListener[] getUndoableEditListeners()
+  {
+    return (UndoableEditListener[]) getListeners(UndoableEditListener.class);
+  }
+
+  /**
+   * Called before some content gets removed from this <code>Document</code>.
+   * The default implementation does nothing but may be overridden by
+   * subclasses to modify the <code>Document</code> structure in response
+   * to a remove request. The method is executed within a write lock.
+   *
+   * @param chng the <code>DefaultDocumentEvent</code> describing the change
+   */
+  protected void removeUpdate(DefaultDocumentEvent chng)
+  {
+    // Do nothing here. Subclasses may wish to override this.
+  }
+
+  /**
+   * Called to render this <code>Document</code> visually. It obtains a read
+   * lock, ensuring that no changes will be made to the <code>document</code>
+   * during the rendering process. It then calls the {@link Runnable#run()}
+   * method on <code>runnable</code>. This method <em>must not</em> attempt
+   * to modifiy the <code>Document</code>, since a deadlock will occur if it
+   * tries to obtain a write lock. When the {@link Runnable#run()} method
+   * completes (either naturally or by throwing an exception), the read lock
+   * is released. Note that there is nothing in this method related to
+   * the actual rendering. It could be used to execute arbitrary code within
+   * a read lock.
+   *
+   * @param runnable the {@link Runnable} to execute
+   */
+  public void render(Runnable runnable)
+  {
+    readLock();
+    try
+    {
+      runnable.run();
+    }
+    finally
+    {
+      readUnlock();
+    }
+  }
+
+  /**
+   * Sets the asynchronous loading priority for this <code>Document</code>.
+   * A value of <code>-1</code> indicates that this <code>Document</code>
+   * should be loaded synchronously.
+   *
+   * @param p the asynchronous loading priority to set
+   */
+  public void setAsynchronousLoadPriority(int p)
+  {
+    // TODO: Implement this properly.
+  }
+
+  /**
+   * Sets the properties of this <code>Document</code>.
+   *
+   * @param p the document properties to set
+   */
+  public void setDocumentProperties(Dictionary p)
+  {
+    // FIXME: make me thread-safe
+    properties = p;
+  }
+
+  /**
+   * Blocks until a write lock can be obtained.  Must wait if there are 
+   * readers currently reading or another thread is currently writing.
+   */
+  protected final void writeLock()
+  {
+    if (currentWriter != null && currentWriter.equals(Thread.currentThread()))
+      return;
+    synchronized (documentCV)
+      {
+        numWritersWaiting++;
+        while (numReaders > 0)
+          {
+            try
+              {
+                documentCV.wait();
+              }
+            catch (InterruptedException ie)
+              {
+                throw new Error("interruped while trying to obtain write lock");
+              }
+          }
+        numWritersWaiting --;
+        currentWriter = Thread.currentThread();
+      }
+  }
+
+  /**
+   * Releases the write lock. This allows waiting readers or writers to
+   * obtain the lock.
+   */
+  protected final void writeUnlock()
+  {
+    synchronized (documentCV)
+    {
+        if (Thread.currentThread().equals(currentWriter))
+          {
+            currentWriter = null;
+            documentCV.notifyAll();
+          }
+    }
+  }
+
+  /**
+   * Returns the currently installed {@link DocumentFilter} for this
+   * <code>Document</code>.
+   *
+   * @return the currently installed {@link DocumentFilter} for this
+   *         <code>Document</code>
+   *
+   * @since 1.4
+   */
+  public DocumentFilter getDocumentFilter()
+  {
+    return documentFilter;
+  }
+
+  /**
+   * Sets the {@link DocumentFilter} for this <code>Document</code>.
+   *
+   * @param filter the <code>DocumentFilter</code> to set
+   *
+   * @since 1.4
+   */
+  public void setDocumentFilter(DocumentFilter filter)
+  {
+    this.documentFilter = filter;
+  }
+
+  /**
+   * Dumps diagnostic information to the specified <code>PrintStream</code>.
+   *
+   * @param out the stream to write the diagnostic information to
+   */
+  public void dump(PrintStream out)
+  {
+    ((AbstractElement) getDefaultRootElement()).dump(out, 0);
+  }
+
+  /**
+   * Defines a set of methods for managing text attributes for one or more
+   * <code>Document</code>s.
+   *
+   * Replicating {@link AttributeSet}s throughout a <code>Document</code> can
+   * be very expensive. Implementations of this interface are intended to
+   * provide intelligent management of <code>AttributeSet</code>s, eliminating
+   * costly duplication.
+   *
+   * @see StyleContext
+   */
+  public interface AttributeContext
+  {
+    /**
+     * Returns an {@link AttributeSet} that contains the attributes
+     * of <code>old</code> plus the new attribute specified by
+     * <code>name</code> and <code>value</code>.
+     *
+     * @param old the attribute set to be merged with the new attribute
+     * @param name the name of the attribute to be added
+     * @param value the value of the attribute to be added
+     *
+     * @return the old attributes plus the new attribute
+     */
+    AttributeSet addAttribute(AttributeSet old, Object name, Object value);
+
+    /**
+     * Returns an {@link AttributeSet} that contains the attributes
+     * of <code>old</code> plus the new attributes in <code>attributes</code>.
+     *
+     * @param old the set of attributes where to add the new attributes
+     * @param attributes the attributes to be added
+     *
+     * @return an {@link AttributeSet} that contains the attributes
+     *         of <code>old</code> plus the new attributes in
+     *         <code>attributes</code>
+     */
+    AttributeSet addAttributes(AttributeSet old, AttributeSet attributes);
+
+    /**
+     * Returns an empty {@link AttributeSet}.
+     *
+     * @return  an empty {@link AttributeSet}
+     */
+    AttributeSet getEmptySet();
+
+    /**
+     * Called to indicate that the attributes in <code>attributes</code> are
+     * no longer used.
+     *
+     * @param attributes the attributes are no longer used
+     */
+    void reclaim(AttributeSet attributes);
+
+    /**
+     * Returns a {@link AttributeSet} that has the attribute with the specified
+     * <code>name</code> removed from <code>old</code>.
+     *
+     * @param old the attribute set from which an attribute is removed
+     * @param name the name of the attribute to be removed
+     *
+     * @return the attributes of <code>old</code> minus the attribute
+     *         specified by <code>name</code>
+     */
+    AttributeSet removeAttribute(AttributeSet old, Object name);
+
+    /**
+     * Removes all attributes in <code>attributes</code> from <code>old</code>
+     * and returns the resulting <code>AttributeSet</code>.
+     *
+     * @param old the set of attributes from which to remove attributes
+     * @param attributes the attributes to be removed from <code>old</code>
+     *
+     * @return the attributes of <code>old</code> minus the attributes in
+     *         <code>attributes</code>
+     */
+    AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes);
+
+    /**
+     * Removes all attributes specified by <code>names</code> from
+     * <code>old</code> and returns the resulting <code>AttributeSet</code>.
+     *
+     * @param old the set of attributes from which to remove attributes
+     * @param names the names of the attributes to be removed from
+     *        <code>old</code>
+     *
+     * @return the attributes of <code>old</code> minus the attributes in
+     *         <code>attributes</code>
+     */
+    AttributeSet removeAttributes(AttributeSet old, Enumeration names);
+  }
+
+  /**
+   * A sequence of data that can be edited. This is were the actual content
+   * in <code>AbstractDocument</code>'s is stored.
+   */
+  public interface Content
+  {
+    /**
+     * Creates a {@link Position} that keeps track of the location at
+     * <code>offset</code>.
+     *
+     * @return a {@link Position} that keeps track of the location at
+     *         <code>offset</code>.
+     *
+     * @throw BadLocationException if <code>offset</code> is not a valid
+     *        location in this <code>Content</code> model
+     */
+    Position createPosition(int offset) throws BadLocationException;
+
+    /**
+     * Returns the length of the content.
+     *
+     * @return the length of the content
+     */
+    int length();
+
+    /**
+     * Inserts a string into the content model.
+     *
+     * @param where the offset at which to insert the string
+     * @param str the string to be inserted
+     *
+     * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
+     *         not supported by this <code>Content</code> model
+     *
+     * @throws BadLocationException if <code>where</code> is not a valid
+     *         location in this <code>Content</code> model
+     */
+    UndoableEdit insertString(int where, String str)
+      throws BadLocationException;
+
+    /**
+     * Removes a piece of content from the content model.
+     *
+     * @param where the offset at which to remove content
+     * @param nitems the number of characters to be removed
+     *
+     * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
+     *         not supported by this <code>Content</code> model
+     *
+     * @throws BadLocationException if <code>where</code> is not a valid
+     *         location in this <code>Content</code> model
+     */
+    UndoableEdit remove(int where, int nitems) throws BadLocationException;
+
+    /**
+     * Returns a piece of content.
+     *
+     * @param where the start offset of the requested fragment
+     * @param len the length of the requested fragment
+     *
+     * @return the requested fragment
+     * @throws BadLocationException if <code>offset</code> or
+     *         <code>offset + len</code>is not a valid
+     *         location in this <code>Content</code> model
+     */
+    String getString(int where, int len) throws BadLocationException;
+
+    /**
+     * Fetches a piece of content and stores it in <code>txt</code>.
+     *
+     * @param where the start offset of the requested fragment
+     * @param len the length of the requested fragment
+     * @param txt the <code>Segment</code> where to fragment is stored into
+     *
+     * @throws BadLocationException if <code>offset</code> or
+     *         <code>offset + len</code>is not a valid
+     *         location in this <code>Content</code> model
+     */
+    void getChars(int where, int len, Segment txt) throws BadLocationException;
+  }
+
+  /**
+   * An abstract base implementation of the {@link Element} interface.
+   */
+  public abstract class AbstractElement
+    implements Element, MutableAttributeSet, TreeNode, Serializable
+  {
+    /** The serialization UID (compatible with JDK1.5). */
+    private static final long serialVersionUID = 1712240033321461704L;
+
+    /** The number of characters that this Element spans. */
+    int count;
+
+    /** The starting offset of this Element. */
+    int offset;
+
+    /** The attributes of this Element. */
+    AttributeSet attributes;
+
+    /** The parent element. */
+    Element element_parent;
+
+    /** The parent in the TreeNode interface. */
+    TreeNode tree_parent;
+
+    /** The children of this element. */
+    Vector tree_children;
+
+    /**
+     * Creates a new instance of <code>AbstractElement</code> with a
+     * specified parent <code>Element</code> and <code>AttributeSet</code>.
+     *
+     * @param p the parent of this <code>AbstractElement</code>
+     * @param s the attributes to be assigned to this
+     *        <code>AbstractElement</code>
+     */
+    public AbstractElement(Element p, AttributeSet s)
+    {
+      element_parent = p;
+      AttributeContext ctx = getAttributeContext();
+      attributes = ctx.getEmptySet();
+      if (s != null)
+        attributes = ctx.addAttributes(attributes, s);
+    }
+
+    /**
+     * Returns the child nodes of this <code>Element</code> as an
+     * <code>Enumeration</code> of {@link TreeNode}s.
+     *
+     * @return the child nodes of this <code>Element</code> as an
+     *         <code>Enumeration</code> of {@link TreeNode}s
+     */
+    public abstract Enumeration children();
+
+    /**
+     * Returns <code>true</code> if this <code>AbstractElement</code>
+     * allows children.
+     *
+     * @return <code>true</code> if this <code>AbstractElement</code>
+     *         allows children
+     */
+    public abstract boolean getAllowsChildren();
+
+    /**
+     * Returns the child of this <code>AbstractElement</code> at
+     * <code>index</code>.
+     *
+     * @param index the position in the child list of the child element to
+     *        be returned
+     *
+     * @return the child of this <code>AbstractElement</code> at
+     *         <code>index</code>
+     */
+    public TreeNode getChildAt(int index)
+    {
+      return (TreeNode) tree_children.get(index);
+    }
+
+    /**
+     * Returns the number of children of this <code>AbstractElement</code>.
+     *
+     * @return the number of children of this <code>AbstractElement</code>
+     */
+    public int getChildCount()
+    {
+      return tree_children.size();
+    }
+
+    /**
+     * Returns the index of a given child <code>TreeNode</code> or
+     * <code>-1</code> if <code>node</code> is not a child of this
+     * <code>AbstractElement</code>.
+     *
+     * @param node the node for which the index is requested
+     *
+     * @return the index of a given child <code>TreeNode</code> or
+     *         <code>-1</code> if <code>node</code> is not a child of this
+     *         <code>AbstractElement</code>
+     */
+    public int getIndex(TreeNode node)
+    {
+      return tree_children.indexOf(node);
+    }
+
+    /**
+     * Returns the parent <code>TreeNode</code> of this
+     * <code>AbstractElement</code> or <code>null</code> if this element
+     * has no parent.
+     *
+     * @return the parent <code>TreeNode</code> of this
+     *         <code>AbstractElement</code> or <code>null</code> if this
+     *         element has no parent
+     */
+    public TreeNode getParent()
+    {
+      return tree_parent;
+    }
+
+    /**
+     * Returns <code>true</code> if this <code>AbstractElement</code> is a
+     * leaf element, <code>false</code> otherwise.
+     *
+     * @return <code>true</code> if this <code>AbstractElement</code> is a
+     *         leaf element, <code>false</code> otherwise
+     */
+    public abstract boolean isLeaf();
+
+    /**
+     * Adds an attribute to this element.
+     *
+     * @param name the name of the attribute to be added
+     * @param value the value of the attribute to be added
+     */
+    public void addAttribute(Object name, Object value)
+    {
+      attributes = getAttributeContext().addAttribute(attributes, name, value);
+    }
+
+    /**
+     * Adds a set of attributes to this element.
+     *
+     * @param attrs the attributes to be added to this element
+     */
+    public void addAttributes(AttributeSet attrs)
+    {
+      attributes = getAttributeContext().addAttributes(attributes, attrs);
+    }
+
+    /**
+     * Removes an attribute from this element.
+     *
+     * @param name the name of the attribute to be removed
+     */
+    public void removeAttribute(Object name)
+    {
+      attributes = getAttributeContext().removeAttribute(attributes, name);
+    }
+
+    /**
+     * Removes a set of attributes from this element.
+     *
+     * @param attrs the attributes to be removed
+     */
+    public void removeAttributes(AttributeSet attrs)
+    {
+      attributes = getAttributeContext().removeAttributes(attributes, attrs);
+    }
+
+    /**
+     * Removes a set of attribute from this element.
+     *
+     * @param names the names of the attributes to be removed
+     */
+    public void removeAttributes(Enumeration names)
+    {
+      attributes = getAttributeContext().removeAttributes(attributes, names);
+    }
+
+    /**
+     * Sets the parent attribute set against which the element can resolve
+     * attributes that are not defined in itself.
+     *
+     * @param parent the resolve parent to set
+     */
+    public void setResolveParent(AttributeSet parent)
+    {
+      attributes = getAttributeContext().addAttribute(attributes,
+                                                      ResolveAttribute,
+                                                      parent);
+    }
+
+    /**
+     * Returns <code>true</code> if this element contains the specified
+     * attribute.
+     *
+     * @param name the name of the attribute to check
+     * @param value the value of the attribute to check
+     *
+     * @return <code>true</code> if this element contains the specified
+     *         attribute
+     */
+    public boolean containsAttribute(Object name, Object value)
+    {
+      return attributes.containsAttribute(name, value);
+    }
+
+    /**
+     * Returns <code>true</code> if this element contains all of the
+     * specified attributes.
+     *
+     * @param attrs the attributes to check
+     *
+     * @return <code>true</code> if this element contains all of the
+     *         specified attributes
+     */
+    public boolean containsAttributes(AttributeSet attrs)
+    {
+      return attributes.containsAttributes(attrs);
+    }
+
+    /**
+     * Returns a copy of the attributes of this element.
+     *
+     * @return a copy of the attributes of this element
+     */
+    public AttributeSet copyAttributes()
+    {
+      return attributes.copyAttributes();
+    }
+
+    /**
+     * Returns the attribute value with the specified key. If this attribute
+     * is not defined in this element and this element has a resolving
+     * parent, the search goes upward to the resolve parent chain.
+     *
+     * @param key the key of the requested attribute
+     *
+     * @return the attribute value for <code>key</code> of <code>null</code>
+     *         if <code>key</code> is not found locally and cannot be resolved
+     *         in this element's resolve parents
+     */
+    public Object getAttribute(Object key)
+    {
+      Object result = attributes.getAttribute(key);
+      if (result == null)
+        {
+          AttributeSet resParent = getResolveParent();
+          if (resParent != null)
+            result = resParent.getAttribute(key);
+        }
+      return result;
+    }
+
+    /**
+     * Returns the number of defined attributes in this element.
+     *
+     * @return the number of defined attributes in this element
+     */
+    public int getAttributeCount()
+    {
+      return attributes.getAttributeCount();
+    }
+
+    /**
+     * Returns the names of the attributes of this element.
+     *
+     * @return the names of the attributes of this element
+     */
+    public Enumeration getAttributeNames()
+    {
+      return attributes.getAttributeNames();
+    }
+
+    /**
+     * Returns the resolve parent of this element.
+     * This is taken from the AttributeSet, but if this is null,
+     * this method instead returns the Element's parent's 
+     * AttributeSet
+     *
+     * @return the resolve parent of this element
+     *
+     * @see #setResolveParent(AttributeSet)
+     */
+    public AttributeSet getResolveParent()
+    {
+      return attributes.getResolveParent();
+    }
+
+    /**
+     * Returns <code>true</code> if an attribute with the specified name
+     * is defined in this element, <code>false</code> otherwise.
+     *
+     * @param attrName the name of the requested attributes
+     *
+     * @return <code>true</code> if an attribute with the specified name
+     *         is defined in this element, <code>false</code> otherwise
+     */
+    public boolean isDefined(Object attrName)
+    {
+      return attributes.isDefined(attrName);
+    }
+
+    /**
+     * Returns <code>true</code> if the specified <code>AttributeSet</code>
+     * is equal to this element's <code>AttributeSet</code>, <code>false</code>
+     * otherwise.
+     *
+     * @param attrs the attributes to compare this element to
+     *
+     * @return <code>true</code> if the specified <code>AttributeSet</code>
+     *         is equal to this element's <code>AttributeSet</code>,
+     *         <code>false</code> otherwise
+     */
+    public boolean isEqual(AttributeSet attrs) 
+    {
+      return attributes.isEqual(attrs);
+    }
+
+    /**
+     * Returns the attributes of this element.
+     *
+     * @return the attributes of this element
+     */
+    public AttributeSet getAttributes()
+    {
+      return this;
+    }
+
+    /**
+     * Returns the {@link Document} to which this element belongs.
+     *
+     * @return the {@link Document} to which this element belongs
+     */
+    public Document getDocument()
+    {
+      return AbstractDocument.this;
+    }
+
+    /**
+     * Returns the child element at the specified <code>index</code>.
+     *
+     * @param index the index of the requested child element
+     *
+     * @return the requested element
+     */
+    public abstract Element getElement(int index);
+
+    /**
+     * Returns the name of this element.
+     *
+     * @return the name of this element
+     */
+    public String getName()
+    {
+      return (String) getAttribute(NameAttribute);
+    }
+
+    /**
+     * Returns the parent element of this element.
+     *
+     * @return the parent element of this element
+     */
+    public Element getParentElement()
+    {
+      return element_parent;
+    }
+
+    /**
+     * Returns the offset inside the document model that is after the last
+     * character of this element.
+     *
+     * @return the offset inside the document model that is after the last
+     *         character of this element
+     */
+    public abstract int getEndOffset();
+
+    /**
+     * Returns the number of child elements of this element.
+     *
+     * @return the number of child elements of this element
+     */
+    public abstract int getElementCount();
+
+    /**
+     * Returns the index of the child element that spans the specified
+     * offset in the document model.
+     *
+     * @param offset the offset for which the responsible element is searched
+     *
+     * @return the index of the child element that spans the specified
+     *         offset in the document model
+     */
+    public abstract int getElementIndex(int offset);
+
+    /**
+     * Returns the start offset if this element inside the document model.
+     *
+     * @return the start offset if this element inside the document model
+     */
+    public abstract int getStartOffset();
+
+    /**
+     * Prints diagnostic output to the specified stream.
+     *
+     * @param stream the stream to write to
+     * @param indent the indentation level
+     */
+    public void dump(PrintStream stream, int indent)
+    {
+      StringBuffer b = new StringBuffer();
+      for (int i = 0; i < indent; ++i)
+        b.append(' ');
+      b.append('<');
+      b.append(getName());
+      // Dump attributes if there are any.
+      if (getAttributeCount() > 0)
+        {
+          b.append('\n');
+          Enumeration attNames = getAttributeNames();
+          while (attNames.hasMoreElements())
+            {
+              for (int i = 0; i < indent + 2; ++i)
+                b.append(' ');
+              Object attName = attNames.nextElement();
+              b.append(attName);
+              b.append('=');
+              Object attribute = getAttribute(attName);
+              b.append(attribute);
+              b.append('\n');
+            }
+        }
+      b.append(">\n");
+
+      // Dump element content for leaf elements.
+      if (isLeaf())
+        {
+          for (int i = 0; i < indent + 2; ++i)
+            b.append(' ');
+          int start = getStartOffset();
+          int end = getEndOffset();
+          b.append('[');
+          b.append(start);
+          b.append(',');
+          b.append(end);
+          b.append("][");
+          try
+            {
+              b.append(getDocument().getText(start, end - start));
+            }
+          catch (BadLocationException ex)
+            {
+              AssertionError err = new AssertionError("BadLocationException "
+                                                      + "must not be thrown "
+                                                      + "here.");
+              err.initCause(ex);
+	      throw err;
+            }
+          b.append("]\n");
+        }
+      stream.print(b.toString());
+
+      // Dump child elements if any.
+      int count = getElementCount();
+      for (int i = 0; i < count; ++i)
+        {
+          Element el = getElement(i);
+          if (el instanceof AbstractElement)
+            ((AbstractElement) el).dump(stream, indent + 2);
+        }
+    }
+  }
+
+  /**
+   * An implementation of {@link Element} to represent composite
+   * <code>Element</code>s that contain other <code>Element</code>s.
+   */
+  public class BranchElement extends AbstractElement
+  {
+    /** The serialization UID (compatible with JDK1.5). */
+    private static final long serialVersionUID = -6037216547466333183L;
+
+    /**
+     * The child elements of this BranchElement.
+     */
+    private Element[] children;;
+
+    /**
+     * The number of children in the branch element.
+     */
+    private int numChildren;
+
+    /**
+     * Creates a new <code>BranchElement</code> with the specified
+     * parent and attributes.
+     *
+     * @param parent the parent element of this <code>BranchElement</code>
+     * @param attributes the attributes to set on this
+     *        <code>BranchElement</code>
+     */
+    public BranchElement(Element parent, AttributeSet attributes)
+    {
+      super(parent, attributes);
+      children = new Element[1];
+      numChildren = 0;
+    }
+
+    /**
+     * Returns the children of this <code>BranchElement</code>.
+     *
+     * @return the children of this <code>BranchElement</code>
+     */
+    public Enumeration children()
+    {
+      if (children.length == 0)
+        return null;
+
+      Vector tmp = new Vector();
+
+      for (int index = 0; index < numChildren; ++index)
+        tmp.add(children[index]);
+      
+      return tmp.elements();
+    }
+
+    /**
+     * Returns <code>true</code> since <code>BranchElements</code> allow
+     * child elements.
+     *
+     * @return <code>true</code> since <code>BranchElements</code> allow
+     *         child elements
+     */
+    public boolean getAllowsChildren()
+    {
+      return true;
+    }
+
+    /**
+     * Returns the child element at the specified <code>index</code>.
+     *
+     * @param index the index of the requested child element
+     *
+     * @return the requested element
+     */
+    public Element getElement(int index)
+    {
+      if (index < 0 || index >= numChildren)
+        return null;
+
+      return children[index];
+    }
+
+    /**
+     * Returns the number of child elements of this element.
+     *
+     * @return the number of child elements of this element
+     */
+    public int getElementCount()
+    {
+      return numChildren;
+    }
+
+    /**
+     * Returns the index of the child element that spans the specified
+     * offset in the document model.
+     *
+     * @param offset the offset for which the responsible element is searched
+     *
+     * @return the index of the child element that spans the specified
+     *         offset in the document model
+     */
+    public int getElementIndex(int offset)
+    {
+      // If offset is less than the start offset of our first child,
+      // return 0
+      if (offset < getStartOffset())
+        return 0;
+
+      // XXX: There is surely a better algorithm
+      // as beginning from first element each time.
+      for (int index = 0; index < numChildren - 1; ++index)
+        {
+          Element elem = children[index];
+
+          if ((elem.getStartOffset() <= offset)
+               && (offset < elem.getEndOffset()))
+            return index;
+          // If the next element's start offset is greater than offset
+          // then we have to return the closest Element, since no Elements
+          // will contain the offset
+          if (children[index + 1].getStartOffset() > offset)
+            {
+              if ((offset - elem.getEndOffset()) > (children[index + 1].getStartOffset() - offset))
+                return index + 1;
+              else
+                return index;
+            }
+        }
+
+      // If offset is greater than the index of the last element, return
+      // the index of the last element.
+      return getElementCount() - 1;
+    }
+
+    /**
+     * Returns the offset inside the document model that is after the last
+     * character of this element.
+     * This is the end offset of the last child element. If this element
+     * has no children, this method throws a <code>NullPointerException</code>.
+     *
+     * @return the offset inside the document model that is after the last
+     *         character of this element
+     *
+     * @throws NullPointerException if this branch element has no children
+     */
+    public int getEndOffset()
+    {
+      // This might accss one cached element or trigger an NPE for
+      // numChildren == 0. This is checked by a Mauve test.
+      Element child = numChildren > 0 ? children[numChildren - 1]
+                                      : children[0];
+      return child.getEndOffset();
+    }
+
+    /**
+     * Returns the name of this element. This is {@link #ParagraphElementName}
+     * in this case.
+     *
+     * @return the name of this element
+     */
+    public String getName()
+    {
+      return ParagraphElementName;
+    }
+
+    /**
+     * Returns the start offset of this element inside the document model.
+     * This is the start offset of the first child element. If this element
+     * has no children, this method throws a <code>NullPointerException</code>.
+     *
+     * @return the start offset of this element inside the document model
+     *
+     * @throws NullPointerException if this branch element has no children and
+     *         no startOffset value has been cached
+     */
+    public int getStartOffset()
+    {
+      // Do not explicitly throw an NPE here. If the first element is null
+      // then the NPE gets thrown anyway. If it isn't, then it either
+      // holds a real value (for numChildren > 0) or a cached value
+      // (for numChildren == 0) as we don't fully remove elements in replace()
+      // when removing single elements.
+      // This is checked by a Mauve test.
+      return children[0].getStartOffset();
+    }
+
+    /**
+     * Returns <code>false</code> since <code>BranchElement</code> are no
+     * leafes.
+     *
+     * @return <code>false</code> since <code>BranchElement</code> are no
+     *         leafes
+     */
+    public boolean isLeaf()
+    {
+      return false;
+    }
+
+    /**
+     * Returns the <code>Element</code> at the specified <code>Document</code>
+     * offset.
+     *
+     * @return the <code>Element</code> at the specified <code>Document</code>
+     *         offset
+     *
+     * @see #getElementIndex(int)
+     */
+    public Element positionToElement(int position)
+    {
+      // XXX: There is surely a better algorithm
+      // as beginning from first element each time.
+      for (int index = 0; index < numChildren; ++index)
+        {
+	  Element elem = children[index];
+
+	  if ((elem.getStartOffset() <= position)
+	      && (position < elem.getEndOffset()))
+	    return elem;
+        }
+
+      return null;
+    }
+
+    /**
+     * Replaces a set of child elements with a new set of child elemens.
+     *
+     * @param offset the start index of the elements to be removed
+     * @param length the number of elements to be removed
+     * @param elements the new elements to be inserted
+     */
+    public void replace(int offset, int length, Element[] elements)
+    {
+      int delta = elements.length - length;
+      int copyFrom = offset + length; // From where to copy.
+      int copyTo = copyFrom + delta;    // Where to copy to.
+      int numMove = numChildren - copyFrom; // How many elements are moved. 
+      if (numChildren + delta > children.length)
+        {
+          // Gotta grow the array.
+          int newSize = Math.max(2 * children.length, numChildren + delta);
+          Element[] target = new Element[newSize];
+          System.arraycopy(children, 0, target, 0, offset);
+          System.arraycopy(elements, 0, target, offset, elements.length);
+          System.arraycopy(children, copyFrom, target, copyTo, numMove);
+          children = target;
+        }
+      else
+        {
+          System.arraycopy(children, copyFrom, children, copyTo, numMove);
+          System.arraycopy(elements, 0, children, offset, elements.length);
+        }
+      numChildren += delta;
+    }
+
+    /**
+     * Returns a string representation of this element.
+     *
+     * @return a string representation of this element
+     */
+    public String toString()
+    {
+      return ("BranchElement(" + getName() + ") "
+	      + getStartOffset() + "," + getEndOffset() + "\n");
+    }
+  }
+
+  /**
+   * Stores the changes when a <code>Document</code> is beeing modified.
+   */
+  public class DefaultDocumentEvent extends CompoundEdit
+    implements DocumentEvent
+  {
+    /** The serialization UID (compatible with JDK1.5). */
+    private static final long serialVersionUID = 5230037221564563284L;
+
+    /** The starting offset of the change. */
+    private int offset;
+
+    /** The length of the change. */
+    private int length;
+
+    /** The type of change. */
+    private DocumentEvent.EventType type;
+
+    /**
+     * Maps <code>Element</code> to their change records.
+     */
+    Hashtable changes;
+
+    /**
+     * Indicates if this event has been modified or not. This is used to
+     * determine if this event is thrown.
+     */
+    boolean modified;
+
+    /**
+     * Creates a new <code>DefaultDocumentEvent</code>.
+     *
+     * @param offset the starting offset of the change
+     * @param length the length of the change
+     * @param type the type of change
+     */
+    public DefaultDocumentEvent(int offset, int length,
+				DocumentEvent.EventType type)
+    {
+      this.offset = offset;
+      this.length = length;
+      this.type = type;
+      changes = new Hashtable();
+      modified = false;
+    }
+
+    /**
+     * Adds an UndoableEdit to this <code>DocumentEvent</code>. If this
+     * edit is an instance of {@link ElementEdit}, then this record can
+     * later be fetched by calling {@link #getChange}.
+     *
+     * @param edit the undoable edit to add
+     */
+    public boolean addEdit(UndoableEdit edit)
+    {
+      // XXX - Fully qualify ElementChange to work around gcj bug #2499.
+      if (edit instanceof DocumentEvent.ElementChange)
+        {
+          modified = true;
+          DocumentEvent.ElementChange elEdit =
+            (DocumentEvent.ElementChange) edit;
+          changes.put(elEdit.getElement(), elEdit);
+        }
+      return super.addEdit(edit);
+    }
+
+    /**
+     * Returns the document that has been modified.
+     *
+     * @return the document that has been modified
+     */
+    public Document getDocument()
+    {
+      return AbstractDocument.this;
+    }
+
+    /**
+     * Returns the length of the modification.
+     *
+     * @return the length of the modification
+     */
+    public int getLength()
+    {
+      return length;
+    }
+
+    /**
+     * Returns the start offset of the modification.
+     *
+     * @return the start offset of the modification
+     */
+    public int getOffset()
+    {
+      return offset;
+    }
+
+    /**
+     * Returns the type of the modification.
+     *
+     * @return the type of the modification
+     */
+    public DocumentEvent.EventType getType()
+    {
+      return type;
+    }
+
+    /**
+     * Returns the changes for an element.
+     *
+     * @param elem the element for which the changes are requested
+     *
+     * @return the changes for <code>elem</code> or <code>null</code> if
+     *         <code>elem</code> has not been changed
+     */
+    public DocumentEvent.ElementChange getChange(Element elem)
+    {
+      // XXX - Fully qualify ElementChange to work around gcj bug #2499.
+      return (DocumentEvent.ElementChange) changes.get(elem);
+    }
+    
+    /**
+     * Returns a String description of the change event.  This returns the
+     * toString method of the Vector of edits.
+     */
+    public String toString()
+    {
+      return edits.toString();
+    }
+  }
+  
+  /**
+   * An implementation of {@link DocumentEvent.ElementChange} to be added
+   * to {@link DefaultDocumentEvent}s.
+   */
+  public static class ElementEdit extends AbstractUndoableEdit
+    implements DocumentEvent.ElementChange
+  {
+    /** The serial version UID of ElementEdit. */
+    private static final long serialVersionUID = -1216620962142928304L;
+
+    /**
+     * The changed element.
+     */
+    private Element elem;
+
+    /**
+     * The index of the change.
+     */
+    private int index;
+
+    /**
+     * The removed elements.
+     */
+    private Element[] removed;
+
+    /**
+     * The added elements.
+     */
+    private Element[] added;
+    
+    /**
+     * Creates a new <code>ElementEdit</code>.
+     *
+     * @param elem the changed element
+     * @param index the index of the change
+     * @param removed the removed elements
+     * @param added the added elements
+     */
+    public ElementEdit(Element elem, int index,
+		       Element[] removed, Element[] added)
+    {
+      this.elem = elem;
+      this.index = index;
+      this.removed = removed;
+      this.added = added;
+    }
+
+    /**
+     * Returns the added elements.
+     *
+     * @return the added elements
+     */
+    public Element[] getChildrenAdded()
+    {
+      return added;
+    }
+
+    /**
+     * Returns the removed elements.
+     *
+     * @return the removed elements
+     */
+    public Element[] getChildrenRemoved()
+    {
+      return removed;
+    }
+
+    /**
+     * Returns the changed element.
+     *
+     * @return the changed element
+     */
+    public Element getElement()
+    {
+      return elem;
+    }
+
+    /**
+     * Returns the index of the change.
+     *
+     * @return the index of the change
+     */
+    public int getIndex()
+    {
+      return index;
+    }
+  }
+
+  /**
+   * An implementation of {@link Element} that represents a leaf in the
+   * document structure. This is used to actually store content.
+   */
+  public class LeafElement extends AbstractElement
+  {
+    /** The serialization UID (compatible with JDK1.5). */
+    private static final long serialVersionUID = -8906306331347768017L;
+
+    /**
+     * Manages the start offset of this element.
+     */
+    private Position startPos;
+
+    /**
+     * Manages the end offset of this element.
+     */
+    private Position endPos;
+
+    /**
+     * Creates a new <code>LeafElement</code>.
+     *
+     * @param parent the parent of this <code>LeafElement</code>
+     * @param attributes the attributes to be set
+     * @param start the start index of this element inside the document model
+     * @param end the end index of this element inside the document model
+     */
+    public LeafElement(Element parent, AttributeSet attributes, int start,
+                       int end)
+    {
+      super(parent, attributes);
+      try
+        {
+          startPos = createPosition(start);
+          endPos = createPosition(end);
+        }
+      catch (BadLocationException ex)
+        {
+          AssertionError as;
+          as = new AssertionError("BadLocationException thrown "
+                                  + "here. start=" + start
+                                  + ", end=" + end
+                                  + ", length=" + getLength());
+          as.initCause(ex);
+          throw as;
+        }
+    }
+
+    /**
+     * Returns <code>null</code> since <code>LeafElement</code>s cannot have
+     * children.
+     *
+     * @return <code>null</code> since <code>LeafElement</code>s cannot have
+     *         children
+     */
+    public Enumeration children()
+    {
+      return null;
+    }
+
+    /**
+     * Returns <code>false</code> since <code>LeafElement</code>s cannot have
+     * children.
+     *
+     * @return <code>false</code> since <code>LeafElement</code>s cannot have
+     *         children
+     */
+    public boolean getAllowsChildren()
+    {
+      return false;
+    }
+
+    /**
+     * Returns <code>null</code> since <code>LeafElement</code>s cannot have
+     * children.
+     *
+     * @return <code>null</code> since <code>LeafElement</code>s cannot have
+     *         children
+     */
+    public Element getElement(int index)
+    {
+      return null;
+    }
+
+    /**
+     * Returns <code>0</code> since <code>LeafElement</code>s cannot have
+     * children.
+     *
+     * @return <code>0</code> since <code>LeafElement</code>s cannot have
+     *         children
+     */
+    public int getElementCount()
+    {
+      return 0;
+    }
+
+    /**
+     * Returns <code>-1</code> since <code>LeafElement</code>s cannot have
+     * children.
+     *
+     * @return <code>-1</code> since <code>LeafElement</code>s cannot have
+     *         children
+     */
+    public int getElementIndex(int offset)
+    {
+      return -1;
+    }
+
+    /**
+     * Returns the end offset of this <code>Element</code> inside the
+     * document.
+     *
+     * @return the end offset of this <code>Element</code> inside the
+     *         document
+     */
+    public int getEndOffset()
+    {
+      return endPos.getOffset();
+    }
+
+    /**
+     * Returns the name of this <code>Element</code>. This is
+     * {@link #ContentElementName} in this case.
+     *
+     * @return the name of this <code>Element</code>
+     */
+    public String getName()
+    {
+      String name = super.getName();
+      if (name == null)
+        name = ContentElementName;
+      return name;
+    }
+
+    /**
+     * Returns the start offset of this <code>Element</code> inside the
+     * document.
+     *
+     * @return the start offset of this <code>Element</code> inside the
+     *         document
+     */
+    public int getStartOffset()
+    {
+      return startPos.getOffset();
+    }
+
+    /**
+     * Returns <code>true</code>.
+     *
+     * @return <code>true</code>
+     */
+    public boolean isLeaf()
+    {
+      return true;
+    }
+
+    /**
+     * Returns a string representation of this <code>Element</code>.
+     *
+     * @return a string representation of this <code>Element</code>
+     */
+    public String toString()
+    {
+      return ("LeafElement(" + getName() + ") "
+	      + getStartOffset() + "," + getEndOffset() + "\n");
+    }
+  }
+  
+  /** A class whose methods delegate to the insert, remove and replace methods
+   * of this document which do not check for an installed DocumentFilter.
+   */
+  class Bypass extends DocumentFilter.FilterBypass
+  {
+
+    public Document getDocument()
+    {
+      return AbstractDocument.this;
+    }
+
+    public void insertString(int offset, String string, AttributeSet attr)
+    throws BadLocationException
+    {
+      AbstractDocument.this.insertStringImpl(offset, string, attr);
+    }
+
+    public void remove(int offset, int length)
+    throws BadLocationException
+    {
+      AbstractDocument.this.removeImpl(offset, length);
+    }
+
+    public void replace(int offset, int length, String string,
+                        AttributeSet attrs)
+    throws BadLocationException
+    {
+      AbstractDocument.this.replaceImpl(offset, length, string, attrs);
+    }
+    
+  }
+  
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,481 @@
+/* AbstractWriter.java --
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Enumeration;
+
+/**
+ * This is an abstract base class for writing Document instances to a
+ * Writer.  A concrete subclass must implement a method to iterate
+ * over the Elements of the Document and correctly format them.
+ */
+public abstract class AbstractWriter
+{
+  /**
+   * The default line separator character.
+   * @specnote although this is a constant, it is not static in the JDK
+   */
+  protected static final char NEWLINE = '\n';
+
+  // Where we write.
+  private Writer writer;
+  // How we iterate over the document.
+  private ElementIterator iter;
+  // The document over which we iterate.
+  private Document document;
+  // Maximum number of characters per line.
+  private int maxLineLength = 100;
+  // Number of characters we have currently written.
+  private int lineLength;
+  // True if we can apply line wrapping.
+  private boolean canWrapLines;	// FIXME default?
+  // The number of spaces per indentation level.
+  private int indentSpace = 2;
+  // The current indentation level.
+  private int indentLevel;
+  // True if we have indented this line.
+  private boolean indented;
+  // Starting offset in document.
+  private int startOffset;
+  // Ending offset in document.
+  private int endOffset;
+  // The line separator string.
+  private String lineSeparator = "" + NEWLINE;
+  // The characters making up the line separator.
+  private char[] lineSeparatorChars = lineSeparator.toCharArray();
+
+  /**
+   * Create a new AbstractWriter with the indicated Writer and
+   * Document.  The full range of the Document will be used.  The
+   * internal ElementIterator will be initialized with the Document's
+   * root node.
+   */
+  protected AbstractWriter(Writer writer, Document doc)
+  {
+    this.writer = writer;
+    this.iter = new ElementIterator(doc);
+    this.document = doc;
+    this.startOffset = 0;
+    this.endOffset = doc.getLength();
+  }
+
+  /**
+   * Create a new AbstractWriter with the indicated Writer and
+   * Document.  The full range of the Document will be used.  The
+   * internal ElementIterator will be initialized with the Document's
+   * root node.
+   */
+  protected AbstractWriter(Writer writer, Document doc, int pos, int len)
+  {
+    this.writer = writer;
+    this.iter = new ElementIterator(doc);
+    this.document = doc;
+    this.startOffset = pos;
+    this.endOffset = pos + len;
+  }
+
+  /**
+   * Create a new AbstractWriter with the indicated Writer and
+   * Element.  The full range of the Element will be used.
+   */
+  protected AbstractWriter(Writer writer, Element elt)
+  {
+    this.writer = writer;
+    this.iter = new ElementIterator(elt);
+    this.document = elt.getDocument();
+    this.startOffset = elt.getStartOffset();
+    this.endOffset = elt.getEndOffset();
+  }
+
+  /**
+   * Create a new AbstractWriter with the indicated Writer and
+   * Element.  The full range of the Element will be used.  The range
+   * will be limited to the indicated range of the Document.
+   */
+  protected AbstractWriter(Writer writer, Element elt, int pos, int len)
+  {
+    this.writer = writer;
+    this.iter = new ElementIterator(elt);
+    this.document = elt.getDocument();
+    this.startOffset = pos;
+    this.endOffset = pos + len;
+  }
+
+  /**
+   * Return the ElementIterator for this writer.
+   */
+  protected ElementIterator getElementIterator()
+  {
+    return iter;
+  }
+
+  /**
+   * Return the Writer to which we are writing.
+   * @since 1.3
+   */
+  protected Writer getWriter()
+  {
+    return writer;
+  }
+
+  /**
+   * Return this writer's Document.
+   */
+  protected Document getDocument()
+  {
+    return document;
+  }
+
+  /**
+   * This method must be overridden by a concrete subclass.  It is
+   * responsible for iterating over the Elements of the Document and
+   * writing them out. 
+   */
+  protected abstract void write() throws IOException, BadLocationException;
+
+  /**
+   * Return the text of the Document that is associated with the given
+   * Element.  If the Element is not a leaf Element, this will throw
+   * BadLocationException.
+   *
+   * @throws BadLocationException if the element is not a leaf
+   */
+  protected String getText(Element elt) throws BadLocationException
+  {
+    if (! elt.isLeaf())
+      throw new BadLocationException("Element is not a leaf",
+				     elt.getStartOffset());
+    return document.getText(elt.getStartOffset(), 
+			    elt.getEndOffset() - elt.getStartOffset());
+  }
+
+  /**
+   * This method calls Writer.write on the indicated data, and updates
+   * the current line length.  This method does not look for newlines
+   * in the written data; the caller is responsible for that.
+   *
+   * @since 1.3
+   */
+  protected void output(char[] data, int start, int len) throws IOException
+  {
+    writer.write(data, start, len);
+    lineLength += len;
+  }
+
+  /**
+   * Write a line separator using the output method, and then reset
+   * the current line length.
+   *
+   * @since 1.3
+   */
+  protected void writeLineSeparator() throws IOException
+  {
+    output(lineSeparatorChars, 0, lineSeparatorChars.length);
+    lineLength = 0;
+    indented = false;
+  }
+
+  /**
+   * Write a single character.
+   */
+  protected void write(char ch) throws IOException
+  {
+    write(new char[] { ch }, 0, 1);
+  }
+
+  /**
+   * Write a String.
+   */
+  protected void write(String s) throws IOException
+  {
+    char[] v = s.toCharArray();
+    write(v, 0, v.length);
+  }
+
+  /**
+   * Write a character array to the output Writer, properly handling
+   * newlines and, if needed, wrapping lines as they are output.
+   * @since 1.3
+   */
+  protected void write(char[] data, int start, int len) throws IOException
+  {
+    if (getCanWrapLines())
+      {
+	// FIXME: should we be handling newlines specially here?
+	for (int i = 0; i < len; )
+	  {
+	    int start_i = i;
+	    // Find next space.
+	    while (i < len && data[start + i] != ' ')
+	      ++i;
+	    if (i < len && lineLength + i - start_i >= maxLineLength)
+	      writeLineSeparator();
+	    else if (i < len)
+	      {
+		// Write the trailing space.
+		++i;
+	      }
+	    // Write out the text.
+	    output(data, start + start_i, start + i - start_i);
+	  }
+      }
+    else
+      {
+	int saved_i = start;
+	for (int i = start; i < start + len; ++i)
+	  {
+	    if (data[i] == NEWLINE)
+	      {
+		output(data, saved_i, i - saved_i);
+		writeLineSeparator();
+	      }
+	  }
+	if (saved_i < start + len - 1)
+	  output(data, saved_i, start + len - saved_i);
+      }
+  }
+
+  /**
+   * Indent this line by emitting spaces, according to the current
+   * indent level and the current number of spaces per indent.  After
+   * this method is called, the current line is no longer considered
+   * to be empty, even if no spaces are actually written.
+   */
+  protected void indent() throws IOException
+  {
+    int spaces = indentLevel * indentSpace;
+    if (spaces > 0)
+      {
+	char[] v = new char[spaces];
+	Arrays.fill(v, ' ');
+	write(v, 0, v.length);
+      }
+    indented = true;
+  }
+
+  /**
+   * Return the index of the Document at which output starts.
+   * @since 1.3
+   */
+  public int getStartOffset()
+  {
+    return startOffset;
+  }
+
+  /**
+   * Return the index of the Document at which output ends.
+   * @since 1.3
+   */
+  public int getEndOffset()
+  {
+    return endOffset;
+  }
+
+  /**
+   * Return true if the Element's range overlaps our desired output
+   * range; false otherwise.
+   */
+  protected boolean inRange(Element elt)
+  {
+    int eltStart = elt.getStartOffset();
+    int eltEnd = elt.getEndOffset();
+    return ((eltStart >= startOffset && eltStart < endOffset)
+	    || (eltEnd >= startOffset && eltEnd < endOffset));
+  }
+
+  /**
+   * Output the text of the indicated Element, properly clipping it to
+   * the range of the Document specified when the AbstractWriter was
+   * created.
+   */
+  protected void text(Element elt) throws BadLocationException, IOException
+  {
+    int eltStart = elt.getStartOffset();
+    int eltEnd = elt.getEndOffset();
+
+    eltStart = Math.max(eltStart, startOffset);
+    eltEnd = Math.min(eltEnd, endOffset);
+    write(document.getText(eltStart, eltEnd));
+  }
+
+  /**
+   * Set the maximum line length.
+   */
+  protected void setLineLength(int maxLineLength)
+  {
+    this.maxLineLength = maxLineLength;
+  }
+
+  /**
+   * Return the maximum line length.
+   * @since 1.3
+   */
+  protected int getLineLength()
+  {
+    return maxLineLength;
+  }
+
+  /**
+   * Set the current line length.
+   * @since 1.3
+   */
+  protected void setCurrentLineLength(int lineLength)
+  {
+    this.lineLength = lineLength;
+  }
+
+  /**
+   * Return the current line length.
+   * @since 1.3
+   */
+  protected int getCurrentLineLength()
+  {
+    return lineLength;
+  }
+
+  /**
+   * Return true if the line is empty, false otherwise.  The line is
+   * empty if nothing has been written since the last newline, and
+   * indent has not been invoked.
+   */
+  protected boolean isLineEmpty()
+  {
+    return lineLength == 0 && ! indented;
+  }
+
+  /**
+   * Set the flag indicating whether lines will wrap.  This affects
+   * the behavior of write().
+   * @since 1.3
+   */
+  protected void setCanWrapLines(boolean canWrapLines)
+  {
+    this.canWrapLines = canWrapLines;
+  }
+
+  /**
+   * Return true if lines printed via write() will wrap, false
+   * otherwise.
+   * @since 1.3
+   */
+  protected boolean getCanWrapLines()
+  {
+    return canWrapLines;
+  }
+
+  /**
+   * Set the number of spaces per indent level.
+   * @since 1.3
+   */
+  protected void setIndentSpace(int indentSpace)
+  {
+    this.indentSpace = indentSpace;
+  }
+
+  /**
+   * Return the number of spaces per indent level.
+   * @since 1.3
+   */
+  protected int getIndentSpace()
+  {
+    return indentSpace;
+  }
+
+  /**
+   * Set the current line separator.
+   * @since 1.3
+   */
+  public void setLineSeparator(String lineSeparator)
+  {
+    this.lineSeparator = lineSeparator;
+    this.lineSeparatorChars = lineSeparator.toCharArray();
+  }
+
+  /**
+   * Return the current line separator.
+   * @since 1.3
+   */
+  public String getLineSeparator()
+  {
+    return lineSeparator;
+  }
+
+  /**
+   * Increment the indent level.
+   */
+  protected void incrIndent()
+  {
+    ++indentLevel;
+  }
+
+  /**
+   * Decrement the indent level.
+   */
+  protected void decrIndent()
+  {
+    --indentLevel;
+  }
+
+  /**
+   * Return the current indent level.
+   * @since 1.3
+   */
+  protected int getIndentLevel()
+  {
+    return indentLevel;
+  }
+
+  /**
+   * Print the given AttributeSet as a sequence of assignment-like
+   * strings, e.g. "key=value".
+   */
+  protected void writeAttributes(AttributeSet attrs) throws IOException
+  {
+    Enumeration e = attrs.getAttributeNames();
+    while (e.hasMoreElements())
+      {
+	Object name = e.nextElement();
+	Object val = attrs.getAttribute(name);
+	write(name + "=" + val);
+	writeLineSeparator();
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1480 @@
+/* AsyncBoxView.java -- A box view that performs layout asynchronously
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.ArrayList;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.Position.Bias;
+
+/**
+ * A {@link View} implementation that lays out its child views in a box, either
+ * vertically or horizontally. The difference to {@link BoxView} is that the
+ * layout is performed in an asynchronous manner. This helps to keep the
+ * eventqueue free from non-GUI related tasks.
+ *
+ * This view is currently not used in standard text components. In order to
+ * use it you would have to implement a special {@link EditorKit} with a
+ * {@link ViewFactory} that returns this view. For example:
+ *
+ * <pre>
+ * static class AsyncEditorKit extends StyledEditorKit implements ViewFactory
+ * {
+ *   public View create(Element el)
+ *   {
+ *     if (el.getName().equals(AbstractDocument.SectionElementName))
+ *       return new AsyncBoxView(el, View.Y_AXIS);
+ *     return super.getViewFactory().create(el);
+ *   }
+ *   public ViewFactory getViewFactory() {
+ *     return this;
+ *   }
+ * }
+ * </pre>
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ *
+ * @since 1.3
+ */
+public class AsyncBoxView
+  extends View
+{
+
+  /**
+   * Manages the effective position of child views. That keeps the visible
+   * layout stable while the AsyncBoxView might be changing until the layout
+   * thread decides to publish the new layout.
+   */
+  public class ChildLocator
+  {
+
+    /**
+     * The last valid location.
+     */
+    protected ChildState lastValidOffset;
+
+    /**
+     * The last allocation.
+     */
+    protected Rectangle lastAlloc;
+
+    /**
+     * A Rectangle used for child allocation calculation to avoid creation
+     * of lots of garbage Rectangle objects.
+     */
+    protected Rectangle childAlloc;
+
+    /**
+     * Creates a new ChildLocator.
+     */
+    public ChildLocator()
+    {
+      lastAlloc = new Rectangle();
+      childAlloc = new Rectangle();
+    }
+
+    /**
+     * Receives notification that a child has changed. This is called by
+     * child state objects that have changed it's major span.
+     *
+     * This sets the {@link #lastValidOffset} field to <code>cs</code> if
+     * the new child state's view start offset is smaller than the start offset
+     * of the current child state's view or when <code>lastValidOffset</code>
+     * is <code>null</code>.
+     *
+     * @param cs the child state object that has changed
+     */
+    public synchronized void childChanged(ChildState cs)
+    {
+      if (lastValidOffset == null
+          || cs.getChildView().getStartOffset()
+             < lastValidOffset.getChildView().getStartOffset())
+        {
+          lastValidOffset = cs;
+        }
+    }
+
+    /**
+     * Returns the view index of the view that occupies the specified area, or
+     * <code>-1</code> if there is no such child view.
+     *
+     * @param x the x coordinate (relative to <code>a</code>)
+     * @param y the y coordinate (relative to <code>a</code>)
+     * @param a the current allocation of this view
+     *
+     * @return the view index of the view that occupies the specified area, or
+     *         <code>-1</code> if there is no such child view
+     */
+    public int getViewIndexAtPoint(float x, float y, Shape a)
+    {
+      setAllocation(a);
+      float targetOffset = (getMajorAxis() == X_AXIS) ? x - lastAlloc.x
+                                                      : y - lastAlloc.y;
+      int index = getViewIndexAtVisualOffset(targetOffset);
+      return index;
+    }
+
+    /**
+     * Returns the current allocation for a child view. This updates the
+     * offsets for all children <em>before</em> the requested child view.
+     *
+     * @param index the index of the child view
+     * @param a the current allocation of this view
+     * 
+     * @return the current allocation for a child view
+     */
+    public synchronized Shape getChildAllocation(int index, Shape a)
+    {
+      if (a == null)
+        return null;
+      setAllocation(a);
+      ChildState cs = getChildState(index);
+      if (cs.getChildView().getStartOffset()
+          > lastValidOffset.getChildView().getStartOffset())
+        {
+          updateChildOffsetsToIndex(index);
+        }
+      Shape ca = getChildAllocation(index);
+      return ca;
+    }
+
+    /**
+     * Paints all child views.
+     *
+     * @param g the graphics context to use
+     */
+    public synchronized void paintChildren(Graphics g)
+    {
+      Rectangle clip = g.getClipBounds();
+      float targetOffset = (getMajorAxis() == X_AXIS) ? clip.x - lastAlloc.x
+                                                      : clip.y - lastAlloc.y;
+      int index = getViewIndexAtVisualOffset(targetOffset);
+      int n = getViewCount();
+      float offs = getChildState(index).getMajorOffset();
+      for (int i = index; i < n; i++)
+        {
+          ChildState cs = getChildState(i);
+          cs.setMajorOffset(offs);
+          Shape ca = getChildAllocation(i);
+          if (ca.intersects(clip))
+            {
+              synchronized (cs)
+                {
+                  View v = cs.getChildView();
+                  v.paint(g, ca);
+                }
+            }
+          else
+            {
+              // done painting intersection
+              break;
+            }
+          offs += cs.getMajorSpan();
+        }
+    }
+
+    /**
+     * Returns the current allocation of the child view with the specified
+     * index. Note that this will <em>not</em> update any location information.
+     * 
+     * @param index the index of the requested child view
+     *
+     * @return the current allocation of the child view with the specified
+     *         index
+     */
+    protected Shape getChildAllocation(int index)
+    {
+      ChildState cs = getChildState(index);
+      if (! cs.isLayoutValid())
+          cs.run();
+
+      if (getMajorAxis() == X_AXIS)
+        {
+          childAlloc.x = lastAlloc.x + (int) cs.getMajorOffset();
+          childAlloc.y = lastAlloc.y + (int) cs.getMinorOffset();
+          childAlloc.width = (int) cs.getMajorSpan();
+          childAlloc.height = (int) cs.getMinorSpan();
+        }
+      else
+        {
+          childAlloc.y = lastAlloc.y + (int) cs.getMajorOffset();
+          childAlloc.x = lastAlloc.x + (int) cs.getMinorOffset();
+          childAlloc.height = (int) cs.getMajorSpan();
+          childAlloc.width = (int) cs.getMinorSpan();
+        }
+      return childAlloc;
+    }
+
+    /**
+     * Sets the current allocation for this view.
+     *
+     * @param a the allocation to set
+     */
+    protected void setAllocation(Shape a)
+    {
+      if (a instanceof Rectangle)
+        lastAlloc.setBounds((Rectangle) a);
+      else
+        lastAlloc.setBounds(a.getBounds());
+
+      setSize(lastAlloc.width, lastAlloc.height);
+    }
+
+    /**
+     * Returns the index of the view at the specified offset along the major
+     * layout axis.
+     *
+     * @param targetOffset the requested offset
+     *
+     * @return the index of the view at the specified offset along the major
+     * layout axis
+     */
+    protected int getViewIndexAtVisualOffset(float targetOffset)
+    {
+      int n = getViewCount();
+      if (n > 0)
+        {
+          if (lastValidOffset == null)
+            lastValidOffset = getChildState(0);
+          if (targetOffset > majorSpan)
+            return 0;
+          else if (targetOffset > lastValidOffset.getMajorOffset())
+            return updateChildOffsets(targetOffset);
+          else
+            {
+              float offs = 0f;
+              for (int i = 0; i < n; i++)
+                {
+                  ChildState cs = getChildState(i);
+                  float nextOffs = offs + cs.getMajorSpan();
+                  if (targetOffset < nextOffs)
+                    return i;
+                  offs = nextOffs;
+                }
+            }
+        }
+      return n - 1;
+    }
+
+    /**
+     * Updates all the child view offsets up to the specified targetOffset.
+     *
+     * @param targetOffset the offset up to which the child view offsets are
+     *        updated
+     *
+     * @return the index of the view at the specified offset
+     */
+    private int updateChildOffsets(float targetOffset)
+    {
+      int n = getViewCount();
+      int targetIndex = n - 1;;
+      int pos = lastValidOffset.getChildView().getStartOffset();
+      int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward);
+      float start = lastValidOffset.getMajorOffset();
+      float lastOffset = start;
+      for (int i = startIndex; i < n; i++)
+        {
+          ChildState cs = getChildState(i);
+          cs.setMajorOffset(lastOffset);
+          lastOffset += cs.getMajorSpan();
+          if (targetOffset < lastOffset)
+            {
+              targetIndex = i;
+              lastValidOffset = cs;
+              break;
+            }
+        }
+      return targetIndex;
+    }
+
+    /**
+     * Updates the offsets of the child views up to the specified index.
+     *
+     * @param index the index up to which the offsets are updated
+     */
+    private void updateChildOffsetsToIndex(int index)
+    {
+      int pos = lastValidOffset.getChildView().getStartOffset();
+      int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward);
+      float lastOffset = lastValidOffset.getMajorOffset();
+      for (int i = startIndex; i <= index; i++)
+        {
+          ChildState cs = getChildState(i);
+          cs.setMajorOffset(lastOffset);
+          lastOffset += cs.getMajorSpan();
+        }
+    }
+  }
+
+  /**
+   * Represents the layout state of a child view.
+   */
+  public class ChildState
+    implements Runnable
+  {
+
+    /**
+     * The child view for this state record.
+     */
+    private View childView;
+
+    /**
+     * Indicates if the minor axis requirements of this child view are valid
+     * or not.
+     */
+    private boolean minorValid;
+
+    /**
+     * Indicates if the major axis requirements of this child view are valid
+     * or not.
+     */
+    private boolean majorValid;
+
+    /**
+     * Indicates if the current child size is valid. This is package private
+     * to avoid synthetic accessor method.
+     */
+    boolean childSizeValid;
+
+    /**
+     * The child views minimumSpan. This is package private to avoid accessor
+     * method.
+     */
+    float minimum;
+
+    /**
+     * The child views preferredSpan. This is package private to avoid accessor
+     * method.
+     */
+    float preferred;
+
+    /**
+     * The current span of the child view along the major axis.
+     */
+    private float majorSpan;
+
+    /**
+     * The current offset of the child view along the major axis.
+     */
+    private float majorOffset;
+
+    /**
+     * The current span of the child view along the minor axis.
+     */
+    private float minorSpan;
+
+    /**
+     * The current offset of the child view along the major axis.
+     */
+    private float minorOffset;
+
+    /**
+     * The child views maximumSpan.
+     */
+    private float maximum;
+
+    /**
+     * Creates a new <code>ChildState</code> object for the specified child
+     * view.
+     *
+     * @param view the child view for which to create the state record
+     */
+    public ChildState(View view)
+    {
+      childView = view;
+    }
+
+    /**
+     * Returns the child view for which this <code>ChildState</code> represents
+     * the layout state.
+     *
+     * @return the child view for this child state object 
+     */
+    public View getChildView()
+    {
+      return childView;
+    }
+
+    /**
+     * Returns <code>true</code> if the current layout information is valid,
+     * <code>false</code> otherwise.
+     *
+     * @return <code>true</code> if the current layout information is valid,
+     *         <code>false</code> otherwise
+     */
+    public boolean isLayoutValid()
+    {
+      return minorValid && majorValid && childSizeValid;
+    }
+
+    /**
+     * Performs the layout update for the child view managed by this
+     * <code>ChildState</code>.
+     */
+    public void run()
+    {
+      Document doc = getDocument();
+      if (doc instanceof AbstractDocument)
+        {
+          AbstractDocument abstractDoc = (AbstractDocument) doc;
+          abstractDoc.readLock();
+        }
+
+      try
+        {
+
+          if (!(minorValid &&  majorValid && childSizeValid)
+              && childView.getParent() == AsyncBoxView.this)
+            {
+              synchronized(AsyncBoxView.this)
+              {
+                changing = this;
+              }
+              update();
+              synchronized(AsyncBoxView.this)
+              {
+                changing = null;
+              }
+              // Changing the major axis may cause the minor axis
+              // requirements to have changed, so we need to do this again.
+              update();
+            }
+        }
+      finally
+        {
+          if (doc instanceof AbstractDocument)
+            {
+              AbstractDocument abstractDoc = (AbstractDocument) doc;
+              abstractDoc.readUnlock();
+            }
+        }
+    }
+
+    /**
+     * Performs the actual update after the run methods has made its checks
+     * and locked the document.
+     */
+    private void update()
+    {
+      int majorAxis = getMajorAxis();
+      boolean minorUpdated = false;
+      synchronized (this)
+        {
+          if (! minorValid)
+            {
+              int minorAxis = getMinorAxis();
+              minimum = childView.getMinimumSpan(minorAxis);
+              preferred = childView.getPreferredSpan(minorAxis);
+              maximum = childView.getMaximumSpan(minorAxis);
+              minorValid = true;
+              minorUpdated = true;
+            }
+        }
+      if (minorUpdated)
+        minorRequirementChange(this);
+
+      boolean majorUpdated = false;
+      float delta = 0.0F;
+      synchronized (this)
+        {
+          if (! majorValid)
+            {
+              float oldSpan = majorSpan;
+              majorSpan = childView.getPreferredSpan(majorAxis);
+              delta = majorSpan - oldSpan;
+              majorValid = true;
+              majorUpdated = true;
+            }
+        }
+      if (majorUpdated)
+        {
+          majorRequirementChange(this, delta);
+          locator.childChanged(this);
+        }
+
+      synchronized (this)
+        {
+          if (! childSizeValid)
+            {
+              float w;
+              float h;
+              if (majorAxis == X_AXIS)
+                {
+                  w = majorSpan;
+                  h = getMinorSpan();
+                }
+              else
+                {
+                  w = getMinorSpan();
+                  h = majorSpan;
+                }
+              childSizeValid = true;
+              childView.setSize(w, h);
+            }
+        }
+    }
+
+    /**
+     * Returns the span of the child view along the minor layout axis.
+     *
+     * @return the span of the child view along the minor layout axis
+     */
+    public float getMinorSpan()
+    {
+      float retVal;
+      if (maximum < minorSpan)
+        retVal = maximum;
+      else
+        retVal = Math.max(minimum, minorSpan);
+      return retVal;
+    }
+
+    /**
+     * Returns the offset of the child view along the minor layout axis.
+     *
+     * @return the offset of the child view along the minor layout axis
+     */
+    public float getMinorOffset()
+    {
+      float retVal;
+      if (maximum < minorSpan)
+        {
+          float align = childView.getAlignment(getMinorAxis());
+          retVal = ((minorSpan - maximum) * align);
+        }
+      else
+        retVal = 0f;
+
+      return retVal;
+    }
+
+    /**
+     * Returns the span of the child view along the major layout axis.
+     *
+     * @return the span of the child view along the major layout axis
+     */
+
+    public float getMajorSpan()
+    {
+      return majorSpan;
+    }
+
+    /**
+     * Returns the offset of the child view along the major layout axis.
+     *
+     * @return the offset of the child view along the major layout axis
+     */
+    public float getMajorOffset()
+    {
+      return majorOffset;
+    }
+
+    /**
+     * Sets the offset of the child view along the major layout axis. This
+     * should only be called by the ChildLocator of that child view.
+     *
+     * @param offset the offset to set
+     */
+    public void setMajorOffset(float offset)
+    {
+      majorOffset = offset;
+    }
+
+    /**
+     * Mark the preferences changed for that child. This forwards to
+     * {@link AsyncBoxView#preferenceChanged}.
+     *
+     * @param width <code>true</code> if the width preference has changed
+     * @param height <code>true</code> if the height preference has changed
+     */
+    public void preferenceChanged(boolean width, boolean height)
+    {
+      if (getMajorAxis() == X_AXIS)
+        {
+          if (width)
+            majorValid = false;
+          if (height)
+            minorValid = false;
+        }
+      else
+        {
+          if (width)
+            minorValid = false;
+          if (height)
+            majorValid = false;
+        }
+      childSizeValid = false;
+    }
+  }
+
+  /**
+   * Flushes the requirements changes upwards asynchronously.
+   */
+  private class FlushTask implements Runnable
+  {
+    /**
+     * Starts the flush task. This obtains a readLock on the document
+     * and then flushes all the updates using
+     * {@link AsyncBoxView#flushRequirementChanges()} after updating the
+     * requirements.
+     */
+    public void run()
+    {
+      try
+        {
+          // Acquire a lock on the document.
+          Document doc = getDocument();
+          if (doc instanceof AbstractDocument)
+            {
+              AbstractDocument abstractDoc = (AbstractDocument) doc;
+              abstractDoc.readLock();
+            }
+
+          int n = getViewCount();
+          if (minorChanged && (n > 0))
+            {
+              LayoutQueue q = getLayoutQueue();
+              ChildState min = getChildState(0);
+              ChildState pref = getChildState(0);
+              for (int i = 1; i < n; i++)
+                {
+                  ChildState cs = getChildState(i);
+                  if (cs.minimum > min.minimum)
+                    min = cs;
+                  if (cs.preferred > pref.preferred)
+                    pref = cs;
+                }
+              synchronized (AsyncBoxView.this)
+              {
+                minReq = min;
+                prefReq = pref;
+              }
+            }
+
+          flushRequirementChanges();
+        }
+      finally
+      {
+        // Release the lock on the document.
+        Document doc = getDocument();
+        if (doc instanceof AbstractDocument)
+          {
+            AbstractDocument abstractDoc = (AbstractDocument) doc;
+            abstractDoc.readUnlock();
+          }
+      }
+    }
+
+  }
+
+  /**
+   * The major layout axis.
+   */
+  private int majorAxis;
+
+  /**
+   * The top inset.
+   */
+  private float topInset;
+
+  /**
+   * The bottom inset.
+   */
+  private float bottomInset;
+
+  /**
+   * The left inset.
+   */
+  private float leftInset;
+
+  /**
+   * Indicates if the major span should be treated as beeing estimated or not.
+   */
+  private boolean estimatedMajorSpan;
+
+  /**
+   * The right inset.
+   */
+  private float rightInset;
+
+  /**
+   * The children and their layout statistics.
+   */
+  private ArrayList childStates;
+
+  /**
+   * The currently changing child state. May be null if there is no child state
+   * updating at the moment. This is package private to avoid a synthetic
+   * accessor method inside ChildState.
+   */
+  ChildState changing;
+
+  /**
+   * Represents the minimum requirements. This is used in
+   * {@link #getMinimumSpan(int)}.
+   */
+  ChildState minReq;
+
+  /**
+   * Represents the minimum requirements. This is used in
+   * {@link #getPreferredSpan(int)}.
+   */
+  ChildState prefReq;
+
+  /**
+   * Indicates that the major axis requirements have changed.
+   */
+  private boolean majorChanged;
+
+  /**
+   * Indicates that the minor axis requirements have changed. This is package
+   * private to avoid synthetic accessor method.
+   */
+  boolean minorChanged;
+
+  /**
+   * The current span along the major layout axis. This is package private to
+   * avoid synthetic accessor method.
+   */
+  float majorSpan;
+
+  /**
+   * The current span along the minor layout axis. This is package private to
+   * avoid synthetic accessor method.
+   */
+  float minorSpan;
+
+  /**
+   * This tasked is placed on the layout queue to flush updates up to the
+   * parent view.
+   */
+  private Runnable flushTask;
+
+  /**
+   * The child locator for this view.
+   */
+  protected ChildLocator locator;
+
+  /**
+   * Creates a new <code>AsyncBoxView</code> that represents the specified
+   * element and layouts its children along the specified axis.
+   *
+   * @param elem the element
+   * @param axis the layout axis
+   */
+  public AsyncBoxView(Element elem, int axis)
+  {
+    super(elem);
+    majorAxis = axis;
+    childStates = new ArrayList();
+    flushTask = new FlushTask();
+    locator = new ChildLocator();
+    minorSpan = Short.MAX_VALUE;
+  }
+
+  /**
+   * Returns the major layout axis.
+   *
+   * @return the major layout axis
+   */
+  public int getMajorAxis()
+  {
+    return majorAxis;
+  }
+
+  /**
+   * Returns the minor layout axis, that is the axis orthogonal to the major
+   * layout axis.
+   *
+   * @return the minor layout axis
+   */
+  public int getMinorAxis()
+  {
+    return majorAxis == X_AXIS ? Y_AXIS : X_AXIS;
+  }
+
+  /**
+   * Returns the view at the specified <code>index</code>.
+   *
+   * @param index the index of the requested child view
+   *
+   * @return the view at the specified <code>index</code>
+   */
+  public View getView(int index)
+  {
+    View view = null;
+    synchronized(childStates)
+      {
+        if ((index >= 0) && (index < childStates.size()))
+          {
+            ChildState cs = (ChildState) childStates.get(index);
+            view = cs.getChildView();
+          }
+      }
+    return view;
+  }
+
+  /**
+   * Returns the number of child views.
+   *
+   * @return the number of child views
+   */
+  public int getViewCount()
+  {
+    synchronized(childStates)
+    {
+      return childStates.size();
+    }
+  }
+
+  /**
+   * Returns the view index of the child view that represents the specified
+   * model position.
+   *
+   * @param pos the model position for which we search the view index
+   * @param bias the bias
+   *
+   * @return the view index of the child view that represents the specified
+   *         model position
+   */
+  public int getViewIndex(int pos, Position.Bias bias)
+  {
+    int retVal = -1;
+
+    if (bias == Position.Bias.Backward)
+      pos = Math.max(0, pos - 1);
+
+    // TODO: A possible optimization would be to implement a binary search
+    // here.
+    int numChildren = childStates.size();
+    if (numChildren > 0)
+      {
+        for (int i = 0; i < numChildren; ++i)
+          {
+            View child = ((ChildState) childStates.get(i)).getChildView();
+            if (child.getStartOffset() <= pos && child.getEndOffset() > pos)
+              {
+                retVal = i;
+                break;
+              }
+          }
+      }
+    return retVal;
+  }
+
+  /**
+   * Returns the top inset.
+   *
+   * @return the top inset
+   */
+  public float getTopInset()
+  {
+    return topInset;
+  }
+
+  /**
+   * Sets the top inset.
+   *
+   * @param top the top inset
+   */
+  public void setTopInset(float top)
+  {
+    topInset = top;
+  }
+
+  /**
+   * Returns the bottom inset.
+   *
+   * @return the bottom inset
+   */
+  public float getBottomInset()
+  {
+    return bottomInset;
+  }
+
+  /**
+   * Sets the bottom inset.
+   *
+   * @param bottom the bottom inset
+   */
+  public void setBottomInset(float bottom)
+  {
+    bottomInset = bottom;
+  }
+
+  /**
+   * Returns the left inset.
+   *
+   * @return the left inset
+   */
+  public float getLeftInset()
+  {
+    return leftInset;
+  }
+
+  /**
+   * Sets the left inset.
+   *
+   * @param left the left inset
+   */
+  public void setLeftInset(float left)
+  {
+    leftInset = left;
+  }
+
+  /**
+   * Returns the right inset.
+   *
+   * @return the right inset
+   */
+  public float getRightInset()
+  {
+    return rightInset;
+  }
+
+  /**
+   * Sets the right inset.
+   *
+   * @param right the right inset
+   */
+  public void setRightInset(float right)
+  {
+    rightInset = right;
+  }
+
+  /**
+   * Loads the child views of this view. This is triggered by
+   * {@link #setParent(View)}.
+   *
+   * @param f the view factory to build child views with
+   */
+  protected void loadChildren(ViewFactory f)
+  {
+    Element e = getElement();
+    int n = e.getElementCount();
+    if (n > 0)
+      {
+        View[] added = new View[n];
+        for (int i = 0; i < n; i++)
+          {
+            added[i] = f.create(e.getElement(i));
+          }
+        replace(0, 0, added);
+      }
+  }
+  
+  /**
+   * Returns the span along an axis that is taken up by the insets.
+   *
+   * @param axis the axis
+   *
+   * @return the span along an axis that is taken up by the insets
+   *
+   * @since 1.4
+   */
+  protected float getInsetSpan(int axis)
+  {
+    float span;
+    if (axis == X_AXIS)
+      span = leftInset + rightInset;
+    else
+      span = topInset + bottomInset;
+    return span;
+  }
+
+  /**
+   * Sets the <code>estimatedMajorSpan</code> property that determines if
+   * the major span should be treated as beeing estimated.
+   *
+   * @param estimated if the major span should be treated as estimated or not
+   *
+   * @since 1.4
+   */
+  protected void setEstimatedMajorSpan(boolean estimated)
+  {
+    estimatedMajorSpan = estimated;
+  }
+
+  /**
+   * Determines whether the major span should be treated as estimated or as
+   * beeing accurate.
+   *
+   * @return <code>true</code> if the major span should be treated as
+   *         estimated, <code>false</code> if the major span should be treated
+   *         as accurate
+   *
+   * @since 1.4
+   */
+  protected boolean getEstimatedMajorSpan()
+  {
+    return estimatedMajorSpan;
+  }
+
+  /**
+   * Receives notification from the child states that the requirements along
+   * the minor axis have changed.
+   *
+   * @param cs the child state from which this notification is messaged
+   */
+  protected synchronized void minorRequirementChange(ChildState cs)
+  {
+    minorChanged = true;
+  }
+
+  /**
+   * Receives notification from the child states that the requirements along
+   * the major axis have changed.
+   *
+   * @param cs the child state from which this notification is messaged
+   */
+  protected void majorRequirementChange(ChildState cs, float delta)
+  {
+    if (! estimatedMajorSpan)
+      majorSpan += delta;
+    majorChanged = true;
+  }
+
+  /**
+   * Sets the parent for this view. This calls loadChildren if
+   * <code>parent</code> is not <code>null</code> and there have not been any
+   * child views initializes.
+   *
+   * @param parent the new parent view; <code>null</code> if this view is
+   *        removed from the view hierarchy
+   *
+   * @see View#setParent(View)
+   */
+  public void setParent(View parent)
+  {
+    super.setParent(parent);
+    if ((parent != null) && (getViewCount() == 0))
+      {
+        ViewFactory f = getViewFactory();
+        loadChildren(f);
+      }
+  }
+
+  /**
+   * Sets the size of this view. This is ususally called before {@link #paint}
+   * is called to make sure the view has a valid layout.
+   *
+   * This implementation queues layout requests for every child view if the
+   * minor axis span has changed. (The major axis span is requested to never
+   * change for this view).
+   *
+   * @param width the width of the view
+   * @param height the height of the view
+   */
+  public void setSize(float width, float height)
+  {
+    float targetSpan;
+    if (majorAxis == X_AXIS)
+      targetSpan = height - getTopInset() - getBottomInset();
+    else
+      targetSpan = width - getLeftInset() - getRightInset();
+
+    if (targetSpan != minorSpan)
+      {
+        minorSpan = targetSpan;
+
+        int n = getViewCount();
+        LayoutQueue q = getLayoutQueue();
+        for (int i = 0; i < n; i++)
+          {
+            ChildState cs = getChildState(i);
+            cs.childSizeValid = false;
+            q.addTask(cs);
+          }
+        q.addTask(flushTask);
+    }
+  }
+
+  /**
+   * Replaces child views with new child views.
+   *
+   * This creates ChildState objects for all the new views and adds layout
+   * requests for them to the layout queue.
+   *
+   * @param offset the offset at which to remove/insert
+   * @param length the number of child views to remove
+   * @param views the new child views to insert
+   */
+  public void replace(int offset, int length, View[] views)
+  {
+    synchronized(childStates)
+      {
+        LayoutQueue q = getLayoutQueue();
+        for (int i = 0; i < length; i++)
+          childStates.remove(offset);
+
+        for (int i = views.length - 1; i >= 0; i--)
+          childStates.add(offset, createChildState(views[i]));
+
+        // We need to go through the new child states _after_ they have been
+        // added to the childStates list, otherwise the layout tasks may find
+        // an incomplete child list. That means we have to loop through
+        // them again, but what else can we do?
+        if (views.length != 0)
+          {
+            for (int i = 0; i < views.length; i++)
+              {
+                ChildState cs = (ChildState) childStates.get(i + offset);
+                cs.getChildView().setParent(this);
+                q.addTask(cs);
+              }
+            q.addTask(flushTask);
+          }
+      }
+  }
+
+  /**
+   * Paints the view. This requests the {@link ChildLocator} to paint the views
+   * after setting the allocation on it.
+   *
+   * @param g the graphics context to use
+   * @param s the allocation for this view
+   */
+  public void paint(Graphics g, Shape s)
+  {
+    synchronized (locator)
+      {
+        locator.setAllocation(s);
+        locator.paintChildren(g);
+      }
+  }
+
+  /**
+   * Returns the preferred span of this view along the specified layout axis.
+   *
+   * @return the preferred span of this view along the specified layout axis
+   */
+  public float getPreferredSpan(int axis)
+  {
+    float retVal;
+    if (majorAxis == axis)
+      retVal = majorSpan;
+
+    else if (prefReq != null)
+      {
+        View child = prefReq.getChildView();
+        retVal = child.getPreferredSpan(axis);
+      }
+
+    // If we have no layout information yet, then return insets + 30 as
+    // an estimation.
+    else
+      {
+        if (axis == X_AXIS)
+          retVal = getLeftInset() + getRightInset() + 30;
+        else
+          retVal = getTopInset() + getBottomInset() + 30;
+      }
+    return retVal;
+  }
+
+  /**
+   * Maps a model location to view coordinates.
+   *
+   * @param pos the model location
+   * @param a the current allocation of this view
+   * @param b the bias
+   *
+   * @return the view allocation for the specified model location
+   */
+  public Shape modelToView(int pos, Shape a, Bias b)
+    throws BadLocationException
+  {
+    int index = getViewIndexAtPosition(pos, b);
+    Shape ca = locator.getChildAllocation(index, a);
+
+    ChildState cs = getChildState(index);
+    synchronized (cs)
+      {
+        View cv = cs.getChildView();
+        Shape v = cv.modelToView(pos, ca, b);
+        return v;
+      }
+  }
+
+  /**
+   * Maps view coordinates to a model location.
+   *
+   * @param x the x coordinate (relative to <code>a</code>)
+   * @param y the y coordinate (relative to <code>a</code>)
+   * @param b holds the bias of the model location on method exit
+   *
+   * @return the model location for the specified view location
+   */
+  public int viewToModel(float x, float y, Shape a, Bias[] b)
+  {
+    int pos;
+    int index;
+    Shape ca;
+
+    synchronized (locator)
+      {
+        index = locator.getViewIndexAtPoint(x, y, a);
+        ca = locator.getChildAllocation(index, a);
+      }
+
+    ChildState cs = getChildState(index);
+    synchronized (cs)
+      {
+        View v = cs.getChildView();
+        pos = v.viewToModel(x, y, ca, b);
+      }
+    return pos;
+  }
+
+  /**
+   * Returns the child allocation for the child view with the specified
+   * <code>index</code>.
+   *
+   * @param index the index of the child view
+   * @param a the current allocation of this view
+   *
+   * @return the allocation of the child view
+   */
+  public Shape getChildAllocation(int index, Shape a)
+  {
+    Shape ca = locator.getChildAllocation(index, a);
+    return ca;
+  }
+
+  /**
+   * Returns the maximum span of this view along the specified axis.
+   * This is implemented to return the <code>preferredSpan</code> for the
+   * major axis (that means the box can't be resized along the major axis) and
+   * {@link Short#MAX_VALUE} for the minor axis.
+   *
+   * @param axis the axis
+   *
+   * @return the maximum span of this view along the specified axis
+   */
+  public float getMaximumSpan(int axis)
+  {
+    float max;
+    if (axis == majorAxis)
+      max = getPreferredSpan(axis);
+    else
+      max = Short.MAX_VALUE;
+    return max;
+  }
+
+  /**
+   * Returns the minimum span along the specified axis.
+   */
+  public float getMinimumSpan(int axis)
+  {
+    float min;
+    if (axis == majorAxis)
+      min = getPreferredSpan(axis);
+    else
+      {
+        if (minReq != null)
+          {
+            View child = minReq.getChildView();
+            min = child.getMinimumSpan(axis);
+          }
+        else
+          {
+            // No layout information yet. Return insets + 5 as some kind of
+            // estimation.
+            if (axis == X_AXIS)
+              min = getLeftInset() + getRightInset() + 5;
+            else
+              min = getTopInset() + getBottomInset() + 5;
+          }
+      }
+    return min;
+  }
+
+  /**
+   * Receives notification that one of the child views has changed its
+   * layout preferences along one or both axis.
+   *
+   * This queues a layout request for that child view if necessary.
+   *
+   * @param view the view that has changed its preferences
+   * @param width <code>true</code> if the width preference has changed
+   * @param height <code>true</code> if the height preference has changed
+   */
+  public synchronized void preferenceChanged(View view, boolean width,
+                                             boolean height)
+  {
+    if (view == null)
+      getParent().preferenceChanged(this, width, height);
+    else
+      {
+        if (changing != null)
+          {
+            View cv = changing.getChildView();
+            if (cv == view)
+              {
+                changing.preferenceChanged(width, height);
+                return;
+              }
+          }
+        int index = getViewIndexAtPosition(view.getStartOffset(), 
+                                           Position.Bias.Forward);
+        ChildState cs = getChildState(index);
+        cs.preferenceChanged(width, height);
+        LayoutQueue q = getLayoutQueue();
+        q.addTask(cs);
+        q.addTask(flushTask);
+      }    
+  }
+
+  /**
+   * Updates the layout for this view. This is implemented to trigger
+   * {@link ChildLocator#childChanged} for the changed view, if there is
+   * any.
+   *
+   * @param ec the element change, may be <code>null</code> if there were
+   *        no changes to the element of this view
+   * @param e the document event
+   * @param a the current allocation of this view
+   */
+  protected void updateLayout(DocumentEvent.ElementChange ec, 
+                              DocumentEvent e, Shape a)
+  {
+    if (ec != null)
+      {
+        int index = Math.max(ec.getIndex() - 1, 0);
+        ChildState cs = getChildState(index);
+        locator.childChanged(cs);
+      }
+  }
+  
+  
+  /**
+   * Returns the <code>ChildState</code> object associated with the child view
+   * at the specified <code>index</code>.
+   *
+   * @param index the index of the child view for which to query the state
+   *
+   * @return the child state for the specified child view
+   */
+  protected ChildState getChildState(int index) {
+    synchronized (childStates)
+      {
+        return (ChildState) childStates.get(index);
+      }
+  }
+
+  /**
+   * Returns the <code>LayoutQueue</code> used for layouting the box view.
+   * This simply returns {@link LayoutQueue#getDefaultQueue()}.
+   *
+   * @return the <code>LayoutQueue</code> used for layouting the box view
+   */
+  protected LayoutQueue getLayoutQueue()
+  {
+    return LayoutQueue.getDefaultQueue();
+  }
+
+  /**
+   * Returns the child view index of the view that represents the specified
+   * position in the document model.
+   * 
+   * @param pos the position in the model
+   * @param b the bias
+   *
+   * @return the child view index of the view that represents the specified
+   *         position in the document model
+   */
+  protected synchronized int getViewIndexAtPosition(int pos, Position.Bias b)
+  {
+    if (b == Position.Bias.Backward)
+      pos = Math.max(0, pos - 1);
+    Element elem = getElement();
+    return elem.getElementIndex(pos);
+  }
+
+  /**
+   * Creates a <code>ChildState</code> object for the specified view.
+   *
+   * @param v the view for which to create a child state object
+   *
+   * @return the created child state
+   */
+  protected ChildState createChildState(View v)
+  {
+    return new ChildState(v);
+  }
+
+  /**
+   * Flushes the requirements changes upwards to the parent view. This is
+   * called from the layout thread.
+   */
+  protected synchronized void flushRequirementChanges()
+  {
+    if (majorChanged || minorChanged)
+      {
+        View p = getParent();
+        if (p != null)
+          {
+            boolean horizontal;
+            boolean vertical;
+            if (majorAxis == X_AXIS)
+              {
+                horizontal = majorChanged;
+                vertical = minorChanged;
+              }
+            else
+              {
+                vertical = majorChanged;
+                horizontal = minorChanged;
+              }
+
+            p.preferenceChanged(this, horizontal, vertical);
+            majorChanged = false;
+            minorChanged = false;
+
+            Component c = getContainer();
+            if (c != null)
+              c.repaint();
+          }
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,195 @@
+/* AttributeSet.java -- 
+   Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.util.Enumeration;
+
+/**
+ * A set of attributes. An attribute has a key and a value. They typically
+ * describe features of a piece of text that make up its graphical
+ * representation.
+ *
+ * An <code>AttributeSet</code> may have a resolving parent,
+ * that is another <code>AttributeSet</code> that is searched for attribute
+ * keys that are not stored locally in this <code>AttributeSet</code>.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public interface AttributeSet
+{ 
+  /**
+   * Used as keys to identify character-run attributes.
+   */
+  static interface CharacterAttribute
+  {
+    // This interface is a marker interface and has no methods.
+  }
+
+  /**
+   * Used as keys to identify color attributes.
+   */
+  static interface ColorAttribute
+  {
+    // This interface is a marker interface and has no methods.
+  }
+
+  /**
+   * Used as keys to identify font attributes.
+   */
+  static interface FontAttribute
+  {
+    // This interface is a marker interface and has no methods.
+  }
+
+  /**
+   * Used as keys to identify paragraph level attributes.
+   */
+  static interface ParagraphAttribute
+  {
+    // This interface is a marker interface and has no methods.
+  }
+
+  /**
+   * Key of the attribute that is used to describe the name of an
+   * <code>AttributeSet</code>.
+   */
+  Object NameAttribute = StyleConstants.NameAttribute;
+
+  /**
+   * Key of the attribute that is used to identify the resolving parent of
+   * an <code>AttributeSet</code>.
+   */
+  Object ResolveAttribute = StyleConstants.ResolveAttribute;
+
+  /**
+   * Returns <code>true</code> if this <code>AttributeSet</code> contains
+   * an attribute with the specified <code>name</code> and <code>value</code>,
+   * <code>false</code> otherwise.
+   *
+   * @param name the name of the requested attribute
+   * @param value the value of the requested attribute
+   *
+   * @return <code>true</code> if this <code>AttributeSet</code> contains
+   *         an attribute with the specified <code>name</code> and
+   *         <code>value</code>, <code>false</code> otherwise
+   */
+  boolean containsAttribute(Object name, Object value);
+
+  /**
+   * Returns <code>true</code> of this <code>AttributeSet</code> contains all
+   * of the specified <code>attributes</code>.
+   *
+   * @param attributes the requested attributes
+   *
+   * @return <code>true</code> of this <code>AttributeSet</code> contains all
+   *         of the specified <code>attributes</code>
+   */
+  boolean containsAttributes(AttributeSet attributes);
+
+  /**
+   * Creates and returns a copy of this <code>AttributeSet</code>.
+   *
+   * @return a copy of this <code>AttributeSet</code>
+   */
+  AttributeSet copyAttributes();
+
+  /**
+   * Returns the attribute with the specified <code>key</code> or
+   * <code>null</code> if no such attribute is defined in this
+   * <code>AttributeSet</code> and its resolving parents.
+   *
+   * @param key the key of the attribute that is looked up
+   *
+   * @return the attribute with the specified <code>key</code> or
+   *         <code>null</code> if no such attribute is defined in this
+   *         <code>AttributeSet</code> and its resolving parents
+   */
+  Object getAttribute(Object key);
+
+  /**
+   * Returns the number of attributes that are stored locally in this
+   * <code>AttributeSet</code>.
+   *
+   * @return the number of attributes that are stored locally in this
+   * <code>AttributeSet</code>
+   */
+  int getAttributeCount();
+
+  /**
+   * Returns the names of the attributes that are stored in this
+   * <code>AttributeSet</code>.
+   *
+   * @return the names of the attributes that are stored in this
+   *         <code>AttributeSet</code>
+   */
+  Enumeration getAttributeNames();
+
+  /**
+   * Returns the resolving parent of this <code>AttributeSet</code>.
+   * If a key is not stored locally, then a {@link #getAttribute(Object)}
+   * request is resolved up in the resolving parent of this
+   * <code>AttributeSet</code>.
+   *
+   * @return the resolving parent of this <code>AttributeSet</code>
+   */
+  AttributeSet getResolveParent();
+
+  /**
+   * Returns <code>true</code> if an attribute with the specified name is
+   * defined locally in this <code>AttributeSet</code>, without resolving
+   * through the resolving parents.
+   *
+   * @return <code>true</code> if an attribute with the specified name is
+   *          defined locally in this <code>AttributeSet</code>
+   */
+  boolean isDefined(Object attrName);
+
+  /**
+   * Returns <code>true</code> if all of the attributes in <code>attr</code>
+   * are equal to the attributes in this <code>AttributeSet</code>,
+   * <code>false</code> otherwise.
+   *
+   * @param attr the attributes to be compared to <code>this</code>
+   *
+   * @return <code>true</code> if all of the attributes in <code>attr</code>
+   *         are equal to the attributes in this <code>AttributeSet</code>,
+   *         <code>false</code> otherwise
+   */
+  boolean isEqual(AttributeSet attr);     
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,78 @@
+/* BadLocationException.java --
+   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+/**
+ * Indicates that an invalid location within a <code>Document</code> has been
+ * accessed.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class BadLocationException extends Exception
+{
+  /** The serial version UID for BadLocationException. */
+  private static final long serialVersionUID = -7712259886815656766L;
+
+  /**
+   * The invalid location.
+   */
+  int offset;
+
+  /**
+   * Constructs a <code>BadLocationException</code>
+   *
+   * @param str a string indicating what was wrong with the arguments
+   * @param offset offset within the document that was requested >= 0
+   */
+  public BadLocationException(String str, int offset)
+  {
+    super(str);
+    this.offset = offset;
+  }
+
+  /**
+   * Returns the offset into the document that was not legal.
+   *
+   * @return the offset into the document that was not legal
+   */
+  public int offsetRequested()
+  {
+    return offset;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1038 @@
+/* BoxView.java -- An composite view
+   Copyright (C) 2005, 2006  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SizeRequirements;
+import javax.swing.event.DocumentEvent;
+
+/**
+ * An implementation of {@link CompositeView} that arranges its children in
+ * a box along one axis. This is comparable to how the <code>BoxLayout</code>
+ * works, but for <code>View</code> children.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class BoxView
+  extends CompositeView
+{
+
+  /**
+   * The axis along which this <code>BoxView</code> is laid out.
+   */
+  private int myAxis;
+
+  /**
+   * Indicates if the layout is valid along X_AXIS or Y_AXIS.
+   */
+  private boolean[] layoutValid = new boolean[2];
+
+  /**
+   * Indicates if the requirements for an axis are valid.
+   */
+  private boolean[] requirementsValid = new boolean[2];
+
+  /**
+   * The spans along the X_AXIS and Y_AXIS.
+   */
+  private int[][] spans = new int[2][];
+
+  /**
+   * The offsets of the children along the X_AXIS and Y_AXIS.
+   */
+  private int[][] offsets = new int[2][];
+
+  /**
+   * The size requirements along the X_AXIS and Y_AXIS.
+   */
+  private SizeRequirements[] requirements = new SizeRequirements[2];
+
+  /**
+   * The current span along X_AXIS or Y_AXIS.
+   */
+  private int[] span = new int[2];
+
+  /**
+   * The SizeRequirements of the child views along the X_AXIS and Y_AXIS.
+   */
+  private SizeRequirements[][] childReqs = new SizeRequirements[2][];
+
+  /**
+   * Creates a new <code>BoxView</code> for the given
+   * <code>Element</code> and axis. Valid values for the axis are
+   * {@link View#X_AXIS} and {@link View#Y_AXIS}.
+   *
+   * @param element the element that is rendered by this BoxView
+   * @param axis the axis along which the box is laid out
+   */
+  public BoxView(Element element, int axis)
+  {
+    super(element);
+    myAxis = axis;
+    layoutValid[0] = false;
+    layoutValid[1] = false;
+    span[0] = 0;
+    span[1] = 0;
+    requirements[0] = new SizeRequirements();
+    requirements[1] = new SizeRequirements();
+
+    // Initialize the cache arrays.
+    spans[0] = new int[0];
+    spans[1] = new int[0];
+    offsets[0] = new int[0];
+    offsets[1] = new int[0];
+  }
+
+  /**
+   * Returns the axis along which this <code>BoxView</code> is laid out.
+   *
+   * @return the axis along which this <code>BoxView</code> is laid out
+   *
+   * @since 1.3
+   */
+  public int getAxis()
+  {
+    return myAxis;
+  }
+
+  /**
+   * Sets the axis along which this <code>BoxView</code> is laid out.
+   *
+   * Valid values for the axis are {@link View#X_AXIS} and
+   * {@link View#Y_AXIS}.
+   *
+   * @param axis the axis along which this <code>BoxView</code> is laid out
+   *
+   * @since 1.3
+   */
+  public void setAxis(int axis)
+  {
+    myAxis = axis;
+  }
+
+  /**
+   * Marks the layout along the specified axis as invalid. This is triggered
+   * automatically when any of the child view changes its preferences
+   * via {@link #preferenceChanged(View, boolean, boolean)}.
+   *
+   * The layout will be updated the next time when 
+   * {@link #setSize(float, float)} is called, typically from within the 
+   * {@link #paint(Graphics, Shape)} method.
+   *
+   * Valid values for the axis are {@link View#X_AXIS} and
+   * {@link View#Y_AXIS}.
+   *
+   * @param axis an <code>int</code> value
+   *
+   * @since 1.3
+   */
+  public void layoutChanged(int axis)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException("Invalid axis parameter.");
+    layoutValid[axis] = false;
+  }
+
+  /**
+   * Returns <code>true</code> if the layout along the specified
+   * <code>axis</code> is valid, <code>false</code> otherwise.
+   *
+   * Valid values for the axis are {@link View#X_AXIS} and
+   * {@link View#Y_AXIS}.
+   *
+   * @param axis the axis
+   *
+   * @return <code>true</code> if the layout along the specified
+   *         <code>axis</code> is valid, <code>false</code> otherwise
+   *
+   * @since 1.4
+   */
+  protected boolean isLayoutValid(int axis)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException("Invalid axis parameter.");
+    return layoutValid[axis];
+  }
+
+  /**
+   * Paints the child <code>View</code> at the specified <code>index</code>.
+   * This method modifies the actual values in <code>alloc</code> so make
+   * sure you have a copy of the original values if you need them.
+   *
+   * @param g the <code>Graphics</code> context to paint to
+   * @param alloc the allocated region for the child to paint into
+   * @param index the index of the child to be painted
+   *
+   * @see #childAllocation(int, Rectangle)
+   */
+  protected void paintChild(Graphics g, Rectangle alloc, int index)
+  {
+    View child = getView(index);
+    child.paint(g, alloc);
+  }
+
+  /**
+   * Replaces child views by some other child views. If there are no views to
+   * remove (<code>length == 0</code>), the result is a simple insert, if
+   * there are no children to add (<code>view == null</code>) the result
+   * is a simple removal.
+   *
+   * In addition this invalidates the layout and resizes the internal cache
+   * for the child allocations. The old children's cached allocations can
+   * still be accessed (although they are not guaranteed to be valid), and
+   * the new children will have an initial offset and span of 0.
+   *
+   * @param offset the start offset from where to remove children
+   * @param length the number of children to remove
+   * @param views the views that replace the removed children
+   */
+  public void replace(int offset, int length, View[] views)
+  {
+    int numViews = 0;
+    if (views != null)
+      numViews = views.length;
+
+    // Resize and copy data for cache arrays.
+    // The spansX cache.
+    int oldSize = getViewCount();
+
+    int[] newSpansX = new int[oldSize - length + numViews];
+    System.arraycopy(spans[X_AXIS], 0, newSpansX, 0, offset);
+    System.arraycopy(spans[X_AXIS], offset + length, newSpansX,
+                     offset + numViews,
+                     oldSize - (offset + length));
+    spans[X_AXIS] = newSpansX;
+
+    // The spansY cache.
+    int[] newSpansY = new int[oldSize - length + numViews];
+    System.arraycopy(spans[Y_AXIS], 0, newSpansY, 0, offset);
+    System.arraycopy(spans[Y_AXIS], offset + length, newSpansY,
+                     offset + numViews,
+                     oldSize - (offset + length));
+    spans[Y_AXIS] = newSpansY;
+
+    // The offsetsX cache.
+    int[] newOffsetsX = new int[oldSize - length + numViews];
+    System.arraycopy(offsets[X_AXIS], 0, newOffsetsX, 0, offset);
+    System.arraycopy(offsets[X_AXIS], offset + length, newOffsetsX,
+                     offset + numViews,
+                     oldSize - (offset + length));
+    offsets[X_AXIS] = newOffsetsX;
+
+    // The offsetsY cache.
+    int[] newOffsetsY = new int[oldSize - length + numViews];
+    System.arraycopy(offsets[Y_AXIS], 0, newOffsetsY, 0, offset);
+    System.arraycopy(offsets[Y_AXIS], offset + length, newOffsetsY,
+                     offset + numViews,
+                     oldSize - (offset + length));
+    offsets[Y_AXIS] = newOffsetsY;
+
+    // Actually perform the replace.
+    super.replace(offset, length, views);
+
+    // Invalidate layout information.
+    layoutValid[X_AXIS] = false;
+    requirementsValid[X_AXIS] = false;
+    layoutValid[Y_AXIS] = false;
+    requirementsValid[Y_AXIS] = false;
+  }
+
+  /**
+   * Renders the <code>Element</code> that is associated with this
+   * <code>View</code>.
+   *
+   * @param g the <code>Graphics</code> context to render to
+   * @param a the allocated region for the <code>Element</code>
+   */
+  public void paint(Graphics g, Shape a)
+  {
+    Rectangle alloc;
+    if (a instanceof Rectangle)
+      alloc = (Rectangle) a;
+    else
+      alloc = a.getBounds();
+
+    int x = alloc.x + getLeftInset();
+    int y = alloc.y + getTopInset();
+
+    Rectangle clip = g.getClipBounds();
+    Rectangle tmp = new Rectangle();
+    int count = getViewCount();
+    for (int i = 0; i < count; ++i)
+      {
+        tmp.x = x + getOffset(X_AXIS, i);
+        tmp.y = y + getOffset(Y_AXIS, i);
+        tmp.width = getSpan(X_AXIS, i);
+        tmp.height = getSpan(Y_AXIS, i);
+        if (tmp.intersects(clip))
+          paintChild(g, tmp, i);
+      }
+  }
+
+  /**
+   * Returns the preferred span of the content managed by this
+   * <code>View</code> along the specified <code>axis</code>.
+   *
+   * @param axis the axis
+   *
+   * @return the preferred span of this <code>View</code>.
+   */
+  public float getPreferredSpan(int axis)
+  {
+    updateRequirements(axis);
+    // Add margin.
+    float margin;
+    if (axis == X_AXIS)
+      margin = getLeftInset() + getRightInset();
+    else
+      margin = getTopInset() + getBottomInset();
+    return requirements[axis].preferred + margin;
+  }
+
+  /**
+   * Returns the maximum span of this view along the specified axis.
+   * This returns <code>Integer.MAX_VALUE</code> for the minor axis
+   * and the preferred span for the major axis.
+   *
+   * @param axis the axis
+   *
+   * @return the maximum span of this view along the specified axis
+   */
+  public float getMaximumSpan(int axis)
+  {
+    updateRequirements(axis);
+    // Add margin.
+    float margin;
+    if (axis == X_AXIS)
+      margin = getLeftInset() + getRightInset();
+    else
+      margin = getTopInset() + getBottomInset();
+    return requirements[axis].maximum + margin;
+  }
+
+  /**
+   * Returns the minimum span of this view along the specified axis.
+   * This calculates the minimum span using
+   * {@link #calculateMajorAxisRequirements} or
+   * {@link #calculateMinorAxisRequirements} (depending on the axis) and
+   * returns the resulting minimum span.
+   *
+   * @param axis the axis
+   *
+   * @return the minimum span of this view along the specified axis
+   */
+  public float getMinimumSpan(int axis)
+  {
+    updateRequirements(axis);
+    // Add margin.
+    float margin;
+    if (axis == X_AXIS)
+      margin = getLeftInset() + getRightInset();
+    else
+      margin = getTopInset() + getBottomInset();
+    return requirements[axis].minimum + margin;
+  }
+
+  /**
+   * This method is obsolete and no longer in use. It is replaced by
+   * {@link #calculateMajorAxisRequirements(int, SizeRequirements)} and
+   * {@link #calculateMinorAxisRequirements(int, SizeRequirements)}.
+   *
+   * @param axis the axis that is examined
+   * @param sr the <code>SizeRequirements</code> object to hold the result,
+   *        if <code>null</code>, a new one is created
+   *
+   * @return the size requirements for this <code>BoxView</code> along
+   *         the specified axis
+   */
+  protected SizeRequirements baselineRequirements(int axis,
+                                                  SizeRequirements sr)
+  {
+    updateChildRequirements(axis);
+
+    SizeRequirements res = sr;
+    if (res == null)
+      res = new SizeRequirements();
+
+    float minLeft = 0;
+    float minRight = 0;
+    float prefLeft = 0;
+    float prefRight = 0;
+    float maxLeft = 0;
+    float maxRight = 0;
+    for (int i = 0; i < childReqs[axis].length; i++)
+      {
+        float myMinLeft = childReqs[axis][i].minimum * childReqs[axis][i].alignment;
+        float myMinRight = childReqs[axis][i].minimum - myMinLeft;
+        minLeft = Math.max(myMinLeft, minLeft);
+        minRight = Math.max(myMinRight, minRight);
+        float myPrefLeft = childReqs[axis][i].preferred * childReqs[axis][i].alignment;
+        float myPrefRight = childReqs[axis][i].preferred - myPrefLeft;
+        prefLeft = Math.max(myPrefLeft, prefLeft);
+        prefRight = Math.max(myPrefRight, prefRight);
+        float myMaxLeft = childReqs[axis][i].maximum * childReqs[axis][i].alignment;
+        float myMaxRight = childReqs[axis][i].maximum - myMaxLeft;
+        maxLeft = Math.max(myMaxLeft, maxLeft);
+        maxRight = Math.max(myMaxRight, maxRight);
+      }
+    int minSize = (int) (minLeft + minRight);
+    int prefSize = (int) (prefLeft + prefRight);
+    int maxSize = (int) (maxLeft + maxRight);
+    float align = prefLeft / (prefRight + prefLeft);
+    if (Float.isNaN(align))
+      align = 0;
+
+    res.alignment = align;
+    res.maximum = maxSize;
+    res.preferred = prefSize;
+    res.minimum = minSize;
+    return res;
+  }
+
+  /**
+   * Calculates the layout of the children of this <code>BoxView</code> along
+   * the specified axis.
+   *
+   * @param span the target span
+   * @param axis the axis that is examined
+   * @param offsets an empty array, filled with the offsets of the children
+   * @param spans an empty array, filled with the spans of the children
+   */
+  protected void baselineLayout(int span, int axis, int[] offsets,
+                                int[] spans)
+  {
+    updateChildRequirements(axis);
+    updateRequirements(axis);
+
+    // Calculate the spans and offsets using the SizeRequirements uility
+    // methods.
+    SizeRequirements.calculateAlignedPositions(span, requirements[axis],
+                                               childReqs[axis], offsets, spans);
+  }
+
+  /**
+   * Calculates the size requirements of this <code>BoxView</code> along
+   * its major axis, that is the axis specified in the constructor.
+   *
+   * @param axis the axis that is examined
+   * @param sr the <code>SizeRequirements</code> object to hold the result,
+   *        if <code>null</code>, a new one is created
+   *
+   * @return the size requirements for this <code>BoxView</code> along
+   *         the specified axis
+   */
+  protected SizeRequirements calculateMajorAxisRequirements(int axis,
+                                                           SizeRequirements sr)
+  {
+    SizeRequirements res = sr;
+    if (res == null)
+      res = new SizeRequirements();
+
+    float min = 0;
+    float pref = 0;
+    float max = 0;
+
+    int n = getViewCount();
+    for (int i = 0; i < n; i++)
+      {
+        View child = getView(i);
+        min += child.getMinimumSpan(axis);
+        pref = child.getPreferredSpan(axis);
+        max = child.getMaximumSpan(axis);
+      }
+
+    res.minimum = (int) min;
+    res.preferred = (int) pref;
+    res.maximum = (int) max;
+    res.alignment = 0.5F;
+
+    return res;
+  }
+
+  /**
+   * Calculates the size requirements of this <code>BoxView</code> along
+   * its minor axis, that is the axis opposite to the axis specified in the
+   * constructor.
+   *
+   * @param axis the axis that is examined
+   * @param sr the <code>SizeRequirements</code> object to hold the result,
+   *        if <code>null</code>, a new one is created
+   *
+   * @return the size requirements for this <code>BoxView</code> along
+   *         the specified axis
+   */
+  protected SizeRequirements calculateMinorAxisRequirements(int axis,
+                                                            SizeRequirements sr)
+  {
+    SizeRequirements res = sr;
+    if (res == null)
+      res = new SizeRequirements();
+
+    res.minimum = 0;
+    res.preferred = 0;
+    res.maximum = 0;
+    res.alignment = 0.5F;
+    int n = getViewCount();
+    for (int i = 0; i < n; i++)
+      {
+        View child = getView(i);
+        res.minimum = Math.max((int) child.getMinimumSpan(axis), res.minimum);
+        res.preferred = Math.max((int) child.getPreferredSpan(axis),
+                                 res.preferred);
+        res.maximum = Math.max((int) child.getMaximumSpan(axis), res.maximum);
+      }
+
+    return res;
+  }
+  
+
+  /**
+   * Returns <code>true</code> if the specified point lies before the
+   * given <code>Rectangle</code>, <code>false</code> otherwise.
+   *
+   * "Before" is typically defined as being to the left or above.
+   *
+   * @param x the X coordinate of the point
+   * @param y the Y coordinate of the point
+   * @param r the rectangle to test the point against
+   *
+   * @return <code>true</code> if the specified point lies before the
+   *         given <code>Rectangle</code>, <code>false</code> otherwise
+   */
+  protected boolean isBefore(int x, int y, Rectangle r)
+  {
+    boolean result = false;
+
+    if (myAxis == X_AXIS)
+      result = x < r.x;
+    else
+      result = y < r.y;
+
+    return result;
+  }
+
+  /**
+   * Returns <code>true</code> if the specified point lies after the
+   * given <code>Rectangle</code>, <code>false</code> otherwise.
+   *
+   * "After" is typically defined as being to the right or below.
+   *
+   * @param x the X coordinate of the point
+   * @param y the Y coordinate of the point
+   * @param r the rectangle to test the point against
+   *
+   * @return <code>true</code> if the specified point lies after the
+   *         given <code>Rectangle</code>, <code>false</code> otherwise
+   */
+  protected boolean isAfter(int x, int y, Rectangle r)
+  {
+    boolean result = false;
+
+    if (myAxis == X_AXIS)
+      result = x > r.x;
+    else
+      result = y > r.y;
+
+    return result;
+  }
+
+  /**
+   * Returns the child <code>View</code> at the specified location.
+   *
+   * @param x the X coordinate
+   * @param y the Y coordinate
+   * @param r the inner allocation of this <code>BoxView</code> on entry,
+   *        the allocation of the found child on exit
+   *
+   * @return the child <code>View</code> at the specified location
+   */
+  protected View getViewAtPoint(int x, int y, Rectangle r)
+  {
+    View result = null;
+    int count = getViewCount();
+    Rectangle copy = new Rectangle(r);
+
+    for (int i = 0; i < count; ++i)
+      {
+        copy.setBounds(r);
+        // The next call modifies copy.
+        childAllocation(i, copy);
+        if (copy.contains(x, y))
+          {
+            // Modify r on success.
+            r.setBounds(copy);
+            result = getView(i);
+            break;
+          }
+      }
+    
+    if (result == null && count > 0)
+      return getView(count - 1);
+    return result;
+  }
+
+  /**
+   * Computes the allocation for a child <code>View</code>. The parameter
+   * <code>a</code> stores the allocation of this <code>CompositeView</code>
+   * and is then adjusted to hold the allocation of the child view.
+   * 
+   * @param index
+   *          the index of the child <code>View</code>
+   * @param a
+   *          the allocation of this <code>CompositeView</code> before the
+   *          call, the allocation of the child on exit
+   */
+  protected void childAllocation(int index, Rectangle a)
+  {
+    if (! isAllocationValid())
+      layout(a.width, a.height);
+
+    a.x += offsets[X_AXIS][index];
+    a.y += offsets[Y_AXIS][index];
+    a.width = spans[X_AXIS][index];
+    a.height = spans[Y_AXIS][index];
+  }
+
+  /**
+   * Lays out the children of this <code>BoxView</code> with the specified
+   * bounds.
+   *
+   * @param width the width of the allocated region for the children (that
+   *        is the inner allocation of this <code>BoxView</code>
+   * @param height the height of the allocated region for the children (that
+   *        is the inner allocation of this <code>BoxView</code>
+   */
+  protected void layout(int width, int height)
+  {
+    int[] newSpan = new int[]{ width, height };
+    int count = getViewCount();
+
+    // Update minor axis as appropriate. We need to first update the minor
+    // axis layout because that might affect the children's preferences along
+    // the major axis.
+    int minorAxis = myAxis == X_AXIS ? Y_AXIS : X_AXIS;
+    if ((! isLayoutValid(minorAxis)) || newSpan[minorAxis] != span[minorAxis])
+      {
+        layoutValid[minorAxis] = false;
+        span[minorAxis] = newSpan[minorAxis];
+        layoutMinorAxis(span[minorAxis], minorAxis, offsets[minorAxis],
+                        spans[minorAxis]);
+
+        // Update the child view's sizes.
+        for (int i = 0; i < count; ++i)
+          {
+            getView(i).setSize(spans[X_AXIS][i], spans[Y_AXIS][i]);
+          }
+        layoutValid[minorAxis] = true;
+      }
+
+
+    // Update major axis as appropriate.
+    if ((! isLayoutValid(myAxis)) || newSpan[myAxis] != span[myAxis])
+      {
+        layoutValid[myAxis] = false;
+        span[myAxis] = newSpan[myAxis];
+        layoutMajorAxis(span[myAxis], myAxis, offsets[myAxis],
+                        spans[myAxis]);
+
+        // Update the child view's sizes.
+        for (int i = 0; i < count; ++i)
+          {
+            getView(i).setSize(spans[X_AXIS][i], spans[Y_AXIS][i]);
+          }
+        layoutValid[myAxis] = true;
+      }
+
+    if (layoutValid[myAxis] == false)
+	  System.err.println("WARNING: Major axis layout must be valid after layout");
+    if (layoutValid[minorAxis] == false)
+      System.err.println("Minor axis layout must be valid after layout");
+  }
+
+  /**
+   * Performs the layout along the major axis of a <code>BoxView</code>.
+   *
+   * @param targetSpan the (inner) span of the <code>BoxView</code> in which
+   *        to layout the children
+   * @param axis the axis along which the layout is performed
+   * @param offsets the array that holds the offsets of the children on exit
+   * @param spans the array that holds the spans of the children on exit
+   */
+  protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
+                                 int[] spans)
+  {
+    // Set the spans to the preferred sizes. Determine the space
+    // that we have to adjust the sizes afterwards.
+    long sumPref = 0;
+    int n = getViewCount();
+    for (int i = 0; i < n; i++)
+      {
+        View child = getView(i);
+        spans[i] = (int) child.getPreferredSpan(axis);
+        sumPref = spans[i];
+      }
+
+    // Try to adjust the spans so that we fill the targetSpan.
+    long diff = targetSpan - sumPref;
+    float factor = 0.0F;
+    int[] diffs = null;
+    if (diff != 0)
+      {
+        long total = 0;
+        diffs = new int[n];
+        for (int i = 0; i < n; i++)
+          {
+            View child = getView(i);
+            int span;
+            if (diff < 0)
+              {
+                span = (int) child.getMinimumSpan(axis);
+                diffs[i] = spans[i] - span;
+              }
+            else
+              {
+                span = (int) child.getMaximumSpan(axis);
+                diffs[i] = span - spans[i];
+              }
+            total += span;
+          }
+
+        float maxAdjust = Math.abs(total - sumPref);
+        factor = diff / maxAdjust;
+        factor = Math.min(factor, 1.0F);
+        factor = Math.max(factor, -1.0F);
+      }
+
+    // Actually perform adjustments.
+    int totalOffs = 0;
+    for (int i = 0; i < n; i++)
+      {
+        offsets[i] = totalOffs;
+        if (diff != 0)
+          {
+            float adjust = factor * diffs[i];
+            spans[i] += Math.round(adjust);
+          }
+        // Avoid overflow here.
+        totalOffs = (int) Math.min((long) totalOffs + (long) spans[i],
+                                    Integer.MAX_VALUE);
+      }
+  }
+
+  /**
+   * Performs the layout along the minor axis of a <code>BoxView</code>.
+   *
+   * @param targetSpan the (inner) span of the <code>BoxView</code> in which
+   *        to layout the children
+   * @param axis the axis along which the layout is performed
+   * @param offsets the array that holds the offsets of the children on exit
+   * @param spans the array that holds the spans of the children on exit
+   */
+  protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
+                                 int[] spans)
+  {
+    int count = getViewCount();
+    for (int i = 0; i < count; i++)
+      {
+        View child = getView(i);
+        int max = (int) child.getMaximumSpan(axis);
+        if (max < targetSpan)
+          {System.err.println("align: " + child);
+            // Align child when it can't be made as wide as the target span.
+            float align = child.getAlignment(axis);
+            offsets[i] = (int) ((targetSpan - max) * align);
+            spans[i] = max;
+          }
+        else
+          {
+            // Expand child to target width if possible.
+            int min = (int) child.getMinimumSpan(axis);
+            offsets[i] = 0;
+            spans[i] = Math.max(min, targetSpan);
+          }
+      }
+  }
+
+  /**
+   * Returns <code>true</code> if the cached allocations for the children
+   * are still valid, <code>false</code> otherwise.
+   *
+   * @return <code>true</code> if the cached allocations for the children
+   *         are still valid, <code>false</code> otherwise
+   */
+  protected boolean isAllocationValid()
+  {
+    return isLayoutValid(X_AXIS) && isLayoutValid(Y_AXIS);
+  }
+
+  /**
+   * Return the current width of the box. This is the last allocated width.
+   *
+   * @return the current width of the box
+   */
+  public int getWidth()
+  {
+    return span[X_AXIS];
+  }
+
+  /**
+   * Return the current height of the box. This is the last allocated height.
+   *
+   * @return the current height of the box
+   */
+  public int getHeight()
+  {
+    return span[Y_AXIS];
+  }
+
+  /**
+   * Sets the size of the view. If the actual size has changed, the layout
+   * is updated accordingly.
+   *
+   * @param width the new width
+   * @param height the new height
+   */
+  public void setSize(float width, float height)
+  {
+    layout((int) width, (int) height);
+  }
+
+  /**
+   * Returns the span for the child view with the given index for the specified
+   * axis.
+   *
+   * @param axis the axis to examine, either <code>X_AXIS</code> or
+   *        <code>Y_AXIS</code>
+   * @param childIndex the index of the child for for which to return the span
+   *
+   * @return the span for the child view with the given index for the specified
+   *         axis
+   */
+  protected int getSpan(int axis, int childIndex)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException("Illegal axis argument");
+    return spans[axis][childIndex];
+  }
+
+  /**
+   * Returns the offset for the child view with the given index for the
+   * specified axis.
+   *
+   * @param axis the axis to examine, either <code>X_AXIS</code> or
+   *        <code>Y_AXIS</code>
+   * @param childIndex the index of the child for for which to return the span
+   *
+   * @return the offset for the child view with the given index for the
+   *         specified axis
+   */
+  protected int getOffset(int axis, int childIndex)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException("Illegal axis argument");
+    return offsets[axis][childIndex];
+  }
+
+  /**
+   * Returns the alignment for this box view for the specified axis. The
+   * axis that is tiled (the major axis) will be requested to be aligned
+   * centered (0.5F). The minor axis alignment depends on the child view's
+   * total alignment.
+   *
+   * @param axis the axis which is examined
+   *
+   * @return the alignment for this box view for the specified axis
+   */
+  public float getAlignment(int axis)
+  {
+     updateRequirements(axis);
+     return requirements[axis].alignment;
+  }
+  
+  /**
+   * Called by a child View when its preferred span has changed.
+   * 
+   * @param width indicates that the preferred width of the child changed.
+   * @param height indicates that the preferred height of the child changed.
+   * @param child the child View. 
+   */
+  public void preferenceChanged(View child, boolean width, boolean height)
+  {
+    if (width)
+      {
+        layoutValid[X_AXIS] = false;
+        requirementsValid[X_AXIS] = false;
+      }
+    if (height)
+      {
+        layoutValid[Y_AXIS] = false;
+        requirementsValid[Y_AXIS] = false;
+      }
+    super.preferenceChanged(child, width, height);
+  }
+  
+  /**
+   * Maps the document model position <code>pos</code> to a Shape
+   * in the view coordinate space.  This method overrides CompositeView's
+   * method to make sure the children are allocated properly before
+   * calling the super's behaviour.
+   */
+  public Shape modelToView(int pos, Shape a, Position.Bias bias)
+      throws BadLocationException
+  {
+    // Make sure everything is allocated properly and then call super
+    if (! isAllocationValid())
+      {
+        Rectangle bounds = a.getBounds();
+        setSize(bounds.width, bounds.height);
+      }
+    return super.modelToView(pos, a, bias);
+  }
+
+  /**
+   * Returns the resize weight of this view. A value of <code>0</code> or less
+   * means this view is not resizeable. Positive values make the view
+   * resizeable. This implementation returns <code>0</code> for the major
+   * axis and <code>1</code> for the minor axis of this box view.
+   *
+   * @param axis the axis
+   *
+   * @return the resizability of this view along the specified axis
+   *
+   * @throws IllegalArgumentException if <code>axis</code> is invalid
+   */
+  public int getResizeWeight(int axis)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException("Illegal axis argument");
+    int weight = 1;
+    if (axis == myAxis)
+      weight = 0;
+    return weight;
+  }
+
+  /**
+   * Returns the child allocation for the child view with the specified
+   * <code>index</code>. If the layout is invalid, this returns
+   * <code>null</code>.
+   *
+   * @param index the child view index
+   * @param a the allocation to this view
+   *
+   * @return the child allocation for the child view with the specified
+   *         <code>index</code> or <code>null</code> if the layout is invalid
+   *         or <code>a</code> is null
+   */
+  public Shape getChildAllocation(int index, Shape a)
+  {
+    Shape ret = null;
+    if (isAllocationValid() && a != null)
+      ret = super.getChildAllocation(index, a);
+    return ret;
+  }
+
+  protected void forwardUpdate(DocumentEvent.ElementChange ec, DocumentEvent e,
+                               Shape a, ViewFactory vf)
+  {
+    // FIXME: What to do here?
+    super.forwardUpdate(ec, e, a, vf);
+  }
+
+  public int viewToModel(float x, float y, Shape a, Position.Bias[] bias)
+  {
+    // FIXME: What to do here?
+    return super.viewToModel(x, y, a, bias);
+  }
+
+  protected boolean flipEastAndWestAtEnds(int position, Position.Bias bias)
+  {
+    // FIXME: What to do here?
+    return super.flipEastAndWestAtEnds(position, bias);
+  }
+
+  /**
+   * Updates the child requirements along the specified axis. The requirements
+   * are only updated if the layout for the specified axis is marked as
+   * invalid.
+   *
+   * @param axis the axis to be updated
+   */
+  private void updateChildRequirements(int axis)
+  {
+    if (! isLayoutValid(axis))
+      {
+        int numChildren = getViewCount();
+        if (childReqs[axis] == null || childReqs[axis].length != numChildren)
+          childReqs[axis] = new SizeRequirements[numChildren];
+        for (int i = 0; i < numChildren; ++i)
+          {
+            View child = getView(i);
+            childReqs[axis][i] =
+              new SizeRequirements((int) child.getMinimumSpan(axis),
+                                   (int) child.getPreferredSpan(axis),
+                                   (int) child.getMaximumSpan(axis),
+                                   child.getAlignment(axis));
+          }
+      }
+  }
+
+  /**
+   * Updates the view's cached requirements along the specified axis if
+   * necessary. The requirements are only updated if the layout for the
+   * specified axis is marked as invalid.
+   *
+   * @param axis the axis
+   */
+  private void updateRequirements(int axis)
+  {
+    if (! requirementsValid[axis])
+      {
+        if (axis == myAxis)
+          requirements[axis] = calculateMajorAxisRequirements(axis,
+                                                           requirements[axis]);
+        else
+          requirements[axis] = calculateMinorAxisRequirements(axis,
+                                                           requirements[axis]);
+        requirementsValid[axis] = true;
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,207 @@
+/* Caret.java -- 
+   Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Point;
+
+import javax.swing.event.ChangeListener;
+
+/**
+ * Defines the method to be implemented by a caret that can be used in Swing
+ * text components.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public interface Caret
+{
+  /**
+   * Registers a {@link ChangeListener} that is notified whenever that state
+   * of this <code>Caret</code> changes.
+   *
+   * @param l the listener to register to this caret
+   */
+  void addChangeListener(ChangeListener l);
+
+  /**
+   * Removes a {@link ChangeListener} from the list of registered listeners.
+   *
+   * @param l the listener to remove
+   */
+  void removeChangeListener(ChangeListener l);
+
+  /**
+   * Installs this <code>Caret</code> on the specified text component. This
+   * usually involves setting up listeners.
+   *
+   * This method is called by {@link JTextComponent#setCaret(Caret)} after
+   * this caret has been set on the text component.
+   *
+   * @param c the text component to install this caret to
+   */
+  void install(JTextComponent c);
+  
+  /**
+   * Deinstalls this <code>Caret</code> from the specified text component.
+   * This usually involves removing listeners from the text component.
+   *
+   * This method is called by {@link JTextComponent#setCaret(Caret)} before
+   * this caret is removed from the text component.
+   *
+   * @param c the text component to deinstall this caret from
+   */
+  void deinstall(JTextComponent c);
+
+  /**
+   * Returns the blink rate of this <code>Caret</code> in milliseconds.
+   * A value of <code>0</code> means that the caret does not blink.
+   *
+   * @return the blink rate of this <code>Caret</code> or <code>0</code> if
+   *         this caret does not blink
+   */
+  int getBlinkRate();
+
+  /**
+   * Sets the blink rate of this <code>Caret</code> in milliseconds.
+   * A value of <code>0</code> means that the caret does not blink.
+   *
+   * @param rate the new blink rate to set
+   */
+  void setBlinkRate(int rate);
+  
+  /**
+   * Returns the current position of this <code>Caret</code> within the
+   * <code>Document</code>.
+   *
+   * @return the current position of this <code>Caret</code> within the
+   *         <code>Document</code>
+   */
+  int getDot();
+
+  /**
+   * Sets the current position of this <code>Caret</code> within the
+   * <code>Document</code>. This also sets the <code>mark</code> to the
+   * new location.
+   *
+   * @param dot the new position to be set
+   *
+   * @see #moveDot(int)
+   */
+  void setDot(int dot);
+  
+  /**
+   * Moves the <code>dot</code> location without touching the
+   * <code>mark</code>. This is used when making a selection.
+   *
+   * @param dot the location where to move the dot
+   *
+   * @see #setDot(int)
+   */
+  void moveDot(int dot);
+  
+  /**
+   * Returns the current position of the <code>mark</code>. The
+   * <code>mark</code> marks the location in the <code>Document</code> that
+   * is the end of a selection. If there is no selection, the <code>mark</code>
+   * is the same as the <code>dot</code>.
+   *
+   * @return the current position of the mark
+   */
+  int getMark();
+  
+  /**
+   * Returns the current visual position of this <code>Caret</code>.
+   *
+   * @return the current visual position of this <code>Caret</code>
+   *
+   * @see #setMagicCaretPosition
+   */
+  Point getMagicCaretPosition();
+
+  /**
+   * Sets the current visual position of this <code>Caret</code>.
+   *
+   * @param p the Point to use for the saved location. May be <code>null</code>
+   *        to indicate that there is no visual location
+   */
+  void setMagicCaretPosition(Point p);
+
+  /**
+   * Returns <code>true</code> if the selection is currently visible,
+   * <code>false</code> otherwise.
+   *
+   * @return <code>true</code> if the selection is currently visible,
+   *         <code>false</code> otherwise
+   */
+  boolean isSelectionVisible();
+
+  /**
+   * Sets the visiblity state of the selection.
+   *
+   * @param v <code>true</code> if the selection should be visible,
+   *        <code>false</code> otherwise
+   */
+  void setSelectionVisible(boolean v);
+
+  /**
+   * Returns <code>true</code> if this <code>Caret</code> is currently visible,
+   * and <code>false</code> if it is not.
+   *
+   * @return <code>true</code> if this <code>Caret</code> is currently visible,
+   *         and <code>false</code> if it is not
+   */
+  boolean isVisible();
+
+  /**
+   * Sets the visibility state of the caret. <code>true</code> shows the
+   * <code>Caret</code>, <code>false</code> hides it.
+   *
+   * @param v the visibility to set
+   */  
+  void setVisible(boolean v);
+
+  /**
+   * Paints this <code>Caret</code> to the specified <code>Graphics</code>
+   * context.
+   *
+   * @param g the graphics context to render to
+   */
+  void paint(Graphics g);  
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,100 @@
+/* ChangedCharSetException.java --
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * The exception is thrown when the document charset is changed.
+ *
+ * @author Audrius Meskauskas (AudriusA at Bioinformatics.org)
+ */
+public class ChangedCharSetException
+  extends IOException
+  implements Serializable
+{
+  /**
+   * Use serialVersionUID for interoperability.
+   * This value corresponds the version 1.4.
+   */
+  private static final long serialVersionUID = 9119851554465432389L;
+
+  /**
+   * The char set specification.
+   */
+  private final String m_charSetSpec;
+
+  /**
+   * The char set key.
+   */
+  private final boolean m_charSetKey;
+
+  /**
+   * Constructs a new char set exception with two additional parameters,
+   * defining the circumstances under that the exception was raised.
+   */
+  public ChangedCharSetException(String charSetSpec, boolean charSetKey)
+  {
+    m_charSetSpec = charSetSpec;
+    m_charSetKey = charSetKey;
+  }
+
+  /**
+   * Get the value of the first parameter, previously passed to the
+   * constructor.
+   *
+   * @return the value of the first parameter
+   */
+  public String getCharSetSpec()
+  {
+    return m_charSetSpec;
+  }
+
+  /**
+   * Get the value of the second parameter, previously passed to the
+   * constructor.
+   *
+   * @return the value of the second parameter
+   */
+  public boolean keyEqualsCharSet()
+  {
+    return m_charSetKey;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,268 @@
+/* ComponentView.java -- 
+   Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+
+/**
+ * A {@link View} implementation that is able to render arbitrary
+ * {@link Component}s. This uses the attribute
+ * {@link StyleConstants#ComponentAttribute} to determine the
+ * <code>Component</code> that should be rendered. This <code>Component</code>
+ * becomes a direct child of the <code>JTextComponent</code> that contains
+ * this <code>ComponentView</code>, so this view must not be shared between
+ * multiple <code>JTextComponent</code>s.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ * @author original author unknown
+ */
+public class ComponentView extends View
+{
+
+  /**
+   * The component that is displayed by this view.
+   */
+  private Component comp;
+
+  /**
+   * Creates a new instance of <code>ComponentView</code> for the specified
+   * <code>Element</code>.
+   *
+   * @param elem the element that this <code>View</code> is rendering
+   */
+  public ComponentView(Element elem)
+  {
+    super(elem);
+  }
+
+  /**
+   * Creates the <code>Component</code> that this <code>View</code> is
+   * rendering. The <code>Component</code> is determined using
+   * the {@link StyleConstants#ComponentAttribute} of the associated
+   * <code>Element</code>.
+   *
+   * @return the component that is rendered
+   */
+  protected Component createComponent()
+  {
+    return StyleConstants.getComponent(getElement().getAttributes());
+  }
+
+  /**
+   * Returns the alignment of this <code>View</code> along the specified axis.
+   *
+   * @param axis either {@link View#X_AXIS} or {@link View#Y_AXIS}
+   *
+   * @return the alignment of this <code>View</code> along the specified axis
+   */
+  public float getAlignment(int axis)
+  {
+    float align;
+    if (axis == X_AXIS)
+      align = getComponent().getAlignmentX();
+    else if (axis == Y_AXIS)
+      align = getComponent().getAlignmentY();
+    else
+      throw new IllegalArgumentException();
+    return align;
+  }
+
+  /**
+   * Returns the <code>Component</code> that is rendered by this
+   * <code>ComponentView</code>.
+   *
+   * @return the <code>Component</code> that is rendered by this
+   *         <code>ComponentView</code>
+   */
+  public final Component getComponent()
+  {
+    if (comp == null)
+      comp = createComponent();
+    return comp;
+  }
+
+  /**
+   * Returns the maximum span of this <code>View</code> along the specified
+   * axis.
+   *
+   * This will return {@link Component#getMaximumSize()} for the specified
+   * axis.
+   *
+   * @return the maximum span of this <code>View</code> along the specified
+   *         axis
+   */
+  public float getMaximumSpan(int axis)
+  {
+    float span;
+    if (axis == X_AXIS)
+      span = getComponent().getMaximumSize().width;
+    else if (axis == Y_AXIS)
+      span = getComponent().getMaximumSize().height;
+    else
+      throw new IllegalArgumentException();
+    return span;
+  }
+
+  public float getMinimumSpan(int axis)
+  {
+    float span;
+    if (axis == X_AXIS)
+      span = getComponent().getMinimumSize().width;
+    else if (axis == Y_AXIS)
+      span = getComponent().getMinimumSize().height;
+    else
+      throw new IllegalArgumentException();
+    return span;
+  }
+
+  public float getPreferredSpan(int axis)
+  {
+    float span;
+    if (axis == X_AXIS)
+      span = getComponent().getPreferredSize().width;
+    else if (axis == Y_AXIS)
+      span = getComponent().getPreferredSize().height;
+    else
+      throw new IllegalArgumentException();
+    return span;
+  }
+
+  public Shape modelToView(int pos, Shape a, Position.Bias b)
+    throws BadLocationException
+  {
+    Element el = getElement();
+    if (pos < el.getStartOffset() || pos >= el.getEndOffset())
+      throw new BadLocationException("Illegal offset for this view", pos);
+    Rectangle r = a.getBounds();
+    Component c = getComponent();
+    return new Rectangle(r.x, r.y, c.getWidth(), c.getHeight());
+  }
+
+  /**
+   * The real painting behavour is performed by normal component painting,
+   * triggered by the text component that hosts this view. This method does
+   * not paint by itself. However, it sets the size of the component according
+   * to the allocation that is passed here.
+   *
+   * @param g the graphics context
+   * @param a the allocation of the child
+   */
+  public void paint(Graphics g, Shape a)
+  {
+    Rectangle r = a.getBounds();
+    getComponent().setBounds(r.x, r.y, r.width, r.height);
+  }
+
+  /**
+   * This sets up the component when the view is added to its parent, or
+   * cleans up the view when it is removed from its parent.
+   *
+   * When this view is added to a parent view, the component of this view
+   * is added to the container that hosts this view. When <code>p</code> is
+   * <code>null</code>, then the view is removed from it's parent and we have
+   * to also remove the component from it's parent container.
+   *
+   * @param p the parent view or <code>null</code> if this view is removed
+   *        from it's parent
+   */
+  public void setParent(final View p)
+  {
+    if (SwingUtilities.isEventDispatchThread())
+      setParentImpl(p);
+    else
+      SwingUtilities.invokeLater
+      (new Runnable()
+       {
+         public void run()
+         {
+           setParentImpl(p);
+         }
+       });
+  }
+
+  /**
+   * The implementation of {@link #setParent}. This is package private to
+   * avoid a synthetic accessor method.
+   *
+   * @param p the parent view to set
+   */
+  private void setParentImpl(View p)
+  {
+    super.setParent(p);
+    if (p != null)
+      {
+        Component c = getComponent();
+        p.getContainer().add(c);
+      }
+    else
+      {
+        Component c = getComponent();
+        Container parent = c.getParent();
+        parent.remove(c);
+        comp = null;
+      }
+  }
+    
+  /**
+   * Maps coordinates from the <code>View</code>'s space into a position
+   * in the document model.
+   *
+   * @param x the x coordinate in the view space
+   * @param y the y coordinate in the view space
+   * @param a the allocation of this <code>View</code>
+   * @param b the bias to use
+   *
+   * @return the position in the document that corresponds to the screen
+   *         coordinates <code>x, y</code>
+   */
+  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+  {
+    // The element should only have one character position and it is clear
+    // that this position is the position that best matches the given screen
+    // coordinates, simply because this view has only this one position.
+    Element el = getElement();
+    return el.getStartOffset();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,799 @@
+/* CompositeView.java -- An abstract view that manages child views
+   Copyright (C) 2005, 2006  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SwingConstants;
+
+/**
+ * An abstract base implementation of {@link View} that manages child
+ * <code>View</code>s.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public abstract class CompositeView
+  extends View
+{
+
+  /**
+   * The child views of this <code>CompositeView</code>.
+   */
+  View[] children;
+
+  /**
+   * The allocation of this <code>View</code> minus its insets. This is
+   * initialized in {@link #getInsideAllocation} and reused and modified in
+   * {@link #childAllocation(int, Rectangle)}.
+   */
+  Rectangle insideAllocation;
+
+  /**
+   * The insets of this <code>CompositeView</code>. This is initialized
+   * in {@link #setInsets}.
+   */
+  Insets insets;
+
+  /**
+   * Creates a new <code>CompositeView</code> for the given
+   * <code>Element</code>.
+   *
+   * @param element the element that is rendered by this CompositeView
+   */
+  public CompositeView(Element element)
+  {
+    super(element);
+    children = new View[0];
+    insets = new Insets(0, 0, 0, 0);
+  }
+
+  /**
+   * Loads the child views of this <code>CompositeView</code>. This method
+   * is called from {@link #setParent} to initialize the child views of
+   * this composite view.
+   *
+   * @param f the view factory to use for creating new child views
+   *
+   * @see #setParent
+   */
+  protected void loadChildren(ViewFactory f)
+  {
+    Element el = getElement();
+    int count = el.getElementCount();
+    View[] newChildren = new View[count];
+    for (int i = 0; i < count; ++i)
+      {
+        Element child = el.getElement(i);
+        View view = f.create(child);
+        newChildren[i] = view;
+      }
+    replace(0, getViewCount(), newChildren);
+  }
+
+  /**
+   * Sets the parent of this <code>View</code>.
+   * In addition to setting the parent, this calls {@link #loadChildren}, if
+   * this <code>View</code> does not already have its children initialized.
+   *
+   * @param parent the parent to set
+   */
+  public void setParent(View parent)
+  {
+    super.setParent(parent);
+    if (parent != null && ((children == null) || children.length == 0))
+      loadChildren(getViewFactory());
+  }
+
+  /**
+   * Returns the number of child views.
+   *
+   * @return the number of child views
+   */
+  public int getViewCount()
+  {
+    return children.length;
+  }
+
+  /**
+   * Returns the child view at index <code>n</code>.
+   *
+   * @param n the index of the requested child view
+   *
+   * @return the child view at index <code>n</code>
+   */
+  public View getView(int n)
+  {
+    return children[n];
+  }
+
+  /**
+   * Replaces child views by some other child views. If there are no views to
+   * remove (<code>length == 0</code>), the result is a simple insert, if
+   * there are no children to add (<code>view == null</code>) the result
+   * is a simple removal.
+   *
+   * @param offset the start offset from where to remove children
+   * @param length the number of children to remove
+   * @param views the views that replace the removed children
+   */
+  public void replace(int offset, int length, View[] views)
+  {
+    // Check for null views to add.
+    for (int i = 0; i < views.length; ++i)
+      if (views[i] == null)
+        throw new NullPointerException("Added views must not be null");
+
+    int endOffset = offset + length;
+
+    // First we set the parent of the removed children to null.
+    for (int i = offset; i < endOffset; ++i)
+      children[i].setParent(null);
+
+    View[] newChildren = new View[children.length - length + views.length];
+    System.arraycopy(children, 0, newChildren, 0, offset);
+    System.arraycopy(views, 0, newChildren, offset, views.length);
+    System.arraycopy(children, offset + length, newChildren,
+                     offset + views.length,
+                     children.length - (offset + length));
+    children = newChildren;
+
+    // Finally we set the parent of the added children to this.
+    for (int i = 0; i < views.length; ++i)
+      views[i].setParent(this);
+  }
+
+  /**
+   * Returns the allocation for the specified child <code>View</code>.
+   *
+   * @param index the index of the child view
+   * @param a the allocation for this view
+   *
+   * @return the allocation for the specified child <code>View</code>
+   */
+  public Shape getChildAllocation(int index, Shape a)
+  {
+    Rectangle r = getInsideAllocation(a);
+    childAllocation(index, r);
+    return r;
+  }
+
+  /**
+   * Maps a position in the document into the coordinate space of the View.
+   * The output rectangle usually reflects the font height but has a width
+   * of zero.
+   *
+   * @param pos the position of the character in the model
+   * @param a the area that is occupied by the view
+   * @param bias either {@link Position.Bias#Forward} or
+   *        {@link Position.Bias#Backward} depending on the preferred
+   *        direction bias. If <code>null</code> this defaults to
+   *        <code>Position.Bias.Forward</code>
+   *
+   * @return a rectangle that gives the location of the document position
+   *         inside the view coordinate space
+   *
+   * @throws BadLocationException if <code>pos</code> is invalid
+   * @throws IllegalArgumentException if b is not one of the above listed
+   *         valid values
+   */
+  public Shape modelToView(int pos, Shape a, Position.Bias bias)
+    throws BadLocationException
+  {
+    boolean backward = bias == Position.Bias.Backward;
+    int testpos = backward ? Math.max(0, pos - 1) : pos;
+
+    Shape ret = null;
+    if (! backward || testpos >= getStartOffset())
+      {
+        int childIndex = getViewIndexAtPosition(testpos);
+        if (childIndex != -1 && childIndex < getViewCount())
+          {
+            View child = getView(childIndex);
+            if (child != null && testpos >= child.getStartOffset()
+                && testpos < child.getEndOffset())
+              {
+                Shape childAlloc = getChildAllocation(childIndex, a);
+                if (childAlloc != null)
+                  {
+                    ret = child.modelToView(pos, childAlloc, bias);
+                    // Handle corner case.
+                    if (ret == null && child.getEndOffset() == pos)
+                      {
+                        childIndex++;
+                        if (childIndex < getViewCount())
+                          {
+                            child = getView(childIndex);
+                            childAlloc = getChildAllocation(childIndex, a);
+                            ret = child.modelToView(pos, childAlloc, bias);
+                          }
+                      }
+                  }
+              }
+          }
+        else
+          {
+            throw new BadLocationException("Position " + pos
+                                           + " is not represented by view.", pos);
+          }    
+      }
+    return ret;
+  }
+
+  /**
+   * A helper method for {@link #modelToView(int, Position.Bias, int,
+   * Position.Bias, Shape)}. This creates a default location when there is
+   * no child view that can take responsibility for mapping the position to
+   * view coordinates. Depending on the specified bias this will be the
+   * left or right edge of this view's allocation.
+   *
+   * @param a the allocation for this view
+   * @param bias the bias
+   *
+   * @return a default location
+   */
+  private Shape createDefaultLocation(Shape a, Position.Bias bias)
+  {
+    Rectangle alloc = a.getBounds();
+    Rectangle location = new Rectangle(alloc.x, alloc.y, 1, alloc.height);
+    if (bias == Position.Bias.Forward)
+      location.x = alloc.x + alloc.width;
+    return location;
+  }
+
+  /**
+   * Maps a region in the document into the coordinate space of the View.
+   *
+   * @param p1 the beginning position inside the document
+   * @param b1 the direction bias for the beginning position
+   * @param p2 the end position inside the document
+   * @param b2 the direction bias for the end position
+   * @param a the area that is occupied by the view
+   *
+   * @return a rectangle that gives the span of the document region
+   *         inside the view coordinate space
+   *
+   * @throws BadLocationException if <code>p1</code> or <code>p2</code> are
+   *         invalid
+   * @throws IllegalArgumentException if b1 or b2 is not one of the above
+   *         listed valid values
+   */
+  public Shape modelToView(int p1, Position.Bias b1,
+			   int p2, Position.Bias b2, Shape a)
+    throws BadLocationException
+  {
+    // TODO: This is most likely not 100% ok, figure out what else is to
+    // do here.
+    return super.modelToView(p1, b1, p2, b2, a);
+  }
+
+  /**
+   * Maps coordinates from the <code>View</code>'s space into a position
+   * in the document model.
+   *
+   * @param x the x coordinate in the view space, x >= 0
+   * @param y the y coordinate in the view space, y >= 0
+   * @param a the allocation of this <code>View</code>
+   * @param b the bias to use
+   *
+   * @return the position in the document that corresponds to the screen
+   *         coordinates <code>x, y</code> >= 0
+   */
+  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+  {
+    if (x >= 0 && y >= 0)
+      {
+        Rectangle r = getInsideAllocation(a);
+        View view = getViewAtPoint((int) x, (int) y, r);
+        return view.viewToModel(x, y, r, b);
+      }
+    return 0;
+  }
+
+  /**
+   * Returns the next model location that is visible in eiter north / south
+   * direction or east / west direction. This is used to determine the placement
+   * of the caret when navigating around the document with the arrow keys. This
+   * is a convenience method for {@link #getNextNorthSouthVisualPositionFrom}
+   * and {@link #getNextEastWestVisualPositionFrom}.
+   * 
+   * @param pos
+   *          the model position to start search from
+   * @param b
+   *          the bias for <code>pos</code>
+   * @param a
+   *          the allocated region for this view
+   * @param direction
+   *          the direction from the current position, can be one of the
+   *          following:
+   *          <ul>
+   *          <li>{@link SwingConstants#WEST}</li>
+   *          <li>{@link SwingConstants#EAST}</li>
+   *          <li>{@link SwingConstants#NORTH}</li>
+   *          <li>{@link SwingConstants#SOUTH}</li>
+   *          </ul>
+   * @param biasRet
+   *          the bias of the return value gets stored here
+   * @return the position inside the model that represents the next visual
+   *         location
+   * @throws BadLocationException
+   *           if <code>pos</code> is not a valid location inside the document
+   *           model
+   * @throws IllegalArgumentException
+   *           if <code>direction</code> is invalid
+   */
+  public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
+                                       int direction, Position.Bias[] biasRet)
+    throws BadLocationException
+  {
+    int retVal = -1;
+    switch (direction)
+      {
+      case SwingConstants.WEST:
+      case SwingConstants.EAST:
+        retVal = getNextEastWestVisualPositionFrom(pos, b, a, direction,
+                                                   biasRet);
+        break;
+      case SwingConstants.NORTH:
+      case SwingConstants.SOUTH:
+        retVal = getNextNorthSouthVisualPositionFrom(pos, b, a, direction,
+                                                     biasRet);
+        break;
+      default:
+        throw new IllegalArgumentException("Illegal value for direction.");
+      }
+    return retVal;
+  }
+
+  /**
+   * Returns the index of the child view that represents the specified
+   * model location.
+   *
+   * @param pos the model location for which to determine the child view index
+   * @param b the bias to be applied to <code>pos</code>
+   *
+   * @return the index of the child view that represents the specified
+   *         model location
+   */
+  public int getViewIndex(int pos, Position.Bias b)
+  {
+    if (b == Position.Bias.Backward && pos != 0)
+      pos -= 1;
+    int i = -1;
+    if (pos >= getStartOffset() && pos < getEndOffset())
+      i = getViewIndexAtPosition(pos);
+    return i;
+  }
+
+  /**
+   * Returns <code>true</code> if the specified point lies before the
+   * given <code>Rectangle</code>, <code>false</code> otherwise.
+   *
+   * "Before" is typically defined as being to the left or above.
+   *
+   * @param x the X coordinate of the point
+   * @param y the Y coordinate of the point
+   * @param r the rectangle to test the point against
+   *
+   * @return <code>true</code> if the specified point lies before the
+   *         given <code>Rectangle</code>, <code>false</code> otherwise
+   */
+  protected abstract boolean isBefore(int x, int y, Rectangle r);
+
+  /**
+   * Returns <code>true</code> if the specified point lies after the
+   * given <code>Rectangle</code>, <code>false</code> otherwise.
+   *
+   * "After" is typically defined as being to the right or below.
+   *
+   * @param x the X coordinate of the point
+   * @param y the Y coordinate of the point
+   * @param r the rectangle to test the point against
+   *
+   * @return <code>true</code> if the specified point lies after the
+   *         given <code>Rectangle</code>, <code>false</code> otherwise
+   */
+  protected abstract boolean isAfter(int x, int y, Rectangle r);
+
+  /**
+   * Returns the child <code>View</code> at the specified location.
+   *
+   * @param x the X coordinate
+   * @param y the Y coordinate
+   * @param r the inner allocation of this <code>BoxView</code> on entry,
+   *        the allocation of the found child on exit
+   *
+   * @return the child <code>View</code> at the specified location
+   */
+  protected abstract View getViewAtPoint(int x, int y, Rectangle r);
+
+  /**
+   * Computes the allocation for a child <code>View</code>. The parameter
+   * <code>a</code> stores the allocation of this <code>CompositeView</code>
+   * and is then adjusted to hold the allocation of the child view.
+   *
+   * @param index the index of the child <code>View</code>
+   * @param a the allocation of this <code>CompositeView</code> before the
+   *        call, the allocation of the child on exit
+   */
+  protected abstract void childAllocation(int index, Rectangle a);
+
+  /**
+   * Returns the child <code>View</code> that contains the given model
+   * position. The given <code>Rectangle</code> gives the parent's allocation
+   * and is changed to the child's allocation on exit.
+   *
+   * @param pos the model position to query the child <code>View</code> for
+   * @param a the parent allocation on entry and the child allocation on exit
+   *
+   * @return the child view at the given model position
+   */
+  protected View getViewAtPosition(int pos, Rectangle a)
+  {
+    View view = null;
+    int i = getViewIndexAtPosition(pos);
+    if (i >= 0 && i < getViewCount() && a != null)
+      {
+        view = getView(i);
+        childAllocation(i, a);
+      }
+    return view;
+  }
+
+  /**
+   * Returns the index of the child <code>View</code> for the given model
+   * position.
+   *
+   * @param pos the model position for whicht the child <code>View</code> is
+   *        queried
+   *
+   * @return the index of the child <code>View</code> for the given model
+   *         position
+   */
+  protected int getViewIndexAtPosition(int pos)
+  {
+    // We have a 1:1 mapping of elements to views here, so we forward
+    // this to the element.
+    Element el = getElement();
+    return el.getElementIndex(pos);
+  }
+
+  /**
+   * Returns the allocation that is given to this <code>CompositeView</code>
+   * minus this <code>CompositeView</code>'s insets.
+   *
+   * Also this translates from an immutable allocation to a mutable allocation
+   * that is typically reused and further narrowed, like in
+   * {@link #childAllocation}.
+   *
+   * @param a the allocation given to this <code>CompositeView</code>
+   *
+   * @return the allocation that is given to this <code>CompositeView</code>
+   *         minus this <code>CompositeView</code>'s insets or
+   *         <code>null</code> if a was <code>null</code>
+   */
+  protected Rectangle getInsideAllocation(Shape a)
+  {
+    if (a == null)
+      return null;
+
+    Rectangle alloc = a.getBounds();
+    // Initialize the inside allocation rectangle. This is done inside
+    // a synchronized block in order to avoid multiple threads creating
+    // this instance simultanously.
+    Rectangle inside;
+    synchronized(this)
+      {
+        inside = insideAllocation;
+        if (inside == null)
+          {
+            inside = new Rectangle();
+            insideAllocation = inside;
+          }
+      }
+    inside.x = alloc.x + insets.left;
+    inside.y = alloc.y + insets.top;
+    inside.width = alloc.width - insets.left - insets.right;
+    inside.height = alloc.height - insets.top - insets.bottom;
+    return inside;
+  }
+
+  /**
+   * Sets the insets defined by attributes in <code>attributes</code>. This
+   * queries the attribute keys {@link StyleConstants#SpaceAbove},
+   * {@link StyleConstants#SpaceBelow}, {@link StyleConstants#LeftIndent} and
+   * {@link StyleConstants#RightIndent} and calls {@link #setInsets} to
+   * actually set the insets on this <code>CompositeView</code>.
+   *
+   * @param attributes the attributes from which to query the insets
+   */
+  protected void setParagraphInsets(AttributeSet attributes)
+  {
+    Float l = (Float) attributes.getAttribute(StyleConstants.LeftIndent);
+    short left = 0;
+    if (l != null)
+      left = l.shortValue();
+    Float r = (Float) attributes.getAttribute(StyleConstants.RightIndent);
+    short right = 0;
+    if (r != null)
+      right = r.shortValue();
+    Float t = (Float) attributes.getAttribute(StyleConstants.SpaceAbove);
+    short top = 0;
+    if (t != null)
+      top = t.shortValue();
+    Float b = (Float) attributes.getAttribute(StyleConstants.SpaceBelow);
+    short bottom = 0;
+    if (b != null)
+      bottom = b.shortValue();
+    setInsets(top, left, bottom, right);
+  }
+
+  /**
+   * Sets the insets of this <code>CompositeView</code>.
+   *
+   * @param top the top inset
+   * @param left the left inset
+   * @param bottom the bottom inset
+   * @param right the right inset
+   */
+  protected void setInsets(short top, short left, short bottom, short right)
+  {
+    insets.top = top;
+    insets.left = left;
+    insets.bottom = bottom;
+    insets.right = right;
+  }
+
+  /**
+   * Returns the left inset of this <code>CompositeView</code>.
+   *
+   * @return the left inset of this <code>CompositeView</code>
+   */
+  protected short getLeftInset()
+  {
+    return (short) insets.left;
+  }
+
+  /**
+   * Returns the right inset of this <code>CompositeView</code>.
+   *
+   * @return the right inset of this <code>CompositeView</code>
+   */
+  protected short getRightInset()
+  {
+    return (short) insets.right;
+  }
+
+  /**
+   * Returns the top inset of this <code>CompositeView</code>.
+   *
+   * @return the top inset of this <code>CompositeView</code>
+   */
+  protected short getTopInset()
+  {
+    return (short) insets.top;
+  }
+
+  /**
+   * Returns the bottom inset of this <code>CompositeView</code>.
+   *
+   * @return the bottom inset of this <code>CompositeView</code>
+   */
+  protected short getBottomInset()
+  {
+    return (short) insets.bottom;
+  }
+
+  /**
+   * Returns the next model location that is visible in north or south
+   * direction.
+   * This is used to determine the
+   * placement of the caret when navigating around the document with
+   * the arrow keys.
+   *
+   * @param pos the model position to start search from
+   * @param b the bias for <code>pos</code>
+   * @param a the allocated region for this view
+   * @param direction the direction from the current position, can be one of
+   *        the following:
+   *        <ul>
+   *        <li>{@link SwingConstants#NORTH}</li>
+   *        <li>{@link SwingConstants#SOUTH}</li>
+   *        </ul>
+   * @param biasRet the bias of the return value gets stored here
+   *
+   * @return the position inside the model that represents the next visual
+   *         location
+   *
+   * @throws BadLocationException if <code>pos</code> is not a valid location
+   *         inside the document model
+   * @throws IllegalArgumentException if <code>direction</code> is invalid
+   */
+  protected int getNextNorthSouthVisualPositionFrom(int pos, Position.Bias b,
+                                                    Shape a, int direction,
+                                                    Position.Bias[] biasRet)
+    throws BadLocationException
+  {
+    // TODO: It is unknown to me how this method has to be implemented and
+    // there is no specification telling me how to do it properly. Therefore
+    // the implementation was done for cases that are known.
+    //
+    // If this method ever happens to act silly for your particular case then
+    // it is likely that it is a cause of not knowing about your case when it
+    // was implemented first. You are free to fix the behavior.
+    //
+    // Here are the assumptions that lead to the implementation:
+    // If direction is NORTH chose the View preceding the one that contains the
+    // offset 'pos' (imagine the views are stacked on top of each other where
+    // the top is 0 and the bottom is getViewCount()-1.
+    // Consecutively when the direction is SOUTH the View following the one
+    // the offset 'pos' lies in is questioned.
+    //
+    // This limitation is described as PR 27345.
+    int index = getViewIndex(pos, b);
+    View v = null;
+    
+    if (index == -1)
+      return pos;
+
+    switch (direction)
+    {
+      case NORTH:
+        // If we cannot calculate a proper offset return the one that was
+        // provided.
+        if (index <= 0)
+          return pos;
+        
+        v = getView(index - 1);
+        break;
+      case SOUTH:
+        // If we cannot calculate a proper offset return the one that was
+        // provided.
+        if (index >= getViewCount() - 1)
+          return pos;
+        
+        v = getView(index + 1);
+        break;
+      default:
+          throw new IllegalArgumentException();
+    }
+    
+    return v.getNextVisualPositionFrom(pos, b, a, direction, biasRet);
+  }
+
+  /**
+   * Returns the next model location that is visible in east or west
+   * direction.
+   * This is used to determine the
+   * placement of the caret when navigating around the document with
+   * the arrow keys.
+   *
+   * @param pos the model position to start search from
+   * @param b the bias for <code>pos</code>
+   * @param a the allocated region for this view
+   * @param direction the direction from the current position, can be one of
+   *        the following:
+   *        <ul>
+   *        <li>{@link SwingConstants#EAST}</li>
+   *        <li>{@link SwingConstants#WEST}</li>
+   *        </ul>
+   * @param biasRet the bias of the return value gets stored here
+   *
+   * @return the position inside the model that represents the next visual
+   *         location
+   *
+   * @throws BadLocationException if <code>pos</code> is not a valid location
+   *         inside the document model
+   * @throws IllegalArgumentException if <code>direction</code> is invalid
+   */
+  protected int getNextEastWestVisualPositionFrom(int pos, Position.Bias b,
+                                                  Shape a, int direction,
+                                                  Position.Bias[] biasRet)
+    throws BadLocationException
+  {
+    // TODO: It is unknown to me how this method has to be implemented and
+    // there is no specification telling me how to do it properly. Therefore
+    // the implementation was done for cases that are known.
+    //
+    // If this method ever happens to act silly for your particular case then
+    // it is likely that it is a cause of not knowing about your case when it
+    // was implemented first. You are free to fix the behavior.
+    //
+    // Here are the assumptions that lead to the implementation:
+    // If direction is EAST increase the offset by one and ask the View to
+    // which that index belong to calculate the 'next visual position'.
+    // If the direction is WEST do the same with offset 'pos' being decreased
+    // by one.
+    // This behavior will fail in a right-to-left or bidi environment!
+    //
+    // This limitation is described as PR 27346.
+    int index;
+    
+    View v = null;
+    
+    switch (direction)
+    {
+      case EAST:
+        index = getViewIndex(pos + 1, b);
+        // If we cannot calculate a proper offset return the one that was
+        // provided.
+        if (index == -1)
+          return pos;
+        
+        v  = getView(index);
+        break;
+      case WEST:
+        index = getViewIndex(pos - 1, b);
+        // If we cannot calculate a proper offset return the one that was
+        // provided.
+        if (index == -1)
+          return pos;
+        
+        v  = getView(index);
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+    
+    return v.getNextVisualPositionFrom(pos,
+                                       b,
+                                       a,
+                                       direction,
+                                       biasRet);
+  }
+
+  /**
+   * Determines if the next view in horinzontal direction is located to
+   * the east or west of the view at position <code>pos</code>. Usually
+   * the <code>View</code>s are laid out from the east to the west, so
+   * we unconditionally return <code>false</code> here. Subclasses that
+   * support bidirectional text may wish to override this method.
+   *
+   * @param pos the position in the document
+   * @param bias the bias to be applied to <code>pos</code>
+   *
+   * @return <code>true</code> if the next <code>View</code> is located
+   *         to the EAST, <code>false</code> otherwise
+   */
+  protected boolean flipEastAndWestAtEnds(int pos, Position.Bias bias)
+  {
+    return false;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,85 @@
+/* DateFormatter.java --
+Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.text.DateFormat;
+
+/**
+ * <code>DateFormatter</code> is an {@link InternationalFormatter}
+ * that implements value to string and string to value conversion via
+ * an instance of {@link DateFormat}.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DateFormatter extends InternationalFormatter
+{
+
+  /** The serialVersoinUID. */
+  private static final long serialVersionUID = 5423279572591848797L;
+
+  /**
+   * Creates a new instance using the default {@link DateFormat} object
+   * returned by {@link DateFormat#getDateInstance()}.
+   */
+  public DateFormatter()
+  {
+    this(DateFormat.getDateInstance());
+  }
+
+  /**
+   * Creates a new instance of <code>DateFormatter</code> using the
+   * specified <code>DateFormat</code>
+   *
+   * @param format the <code>DateFormat</code> to use
+   */
+  public DateFormatter(DateFormat format)
+  {
+    super();
+    setFormat(format);
+  }
+
+  /**
+   * Sets the format that is used by this <code>DateFormatter</code>.
+   *
+   * @param format the <code>DateFormat</code> to use
+   */
+  public void setFormat(DateFormat format)
+  {
+    super.setFormat(format);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1286 @@
+/* DefaultCaret.java --
+   Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.EventListener;
+
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.EventListenerList;
+import javax.swing.text.Position.Bias;
+
+/**
+ * The default implementation of the {@link Caret} interface.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DefaultCaret extends Rectangle
+  implements Caret, FocusListener, MouseListener, MouseMotionListener
+{
+  
+  /** A text component in the current VM which currently has a
+   * text selection or <code>null</code>.
+   */ 
+  static JTextComponent componentWithSelection;
+
+  /** An implementation of NavigationFilter.FilterBypass which delegates
+   * to the corresponding methods of the <code>DefaultCaret</code>. 
+   * 
+   * @author Robert Schuster (robertschuster at fsfe.org)
+   */
+  class Bypass extends NavigationFilter.FilterBypass
+  {
+
+    public Caret getCaret()
+    {
+      return DefaultCaret.this;
+    }
+
+    public void moveDot(int dot, Bias bias)
+    {
+      DefaultCaret.this.moveDotImpl(dot);
+    }
+
+    public void setDot(int dot, Bias bias)
+    {
+      DefaultCaret.this.setDotImpl(dot);
+    }
+    
+  }
+  
+  /**
+   * Controls the blinking of the caret.
+   *
+   * @author Roman Kennke (kennke at aicas.com)
+   * @author Audrius Meskauskas (AudriusA at Bioinformatics.org)
+   */
+  private class BlinkTimerListener implements ActionListener
+  {
+    /**
+     * Forces the next event to be ignored. The next event should be ignored
+     * if we force the caret to appear. We do not know how long will it take
+     * to fire the comming event; this may be near immediately. Better to leave
+     * the caret visible one iteration longer.
+     */
+    boolean ignoreNextEvent;
+    
+    /**
+     * Receives notification when the blink timer fires and updates the visible
+     * state of the caret.
+     * 
+     * @param event the action event
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      if (ignoreNextEvent)
+        ignoreNextEvent = false;
+      else
+        {
+          visible = !visible;
+          repaint();
+        }
+    }
+  }
+
+  /**
+   * Listens for changes in the text component's document and updates the
+   * caret accordingly.
+   * 
+   * @author Roman Kennke (kennke at aicas.com)
+   */
+  private class DocumentHandler implements DocumentListener
+  {
+    /**
+     * Receives notification that some text attributes have changed. No action
+     * is taken here.
+     *
+     * @param event the document event
+     */
+    public void changedUpdate(DocumentEvent event)
+    {
+      // Nothing to do here.
+    }
+
+    /**
+     * Receives notification that some text has been inserted from the text
+     * component. The caret is moved forward accordingly.
+     *
+     * @param event the document event
+     */
+    public void insertUpdate(DocumentEvent event)
+    {
+      if (policy == ALWAYS_UPDATE || 
+          (SwingUtilities.isEventDispatchThread() && 
+           policy == UPDATE_WHEN_ON_EDT))
+        {        
+          int dot = getDot();
+          setDot(dot + event.getLength());
+        }
+    }
+
+    /**
+     * Receives notification that some text has been removed into the text
+     * component. The caret is moved backwards accordingly.
+     *
+     * @param event the document event
+     */
+    public void removeUpdate(DocumentEvent event)
+    {
+      if (policy == ALWAYS_UPDATE
+          || (SwingUtilities.isEventDispatchThread()
+              && policy == UPDATE_WHEN_ON_EDT))
+        {
+          int dot = getDot();
+          setDot(dot - event.getLength());
+        }
+      else if (policy == NEVER_UPDATE
+               || (! SwingUtilities.isEventDispatchThread()
+                   && policy == UPDATE_WHEN_ON_EDT))
+        {
+          int docLength = event.getDocument().getLength();
+          if (getDot() > docLength)
+            setDot(docLength);
+        }
+    }
+  }
+
+  /**
+   * Listens for property changes on the text document. This is used to add and
+   * remove our document listener, if the document of the text component has
+   * changed.
+   *
+   * @author Roman Kennke (kennke at aicas.com)
+   */
+  private class PropertyChangeHandler implements PropertyChangeListener
+  {
+
+    /**
+     * Receives notification when a property has changed on the text component.
+     * This adds/removes our document listener from the text component's
+     * document when the document changes.
+     *
+     * @param e the property change event
+     */
+    public void propertyChange(PropertyChangeEvent e)
+    {
+      String name = e.getPropertyName(); 
+      
+      if (name.equals("document"))
+        {
+          Document oldDoc = (Document) e.getOldValue();
+          if (oldDoc != null)
+            oldDoc.removeDocumentListener(documentListener);
+          
+          Document newDoc = (Document) e.getNewValue();
+          if (newDoc != null)
+            newDoc.addDocumentListener(documentListener);
+        }
+      else if (name.equals("editable"))
+        {
+          active = (((Boolean) e.getNewValue()).booleanValue()
+                   && textComponent.isEnabled());
+        }
+      else if (name.equals("enabled"))
+        {
+          active = (((Boolean) e.getNewValue()).booleanValue()
+                   && textComponent.isEditable());
+        }
+      
+    }
+    
+  }
+
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 4325555698756477346L;
+  
+  /**
+   * Indicates the Caret position should always be updated after Document
+   * changes even if the updates are not performed on the Event Dispatching
+   * thread.
+   * 
+   * @since 1.5
+   */
+  public static final int ALWAYS_UPDATE = 2;
+
+  /**
+   * Indicates the Caret position should not be changed unless the Document
+   * length becomes less than the Caret position, in which case the Caret
+   * is moved to the end of the Document.
+   * 
+   * @since 1.5
+   */
+  public static final int NEVER_UPDATE = 1;
+  
+  /** 
+   * Indicates the Caret position should be updated only if Document changes
+   * are made on the Event Dispatcher thread.
+   *  
+   * @since 1.5
+   */
+  public static final int UPDATE_WHEN_ON_EDT = 0;
+  
+  /** Keeps track of the current update policy **/
+  int policy = UPDATE_WHEN_ON_EDT;
+    
+  /**
+   * The <code>ChangeEvent</code> that is fired by {@link #fireStateChanged()}.
+   */
+  protected ChangeEvent changeEvent = new ChangeEvent(this);
+
+  /**
+   * Stores all registered event listeners.
+   */
+  protected EventListenerList listenerList = new EventListenerList();
+
+  /**
+   * Our document listener.
+   */
+  DocumentListener documentListener;
+
+  /**
+   * Our property listener.
+   */
+  PropertyChangeListener propertyChangeListener;
+
+  /**
+   * The text component in which this caret is installed.
+   * 
+   * (Package private to avoid synthetic accessor method.)
+   */
+  JTextComponent textComponent;
+
+  /**
+   * Indicates if the selection should be visible or not.
+   */
+  private boolean selectionVisible = true;
+
+  /**
+   * The blink rate of this <code>Caret</code>.
+   */
+  private int blinkRate = 500;
+
+  /**
+   * The current dot position.
+   */
+  private int dot = 0;
+
+  /**
+   * The current mark position.
+   */
+  private int mark = 0;
+
+  /**
+   * The current visual caret position.
+   */
+  private Point magicCaretPosition = null;
+
+  /**
+   * Indicates if this <code>Caret</code> is currently visible or not. This is
+   * package private to avoid an accessor method.
+   */
+  boolean visible = false;
+  
+  /** Indicates whether the text component where the caret is installed is
+   * editable and enabled. If either of these properties is <code>false</code>
+   * the caret is not drawn.
+   */ 
+  boolean active = true;
+
+  /**
+   * The current highlight entry.
+   */
+  private Object highlightEntry;
+
+  private Timer blinkTimer;
+  
+  private BlinkTimerListener blinkListener;
+
+  /**
+   * A <code>NavigationFilter.FilterBypass</code> instance which
+   * is provided to the a <code>NavigationFilter</code> to
+   * unconditionally set or move the caret.
+   */
+  NavigationFilter.FilterBypass bypass;
+
+  /**
+   * Creates a new <code>DefaultCaret</code> instance.
+   */
+  public DefaultCaret()
+  {
+    // Nothing to do here.
+  }
+  
+  /** Returns the caret's <code>NavigationFilter.FilterBypass</code> instance
+   * and creates it if it does not yet exist.
+   * 
+   * @return The caret's <code>NavigationFilter.FilterBypass</code> instance.
+   */
+  private NavigationFilter.FilterBypass getBypass()
+  {
+    return (bypass == null) ? bypass = new Bypass() : bypass;
+  }
+
+  /**
+   * Sets the Caret update policy.
+   *    
+   * @param policy the new policy.  Valid values are:
+   * ALWAYS_UPDATE: always update the Caret position, even when Document
+   * updates don't occur on the Event Dispatcher thread.
+   * NEVER_UPDATE: don't update the Caret position unless the Document
+   * length becomes less than the Caret position (then update the
+   * Caret to the end of the Document).
+   * UPDATE_WHEN_ON_EDT: update the Caret position when the 
+   * Document updates occur on the Event Dispatcher thread.  This is the 
+   * default.
+   * 
+   * @since 1.5
+   * @throws IllegalArgumentException if policy is not one of the above.
+   */
+  public void setUpdatePolicy (int policy)
+  {
+    if (policy != ALWAYS_UPDATE && policy != NEVER_UPDATE
+        && policy != UPDATE_WHEN_ON_EDT)
+      throw new 
+        IllegalArgumentException
+        ("policy must be ALWAYS_UPDATE, NEVER__UPDATE, or UPDATE_WHEN_ON_EDT");
+    this.policy = policy;
+  }
+  
+  /**
+   * Gets the caret update policy.
+   * 
+   * @return the caret update policy.
+   * @since 1.5
+   */
+  public int getUpdatePolicy ()
+  {
+    return policy;
+  }
+  
+  /**
+   * Moves the caret position when the mouse is dragged over the text
+   * component, modifying the selectiony.
+   * 
+   * <p>When the text component where the caret is installed is disabled,
+   * the selection is not change but you can still scroll the text and
+   * update the caret's location.</p>
+   *
+   * @param event the <code>MouseEvent</code> describing the drag operation
+   */
+  public void mouseDragged(MouseEvent event)
+  {
+    if (event.getButton() == MouseEvent.BUTTON1)
+      {
+        if (textComponent.isEnabled())
+          moveCaret(event);
+        else
+          positionCaret(event);
+      }
+  }
+
+  /**
+   * Indicates a mouse movement over the text component. Does nothing here.
+   *
+   * @param event the <code>MouseEvent</code> describing the mouse operation
+   */
+  public void mouseMoved(MouseEvent event)
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * When the click is received from Button 1 then the following actions
+   * are performed here:
+   *
+   * <ul>
+   * <li>If we receive a double click, the caret position (dot) is set
+   *   to the position associated to the mouse click and the word at
+   *   this location is selected. If there is no word at the pointer
+   *   the gap is selected instead.</li>
+   * <li>If we receive a triple click, the caret position (dot) is set
+   *   to the position associated to the mouse click and the line at
+   *   this location is selected.</li>
+   * </ul>
+   *
+   * @param event the <code>MouseEvent</code> describing the click operation
+   */
+  public void mouseClicked(MouseEvent event)
+  {
+    // Do not modify selection if component is disabled.
+    if (!textComponent.isEnabled())
+      return;
+    
+    int count = event.getClickCount();
+    
+    if (event.getButton() == MouseEvent.BUTTON1 && count >= 2)
+      {
+        int newDot = getComponent().viewToModel(event.getPoint());
+        JTextComponent t = getComponent();
+
+        try
+          {
+            if (count == 3)
+              {
+                setDot(Utilities.getRowStart(t, newDot));
+                moveDot( Utilities.getRowEnd(t, newDot));
+              }
+            else
+              {
+                int wordStart = Utilities.getWordStart(t, newDot);
+                
+                // When the mouse points at the offset of the first character
+                // in a word Utilities().getPreviousWord will not return that
+                // word but we want to select that. We have to use
+                // Utilities.getWordStart() to get it.
+                if (newDot == wordStart)
+                  {
+                    setDot(wordStart);
+                    moveDot(Utilities.getWordEnd(t, wordStart));
+                  }
+                else
+                  {
+                    int nextWord = Utilities.getNextWord(t, newDot);
+                    int previousWord = Utilities.getPreviousWord(t, newDot);
+                    int previousWordEnd = Utilities.getWordEnd(t, previousWord);
+                    
+                    // If the user clicked in the space between two words,
+                    // then select the space.
+                    if (newDot >= previousWordEnd && newDot <= nextWord)
+                      {
+                        setDot(previousWordEnd);
+                        moveDot(nextWord);
+                      }
+                    // Otherwise select the word under the mouse pointer.
+                    else
+                      {
+                        setDot(previousWord);
+                        moveDot(previousWordEnd);
+                      }
+                  }
+              }
+          }
+        catch(BadLocationException ble)
+          {
+            // TODO: Swallowing ok here?
+          }
+      }
+    
+  }
+
+  /**
+   * Indicates that the mouse has entered the text component. Nothing is done
+   * here.
+   *
+   * @param event the <code>MouseEvent</code> describing the mouse operation
+   */
+  public void mouseEntered(MouseEvent event)
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * Indicates that the mouse has exited the text component. Nothing is done
+   * here.
+   *
+   * @param event the <code>MouseEvent</code> describing the mouse operation
+   */
+  public void mouseExited(MouseEvent event)
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * If the button 1 is pressed, the caret position is updated to the
+   * position of the mouse click and the text component requests the input
+   * focus if it is enabled. If the SHIFT key is held down, the caret will
+   * be moved, which might select the text between the old and new location.
+   *
+   * @param event the <code>MouseEvent</code> describing the press operation
+   */
+  public void mousePressed(MouseEvent event)
+  {
+    
+    // The implementation assumes that consuming the event makes the AWT event
+    // mechanism forget about this event instance and not transfer focus.
+    // By observing how the RI reacts the following behavior has been
+    // implemented (in regard to text components):
+    // - a left-click moves the caret
+    // - a left-click when shift is held down expands the selection
+    // - a right-click or click with any additional mouse button
+    //   on a text component is ignored
+    // - a middle-click positions the caret and pastes the clipboard
+    //   contents.
+    // - a middle-click when shift is held down is ignored
+
+    if (SwingUtilities.isLeftMouseButton(event))
+      {
+        // Handle the caret.
+        if (event.isShiftDown() && getDot() != -1)
+          {
+            moveCaret(event);
+          }
+        else
+          {
+            positionCaret(event);
+          }
+
+        // Handle the focus.
+        if (textComponent != null && textComponent.isEnabled()
+            && textComponent.isRequestFocusEnabled())
+          {
+            textComponent.requestFocus();
+          }
+
+        // TODO: Handle double click for selecting words.
+      }
+    else if(event.getButton() == MouseEvent.BUTTON2)
+      {
+        // Special handling for X11-style pasting.
+        if (! event.isShiftDown())
+          {
+            positionCaret(event);
+            textComponent.paste();
+          }
+      }
+  }
+
+  /**
+   * Indicates that a mouse button has been released on the text component.
+   * Nothing is done here.
+   *
+   * @param event the <code>MouseEvent</code> describing the mouse operation
+   */
+  public void mouseReleased(MouseEvent event)
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * Sets the caret to <code>visible</code> if the text component is editable.
+   *
+   * @param event the <code>FocusEvent</code>
+   */
+  public void focusGained(FocusEvent event)
+  {
+    if (textComponent.isEditable())
+      {
+        setVisible(true);    
+        updateTimerStatus();
+      }
+  }
+
+  /**
+   * Sets the caret to <code>invisible</code>.
+   * 
+   * @param event the <code>FocusEvent</code>
+   */
+  public void focusLost(FocusEvent event)
+  {
+    if (textComponent.isEditable() && event.isTemporary() == false)
+      {
+        setVisible(false);
+        
+        // Stop the blinker, if running.
+        if (blinkTimer != null && blinkTimer.isRunning())
+          blinkTimer.stop();
+      }
+  }
+  
+  /**
+   * Install (if not present) and start the timer, if the caret must blink. The
+   * caret does not blink if it is invisible, or the component is disabled or
+   * not editable.
+   */
+  private void updateTimerStatus()
+  {
+    if (textComponent.isEnabled() && textComponent.isEditable())
+      {
+        if (blinkTimer == null)
+          initBlinkTimer();
+        if (!blinkTimer.isRunning())
+          blinkTimer.start();
+      }
+    else
+      {
+        if (blinkTimer != null)
+          blinkTimer.stop();
+      }
+  }
+
+  /**
+   * Moves the caret to the position specified in the <code>MouseEvent</code>.
+   * This will cause a selection if the dot and mark are different.
+   *
+   * @param event the <code>MouseEvent</code> from which to fetch the position
+   */
+  protected void moveCaret(MouseEvent event)
+  {
+    int newDot = getComponent().viewToModel(event.getPoint());
+    moveDot(newDot);
+  }
+
+  /**
+   * Repositions the caret to the position specified in the
+   * <code>MouseEvent</code>.
+   *
+   * @param event the <code>MouseEvent</code> from which to fetch the position
+   */
+  protected void positionCaret(MouseEvent event)
+  {
+    int newDot = getComponent().viewToModel(event.getPoint());
+    setDot(newDot);
+  }
+
+  /**
+   * Deinstalls this <code>Caret</code> from the specified
+   * <code>JTextComponent</code>. This removes any listeners that have been
+   * registered by this <code>Caret</code>.
+   *
+   * @param c the text component from which to install this caret
+   */
+  public void deinstall(JTextComponent c)
+  {
+    textComponent.removeFocusListener(this);
+    textComponent.removeMouseListener(this);
+    textComponent.removeMouseMotionListener(this);
+    textComponent.getDocument().removeDocumentListener(documentListener);
+    documentListener = null;
+    textComponent.removePropertyChangeListener(propertyChangeListener);
+    propertyChangeListener = null;
+    textComponent = null;
+
+    // Deinstall blink timer if present.
+    if (blinkTimer != null)
+      blinkTimer.stop();
+    blinkTimer = null;
+  }
+
+  /**
+   * Installs this <code>Caret</code> on the specified
+   * <code>JTextComponent</code>. This registers a couple of listeners
+   * on the text component.
+   *
+   * @param c the text component on which to install this caret
+   */
+  public void install(JTextComponent c)
+  {
+    textComponent = c;
+    textComponent.addFocusListener(this);
+    textComponent.addMouseListener(this);
+    textComponent.addMouseMotionListener(this);
+    propertyChangeListener = new PropertyChangeHandler();
+    textComponent.addPropertyChangeListener(propertyChangeListener);
+    documentListener = new DocumentHandler();
+    
+    Document doc = textComponent.getDocument();
+    if (doc != null)
+      doc.addDocumentListener(documentListener);
+    
+    active = textComponent.isEditable() && textComponent.isEnabled();
+
+    repaint();
+  }
+
+  /**
+   * Sets the current visual position of this <code>Caret</code>.
+   *
+   * @param p the Point to use for the saved location. May be <code>null</code>
+   *        to indicate that there is no visual location
+   */
+  public void setMagicCaretPosition(Point p)
+  {
+    magicCaretPosition = p;
+  }
+
+  /**
+   * Returns the current visual position of this <code>Caret</code>.
+   *
+   * @return the current visual position of this <code>Caret</code>
+   *
+   * @see #setMagicCaretPosition
+   */
+  public Point getMagicCaretPosition()
+  {
+    return magicCaretPosition;
+  }
+
+  /**
+   * Returns the current position of the <code>mark</code>. The
+   * <code>mark</code> marks the location in the <code>Document</code> that
+   * is the end of a selection. If there is no selection, the <code>mark</code>
+   * is the same as the <code>dot</code>.
+   *
+   * @return the current position of the mark
+   */
+  public int getMark()
+  {
+    return mark;
+  }
+  
+  private void clearHighlight()
+  {
+    Highlighter highlighter = textComponent.getHighlighter();
+    
+    if (highlighter == null)
+      return;
+    
+    if (selectionVisible)
+      {
+    try
+      {
+        if (highlightEntry != null)
+          highlighter.changeHighlight(highlightEntry, 0, 0);
+        
+        // Free the global variable which stores the text component with an active
+        // selection.
+        if (componentWithSelection == textComponent)
+          componentWithSelection = null;
+      }
+    catch (BadLocationException e)
+      {
+        // This should never happen.
+        throw new InternalError();
+      }
+      }
+    else
+      {
+    if (highlightEntry != null)
+      {
+        highlighter.removeHighlight(highlightEntry);
+        highlightEntry = null;
+      }
+      }
+  }
+  
+  private void handleHighlight()
+  {
+    Highlighter highlighter = textComponent.getHighlighter();
+    
+    if (highlighter == null)
+      return;
+    
+    int p0 = Math.min(dot, mark);
+    int p1 = Math.max(dot, mark);
+    
+    if (selectionVisible)
+      {
+	try
+	  {
+	    if (highlightEntry == null)
+	      highlightEntry = highlighter.addHighlight(p0, p1, getSelectionPainter());
+	    else
+	      highlighter.changeHighlight(highlightEntry, p0, p1);
+            
+            // If another component currently has a text selection clear that selection
+            // first.
+            if (componentWithSelection != null)
+              if (componentWithSelection != textComponent)
+                {
+                  Caret c = componentWithSelection.getCaret();
+                  c.setDot(c.getDot());
+                }
+            componentWithSelection = textComponent;
+            
+	  }
+	catch (BadLocationException e)
+	  {
+	    // This should never happen.
+	    throw new InternalError();
+	  }
+      }
+    else
+      {
+	if (highlightEntry != null)
+	  {
+	    highlighter.removeHighlight(highlightEntry);
+	    highlightEntry = null;
+	  }
+      }
+  }
+
+  /**
+   * Sets the visiblity state of the selection.
+   *
+   * @param v <code>true</code> if the selection should be visible,
+   *        <code>false</code> otherwise
+   */
+  public void setSelectionVisible(boolean v)
+  {
+    if (selectionVisible == v)
+      return;
+    
+    selectionVisible = v;
+    handleHighlight();
+    repaint();
+  }
+
+  /**
+   * Returns <code>true</code> if the selection is currently visible,
+   * <code>false</code> otherwise.
+   *
+   * @return <code>true</code> if the selection is currently visible,
+   *         <code>false</code> otherwise
+   */
+  public boolean isSelectionVisible()
+  {
+    return selectionVisible;
+  }
+
+  /**
+   * Causes the <code>Caret</code> to repaint itself.
+   */
+  protected final void repaint()
+  {
+    getComponent().repaint(x, y, width, height);
+  }
+
+  /**
+   * Paints this <code>Caret</code> using the specified <code>Graphics</code>
+   * context.
+   *
+   * @param g the graphics context to use
+   */
+  public void paint(Graphics g)
+  {
+    JTextComponent comp = getComponent();
+    if (comp == null)
+      return;
+
+    // Make sure the dot has a sane position.
+    dot = Math.min(dot, textComponent.getDocument().getLength());
+    dot = Math.max(dot, 0);
+
+    Rectangle rect = null;
+
+    try
+      {
+        rect = textComponent.modelToView(dot);
+      }
+    catch (BadLocationException e)
+      {
+        // Let's ignore that. This shouldn't really occur. But if it
+        // does (it seems that this happens when the model is mutating),
+        // it causes no real damage. Uncomment this for debugging.
+        // e.printStackTrace();
+      }
+
+    if (rect == null)
+      return;
+
+    // Check if paint has possibly been called directly, without a previous
+    // call to damage(). In this case we need to do some cleanup first.
+    if ((x != rect.x) || (y != rect.y))
+      {
+        repaint(); // Erase previous location of caret.
+        x = rect.x;
+        y = rect.y;
+        width = 1;
+        height = rect.height;
+      }
+
+    // Now draw the caret on the new position if visible.
+    if (visible && active)
+      {
+        g.setColor(textComponent.getCaretColor());
+        g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height - 1);
+      }
+  }
+
+  /**
+   * Returns all registered event listeners of the specified type.
+   *
+   * @param listenerType the type of listener to return
+   *
+   * @return all registered event listeners of the specified type
+   */
+  public EventListener[] getListeners(Class listenerType)
+  {
+    return listenerList.getListeners(listenerType);
+  }
+
+  /**
+   * Registers a {@link ChangeListener} that is notified whenever that state
+   * of this <code>Caret</code> changes.
+   *
+   * @param listener the listener to register to this caret
+   */
+  public void addChangeListener(ChangeListener listener)
+  {
+    listenerList.add(ChangeListener.class, listener);
+  }
+
+  /**
+   * Removes a {@link ChangeListener} from the list of registered listeners.
+   *
+   * @param listener the listener to remove
+   */
+  public void removeChangeListener(ChangeListener listener)
+  {
+    listenerList.remove(ChangeListener.class, listener);
+  }
+
+  /**
+   * Returns all registered {@link ChangeListener}s of this <code>Caret</code>.
+   *
+   * @return all registered {@link ChangeListener}s of this <code>Caret</code>
+   */
+  public ChangeListener[] getChangeListeners()
+  {
+    return (ChangeListener[]) getListeners(ChangeListener.class);
+  }
+
+  /**
+   * Notifies all registered {@link ChangeListener}s that the state
+   * of this <code>Caret</code> has changed.
+   */
+  protected void fireStateChanged()
+  {
+    ChangeListener[] listeners = getChangeListeners();
+
+    for (int index = 0; index < listeners.length; ++index)
+      listeners[index].stateChanged(changeEvent);
+  }
+
+  /**
+   * Returns the <code>JTextComponent</code> on which this <code>Caret</code>
+   * is installed.
+   *
+   * @return the <code>JTextComponent</code> on which this <code>Caret</code>
+   *         is installed
+   */
+  protected final JTextComponent getComponent()
+  {
+    return textComponent;
+  }
+
+  /**
+   * Returns the blink rate of this <code>Caret</code> in milliseconds.
+   * A value of <code>0</code> means that the caret does not blink.
+   *
+   * @return the blink rate of this <code>Caret</code> or <code>0</code> if
+   *         this caret does not blink
+   */
+  public int getBlinkRate()
+  {
+    return blinkRate;
+  }
+
+  /**
+   * Sets the blink rate of this <code>Caret</code> in milliseconds.
+   * A value of <code>0</code> means that the caret does not blink.
+   *
+   * @param rate the new blink rate to set
+   */
+  public void setBlinkRate(int rate)
+  {
+    if (blinkTimer != null)
+      blinkTimer.setDelay(rate);
+    blinkRate = rate;
+  }
+
+  /**
+   * Returns the current position of this <code>Caret</code> within the
+   * <code>Document</code>.
+   *
+   * @return the current position of this <code>Caret</code> within the
+   *         <code>Document</code>
+   */
+  public int getDot()
+  {
+    return dot;
+  }
+
+  /**
+   * Moves the <code>dot</code> location without touching the
+   * <code>mark</code>. This is used when making a selection.
+   *
+   * <p>If the underlying text component has a {@link NavigationFilter}
+   * installed the caret will call the corresponding method of that object.</p>
+   * 
+   * @param dot the location where to move the dot
+   *
+   * @see #setDot(int)
+   */
+  public void moveDot(int dot)
+  {
+    NavigationFilter filter = textComponent.getNavigationFilter();
+    if (filter != null)
+      filter.moveDot(getBypass(), dot, Bias.Forward);
+    else
+      moveDotImpl(dot);
+  }
+  
+  void moveDotImpl(int dot)
+  {
+    if (dot >= 0)
+      {
+        Document doc = textComponent.getDocument();
+        if (doc != null)
+          this.dot = Math.min(dot, doc.getLength());
+        this.dot = Math.max(this.dot, 0);
+        
+        handleHighlight();
+
+        appear();
+
+        adjustVisibility(this);
+      }
+  }
+
+  /**
+   * Sets the current position of this <code>Caret</code> within the
+   * <code>Document</code>. This also sets the <code>mark</code> to the new
+   * location.
+   * 
+   * <p>If the underlying text component has a {@link NavigationFilter}
+   * installed the caret will call the corresponding method of that object.</p>
+   * 
+   * @param dot
+   *          the new position to be set
+   * @see #moveDot(int)
+   */
+  public void setDot(int dot)
+  {
+    NavigationFilter filter = textComponent.getNavigationFilter();
+    if (filter != null)
+      filter.setDot(getBypass(), dot, Bias.Forward);
+    else
+      setDotImpl(dot);
+  }
+  
+  void setDotImpl(int dot)
+  {
+    if (dot >= 0)
+      {        
+        Document doc = textComponent.getDocument();
+        if (doc != null)
+          this.dot = Math.min(dot, doc.getLength());
+        this.dot = Math.max(this.dot, 0);
+        this.mark = this.dot;
+        
+        clearHighlight();
+        
+        appear();
+        
+        adjustVisibility(this);
+      }
+  }
+  
+  /**
+   * Show the caret (may be hidden due blinking) and adjust the timer not to
+   * hide it (possibly immediately).
+   * 
+   * @author Audrius Meskauskas (AudriusA at Bioinformatics.org)
+   */
+  void appear()
+  {
+    // All machinery is only required if the carret is blinking.
+    if (blinkListener != null)
+      {
+        blinkListener.ignoreNextEvent = true;
+
+        // If the caret is visible, erase the current position by repainting
+        // over.
+        if (visible)
+          repaint();
+
+        // Draw the caret in the new position.
+        visible = true;
+
+        Rectangle area = null;
+	int dot = getDot();
+        try
+          {
+            area = getComponent().modelToView(dot);
+          }
+        catch (BadLocationException e)
+          {
+            // Let's ignore that. This shouldn't really occur. But if it
+            // does (it seems that this happens when the model is mutating),
+            // it causes no real damage. Uncomment this for debugging.
+            // e.printStackTrace();
+          }
+        if (area != null)
+          damage(area);
+      }
+    repaint();
+  }  
+
+  /**
+   * Returns <code>true</code> if this <code>Caret</code> is blinking,
+   * and <code>false</code> if not. The returned value is independent of
+   * the visiblity of this <code>Caret</code> as returned by {@link #isVisible()}.
+   *
+   * @return <code>true</code> if this <code>Caret</code> is blinking,
+   *         and <code>false</code> if not.
+   * @see #isVisible()
+   * @since 1.5
+   */
+  public boolean isActive()
+  {
+    if (blinkTimer != null)
+      return blinkTimer.isRunning();
+
+    return false;
+  }
+
+  /**
+   * Returns <code>true</code> if this <code>Caret</code> is currently visible,
+   * and <code>false</code> if it is not.
+   *
+   * @return <code>true</code> if this <code>Caret</code> is currently visible,
+   *         and <code>false</code> if it is not
+   */
+  public boolean isVisible()
+  {
+    return visible && active;
+  }
+
+  /**
+   * Sets the visibility state of the caret. <code>true</code> shows the
+   * <code>Caret</code>, <code>false</code> hides it.
+   *
+   * @param v the visibility to set
+   */  
+  public void setVisible(boolean v)
+  {
+    if (v != visible)
+      {
+        visible = v;
+        updateTimerStatus();
+        Rectangle area = null;
+	int dot = getDot();
+        try
+          {            
+            area = getComponent().modelToView(dot);
+          }
+        catch (BadLocationException e)
+          {
+	    AssertionError ae;
+	    ae = new AssertionError("Unexpected bad caret location: " + dot);
+	    ae.initCause(e);
+	    throw ae;
+          }
+        if (area != null)
+          damage(area);
+      }
+  }
+
+  /**
+   * Returns the {@link Highlighter.HighlightPainter} that should be used
+   * to paint the selection.
+   *
+   * @return the {@link Highlighter.HighlightPainter} that should be used
+   *         to paint the selection
+   */
+  protected Highlighter.HighlightPainter getSelectionPainter()
+  {
+    return DefaultHighlighter.DefaultPainter;
+  }
+
+  /**
+   * Updates the carets rectangle properties to the specified rectangle and
+   * repaints the caret.
+   *
+   * @param r the rectangle to set as the caret rectangle
+   */
+  protected void damage(Rectangle r)
+  {
+    if (r == null)
+      return;
+    x = r.x;
+    y = r.y;
+    width = 1;
+    // height is normally set in paint and we leave it untouched. However, we
+    // must set a valid value here, since otherwise the painting mechanism
+    // sets a zero clip and never calls paint.
+    if (height <= 0)
+      try
+        {
+          height = textComponent.modelToView(dot).height;
+        }
+      catch (BadLocationException ble)
+        {
+          // Should not happen.
+          throw new InternalError("Caret location not within document range.");
+        }
+      
+    repaint();
+  }
+
+  /**
+   * Adjusts the text component so that the caret is visible. This default
+   * implementation simply calls
+   * {@link JComponent#scrollRectToVisible(Rectangle)} on the text component.
+   * Subclasses may wish to change this.
+   */
+  protected void adjustVisibility(Rectangle rect)
+  {
+    getComponent().scrollRectToVisible(rect);
+  }
+
+  /**
+   * Initializes the blink timer.
+   */
+  private void initBlinkTimer()
+  {
+    // Setup the blink timer.
+    blinkListener = new BlinkTimerListener();
+    blinkTimer = new Timer(getBlinkRate(), blinkListener);
+    blinkTimer.setRepeats(true);
+  }
+  
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1657 @@
+/* DefaultEditorKit.java --
+   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+
+import javax.swing.Action;
+import javax.swing.SwingConstants;
+
+/**
+ * The default implementation of {@link EditorKit}. This <code>EditorKit</code>
+ * a plain text <code>Document</code> and several commands that together
+ * make up a basic editor, like cut / copy + paste.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ * @author Robert Schuster (robertschuster at fsfe.org)
+ */
+public class DefaultEditorKit extends EditorKit
+{
+  static class SelectionPreviousWordAction
+      extends TextAction
+  {
+    SelectionPreviousWordAction()
+    {
+      super(selectionPreviousWordAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.moveDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+
+  static class SelectionNextWordAction
+      extends TextAction
+  {
+    SelectionNextWordAction()
+    {
+      super(selectionNextWordAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getNextWord(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.moveDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+
+  static class SelectionBeginWordAction extends TextAction
+  {
+    SelectionBeginWordAction()
+    {
+      super(selectionBeginWordAction);
+    }
+  
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getWordStart(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.moveDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+  
+  static class SelectionEndWordAction extends TextAction
+  {
+    SelectionEndWordAction()
+    {
+      super(selectionEndWordAction);
+    }
+  
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getWordEnd(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.moveDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+  
+  static class BeginWordAction extends TextAction
+  {
+    BeginWordAction()
+    {
+      super(beginWordAction);
+    }
+  
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getWordStart(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.setDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+  
+  static class EndWordAction extends TextAction
+  {
+    EndWordAction()
+    {
+      super(endWordAction);
+    }
+  
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getWordEnd(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.setDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+
+  static class PreviousWordAction
+      extends TextAction
+  {
+    PreviousWordAction()
+    {
+      super(previousWordAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.setDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+
+  static class NextWordAction
+      extends TextAction
+  {
+    NextWordAction()
+    {
+      super(nextWordAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      try
+        {
+          JTextComponent t = getTextComponent(event);
+      
+          if (t != null)
+            {
+              int offs = Utilities.getNextWord(t, t.getCaretPosition());
+      
+              Caret c = t.getCaret();
+              c.setDot(offs);
+              c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+            }
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+
+  static class SelectAllAction
+      extends TextAction
+  {
+    SelectAllAction()
+    {
+      super(selectAllAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      int offs = t.getDocument().getLength();
+      Caret c = t.getCaret();
+      c.setDot(0);
+      c.moveDot(offs);
+      
+      try
+      {   
+        c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+      }
+    catch(BadLocationException ble)
+      {
+        // Can't happen.
+      }
+    }
+  }
+
+  static class SelectionBeginAction
+      extends TextAction
+  {
+    SelectionBeginAction()
+    {
+      super(selectionBeginAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      Caret c = t.getCaret();
+      c.moveDot(0);
+      try
+        {   
+          c.setMagicCaretPosition(t.modelToView(0).getLocation());
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+
+  static class SelectionEndAction
+      extends TextAction
+  {
+    SelectionEndAction()
+    {
+      super(selectionEndAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      int offs = t.getDocument().getLength();
+      Caret c = t.getCaret();
+      c.moveDot(offs);
+      try
+        {   
+          c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+  
+  static class SelectionBeginLineAction
+    extends TextAction
+  {
+    
+    SelectionBeginLineAction()
+    {
+      super(selectionBeginLineAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      Caret c = t.getCaret();
+      try
+        {
+          int offs = Utilities.getRowStart(t, c.getDot());
+          c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+        }
+      catch(BadLocationException ble)
+      {
+        // Can't happen.
+      }
+
+    }
+  }
+
+  static class SelectionEndLineAction
+      extends TextAction
+  {
+    SelectionEndLineAction()
+    {
+      super(selectionEndLineAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      Caret c = t.getCaret();
+      try
+        {
+          int offs = Utilities.getRowEnd(t, c.getDot());
+          c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+        }
+      catch(BadLocationException ble)
+        {
+        // Can't happen.
+        }
+
+    }
+  }
+  
+  static class SelectLineAction extends TextAction
+  {
+    SelectLineAction()
+    {
+      super(selectLineAction);
+    }
+  
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      Caret c = t.getCaret();
+      try
+        {
+          int offs1 = Utilities.getRowStart(t, c.getDot());
+          int offs2 = Utilities.getRowEnd(t, c.getDot());
+          
+          c.setDot(offs2);
+          c.moveDot(offs1);
+          
+          c.setMagicCaretPosition(t.modelToView(offs2).getLocation());
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+  
+  static class SelectWordAction extends TextAction
+  {
+    SelectWordAction()
+    {
+      super(selectWordAction);
+    }
+  
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      Caret c = t.getCaret();
+      int dot = c.getDot();
+
+      try
+        {
+          int wordStart = Utilities.getWordStart(t, dot);
+      
+          if (dot == wordStart)
+            {
+              // Current cursor position is on the first character in a word.
+              c.setDot(wordStart);
+              c.moveDot(Utilities.getWordEnd(t, wordStart));
+            }
+          else
+            {
+              // Current cursor position is not on the first character
+              // in a word. 
+              int nextWord = Utilities.getNextWord(t, dot);
+              int previousWord = Utilities.getPreviousWord(t, dot);
+              int previousWordEnd = Utilities.getWordEnd(t, previousWord);
+              
+              // Cursor position is in the space between two words. In such a
+              // situation just select the space.
+              if (dot >= previousWordEnd && dot <= nextWord)
+                {
+                  c.setDot(previousWordEnd);
+                  c.moveDot(nextWord);
+                }
+              else
+                {
+                  // Cursor position is inside a word. Just select it then.
+                  c.setDot(previousWord);
+                  c.moveDot(previousWordEnd);
+                }
+            }
+
+          // If the position was updated change the magic caret position
+          // as well.
+          if (c.getDot() != dot)
+            c.setMagicCaretPosition(t.modelToView(c.getDot()).getLocation());
+          
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+
+  static class SelectionDownAction
+      extends TextAction.VerticalMovementAction
+  {
+    SelectionDownAction()
+    {
+      super(selectionDownAction, SwingConstants.SOUTH);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.moveDot(offs);
+    }
+    
+  }
+
+  static class SelectionUpAction
+  extends TextAction.VerticalMovementAction
+  {
+    SelectionUpAction()
+    {
+      super(selectionUpAction, SwingConstants.NORTH);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.moveDot(offs);
+    }
+
+  }
+
+  static class SelectionForwardAction
+      extends TextAction.HorizontalMovementAction
+  {
+    SelectionForwardAction()
+    {
+      super(selectionForwardAction, SwingConstants.EAST);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.moveDot(offs);
+    }
+  }
+
+  static class SelectionBackwardAction
+      extends TextAction.HorizontalMovementAction
+  {
+    SelectionBackwardAction()
+    {
+      super(selectionBackwardAction, SwingConstants.WEST);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.moveDot(offs);
+    }
+  }
+
+  static class DownAction
+      extends TextAction.VerticalMovementAction
+  {
+    DownAction()
+    {
+      super(downAction, SwingConstants.SOUTH);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.setDot(offs);
+    }
+  }
+
+  static class UpAction
+      extends TextAction.VerticalMovementAction
+  {
+    UpAction()
+    {
+      super(upAction, SwingConstants.NORTH);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.setDot(offs);
+    }
+    
+  }
+
+  static class ForwardAction
+      extends TextAction.HorizontalMovementAction
+  {
+    ForwardAction()
+    {
+      super(forwardAction, SwingConstants.EAST);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.setDot(offs);
+    }
+    
+  }
+
+  static class BackwardAction
+      extends TextAction.HorizontalMovementAction
+  {
+    BackwardAction()
+    {
+      super(backwardAction, SwingConstants.WEST);
+    }
+
+    protected void actionPerformedImpl(Caret c, int offs)
+    {
+      c.setDot(offs);
+    }
+    
+  }
+
+  static class DeletePrevCharAction
+      extends TextAction
+  {
+    DeletePrevCharAction()
+    {
+      super(deletePrevCharAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      if (t != null)
+        {
+          try
+            {
+              int pos = t.getSelectionStart();
+              int len = t.getSelectionEnd() - pos;
+              
+              if (len > 0)
+                  t.getDocument().remove(pos, len);
+              else if (pos > 0)
+                {
+                  pos--;
+                  t.getDocument().remove(pos, 1);
+                  Caret c = t.getCaret();
+                  c.setDot(pos);
+                  c.setMagicCaretPosition(t.modelToView(pos).getLocation());
+                }
+            }
+          catch (BadLocationException e)
+            {
+              // FIXME: we're not authorized to throw this.. swallow it?
+            }
+        }
+    }
+  }
+
+  static class DeleteNextCharAction
+      extends TextAction
+  {
+    DeleteNextCharAction()
+    {
+      super(deleteNextCharAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      if (t != null)
+        {
+          try
+            {
+              int pos = t.getSelectionStart();
+              int len = t.getSelectionEnd() - pos;
+              
+              if (len > 0)
+                  t.getDocument().remove(pos, len);
+              else if (pos < t.getDocument().getLength())
+                  t.getDocument().remove(pos, 1);
+    
+              Caret c = t.getCaret();
+              c.setDot(pos);
+              c.setMagicCaretPosition(t.modelToView(pos).getLocation());
+            }
+          catch (BadLocationException e)
+            {
+              // FIXME: we're not authorized to throw this.. swallow it?
+            }
+        }
+    }
+  }
+
+  static class EndLineAction
+      extends TextAction
+  {
+    EndLineAction()
+    {
+      super(endLineAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      try
+     {
+       int offs = Utilities.getRowEnd(t, t.getCaretPosition());
+       
+       if (offs > -1)
+         {
+           Caret c = t.getCaret();
+           c.setDot(offs);
+           c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+         }
+     }
+     catch (BadLocationException ble)
+     {
+       // Nothing to do here
+     }
+    }
+  }
+
+  static class BeginLineAction
+      extends TextAction
+  {
+    BeginLineAction()
+    {
+      super(beginLineAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      try
+      {
+        int offs = Utilities.getRowStart(t, t.getCaretPosition());
+        
+        if (offs > -1)
+          {
+            Caret c = t.getCaret();
+            c.setDot(offs);
+            c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+          }
+      }
+      catch (BadLocationException ble)
+      {
+        // Do nothing here.
+      }
+    }
+  }
+
+  static class BeginAction extends TextAction
+  {
+    
+    BeginAction()
+    {
+      super(beginAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      Caret c = t.getCaret();
+      c.setDot(0);
+      try
+      {   
+        c.setMagicCaretPosition(t.modelToView(0).getLocation());
+      }
+      catch(BadLocationException ble)
+      {
+        // Can't happen.
+      }
+    }
+  }
+
+  static class EndAction extends TextAction
+  {
+      
+    EndAction()
+    {
+      super(endAction);
+    }
+
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      int offs = t.getDocument().getLength();
+      Caret c = t.getCaret();
+      c.setDot(offs);
+      try
+        {   
+          c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+        }
+      catch(BadLocationException ble)
+        {
+          // Can't happen.
+        }
+    }
+  }
+  
+  /**
+   * Creates a beep on the PC speaker.
+   *
+   * @see Toolkit#beep()
+   */
+  public static class BeepAction extends TextAction
+  {
+    /**
+     * Creates a new <code>BeepAction</code>.
+     */
+    public BeepAction()
+    {
+      super(beepAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      Toolkit.getDefaultToolkit().beep();
+    }
+  }
+
+  /**
+   * Copies the selected content into the system clipboard.
+   *
+   * @see Toolkit#getSystemClipboard()
+   * @see CutAction
+   * @see PasteAction
+   */
+  public static class CopyAction extends TextAction
+  {
+
+    /**
+     * Create a new <code>CopyAction</code>.
+     */
+    public CopyAction()
+    {
+      super(copyAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      getTextComponent(event).copy();
+    }
+  }
+
+
+  /**
+   * Copies the selected content into the system clipboard and deletes the
+   * selection.
+   *
+   * @see Toolkit#getSystemClipboard()
+   * @see CopyAction
+   * @see PasteAction
+   */
+  public static class CutAction extends TextAction
+  {
+
+    /**
+     * Create a new <code>CutAction</code>.
+     */
+    public CutAction()
+    {
+      super(cutAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      getTextComponent(event).cut();
+    }
+  }
+
+  /**
+   * Copies content from the system clipboard into the editor.
+   *
+   * @see Toolkit#getSystemClipboard()
+   * @see CopyAction
+   * @see CutAction
+   */
+  public static class PasteAction extends TextAction
+  {
+
+    /**
+     * Create a new <code>PasteAction</code>.
+     */
+    public PasteAction()
+    {
+      super(pasteAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      getTextComponent(event).paste();
+    }
+  }
+
+  /**
+   * This action is executed as default action when a KEY_TYPED
+   * event is received and no keymap entry exists for that. The purpose
+   * of this action is to filter out a couple of characters. This includes
+   * the control characters and characters with the ALT-modifier.
+   * 
+   * If an event does not get filtered, it is inserted into the document
+   * of the text component. If there is some text selected in the text
+   * component, this text will be replaced.
+   */
+  public static class DefaultKeyTypedAction 
+    extends TextAction
+  {
+
+    /**
+     * Creates a new <code>DefaultKeyTypedAction</code>.
+     */
+    public DefaultKeyTypedAction()
+    {
+      super(defaultKeyTypedAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      // first we filter the following events:
+      // - control characters
+      // - key events with the ALT modifier (FIXME: filter that too!)
+      int cp = event.getActionCommand().codePointAt(0);
+      if (Character.isISOControl(cp))
+        return;
+
+      JTextComponent t = getTextComponent(event);
+      if (t != null && t.isEnabled() && t.isEditable())
+        t.replaceSelection(event.getActionCommand());
+    }    
+  }
+
+  /**
+   * This action inserts a newline character into the document
+   * of the text component. This is typically triggered by hitting
+   * ENTER on the keyboard.
+   */
+  public static class InsertBreakAction extends TextAction
+  {
+
+    /**
+     * Creates a new <code>InsertBreakAction</code>.
+     */
+    public InsertBreakAction()
+    {
+      super(insertBreakAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      t.replaceSelection("\n");
+    }
+  }
+
+  /**
+   * Places content into the associated editor. If there currently is a
+   * selection, this selection is replaced.
+   */
+  // FIXME: Figure out what this Action is supposed to do. Obviously text
+  // that is entered by the user is inserted through DefaultKeyTypedAction.
+  public static class InsertContentAction extends TextAction
+  {
+
+    /**
+     * Creates a new <code>InsertContentAction</code>.
+     */
+    public InsertContentAction()
+    {
+      super(insertContentAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      // FIXME: Figure out what this Action is supposed to do. Obviously text
+      // that is entered by the user is inserted through DefaultKeyTypedAction.
+    }
+  }
+
+  /**
+   * Inserts a TAB character into the text editor.
+   */
+  public static class InsertTabAction extends TextAction
+  {
+
+    /**
+     * Creates a new <code>TabAction</code>.
+     */
+    public InsertTabAction()
+    {
+      super(insertTabAction);
+    }
+
+    /**
+     * Performs the <code>Action</code>.
+     *
+     * @param event the action event describing the user action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      JTextComponent t = getTextComponent(event);
+      t.replaceSelection("\t");
+    }
+  }
+
+  /**
+   * The serial version of DefaultEditorKit.
+   */
+  private static final long serialVersionUID = 9017245433028523428L;
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one character
+   * backwards.
+   *
+   * @see #getActions()
+   */
+  public static final String backwardAction = "caret-backward";
+
+  /**
+   * The name of the <code>Action</code> that creates a beep in the speaker.
+   *
+   * @see #getActions()
+   */
+  public static final String beepAction = "beep";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the <code>Document</code>.
+   *
+   * @see #getActions()
+   */
+  public static final String beginAction = "caret-begin";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the current line.
+   *
+   * @see #getActions()
+   */
+  public static final String beginLineAction = "caret-begin-line";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the current paragraph.
+   *
+   * @see #getActions()
+   */
+  public static final String beginParagraphAction = "caret-begin-paragraph";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the current word.
+   *
+   * @see #getActions()
+   */
+  public static final String beginWordAction = "caret-begin-word";
+
+  /**
+   * The name of the <code>Action</code> that copies the selected content
+   * into the system clipboard.
+   *
+   * @see #getActions()
+   */
+  public static final String copyAction = "copy-to-clipboard";
+
+  /**
+   * The name of the <code>Action</code> that copies the selected content
+   * into the system clipboard and removes the selection.
+   *
+   * @see #getActions()
+   */
+  public static final String cutAction = "cut-to-clipboard";
+
+  /**
+   * The name of the <code>Action</code> that is performed by default if
+   * a key is typed and there is no keymap entry.
+   *
+   * @see #getActions()
+   */
+  public static final String defaultKeyTypedAction = "default-typed";
+
+  /**
+   * The name of the <code>Action</code> that deletes the character that
+   * follows the current caret position.
+   *
+   * @see #getActions()
+   */
+  public static final String deleteNextCharAction = "delete-next";
+
+  /**
+   * The name of the <code>Action</code> that deletes the character that
+   * precedes the current caret position.
+   *
+   * @see #getActions()
+   */
+  public static final String deletePrevCharAction = "delete-previous";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one line down.
+   *
+   * @see #getActions()
+   */
+  public static final String downAction = "caret-down";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the <code>Document</code>.
+   *
+   * @see #getActions()
+   */
+  public static final String endAction = "caret-end";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the current line.
+   *
+   * @see #getActions()
+   */
+  public static final String endLineAction = "caret-end-line";
+
+  /**
+   * When a document is read and an CRLF is encountered, then we add a property
+   * with this name and a value of "\r\n".
+   */
+  public static final String EndOfLineStringProperty = "__EndOfLine__";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the current paragraph.
+   *
+   * @see #getActions()
+   */
+  public static final String endParagraphAction = "caret-end-paragraph";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the current word.
+   *
+   * @see #getActions()
+   */
+  public static final String endWordAction = "caret-end-word";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one character
+   * forward.
+   *
+   * @see #getActions()
+   */
+  public static final String forwardAction = "caret-forward";
+
+  /**
+   * The name of the <code>Action</code> that inserts a line break.
+   *
+   * @see #getActions()
+   */
+  public static final String insertBreakAction = "insert-break";
+
+  /**
+   * The name of the <code>Action</code> that inserts some content.
+   *
+   * @see #getActions()
+   */
+  public static final String insertContentAction = "insert-content";
+
+  /**
+   * The name of the <code>Action</code> that inserts a TAB.
+   *
+   * @see #getActions()
+   */
+  public static final String insertTabAction = "insert-tab";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the next word.
+   *
+   * @see #getActions()
+   */
+  public static final String nextWordAction = "caret-next-word";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one page down.
+   *
+   * @see #getActions()
+   */
+  public static final String pageDownAction = "page-down";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one page up.
+   *
+   * @see #getActions()
+   */
+  public static final String pageUpAction = "page-up";
+
+  /**
+   * The name of the <code>Action</code> that copies content from the system
+   * clipboard into the document.
+   *
+   * @see #getActions()
+   */
+  public static final String pasteAction = "paste-from-clipboard";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the previous word.
+   *
+   * @see #getActions()
+   */
+  public static final String previousWordAction = "caret-previous-word";
+
+  /**
+   * The name of the <code>Action</code> that sets the editor in read only
+   * mode.
+   *
+   * @see #getActions()
+   */
+  public static final String readOnlyAction = "set-read-only";
+
+  /**
+   * The name of the <code>Action</code> that selects the whole document.
+   *
+   * @see #getActions()
+   */
+  public static final String selectAllAction = "select-all";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one character
+   * backwards, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionBackwardAction = "selection-backward";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the document, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionBeginAction = "selection-begin";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the current line, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionBeginLineAction = "selection-begin-line";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the current paragraph, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionBeginParagraphAction =
+    "selection-begin-paragraph";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the current word, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionBeginWordAction = "selection-begin-word";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one line down,
+   * possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionDownAction = "selection-down";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the document, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionEndAction = "selection-end";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the current line, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionEndLineAction = "selection-end-line";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the current paragraph, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionEndParagraphAction =
+    "selection-end-paragraph";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the end
+   * of the current word, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionEndWordAction = "selection-end-word";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one character
+   * forwards, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionForwardAction = "selection-forward";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the next word, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionNextWordAction = "selection-next-word";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret to the beginning
+   * of the previous word, possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionPreviousWordAction =
+    "selection-previous-word";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one line up,
+   * possibly extending the current selection.
+   *
+   * @see #getActions()
+   */
+  public static final String selectionUpAction = "selection-up";
+
+  /**
+   * The name of the <code>Action</code> that selects the line around the
+   * caret.
+   *
+   * @see #getActions()
+   */
+  public static final String selectLineAction = "select-line";
+
+  /**
+   * The name of the <code>Action</code> that selects the paragraph around the
+   * caret.
+   *
+   * @see #getActions()
+   */
+  public static final String selectParagraphAction = "select-paragraph";
+
+  /**
+   * The name of the <code>Action</code> that selects the word around the
+   * caret.
+   *
+   * @see #getActions()
+   */
+  public static final String selectWordAction = "select-word";
+
+  /**
+   * The name of the <code>Action</code> that moves the caret one line up.
+   *
+   * @see #getActions()
+   */
+  public static final String upAction = "caret-up";
+
+  /**
+   * The name of the <code>Action</code> that sets the editor in read-write
+   * mode.
+   *
+   * @see #getActions()
+   */
+  public static final String writableAction = "set-writable";
+
+  /**
+   * Creates a new <code>DefaultEditorKit</code>.
+   */
+  public DefaultEditorKit()
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * The <code>Action</code>s that are supported by the
+   * <code>DefaultEditorKit</code>.
+   */
+  private static Action[] defaultActions = 
+  new Action[] {
+    // These classes are public because they are so in the RI.            
+    new BeepAction(),
+    new CopyAction(),
+    new CutAction(),
+    new DefaultKeyTypedAction(),
+    new InsertBreakAction(),
+    new InsertContentAction(),
+    new InsertTabAction(),
+    new PasteAction(),
+    
+    // These are (package-)private inner classes.
+    new DeleteNextCharAction(),
+    new DeletePrevCharAction(),
+
+    new BeginLineAction(),
+    new SelectionBeginLineAction(),
+    
+    new EndLineAction(),
+    new SelectionEndLineAction(),
+    
+    new BackwardAction(),
+    new SelectionBackwardAction(),
+
+    new ForwardAction(),
+    new SelectionForwardAction(),
+    
+    new UpAction(),
+    new SelectionUpAction(),
+
+    new DownAction(),
+    new SelectionDownAction(),
+    
+    new NextWordAction(),
+    new SelectionNextWordAction(),
+
+    new PreviousWordAction(),
+    new SelectionPreviousWordAction(),
+
+    new BeginAction(),
+    new SelectionBeginAction(),
+    
+    new EndAction(),
+    new SelectionEndAction(),
+    
+    new BeginWordAction(),
+    new SelectionBeginWordAction(),
+    
+    new EndWordAction(),
+    new SelectionEndWordAction(),
+    
+    new SelectAllAction(),
+    new SelectLineAction(),
+    new SelectWordAction()
+  };
+
+  /**
+   * Creates the <code>Caret</code> for this <code>EditorKit</code>. This
+   * returns a {@link DefaultCaret} in this case.
+   *
+   * @return the <code>Caret</code> for this <code>EditorKit</code>
+   */
+  public Caret createCaret()
+  {
+    return new DefaultCaret();
+  }
+
+  /**
+   * Creates the default {@link Document} that this <code>EditorKit</code>
+   * supports. This is a {@link PlainDocument} in this case.
+   *
+   * @return the default {@link Document} that this <code>EditorKit</code>
+   *         supports
+   */
+  public Document createDefaultDocument()
+  {
+    return new PlainDocument();
+  }
+
+  /**
+   * Returns the <code>Action</code>s supported by this <code>EditorKit</code>.
+   *
+   * @return the <code>Action</code>s supported by this <code>EditorKit</code>
+   */
+  public Action[] getActions()
+  {
+    return defaultActions;
+  }
+
+  /**
+   * Returns the content type that this <code>EditorKit</code> supports.
+   * The <code>DefaultEditorKit</code> supports the content type
+   * <code>text/plain</code>.
+   *
+   * @return the content type that this <code>EditorKit</code> supports
+   */
+  public String getContentType()
+  {
+    return "text/plain";
+  }
+
+  /**
+   * Returns a {@link ViewFactory} that is able to create {@link View}s for
+   * the <code>Element</code>s that are used in this <code>EditorKit</code>'s
+   * model. This returns null which lets the UI of the text component supply
+   * <code>View</code>s.
+   *
+   * @return a {@link ViewFactory} that is able to create {@link View}s for
+   *         the <code>Element</code>s that are used in this
+   *         <code>EditorKit</code>'s model
+   */
+  public ViewFactory getViewFactory()
+  {
+    return null;
+  }
+
+  /**
+   * Reads a document of the supported content type from an {@link InputStream}
+   * into the actual {@link Document} object.
+   *
+   * @param in the stream from which to read the document
+   * @param document the document model into which the content is read
+   * @param offset the offset inside to document where the content is inserted
+   *
+   * @throws BadLocationException if <code>offset</code> is an invalid location
+   *         inside <code>document</code>
+   * @throws IOException if something goes wrong while reading from
+   *        <code>in</code>
+   */
+  public void read(InputStream in, Document document, int offset)
+    throws BadLocationException, IOException
+  {
+    read(new InputStreamReader(in), document, offset);
+  }
+
+  /**
+   * Reads a document of the supported content type from a {@link Reader}
+   * into the actual {@link Document} object.
+   *
+   * @param in the reader from which to read the document
+   * @param document the document model into which the content is read
+   * @param offset the offset inside to document where the content is inserted
+   *
+   * @throws BadLocationException if <code>offset</code> is an invalid location
+   *         inside <code>document</code>
+   * @throws IOException if something goes wrong while reading from
+   *        <code>in</code>
+   */
+  public void read(Reader in, Document document, int offset)
+    throws BadLocationException, IOException
+  {
+    BufferedReader reader = new BufferedReader(in);
+
+    String line;
+    StringBuffer content = new StringBuffer();
+
+    while ((line = reader.readLine()) != null)
+      {
+	content.append(line);
+	content.append("\n");
+      }
+    
+    document.insertString(offset, content.substring(0, content.length() - 1),
+			  SimpleAttributeSet.EMPTY);
+  }
+
+  /**
+   * Writes the <code>Document</code> (or a fragment of the
+   * <code>Document</code>) to an {@link OutputStream} in the
+   * supported content type format.
+   *
+   * @param out the stream to write to
+   * @param document the document that should be written out
+   * @param offset the beginning offset from where to write
+   * @param len the length of the fragment to write
+   *
+   * @throws BadLocationException if <code>offset</code> or
+   *         <code>offset + len</code>is an invalid location inside
+   *         <code>document</code>
+   * @throws IOException if something goes wrong while writing to
+   *        <code>out</code>
+   */
+  public void write(OutputStream out, Document document, int offset, int len)
+    throws BadLocationException, IOException
+  {
+    write(new OutputStreamWriter(out), document, offset, len);
+  }
+
+  /**
+   * Writes the <code>Document</code> (or a fragment of the
+   * <code>Document</code>) to a {@link Writer} in the
+   * supported content type format.
+   *
+   * @param out the writer to write to
+   * @param document the document that should be written out
+   * @param offset the beginning offset from where to write
+   * @param len the length of the fragment to write
+   *
+   * @throws BadLocationException if <code>offset</code> is an 
+   * invalid location inside <code>document</code>.
+   * @throws IOException if something goes wrong while writing to
+   *        <code>out</code>
+   */
+  public void write(Writer out, Document document, int offset, int len)
+      throws BadLocationException, IOException
+  {
+    // Throw a BLE if offset is invalid
+    if (offset < 0 || offset > document.getLength())
+      throw new BadLocationException("Tried to write to invalid location",
+                                     offset);
+
+    // If they gave an overly large len, just adjust it
+    if (offset + len > document.getLength())
+      len = document.getLength() - offset;
+
+    out.write(document.getText(offset, len));
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,433 @@
+/* DefaultFormatter.java --
+Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.text.ParseException;
+
+import javax.swing.JFormattedTextField;
+
+/**
+ * The <code>DefaultFormatter</code> is a concrete formatter for use in
+ * {@link JFormattedTextField}s.
+ *
+ * It can format arbitrary values by invoking
+ * their {@link Object#toString} method.
+ *
+ * In order to convert a String back to
+ * a value, the value class must provide a single argument constructor that
+ * takes a String object as argument value. If no such constructor is found,
+ * the String itself is passed back by #stringToValue.
+ *  
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
+  implements Cloneable, Serializable
+{
+
+  /**
+   * A {@link DocumentFilter} that intercepts modification of the
+   * JFormattedTextField's Document and commits the value depending
+   * on the value of the <code>commitsOnValidEdit</code> property.
+   *
+   */
+  // FIXME: Handle allowsInvalid and overwriteMode properties
+  private class FormatterDocumentFilter
+    extends DocumentFilter
+  {
+    /**
+     * Invoked when text is removed from a text component.
+     *
+     * @param bypass the FilterBypass to use to mutate the document
+     * @param offset the start position of the modification
+     * @param length the length of the removed text
+     *
+     * @throws BadLocationException if offset or lenght are invalid in
+     *     the Document
+     */
+    public void remove(DocumentFilter.FilterBypass bypass, int offset,
+                        int length)
+      throws BadLocationException
+    {
+      super.remove(bypass, offset, length);
+      checkValidInput();
+      commitIfAllowed();
+    }
+    
+    /**
+     * Invoked when text is inserted into a text component.
+     *
+     * @param bypass the FilterBypass to use to mutate the document
+     * @param offset the start position of the modification
+     * @param text the inserted text
+     * @param attributes the attributes of the inserted text
+     *
+     * @throws BadLocationException if offset or lenght are invalid in
+     *     the Document
+     */
+    public void insertString(DocumentFilter.FilterBypass bypass, int offset,
+                              String text, AttributeSet attributes)
+      throws BadLocationException
+    {
+      if (overwriteMode == true)
+        replace(bypass, offset, text.length(), text, attributes);
+      else
+        super.insertString(bypass, offset, text, attributes);
+      checkValidInput();
+      commitIfAllowed();
+    }
+
+    /**
+     * Invoked when text is replaced in a text component.
+     * 
+     * @param bypass the FilterBypass to use to mutate the document
+     * @param offset the start position of the modification
+     * @param length the length of the removed text
+     * @param text the inserted text
+     * @param attributes the attributes of the inserted text
+     *
+     * @throws BadLocationException if offset or lenght are invalid in
+     *     the Document
+     */
+    public void replace(DocumentFilter.FilterBypass bypass, int offset,
+                         int length, String text, AttributeSet attributes)
+      throws BadLocationException
+    {
+      super.replace(bypass, offset, length, text, attributes);
+      checkValidInput();
+      commitIfAllowed();
+    }
+
+    /**
+     * Commits the value to the JTextTextField if the property
+     * <code>commitsOnValidEdit</code> is set to <code>true</code>.
+     */
+    private void commitIfAllowed()
+    {
+      if (commitsOnValidEdit == true)
+        try
+          {
+            getFormattedTextField().commitEdit();
+          }
+        catch (ParseException ex)
+          {
+            // ignore invalid edits
+          }
+    }
+
+    /**
+     * Checks if the value in the input field is valid. If the
+     * property allowsInvalid is set to <code>false</code>, then
+     * the string in the input field is not allowed to be entered.
+     */
+    private void checkValidInput()
+    {
+      JFormattedTextField ftf = getFormattedTextField();
+      try
+        {
+          Object newval = stringToValue(ftf.getText());
+        }
+      catch (ParseException ex)
+        {
+          if (!allowsInvalid)
+            {
+              // roll back the input if invalid edits are not allowed
+              try
+                {
+                  ftf.setText(valueToString(ftf.getValue()));
+                }
+              catch (ParseException pe)
+                {
+                  // if that happens, something serious must be wrong
+                  AssertionError ae;
+		  ae = new AssertionError("values must be parseable");
+		  ae.initCause(pe);
+		  throw ae;
+                }
+            }
+        }
+    }
+  }
+
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = -355018354457785329L;
+
+  /**
+   * Indicates if the value should be committed after every
+   * valid modification of the Document.
+   */
+  boolean commitsOnValidEdit;
+
+  /**
+   * If <code>true</code> newly inserted characters overwrite existing
+   * values, otherwise insertion is done the normal way.
+   */
+  boolean overwriteMode;
+
+  /**
+   * If <code>true</code> invalid edits are allowed for a limited
+   * time.
+   */
+  boolean allowsInvalid;
+
+  /**
+   * The class that is used for values.
+   */
+  Class valueClass;
+
+  /**
+   * Creates a new instance of <code>DefaultFormatter</code>.
+   */
+  public DefaultFormatter()
+  {
+    commitsOnValidEdit = true;
+    overwriteMode = true;
+    allowsInvalid = true;
+  }
+
+  /**
+   * Installs the formatter on the specified {@link JFormattedTextField}.
+   *
+   * This method does the following things:
+   * <ul>
+   * <li>Display the value of #valueToString in the
+   *  <code>JFormattedTextField</code></li>
+   * <li>Install the Actions from #getActions on the <code>JTextField</code>
+   * </li>
+   * <li>Install the DocumentFilter returned by #getDocumentFilter</li>
+   * <li>Install the NavigationFilter returned by #getNavigationFilter</li>
+   * </ul>
+   *
+   * This method is typically not overridden by subclasses. Instead override
+   * one of the mentioned methods in order to customize behaviour.
+   *
+   * @param ftf the {@link JFormattedTextField} in which this formatter
+   *     is installed 
+   */
+  public void install(JFormattedTextField ftf)
+  {
+    super.install(ftf);
+  }
+
+  /**
+   * Returns <code>true</code> if the value should be committed after
+   * each valid modification of the input field, <code>false</code> if
+   * it should never be committed by this formatter.
+   *
+   * @return the state of the <code>commitsOnValidEdit</code> property
+   *
+   * @see #setCommitsOnValidEdit
+   */
+  public boolean getCommitsOnValidEdit()
+  {
+    return commitsOnValidEdit;
+  }
+
+  /**
+   * Sets the value of the <code>commitsOnValidEdit</code> property.
+   *
+   * @param commitsOnValidEdit the new state of the
+   *     <code>commitsOnValidEdit</code> property
+   *
+   * @see #getCommitsOnValidEdit
+   */
+  public void setCommitsOnValidEdit(boolean commitsOnValidEdit)
+  {
+    this.commitsOnValidEdit = commitsOnValidEdit;
+  }
+
+  /**
+   * Returns the value of the <code>overwriteMode</code> property.
+   * If that is set to <code>true</code> then newly inserted characters
+   * overwrite existing values, otherwise the characters are inserted like
+   * normal. The default is <code>true</code>.
+   *
+   * @return the value of the <code>overwriteMode</code> property
+   */
+  public boolean getOverwriteMode()
+  {
+    return overwriteMode;
+  }
+
+  /**
+   * Sets the value of the <code>overwriteMode</code> property.
+   * 
+   * If that is set to <code>true</code> then newly inserted characters
+   * overwrite existing values, otherwise the characters are inserted like
+   * normal. The default is <code>true</code>.
+   *
+   * @param overwriteMode the new value for the <code>overwriteMode</code>
+   *     property
+   */
+  public void setOverwriteMode(boolean overwriteMode)
+  {
+    this.overwriteMode = overwriteMode;
+  }
+
+  /**
+   * Returns whether or not invalid edits are allowed or not. If invalid
+   * edits are allowed, the JFormattedTextField may temporarily contain invalid
+   * characters.
+   *
+   * @return the value of the allowsInvalid property
+   */
+  public boolean getAllowsInvalid()
+  {
+    return allowsInvalid;
+  }
+
+  /**
+   * Sets the value of the <code>allowsInvalid</code> property.
+   *
+   * @param allowsInvalid the new value for the property
+   *
+   * @see #getAllowsInvalid()
+   */
+  public void setAllowsInvalid(boolean allowsInvalid)
+  {
+    this.allowsInvalid = allowsInvalid;
+  }
+
+  /**
+   * Returns the class that is used for values. When Strings are converted
+   * back to values, this class is used to create new value objects.
+   *
+   * @return the class that is used for values
+   */
+  public Class getValueClass()
+  {
+    return valueClass;
+  }
+
+  /**
+   * Sets the class that is used for values.
+   *
+   * @param valueClass the class that is used for values
+   *
+   * @see #getValueClass()
+   */
+  public void setValueClass(Class valueClass)
+  {
+    this.valueClass = valueClass;
+  }
+
+  /**
+   * Converts a String (from the JFormattedTextField input) to a value.
+   * In order to achieve this, the formatter tries to instantiate an object
+   * of the class returned by #getValueClass() using a single argument
+   * constructor that takes a String argument. If such a constructor cannot
+   * be found, the String itself is returned.
+   *
+   * @param string the string to convert
+   *
+   * @return the value for the string
+   *
+   * @throws ParseException if the string cannot be converted into
+   *     a value object (e.g. invalid input)
+   */
+  public Object stringToValue(String string)
+    throws ParseException
+  {
+    Object value = string;
+    Class valueClass = getValueClass();
+    if (valueClass == null)
+      {
+        JFormattedTextField jft = getFormattedTextField();
+        if (jft != null)
+          valueClass = jft.getValue().getClass();
+      }
+    if (valueClass != null)
+      try
+        {
+          Constructor constr = valueClass.getConstructor
+                                             (new Class[]{String.class});
+          value = constr.newInstance(new Object[]{ string });
+        }
+      catch (NoSuchMethodException ex)
+        {
+          // leave value as string
+        }
+      catch (Exception ex)
+        {
+          throw new ParseException(string, 0);
+        }
+    return value;
+  }
+
+  /**
+   * Converts a value object into a String. This is done by invoking the
+   * {@link Object#toString()} method on the value.
+   *
+   * @param value the value to be converted
+   *
+   * @return the string representation of the value
+   *
+   * @throws ParseException if the value cannot be converted
+   */
+  public String valueToString(Object value)
+    throws ParseException
+  {
+    if (value == null)
+      return "";
+    return value.toString();
+  }
+
+  /**
+   * Creates and returns a clone of this DefaultFormatter.
+   *
+   * @return a clone of this object
+   *
+   * @throws CloneNotSupportedException not thrown here
+   */
+  public Object clone()
+    throws CloneNotSupportedException
+  {
+    return super.clone();
+  }
+
+  /**
+   * Returns the DocumentFilter that is used to restrict input.
+   *
+   * @return the DocumentFilter that is used to restrict input
+   */
+  protected DocumentFilter getDocumentFilter()
+  {
+    return new FormatterDocumentFilter();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,280 @@
+/* DefaultFormatterFactory.java -- FIXME: briefly describe file purpose
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+
+import javax.swing.JFormattedTextField;
+import javax.swing.JFormattedTextField.AbstractFormatter;
+import javax.swing.JFormattedTextField.AbstractFormatterFactory;
+
+/**
+ * This class is Swing's only concrete implementation of 
+ * JFormattedTextField.AbstractFormatterFactory.  It holds several
+ * formatters and determines the best one to be used based on the 
+ * passed-in value from the text field.
+ * 
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ * @since 1.4
+ */
+public class DefaultFormatterFactory extends AbstractFormatterFactory implements
+    Serializable
+{
+  /** 
+   * The default formatter. 
+   **/
+  AbstractFormatter defaultFormatter;
+
+  /**
+   * The formatter to use when the JFormattedTextField has focus and either the
+   * value isn't null or the value is null but no <code>nullFormatter</code>
+   * has been specified.
+   */
+  AbstractFormatter editFormatter;
+
+  /**
+   * The formatter to use when the JFormattedTextField doesn't havefocus and 
+   * either the value isn't null or the value is null but no 
+   * <code>nullFormatter</code> has been specified.
+   */
+  AbstractFormatter displayFormatter;
+
+  /**
+   * The formatter to use when the value of the JFormattedTextField is null.   
+   */
+  AbstractFormatter nullFormatter;
+
+  /**
+   * Creates a DefaultFormatterFactory with no formatters
+   */
+  public DefaultFormatterFactory()
+  {
+    // Nothing to be done here.
+  }
+
+  /**
+   * Creates a new DefaultFormatterFactory with the specified formatters.
+   * @param defaultFormat the formatter to use if no other appropriate non-null
+   * formatted can be found.
+   */
+  public DefaultFormatterFactory(AbstractFormatter defaultFormat)
+  {
+    defaultFormatter = defaultFormat;
+  }
+
+  /**
+   * Creates a new DefaultFormatterFactory with the specified formatters.
+   * @param defaultFormat the formatter to use if no other appropriate non-null
+   * formatted can be found.
+   * @param displayFormat the formatter to use if the JFormattedTextField 
+   * doesn't have focus and either the value is not null or the value is null
+   * but no <code>nullFormatter</code> has been specified.
+   */
+  public DefaultFormatterFactory(AbstractFormatter defaultFormat,
+                                 AbstractFormatter displayFormat)
+  {
+    defaultFormatter = defaultFormat;
+    displayFormatter = displayFormat;
+  }
+
+  /**
+   * Creates a new DefaultFormatterFactory with the specified formatters.
+   * @param defaultFormat the formatter to use if no other appropriate non-null
+   * formatted can be found.
+   * @param displayFormat the formatter to use if the JFormattedTextField 
+   * doesn't have focus and either the value is not null or the value is null
+   * but no <code>nullFormatter</code> has been specified.
+   * @param editFormat the formatter to use if the JFormattedTextField has
+   * focus and either the value is not null or the value is null but not
+   * <code>nullFormatter</code> has been specified.
+   */
+  public DefaultFormatterFactory(AbstractFormatter defaultFormat,
+                                 AbstractFormatter displayFormat,
+                                 AbstractFormatter editFormat)
+  {
+    defaultFormatter = defaultFormat;
+    displayFormatter = displayFormat;
+    editFormatter = editFormat;
+  }
+
+  /**
+   * Creates a new DefaultFormatterFactory with the specified formatters.
+   * @param defaultFormat the formatter to use if no other appropriate non-null
+   * formatted can be found.
+   * @param displayFormat the formatter to use if the JFormattedTextField 
+   * doesn't have focus and either the value is not null or the value is null
+   * but no <code>nullFormatter</code> has been specified.
+   * @param editFormat the formatter to use if the JFormattedTextField has
+   * focus and either the value is not null or the value is null but not
+   * <code>nullFormatter</code> has been specified.
+   * @param nullFormat the formatter to use when the value of the 
+   * JFormattedTextField is null.
+   */
+  public DefaultFormatterFactory(AbstractFormatter defaultFormat,
+                                 AbstractFormatter displayFormat,
+                                 AbstractFormatter editFormat,
+                                 AbstractFormatter nullFormat)
+  {
+    defaultFormatter = defaultFormat;
+    displayFormatter = displayFormat;
+    editFormatter = editFormat;
+    nullFormatter = nullFormat;
+  }
+
+  /**
+   * Returns the formatted to be used if no other appropriate non-null 
+   * formatter can be found.
+   * @return the formatted to be used if no other appropriate non-null 
+   * formatter can be found.
+   */
+  public AbstractFormatter getDefaultFormatter()
+  {
+    return defaultFormatter;
+  }
+
+  /**
+   * Sets the formatted to be used if no other appropriate non-null formatter 
+   * can be found.
+   * @param defaultFormatter the formatted to be used if no other appropriate
+   * non-null formatter can be found.
+   */
+  public void setDefaultFormatter(AbstractFormatter defaultFormatter)
+  {
+    this.defaultFormatter = defaultFormatter;
+  }
+
+  /**
+   * Gets the <code>displayFormatter</code>.  This is the formatter to use if 
+   * the JFormattedTextField is not being edited and either the value is not 
+   * null or the value is null and no <code>nullFormatter<code> has been 
+   * specified.
+   * @return the formatter to use if 
+   * the JFormattedTextField is not being edited and either the value is not 
+   * null or the value is null and no <code>nullFormatter<code> has been 
+   * specified.
+   */
+  public AbstractFormatter getDisplayFormatter()
+  {
+    return displayFormatter;
+  }
+
+  /**
+   * Sets the <code>displayFormatter</code>.  This is the formatter to use if 
+   * the JFormattedTextField is not being edited and either the value is not 
+   * null or the value is null and no <code>nullFormatter<code> has been 
+   * specified.
+   * @param displayFormatter the formatter to use.
+   */
+  public void setDisplayFormatter(AbstractFormatter displayFormatter)
+  {
+    this.displayFormatter = displayFormatter;
+  }
+
+  /**
+   * Gets the <code>editFormatter</code>.  This is the formatter to use if the
+   * JFormattedTextField is being edited and either the value is not null or 
+   * the value is null and no <code>nullFormatter<code> has been specified.
+   * @return the formatter to use if the JFormattedTextField is being edited
+   * and the value is not null or the value is null but no nullFormatted has 
+   * been specified.
+   */
+  public AbstractFormatter getEditFormatter()
+  {
+    return editFormatter;
+  }
+
+  /**
+   * Sets the <code>editFormatter</code>.  This is the formatter to use if the
+   * JFormattedTextField is being edited and either the value is not null or 
+   * the value is null and no <code>nullFormatter<code> has been specified.
+   * @param editFormatter the formatter to use.
+   */
+  public void setEditFormatter(AbstractFormatter editFormatter)
+  {
+    this.editFormatter = editFormatter;
+  }
+
+  /**
+   * Gets the formatter to use if the value of the JFormattedTextField is null.
+   * @return the formatter to use for null values.
+   */
+  public AbstractFormatter getNullFormatter()
+  {
+    return nullFormatter;
+  }
+
+  /**
+   * Sets the <code>nullFormatter</code>.  This is the formatter to use if the
+   * value of the JFormattedTextField is null.
+   * @param nullFormatter the formatter to use for null values.
+   */
+  public void setNullFormatter(AbstractFormatter nullFormatter)
+  {
+    this.nullFormatter = nullFormatter;
+  }
+
+  /**
+   * Returns the appropriate formatter based on the state of 
+   * <code>tf</code>. If <code>tf<code> is null we return null, otherwise
+   * we return one of the following:
+   * 1. Returns <code>nullFormatter</code> if <code>tf.getValue()</code> is 
+   * null and <code>nullFormatter</code> is not.  
+   * 2. Returns <code>editFormatter</code> if <code>tf.hasFocus()</code> is
+   * true and <code>editFormatter</code> is not null.
+   * 3. Returns <code>displayFormatter</code> if <code>tf.hasFocus()</code> is
+   * false and <code>displayFormatter</code> is not null.
+   * 4. Otherwise returns <code>defaultFormatter</code>.
+   */
+  public AbstractFormatter getFormatter(JFormattedTextField tf)
+  {
+    if (tf == null)
+      return null;
+    
+    if (tf.getValue() == null && nullFormatter != null)
+      return nullFormatter;
+
+    if (tf.hasFocus() && editFormatter != null)
+      return editFormatter;
+
+    if (!tf.hasFocus() && displayFormatter != null)
+      return displayFormatter;
+
+    return defaultFormatter;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,405 @@
+/* DefaultHighlighter.java --
+   Copyright (C) 2004, 2006  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import gnu.classpath.NotImplementedException;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.ArrayList;
+
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.TextUI;
+
+public class DefaultHighlighter extends LayeredHighlighter
+{
+  public static class DefaultHighlightPainter
+    extends LayerPainter
+  {
+    private Color color;
+    
+    public DefaultHighlightPainter(Color c)
+    {
+      super();
+      color = c;
+    }
+
+    public Color getColor()
+    {
+      return color;
+    }
+
+    private void paintHighlight(Graphics g, Rectangle rect)
+    {
+      g.fillRect(rect.x, rect.y, rect.width, rect.height);
+    }
+    
+    public void paint(Graphics g, int p0, int p1, Shape bounds,
+		      JTextComponent t)
+    {
+      if (p0 == p1)
+        return;
+      
+      Rectangle rect = bounds.getBounds();
+
+      if (color == null)
+        g.setColor(t.getSelectionColor());
+      else
+        g.setColor(color);
+
+      TextUI ui = t.getUI();
+      
+      try
+      {
+        
+        Rectangle l0 = ui.modelToView(t, p0, null);
+        Rectangle l1 = ui.modelToView(t, p1, null);
+        
+        // Note: The computed locations may lie outside of the allocation
+        // area if the text is scrolled.
+        
+        if (l0.y == l1.y)
+          {
+            SwingUtilities.computeUnion(l0.x, l0.y, l0.width, l0.height, l1);
+
+            // Paint only inside the allocation area.
+            SwingUtilities.computeIntersection(rect.x, rect.y, rect.width, rect.height, l1);
+        
+            paintHighlight(g, l1);
+          }
+        else
+          {
+            // 1. The line of p0 is painted from the position of p0
+            // to the right border.
+            // 2. All lines between the ones where p0 and p1 lie on
+            // are completely highlighted. The allocation area is used to find
+            // out the bounds.
+            // 3. The final line is painted from the left border to the
+            // position of p1.
+            
+            // Highlight first line until the end.
+            // If rect.x is non-zero the calculation will properly adjust the
+            // area to be painted.
+            l0.x -= rect.x;
+            l0.width = rect.width - l0.x - rect.x;
+            
+            paintHighlight(g, l0);
+            
+            int posBelow = Utilities.getPositionBelow(t, p0, l0.x);
+            int p1RowStart = Utilities.getRowStart(t, p1);
+            if (posBelow != -1
+                && posBelow != p0
+                && Utilities.getRowStart(t, posBelow)
+                   != p1RowStart)
+              {
+                Rectangle grow = ui.modelToView(t, posBelow);
+                grow.x = rect.x;
+                grow.width = rect.width;
+                
+                // Find further lines which have to be highlighted completely.
+                int nextPosBelow = posBelow;
+                while (nextPosBelow != -1
+                       && Utilities.getRowStart(t, nextPosBelow) != p1RowStart)
+                  {
+                    posBelow = nextPosBelow;
+                    nextPosBelow = Utilities.getPositionBelow(t, posBelow, l0.x);
+                    
+                    if (nextPosBelow == posBelow)
+                      break;
+                  }
+                // Now posBelow is an offset on the last line which has to be painted
+                // completely. (newPosBelow is on the same line as p1)
+                 
+                // Retrieve the rectangle of posBelow and use its y and height
+                // value to calculate the final height of the multiple line
+                // spanning rectangle.
+                Rectangle end = ui.modelToView(t, posBelow);
+                grow.height = end.y + end.height - grow.y;
+                
+                paintHighlight(g, grow);
+              }
+            
+            // Paint last line from its beginning to the position of p1.
+            l1.width = l1.x + l1.width - rect.x;
+            l1.x = rect.x;
+            paintHighlight(g, l1);
+          }
+      }
+    catch (BadLocationException ex)
+      {
+        AssertionError err = new AssertionError("Unexpected bad location exception");
+        err.initCause(ex);
+        throw err;
+      }
+    }
+
+    public Shape paintLayer(Graphics g, int p0, int p1, Shape bounds,
+			    JTextComponent c, View view)
+    {
+      throw new InternalError();
+    }
+  }
+  
+  private class HighlightEntry implements Highlighter.Highlight
+  {
+    int p0;
+    int p1;
+    Highlighter.HighlightPainter painter;
+
+    public HighlightEntry(int p0, int p1, Highlighter.HighlightPainter painter)
+    {
+      this.p0 = p0;
+      this.p1 = p1;
+      this.painter = painter;
+    }
+
+    public int getStartOffset()
+    {
+      return p0;
+    }
+
+    public int getEndOffset()
+    {
+      return p1;
+    }
+
+    public Highlighter.HighlightPainter getPainter()
+    {
+      return painter;
+    }
+  }
+
+  /**
+   * @specnote final as of 1.4
+   */
+  public static final LayeredHighlighter.LayerPainter DefaultPainter =
+    new DefaultHighlightPainter(null);
+  
+  private JTextComponent textComponent;
+  private ArrayList highlights = new ArrayList();
+  private boolean drawsLayeredHighlights = true;
+  
+  public DefaultHighlighter()
+  {
+    // Nothing to do here.
+  }
+
+  public boolean getDrawsLayeredHighlights()
+  {
+    return drawsLayeredHighlights;
+  }
+
+  public void setDrawsLayeredHighlights(boolean newValue)
+  {
+    drawsLayeredHighlights = newValue;
+  }
+  
+  private void checkPositions(int p0, int p1)
+    throws BadLocationException
+  {
+    if (p0 < 0)
+      throw new BadLocationException("DefaultHighlighter", p0);
+    
+    if (p1 < p0)
+      throw new BadLocationException("DefaultHighlighter", p1);
+  }
+
+  public void install(JTextComponent c)
+  {
+    textComponent = c;
+    removeAllHighlights();
+  }
+
+  public void deinstall(JTextComponent c)
+  {
+    textComponent = null;
+  }
+
+  public Object addHighlight(int p0, int p1, Highlighter.HighlightPainter painter)
+    throws BadLocationException
+  {
+    checkPositions(p0, p1);
+    HighlightEntry entry = new HighlightEntry(p0, p1, painter);
+    highlights.add(entry);
+    
+    textComponent.getUI().damageRange(textComponent, p0, p1);
+    
+    return entry;
+  }
+
+  public void removeHighlight(Object tag)
+  {
+    highlights.remove(tag);
+
+    HighlightEntry entry = (HighlightEntry) tag;
+    textComponent.getUI().damageRange(textComponent,
+                                      entry.p0,
+                                      entry.p1);
+  }
+
+  public void removeAllHighlights()
+  {
+    highlights.clear();
+  }
+
+  public Highlighter.Highlight[] getHighlights()
+  {
+    return (Highlighter.Highlight[]) 
+      highlights.toArray(new Highlighter.Highlight[highlights.size()]);
+  }
+
+  public void changeHighlight(Object tag, int n0, int n1)
+    throws BadLocationException
+  {
+    int o0, o1;
+    
+    checkPositions(n0, n1);
+    HighlightEntry entry = (HighlightEntry) tag;
+    o0 = entry.p0;
+    o1 = entry.p1;
+    
+    // Prevent useless write & repaint operations.
+    if (o0 == n0 && o1 == n1)
+      return;
+    
+    entry.p0 = n0;
+    entry.p1 = n1;
+    
+    TextUI ui = textComponent.getUI();
+    
+    // Special situation where the old area has to be cleared simply.
+    if (n0 == n1)
+      ui.damageRange(textComponent, o0, o1);
+    // Calculates the areas where a change is really neccessary
+    else if ((o1 > n0 && o1 <= n1)
+        || (n1 > o0 && n1 <= o1))
+      {
+        // [fds, fde) - the first damage region
+        // [sds, sde] - the second damage region
+        int fds, sds;
+        int fde, sde;
+
+        // Calculate first damaged region.
+        if(o0 < n0)
+          {
+            // Damaged region will be cleared as
+            // the old highlight region starts first.
+            fds = o0;
+            fde = n0;
+          }
+        else
+          {
+            // Damaged region will be painted as
+            // the new highlight region starts first.
+            fds = n0;
+            fde = o0;
+          }
+
+        if (o1 < n1)
+          {
+            // Final region will be painted as the
+            // old highlight region finishes first
+            sds = o1;
+            sde = n1;
+          }
+        else
+          {
+            // Final region will be cleared as the
+            // new highlight region finishes first.
+            sds = n1;
+            sde = o1;
+          }
+        
+        // If there is no undamaged region in between
+        // call damageRange only once.
+        if (fde == sds)
+          ui.damageRange(textComponent, fds, sde);
+        else
+          {
+            if (fds != fde)
+              ui.damageRange(textComponent, fds, fde);
+        
+            if (sds != sde)
+              ui.damageRange(textComponent, sds, sde);
+          }
+      }
+    else
+      {
+        // The two regions do not overlap. So mark
+        // both areas as damaged.
+        ui.damageRange(textComponent, o0, o1);
+        ui.damageRange(textComponent, n0, n1);
+      }
+    
+  }
+
+  public void paintLayeredHighlights(Graphics g, int p0, int p1,
+                                     Shape viewBounds, JTextComponent editor,
+                                     View view)
+  throws NotImplementedException
+  {
+    // TODO: Implement this properly.
+  }
+
+  public void paint(Graphics g)
+  {
+    int size = highlights.size();
+    
+    // Check if there are any highlights.
+    if (size == 0)
+      return;
+
+    // Prepares the rectangle of the inner drawing area.
+    Insets insets = textComponent.getInsets();
+    Shape bounds =
+      new Rectangle(insets.left,
+                    insets.top,
+                    textComponent.getWidth() - insets.left - insets.right,
+                    textComponent.getHeight() - insets.top - insets.bottom);
+    
+    for (int index = 0; index < size; ++index)
+      {
+	HighlightEntry entry = (HighlightEntry) highlights.get(index);
+	entry.painter.paint(g, entry.p0, entry.p1, bounds, textComponent);
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,2421 @@
+/* DefaultStyledDocument.java --
+   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Stack;
+import java.util.Vector;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * The default implementation of {@link StyledDocument}. The document is
+ * modeled as an {@link Element} tree, which has a {@link SectionElement} as
+ * single root, which has one or more {@link AbstractDocument.BranchElement}s
+ * as paragraph nodes and each paragraph node having one or more
+ * {@link AbstractDocument.LeafElement}s as content nodes.
+ * 
+ * @author Michael Koch (konqueror at gmx.de)
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DefaultStyledDocument extends AbstractDocument implements
+    StyledDocument
+{
+
+  /**
+   * An {@link UndoableEdit} that can undo attribute changes to an element.
+   * 
+   * @author Roman Kennke (kennke at aicas.com)
+   */
+  public static class AttributeUndoableEdit extends AbstractUndoableEdit
+  {
+    /**
+     * A copy of the old attributes.
+     */
+    protected AttributeSet copy;
+
+    /**
+     * The new attributes.
+     */
+    protected AttributeSet newAttributes;
+
+    /**
+     * If the new attributes replaced the old attributes or if they only were
+     * added to them.
+     */
+    protected boolean isReplacing;
+
+    /**
+     * The element that has changed.
+     */
+    protected Element element;
+
+    /**
+     * Creates a new <code>AttributeUndoableEdit</code>.
+     * 
+     * @param el
+     *          the element that changes attributes
+     * @param newAtts
+     *          the new attributes
+     * @param replacing
+     *          if the new attributes replace the old or only append to them
+     */
+    public AttributeUndoableEdit(Element el, AttributeSet newAtts,
+                                 boolean replacing)
+    {
+      element = el;
+      newAttributes = newAtts;
+      isReplacing = replacing;
+      copy = el.getAttributes().copyAttributes();
+    }
+
+    /**
+     * Undos the attribute change. The <code>copy</code> field is set as
+     * attributes on <code>element</code>.
+     */
+    public void undo()
+    {
+      super.undo();
+      AttributeSet atts = element.getAttributes();
+      if (atts instanceof MutableAttributeSet)
+        {
+          MutableAttributeSet mutable = (MutableAttributeSet) atts;
+          mutable.removeAttributes(atts);
+          mutable.addAttributes(copy);
+        }
+    }
+
+    /**
+     * Redos an attribute change. This adds <code>newAttributes</code> to the
+     * <code>element</code>'s attribute set, possibly clearing all attributes
+     * if <code>isReplacing</code> is true.
+     */
+    public void redo()
+    {
+      super.undo();
+      AttributeSet atts = element.getAttributes();
+      if (atts instanceof MutableAttributeSet)
+        {
+          MutableAttributeSet mutable = (MutableAttributeSet) atts;
+          if (isReplacing)
+            mutable.removeAttributes(atts);
+          mutable.addAttributes(newAttributes);
+        }
+    }
+  }
+
+  /**
+   * Carries specification information for new {@link Element}s that should be
+   * created in {@link ElementBuffer}. This allows the parsing process to be
+   * decoupled from the <code>Element</code> creation process.
+   */
+  public static class ElementSpec
+  {
+    /**
+     * This indicates a start tag. This is a possible value for {@link #getType}.
+     */
+    public static final short StartTagType = 1;
+
+    /**
+     * This indicates an end tag. This is a possible value for {@link #getType}.
+     */
+    public static final short EndTagType = 2;
+
+    /**
+     * This indicates a content element. This is a possible value for
+     * {@link #getType}.
+     */
+    public static final short ContentType = 3;
+
+    /**
+     * This indicates that the data associated with this spec should be joined
+     * with what precedes it. This is a possible value for {@link #getDirection}.
+     */
+    public static final short JoinPreviousDirection = 4;
+
+    /**
+     * This indicates that the data associated with this spec should be joined
+     * with what follows it. This is a possible value for {@link #getDirection}.
+     */
+    public static final short JoinNextDirection = 5;
+
+    /**
+     * This indicates that the data associated with this spec should be used to
+     * create a new element. This is a possible value for {@link #getDirection}.
+     */
+    public static final short OriginateDirection = 6;
+
+    /**
+     * This indicates that the data associated with this spec should be joined
+     * to the fractured element. This is a possible value for
+     * {@link #getDirection}.
+     */
+    public static final short JoinFractureDirection = 7;
+
+    /**
+     * The type of the tag.
+     */
+    short type;
+
+    /**
+     * The direction of the tag.
+     */
+    short direction;
+
+    /**
+     * The offset of the content.
+     */
+    int offset;
+
+    /**
+     * The length of the content.
+     */
+    int length;
+
+    /**
+     * The actual content.
+     */
+    char[] content;
+
+    /**
+     * The attributes for the tag.
+     */
+    AttributeSet attributes;
+
+    /**
+     * Creates a new <code>ElementSpec</code> with no content, length or
+     * offset. This is most useful for start and end tags.
+     * 
+     * @param a
+     *          the attributes for the element to be created
+     * @param type
+     *          the type of the tag
+     */
+    public ElementSpec(AttributeSet a, short type)
+    {
+      this(a, type, 0);
+    }
+
+    /**
+     * Creates a new <code>ElementSpec</code> that specifies the length but
+     * not the offset of an element. Such <code>ElementSpec</code>s are
+     * processed sequentially from a known starting point.
+     * 
+     * @param a
+     *          the attributes for the element to be created
+     * @param type
+     *          the type of the tag
+     * @param len
+     *          the length of the element
+     */
+    public ElementSpec(AttributeSet a, short type, int len)
+    {
+      this(a, type, null, 0, len);
+    }
+
+    /**
+     * Creates a new <code>ElementSpec</code> with document content.
+     * 
+     * @param a
+     *          the attributes for the element to be created
+     * @param type
+     *          the type of the tag
+     * @param txt
+     *          the actual content
+     * @param offs
+     *          the offset into the <code>txt</code> array
+     * @param len
+     *          the length of the element
+     */
+    public ElementSpec(AttributeSet a, short type, char[] txt, int offs, int len)
+    {
+      attributes = a;
+      this.type = type;
+      offset = offs;
+      length = len;
+      content = txt;
+      direction = OriginateDirection;
+    }
+
+    /**
+     * Sets the type of the element.
+     * 
+     * @param type
+     *          the type of the element to be set
+     */
+    public void setType(short type)
+    {
+      this.type = type;
+    }
+
+    /**
+     * Returns the type of the element.
+     * 
+     * @return the type of the element
+     */
+    public short getType()
+    {
+      return type;
+    }
+
+    /**
+     * Sets the direction of the element.
+     * 
+     * @param dir
+     *          the direction of the element to be set
+     */
+    public void setDirection(short dir)
+    {
+      direction = dir;
+    }
+
+    /**
+     * Returns the direction of the element.
+     * 
+     * @return the direction of the element
+     */
+    public short getDirection()
+    {
+      return direction;
+    }
+
+    /**
+     * Returns the attributes of the element.
+     * 
+     * @return the attributes of the element
+     */
+    public AttributeSet getAttributes()
+    {
+      return attributes;
+    }
+
+    /**
+     * Returns the actual content of the element.
+     * 
+     * @return the actual content of the element
+     */
+    public char[] getArray()
+    {
+      return content;
+    }
+
+    /**
+     * Returns the offset of the content.
+     * 
+     * @return the offset of the content
+     */
+    public int getOffset()
+    {
+      return offset;
+    }
+
+    /**
+     * Returns the length of the content.
+     * 
+     * @return the length of the content
+     */
+    public int getLength()
+    {
+      return length;
+    }
+
+    /**
+     * Returns a String representation of this <code>ElementSpec</code>
+     * describing the type, direction and length of this
+     * <code>ElementSpec</code>.
+     * 
+     * @return a String representation of this <code>ElementSpec</code>
+     */
+    public String toString()
+    {
+      StringBuilder b = new StringBuilder();
+      switch (type)
+        {
+        case StartTagType:
+          b.append("StartTag");
+          break;
+        case EndTagType:
+          b.append("EndTag");
+          break;
+        case ContentType:
+          b.append("Content");
+          break;
+        default:
+          b.append("??");
+          break;
+        }
+
+      b.append(':');
+
+      switch (direction)
+        {
+        case JoinPreviousDirection:
+          b.append("JoinPrevious");
+          break;
+        case JoinNextDirection:
+          b.append("JoinNext");
+          break;
+        case OriginateDirection:
+          b.append("Originate");
+          break;
+        case JoinFractureDirection:
+          b.append("Fracture");
+          break;
+        default:
+          b.append("??");
+          break;
+        }
+
+      b.append(':');
+      b.append(length);
+
+      return b.toString();
+    }
+  }
+
+  /**
+   * Performs all <em>structural</code> changes to the <code>Element</code>
+   * hierarchy.  This class was implemented with much help from the document:
+   * http://java.sun.com/products/jfc/tsc/articles/text/element_buffer/index.html.
+   */
+  public class ElementBuffer implements Serializable
+  {
+    /** The serialization UID (compatible with JDK1.5). */
+    private static final long serialVersionUID = 1688745877691146623L;
+
+    /** The root element of the hierarchy. */
+    private Element root;
+
+    /** Holds the offset for structural changes. */
+    private int offset;
+
+    /** Holds the end offset for structural changes. */
+    private int endOffset;
+
+    /** Holds the length of structural changes. */
+    private int length;
+
+    /** Holds the position of the change. */
+    private int pos;
+
+    /** Holds the element that was last fractured. */
+    private Element lastFractured;
+    
+    /** True if a fracture was not created during a insertFracture call. */
+    private boolean fracNotCreated;
+
+    /**
+     * The current position in the element tree. This is used for bulk inserts
+     * using ElementSpecs.
+     */
+    private Stack elementStack;
+
+    /**
+     * The ElementChange that describes the latest changes.
+     */
+    DefaultDocumentEvent documentEvent;
+
+    /**
+     * Creates a new <code>ElementBuffer</code> for the specified
+     * <code>root</code> element.
+     * 
+     * @param root
+     *          the root element for this <code>ElementBuffer</code>
+     */
+    public ElementBuffer(Element root)
+    {
+      this.root = root;
+      elementStack = new Stack();
+    }
+
+    /**
+     * Returns the root element of this <code>ElementBuffer</code>.
+     * 
+     * @return the root element of this <code>ElementBuffer</code>
+     */
+    public Element getRootElement()
+    {
+      return root;
+    }
+
+    /**
+     * Removes the content. This method sets some internal parameters and
+     * delegates the work to {@link #removeUpdate}.
+     * 
+     * @param offs
+     *          the offset from which content is remove
+     * @param len
+     *          the length of the removed content
+     * @param ev
+     *          the document event that records the changes
+     */
+    public void remove(int offs, int len, DefaultDocumentEvent ev)
+    {
+      if (len == 0)
+        return;
+      offset = offs;
+      length = len;
+      pos = offset;
+      documentEvent = ev;
+      removeUpdate();
+    }
+
+    /**
+     * Updates the element structure of the document in response to removal of
+     * content. It removes the affected {@link Element}s from the document
+     * structure.
+     */
+    protected void removeUpdate()
+    {
+      int startParagraph = root.getElementIndex(offset);
+      int endParagraph = root.getElementIndex(offset + length);
+      Element[] empty = new Element[0];
+      int removeStart = -1;
+      int removeEnd = -1;
+      for (int i = startParagraph; i < endParagraph; i++)
+        {
+          BranchElement paragraph = (BranchElement) root.getElement(i);
+          int contentStart = paragraph.getElementIndex(offset);
+          int contentEnd = paragraph.getElementIndex(offset + length);
+          if (contentStart == paragraph.getStartOffset()
+              && contentEnd == paragraph.getEndOffset())
+            {
+              // In this case we only need to remove the whole paragraph. We
+              // do this in one go after this loop and only record the indices
+              // here.
+              if (removeStart == -1)
+                {
+                  removeStart = i;
+                  removeEnd = i;
+                }
+              else
+                removeEnd = i;
+            }
+          else
+            {
+              // In this case we remove a couple of child elements from this
+              // paragraph.
+              int removeLen = contentEnd - contentStart;
+              Element[] removed = new Element[removeLen];
+              for (int j = contentStart; j < contentEnd; j++)
+                removed[j] = paragraph.getElement(j);
+              Edit edit = getEditForParagraphAndIndex(paragraph, contentStart);
+              edit.addRemovedElements(removed);
+            }
+        }
+      // Now we remove paragraphs from the root that have been tagged for
+      // removal.
+      if (removeStart != -1)
+        {
+          int removeLen = removeEnd - removeStart;
+          Element[] removed = new Element[removeLen];
+          for (int i = removeStart; i < removeEnd; i++)
+            removed[i] = root.getElement(i);
+          Edit edit = getEditForParagraphAndIndex((BranchElement) root,
+                                                  removeStart);
+          edit.addRemovedElements(removed);
+        }
+    }
+
+    /**
+     * Performs the actual work for {@link #change}. The elements at the
+     * interval boundaries are split up (if necessary) so that the interval
+     * boundaries are located at element boundaries.
+     */
+    protected void changeUpdate()
+    {
+      // Split up the element at the start offset if necessary.
+      Element el = getCharacterElement(offset);
+      Element[] res = split(el, offset, 0, el.getElementIndex(offset));
+      BranchElement par = (BranchElement) el.getParentElement();
+      int index = par.getElementIndex(offset);
+      Edit edit = getEditForParagraphAndIndex(par, index);
+      if (res[1] != null)
+        {
+          Element[] removed;
+          Element[] added;
+          if (res[0] == null)
+            {
+              removed = new Element[0];
+              added = new Element[] { res[1] };
+              index++;
+            }
+          else
+            {
+              removed = new Element[] { el };
+              added = new Element[] { res[0], res[1] };
+            }
+          edit.addRemovedElements(removed);
+
+          edit.addAddedElements(added);
+        }
+
+      int endOffset = offset + length;
+      el = getCharacterElement(endOffset);
+      res = split(el, endOffset, 0, el.getElementIndex(endOffset));
+      par = (BranchElement) el.getParentElement();
+      if (res[0] != null)
+        {
+          Element[] removed;
+          Element[] added;
+          if (res[1] == null)
+            {
+              removed = new Element[0];
+              added = new Element[] { res[1] };
+            }
+          else
+            {
+              removed = new Element[] { el };
+              added = new Element[] { res[0], res[1] };
+            }
+          edit.addRemovedElements(removed);
+          edit.addAddedElements(added);
+        }
+    }
+
+    /**
+     * Modifies the element structure so that the specified interval starts and
+     * ends at an element boundary. Content and paragraph elements are split and
+     * created as necessary. This also updates the
+     * <code>DefaultDocumentEvent</code> to reflect the structural changes.
+     * The bulk work is delegated to {@link #changeUpdate()}.
+     * 
+     * @param offset
+     *          the start index of the interval to be changed
+     * @param length
+     *          the length of the interval to be changed
+     * @param ev
+     *          the <code>DefaultDocumentEvent</code> describing the change
+     */
+    public void change(int offset, int length, DefaultDocumentEvent ev)
+    {
+      if (length == 0)
+        return;
+      this.offset = offset;
+      this.pos = offset;
+      this.length = length;
+      documentEvent = ev;
+      changeUpdate();
+    }
+
+    /**
+     * Creates and returns a deep clone of the specified <code>clonee</code>
+     * with the specified parent as new parent.
+     *
+     * This method can only clone direct instances of {@link BranchElement}
+     * or {@link LeafElement}.
+     *
+     * @param parent the new parent
+     * @param clonee the element to be cloned
+     *
+     * @return the cloned element with the new parent
+     */
+    public Element clone(Element parent, Element clonee)
+    {
+      Element clone = clonee;
+      // We can only handle AbstractElements here.
+      if (clonee instanceof BranchElement)
+        {
+          BranchElement branchEl = (BranchElement) clonee;
+          BranchElement branchClone =
+            new BranchElement(parent, branchEl.getAttributes());
+          // Also clone all of the children.
+          int numChildren = branchClone.getElementCount();
+          Element[] cloneChildren = new Element[numChildren];
+          for (int i = 0; i < numChildren; ++i)
+            {
+              cloneChildren[i] = clone(branchClone,
+                                       branchClone.getElement(i));
+            }
+          branchClone.replace(0, 0, cloneChildren);
+          clone = branchClone;
+        }
+      else if (clonee instanceof LeafElement)
+        {
+          clone = new LeafElement(parent, clonee.getAttributes(),
+                                  clonee.getStartOffset(),
+                                  clonee.getEndOffset());
+        }
+      return clone;
+    }
+
+    /**
+     * Inserts new <code>Element</code> in the document at the specified
+     * position. Most of the work is done by {@link #insertUpdate}, after some
+     * fields have been prepared for it.
+     * 
+     * @param offset
+     *          the location in the document at which the content is inserted
+     * @param length
+     *          the length of the inserted content
+     * @param data
+     *          the element specifications for the content to be inserted
+     * @param ev
+     *          the document event that is updated to reflect the structural
+     *          changes
+     */
+    public void insert(int offset, int length, ElementSpec[] data,
+                       DefaultDocumentEvent ev)
+    {
+      if (length == 0)
+        return;
+      
+      this.offset = offset;
+      this.pos = offset;
+      this.endOffset = offset + length;
+      this.length = length;
+      documentEvent = ev;
+      
+      edits.removeAllElements();
+      elementStack.removeAllElements();
+      lastFractured = null;
+      fracNotCreated = false;
+      insertUpdate(data);
+      // This for loop applies all the changes that were made and updates the
+      // DocumentEvent.
+      int size = edits.size();
+      for (int i = 0; i < size; i++)
+        {
+          Edit curr = (Edit) edits.get(i);
+          BranchElement e = (BranchElement) curr.e;
+          Element[] removed = curr.getRemovedElements();
+          Element[] added = curr.getAddedElements();
+          // FIXME: We probably shouldn't create the empty Element[] in the
+          // first place.
+          if (removed.length > 0 || added.length > 0)
+            {
+              if (curr.index + removed.length <= e.getElementCount())
+                {
+                  e.replace(curr.index, removed.length, added);
+                  ElementEdit ee = new ElementEdit(e, curr.index, removed, added);
+                  ev.addEdit(ee);
+                }
+              else
+                {
+                  System.err.println("WARNING: Tried to replace elements ");
+                  System.err.print("beyond boundaries: elementCount: ");
+                  System.err.println(e.getElementCount());
+                  System.err.print("index: " + curr.index);
+                  System.err.println(", removed.length: " + removed.length);
+                }
+            }
+        }
+    }
+
+    /**
+     * Inserts new content
+     * 
+     * @param data
+     *          the element specifications for the elements to be inserted
+     */
+    protected void insertUpdate(ElementSpec[] data)
+    {
+      // Push the root and the paragraph at offset onto the element stack.
+      Element current = root;
+      int index;
+      while (!current.isLeaf())
+        {
+          index = current.getElementIndex(offset);
+          elementStack.push(current);
+          current = current.getElement(index);
+        }
+      
+      int i = 0;
+      int type = data[0].getType();
+      if (type == ElementSpec.ContentType)
+        {
+          // If the first tag is content we must treat it separately to allow
+          // for joining properly to previous Elements and to ensure that
+          // no extra LeafElements are erroneously inserted.
+          insertFirstContentTag(data);
+          pos += data[0].length;
+          i = 1;
+        }
+      else
+        {
+          createFracture(data);
+          i = 0;
+        }
+      
+      // Handle each ElementSpec individually.
+      for (; i < data.length; i++)
+        {
+          BranchElement paragraph = (BranchElement) elementStack.peek();
+          switch (data[i].getType())
+            {
+            case ElementSpec.StartTagType:
+              switch (data[i].getDirection())
+                {
+                case ElementSpec.JoinFractureDirection:
+                  // Fracture the tree and ensure the appropriate element
+                  // is on top of the stack.
+                  fracNotCreated = false;
+                  insertFracture(data[i]);
+                  if (fracNotCreated)
+                    {
+                      if (lastFractured != null)
+                        elementStack.push(lastFractured.getParentElement());
+                      else
+                        elementStack.push(paragraph.getElement(0));
+                    }
+                  break;
+                case ElementSpec.JoinNextDirection:
+                  // Push the next paragraph element onto the stack so
+                  // future insertions are added to it.
+                  int ix = paragraph.getElementIndex(pos) + 1;
+                  elementStack.push(paragraph.getElement(ix));
+                  break;
+                default:
+                  Element br = null;
+                  if (data.length > i + 1)
+                    {
+                      // leaves will be added to paragraph later
+                      int x = 0;
+                      if (paragraph.getElementCount() > 0)
+                        x = paragraph.getElementIndex(pos) + 1;
+                      Edit e = getEditForParagraphAndIndex(paragraph, x);
+                      br = (BranchElement) createBranchElement(paragraph,
+                                                               data[i].getAttributes());
+                      e.added.add(br);
+                      elementStack.push(br);
+                    }
+                  else
+                    // need to add leaves to paragraph now
+                    br = insertParagraph(paragraph, pos);
+                  break;
+                }
+              break;
+            case ElementSpec.EndTagType:
+              elementStack.pop();
+              break;
+            case ElementSpec.ContentType:
+              insertContentTag(data[i]);
+              offset = pos;
+              break;
+            }
+        }
+    }
+    
+    /**
+     * Inserts a new paragraph.
+     * 
+     * @param par -
+     *          the parent
+     * @param offset -
+     *          the offset
+     * @return the new paragraph
+     */
+    private Element insertParagraph(BranchElement par, int offset)
+    {
+      int index = par.getElementIndex(offset);
+      Element current = par.getElement(index);
+      Element[] res = split(current, offset, 0, 0);
+      Edit e = getEditForParagraphAndIndex(par, index + 1);
+      Element ret;
+      if (res[1] != null)
+        {
+          Element[] removed;
+          Element[] added;
+          if (res[0] == null)
+            {
+              removed = new Element[0];
+              if (res[1] instanceof BranchElement)
+                {
+                  added = new Element[] { res[1] };
+                  ret = res[1];
+                }
+              else
+                {
+                  ret = createBranchElement(par, null);
+                  added = new Element[] { ret, res[1] };
+                }
+              index++;
+            }
+          else
+            {
+              removed = new Element[] { current };
+              if (res[1] instanceof BranchElement)
+                {
+                  ret = res[1];
+                  added = new Element[] { res[0], res[1] };
+                }
+              else
+                {
+                  ret = createBranchElement(par, null);
+                  added = new Element[] { res[0], ret, res[1] };
+                }
+            }
+
+          e.addAddedElements(added);
+          e.addRemovedElements(removed);
+        }
+      else
+        {
+          ret = createBranchElement(par, null);
+          e.addAddedElement(ret);
+        }
+      return ret;
+    }
+    
+    /**
+     * Inserts the first tag into the document.
+     * 
+     * @param data -
+     *          the data to be inserted.
+     */
+    private void insertFirstContentTag(ElementSpec[] data)
+    {
+      ElementSpec first = data[0];
+      BranchElement paragraph = (BranchElement) elementStack.peek();
+      int index = paragraph.getElementIndex(pos);
+      Element current = paragraph.getElement(index);
+      int newEndOffset = pos + first.length;
+      boolean onlyContent = data.length == 1;
+      Edit edit = getEditForParagraphAndIndex(paragraph, index);
+      switch (first.getDirection())
+        {
+        case ElementSpec.JoinPreviousDirection:
+          if (current.getEndOffset() != newEndOffset && !onlyContent)
+            {
+              Element newEl1 = createLeafElement(paragraph,
+                                                 current.getAttributes(),
+                                                 current.getStartOffset(),
+                                                 newEndOffset);
+              edit.addAddedElement(newEl1);
+              edit.addRemovedElement(current);
+              offset = newEndOffset;
+            }
+          break;
+        case ElementSpec.JoinNextDirection:
+          if (pos != 0)
+            {
+              Element newEl1 = createLeafElement(paragraph,
+                                                 current.getAttributes(),
+                                                 current.getStartOffset(),
+                                                 pos);
+              edit.addAddedElement(newEl1);
+              Element next = paragraph.getElement(index + 1);
+
+              if (onlyContent)
+                newEl1 = createLeafElement(paragraph, next.getAttributes(),
+                                           pos, next.getEndOffset());
+              else
+                {
+                  newEl1 = createLeafElement(paragraph, next.getAttributes(),
+                                           pos, newEndOffset);
+                  pos = newEndOffset;
+                }
+              edit.addAddedElement(newEl1);
+              edit.addRemovedElement(current);
+              edit.addRemovedElement(next);
+            }
+          break;
+        default:
+          if (current.getStartOffset() != pos)
+            {
+              Element newEl = createLeafElement(paragraph,
+                                                current.getAttributes(),
+                                                current.getStartOffset(),
+                                                pos);
+              edit.addAddedElement(newEl);
+            }
+          edit.addRemovedElement(current);
+          Element newEl1 = createLeafElement(paragraph, first.getAttributes(),
+                                             pos, newEndOffset);
+          edit.addAddedElement(newEl1);
+          if (current.getEndOffset() != endOffset)
+            recreateLeaves(newEndOffset, paragraph, onlyContent);
+          else
+            offset = newEndOffset;
+          break;
+        }
+    }
+
+    /**
+     * Inserts a content element into the document structure.
+     * 
+     * @param tag -
+     *          the element spec
+     */
+    private void insertContentTag(ElementSpec tag)
+    {
+      BranchElement paragraph = (BranchElement) elementStack.peek();
+      int len = tag.getLength();
+      int dir = tag.getDirection();
+      AttributeSet tagAtts = tag.getAttributes();
+      
+      if (dir == ElementSpec.JoinNextDirection)
+        {
+          int index = paragraph.getElementIndex(pos);
+          Element target = paragraph.getElement(index);
+          Edit edit = getEditForParagraphAndIndex(paragraph, index);
+          
+          if (paragraph.getStartOffset() > pos)
+            {
+              Element first = paragraph.getElement(0);
+              Element newEl = createLeafElement(paragraph,
+                                                first.getAttributes(), pos,
+                                                first.getEndOffset());
+              edit.addAddedElement(newEl);
+              edit.addRemovedElement(first);
+            }
+          else if (paragraph.getElementCount() > (index + 1)
+                   && (pos == target.getStartOffset() && !target.equals(lastFractured)))
+            {
+              Element next = paragraph.getElement(index + 1);
+              Element newEl = createLeafElement(paragraph,
+                                                next.getAttributes(), pos,
+                                                next.getEndOffset());
+              edit.addAddedElement(newEl);
+              edit.addRemovedElement(next);
+              edit.addRemovedElement(target);
+            }
+          else
+            {
+              BranchElement parent = (BranchElement) paragraph.getParentElement();
+              int i = parent.getElementIndex(pos);
+              BranchElement next = (BranchElement) parent.getElement(i + 1);
+              AttributeSet atts = tag.getAttributes();
+              
+              if (next != null)
+                {
+                  Element nextLeaf = next.getElement(0);
+                  Edit e = getEditForParagraphAndIndex(next, 0);   
+                  Element newEl2 = createLeafElement(next, atts, pos, nextLeaf.getEndOffset());
+                  e.addAddedElement(newEl2);
+                  e.addRemovedElement(nextLeaf);
+                }
+            }
+        }
+      else 
+        {
+          int end = pos + len;
+          Element leaf = createLeafElement(paragraph, tag.getAttributes(), pos, end);
+          
+          // Check for overlap with other leaves/branches
+          if (paragraph.getElementCount() > 0)
+            {
+              int index = paragraph.getElementIndex(pos);
+              Element target = paragraph.getElement(index);
+              boolean onlyContent = target.isLeaf();
+              
+              BranchElement toRec = paragraph;
+              if (!onlyContent)
+                toRec = (BranchElement) target;
+
+              // Check if we should place the leaf before or after target
+              if (pos > target.getStartOffset())
+                index++;
+
+              Edit edit = getEditForParagraphAndIndex(paragraph, index);
+              edit.addAddedElement(leaf);
+            }
+          else
+            paragraph.replace(0, 0, new Element[] { leaf });
+        }
+                            
+      pos += len;
+    }
+
+    /**
+     * This method fractures the child at offset.
+     * 
+     * @param data
+     *          the ElementSpecs used for the entire insertion
+     */
+    private void createFracture(ElementSpec[] data)
+    {
+      BranchElement paragraph = (BranchElement) elementStack.peek();
+      int index = paragraph.getElementIndex(offset);
+      Element child = paragraph.getElement(index);
+      Edit edit = getEditForParagraphAndIndex(paragraph, index);
+      AttributeSet atts = child.getAttributes();
+      
+      if (offset != 0)
+        {
+          Element newEl1 = createLeafElement(paragraph, atts,
+                                             child.getStartOffset(), offset);
+          edit.addAddedElement(newEl1);
+          edit.addRemovedElement(child);
+        }
+    }
+
+    /**
+     * Recreates a specified part of a the tree after a new leaf
+     * has been inserted.
+     * 
+     * @param start - where to start recreating from
+     * @param paragraph - the paragraph to recreate
+     * @param onlyContent - true if this is the only content
+     */
+    private void recreateLeaves(int start, BranchElement paragraph, boolean onlyContent)
+    {
+      int index = paragraph.getElementIndex(start);
+      Element child = paragraph.getElement(index);
+      AttributeSet atts = child.getAttributes();
+      
+      if (!onlyContent)
+        {
+          BranchElement newBranch = (BranchElement) createBranchElement(paragraph,
+                                                                        atts);
+          Element newLeaf = createLeafElement(newBranch, atts, start, 
+                                              child.getEndOffset());
+          newBranch.replace(0, 0, new Element[] { newLeaf });
+          
+          BranchElement parent = (BranchElement) paragraph.getParentElement();
+          int parSize = parent.getElementCount();
+          Edit edit = getEditForParagraphAndIndex(parent, parSize);
+          edit.addAddedElement(newBranch);
+            
+          int paragraphSize = paragraph.getElementCount();
+          Element[] removed = new Element[paragraphSize - (index + 1)];
+          int s = 0;
+          for (int j = index + 1; j < paragraphSize; j++)
+            removed[s++] = paragraph.getElement(j);
+          
+          edit = getEditForParagraphAndIndex(paragraph, index);
+          edit.addRemovedElements(removed);
+          Element[] added = recreateAfterFracture(removed, newBranch, 0, child.getEndOffset());
+          newBranch.replace(1, 0, added);
+          
+          lastFractured = newLeaf;
+          pos = newBranch.getEndOffset();
+        }
+      else
+        {
+          Element newLeaf = createLeafElement(paragraph, atts, start, 
+                                              child.getEndOffset());
+          Edit edit = getEditForParagraphAndIndex(paragraph, index);
+          edit.addAddedElement(newLeaf);
+        }
+    }
+    
+    /**
+     * Splits an element if <code>offset</code> is not already at its
+     * boundary.
+     * 
+     * @param el
+     *          the Element to possibly split
+     * @param offset
+     *          the offset at which to possibly split
+     * @param space
+     *          the amount of space to create between the splitted parts
+     * @param editIndex 
+     *          the index of the edit to use
+     * @return An array of elements which represent the split result. This array
+     *         has two elements, the two parts of the split. The first element
+     *         might be null, which means that the element which should be
+     *         splitted can remain in place. The second element might also be
+     *         null, which means that the offset is already at an element
+     *         boundary and the element doesn't need to be splitted.
+     */
+    private Element[] split(Element el, int offset, int space, int editIndex)
+    {
+      // If we are at an element boundary, then return an empty array.
+      if ((offset == el.getStartOffset() || offset == el.getEndOffset())
+          && space == 0 && el.isLeaf())
+        return new Element[2];
+
+      // If the element is an instance of BranchElement, then we
+      // recursivly
+      // call this method to perform the split.
+      Element[] res = new Element[2];
+      if (el instanceof BranchElement)
+        {
+          int index = el.getElementIndex(offset);
+          Element child = el.getElement(index);
+          Element[] result = split(child, offset, space, editIndex);
+          Element[] removed;
+          Element[] added;
+          Element[] newAdded;
+
+          int count = el.getElementCount();
+          if (result[1] != null)
+            {
+              // This is the case when we can keep the first element.
+              if (result[0] == null)
+                {
+                  removed = new Element[count - index - 1];
+                  newAdded = new Element[count - index - 1];
+                  added = new Element[] {};
+
+                }
+              // This is the case when we may not keep the first
+              // element.
+              else
+                {
+                  removed = new Element[count - index];
+                  newAdded = new Element[count - index];
+                  added = new Element[] { result[0] };
+                }
+              newAdded[0] = result[1];
+              for (int i = index; i < count; i++)
+                {
+                  Element el2 = el.getElement(i);
+                  int ind = i - count + removed.length;
+                  removed[ind] = el2;
+                  if (ind != 0)
+                    newAdded[ind] = el2;
+                }
+              
+              Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
+              edit.addRemovedElements(removed);
+              edit.addAddedElements(added);
+              
+              BranchElement newPar =
+                (BranchElement) createBranchElement(el.getParentElement(),
+                                                    el.getAttributes());
+              newPar.replace(0, 0, newAdded);
+              res = new Element[] { null, newPar };
+            }
+          else
+            {
+              removed = new Element[count - index];
+              for (int i = index; i < count; ++i)
+                removed[i - index] = el.getElement(i);
+              
+              Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
+              edit.addRemovedElements(removed);
+              
+              BranchElement newPar = (BranchElement) createBranchElement(el.getParentElement(),
+                                                                         el.getAttributes());
+              newPar.replace(0, 0, removed);
+              res = new Element[] { null, newPar };
+            }
+        }
+      else if (el instanceof LeafElement)
+        {
+          BranchElement par = (BranchElement) el.getParentElement();
+          Element el1 = createLeafElement(par, el.getAttributes(),
+                                          el.getStartOffset(), offset);
+
+          Element el2 = createLeafElement(par, el.getAttributes(), 
+                                          offset + space,
+                                          el.getEndOffset());
+          res = new Element[] { el1, el2 };
+        }
+      return res;
+    }
+
+    /**
+     * Inserts a fracture into the document structure.
+     * 
+     * @param tag -
+     *          the element spec.
+     */
+    private void insertFracture(ElementSpec tag)
+    {
+      // insert the fracture at offset.
+      BranchElement parent = (BranchElement) elementStack.peek();
+      int parentIndex = parent.getElementIndex(pos);
+      AttributeSet parentAtts = parent.getAttributes();
+      Element toFracture = parent.getElement(parentIndex);
+      int parSize = parent.getElementCount();
+      Edit edit = getEditForParagraphAndIndex(parent, parentIndex);
+      Element frac = toFracture;
+      int leftIns = 0;
+      int indexOfFrac = toFracture.getElementIndex(pos);
+      int size = toFracture.getElementCount();
+
+      // gets the leaf that falls along the fracture
+      frac = toFracture.getElement(indexOfFrac);
+      while (!frac.isLeaf())
+        frac = frac.getElement(frac.getElementIndex(pos));
+
+      AttributeSet atts = frac.getAttributes();
+      int fracStart = frac.getStartOffset();
+      int fracEnd = frac.getEndOffset();
+      if (pos >= fracStart && pos < fracEnd)
+        {
+          // recreate left-side of branch and all its children before offset
+          // add the fractured leaves to the right branch
+          BranchElement rightBranch =
+            (BranchElement) createBranchElement(parent, parentAtts);
+          
+          // Check if left branch has already been edited. If so, we only
+          // need to create the right branch.
+          BranchElement leftBranch = null;
+          Element[] added = null;
+          if (edit.added.size() > 0 || edit.removed.size() > 0)
+            {
+              added = new Element[] { rightBranch };
+              
+              // don't try to remove left part of tree
+              parentIndex++;
+            }
+          else
+            {
+              leftBranch =
+                (BranchElement) createBranchElement(parent, parentAtts);
+              added = new Element[] { leftBranch, rightBranch };
+
+              // add fracture to leftBranch
+              if (fracStart != pos)
+                {
+                  Element leftFracturedLeaf =
+                    createLeafElement(leftBranch, atts, fracStart, pos);
+                  leftBranch.replace(leftIns, 0,
+                                     new Element[] { leftFracturedLeaf });
+                }
+            }
+
+          if (!toFracture.isLeaf())
+            {
+              // add all non-fracture elements to the branches
+              if (indexOfFrac > 0 && leftBranch != null)
+                {
+                  Element[] add = new Element[indexOfFrac];
+                  for (int i = 0; i < indexOfFrac; i++)
+                    add[i] = toFracture.getElement(i);
+                  leftIns = add.length;
+                  leftBranch.replace(0, 0, add);
+                }
+
+              int count = size - indexOfFrac - 1;
+              if (count > 0)
+                {
+                  Element[] add = new Element[count];
+                  int j = 0;
+                  int i = indexOfFrac + 1;
+                  while (j < count)
+                    add[j++] = toFracture.getElement(i++);
+                  rightBranch.replace(0, 0, add);
+                }
+            }
+          
+          // add to fracture to rightBranch          
+          // Check if we can join the right frac leaf with the next leaf
+          int rm = 0;
+          int end = fracEnd;
+          Element next = rightBranch.getElement(0);
+          if (next != null && next.isLeaf()
+              && next.getAttributes().isEqual(atts))
+            {
+              end = next.getEndOffset();
+              rm = 1;
+            }
+
+          Element rightFracturedLeaf = createLeafElement(rightBranch, atts,
+                                                         pos, end);
+          rightBranch.replace(0, rm, new Element[] { rightFracturedLeaf });
+
+          // recreate those elements after parentIndex and add/remove all
+          // new/old elements to parent
+          int remove = parSize - parentIndex;
+          Element[] removed = new Element[0];
+          Element[] added2 = new Element[0];
+          if (remove > 0)
+            {
+              removed = new Element[remove];
+              int s = 0;
+              for (int j = parentIndex; j < parSize; j++)
+                removed[s++] = parent.getElement(j);
+              edit.addRemovedElements(removed);
+              added2 = recreateAfterFracture(removed, parent, 1,
+                                            rightBranch.getEndOffset());
+            }
+          
+          edit.addAddedElements(added);
+          edit.addAddedElements(added2);
+          elementStack.push(rightBranch);
+          lastFractured = rightFracturedLeaf;
+        }
+      else
+        fracNotCreated = true;
+    }
+
+    /**
+     * Recreates all the elements from the parent to the element on the top of
+     * the stack, starting from startFrom with the starting offset of
+     * startOffset.
+     * 
+     * @param recreate -
+     *          the elements to recreate
+     * @param parent -
+     *          the element to add the new elements to
+     * @param startFrom -
+     *          where to start recreating from
+     * @param startOffset -
+     *          the offset of the first element
+     * @return the array of added elements         
+     */
+    private Element[] recreateAfterFracture(Element[] recreate,
+                                       BranchElement parent, int startFrom,
+                                       int startOffset)
+    {
+      Element[] added = new Element[recreate.length - startFrom];
+      int j = 0;
+      for (int i = startFrom; i < recreate.length; i++)
+        {
+          Element curr = recreate[i];
+          int len = curr.getEndOffset() - curr.getStartOffset();
+          if (curr instanceof LeafElement)
+            added[j] = createLeafElement(parent, curr.getAttributes(),
+                                         startOffset, startOffset + len);
+          else
+            {
+              BranchElement br =
+                (BranchElement) createBranchElement(parent,
+                                                    curr.getAttributes());
+              int bSize = curr.getElementCount();
+              for (int k = 0; k < bSize; k++)
+                {
+                  Element bCurr = curr.getElement(k);
+                  Element[] add = recreateAfterFracture(new Element[] { bCurr }, br, 0,
+                                        startOffset);
+                  br.replace(0, 0, add);
+                  
+                }
+              added[j] = br;
+            }
+          startOffset += len;
+          j++;
+        }
+
+      return added;
+    }
+  }
+
+  /**
+   * This method looks through the Vector of Edits to see if there is already an
+   * Edit object associated with the given paragraph. If there is, then we
+   * return it. Otherwise we create a new Edit object, add it to the vector, and
+   * return it. Note: this method is package private to avoid accessors.
+   * 
+   * @param index
+   *          the index associated with the Edit we want to create
+   * @param para
+   *          the paragraph associated with the Edit we want
+   * @return the found or created Edit object
+   */
+  Edit getEditForParagraphAndIndex(BranchElement para, int index)
+  {
+    Edit curr;
+    int size = edits.size();
+    for (int i = 0; i < size; i++)
+      {
+        curr = (Edit) edits.elementAt(i);
+        if (curr.e.equals(para))
+          return curr;
+      }
+    curr = new Edit(para, index, null, null);
+    edits.add(curr);
+    
+    return curr;
+  }
+  /**
+   * Instance of all editing information for an object in the Vector. This class
+   * is used to add information to the DocumentEvent associated with an
+   * insertion/removal/change as well as to store the changes that need to be
+   * made so they can be made all at the same (appropriate) time.
+   */
+  class Edit
+  {
+    /** The element to edit . */
+    Element e;
+
+    /** The index of the change. */
+    int index;
+
+    /** The removed elements. */
+    Vector removed = new Vector();
+
+    /** The added elements. */
+    Vector added = new Vector();
+
+    /**
+     * Return an array containing the Elements that have been removed from the
+     * paragraph associated with this Edit.
+     * 
+     * @return an array of removed Elements
+     */
+    public Element[] getRemovedElements()
+    {
+      int size = removed.size();
+      Element[] removedElements = new Element[size];
+      for (int i = 0; i < size; i++)
+        removedElements[i] = (Element) removed.elementAt(i);
+      return removedElements;
+    }
+
+    /**
+     * Return an array containing the Elements that have been added to the
+     * paragraph associated with this Edit.
+     * 
+     * @return an array of added Elements
+     */
+    public Element[] getAddedElements()
+    {
+      int size = added.size();
+      Element[] addedElements = new Element[size];
+      for (int i = 0; i < size; i++)
+        addedElements[i] = (Element) added.elementAt(i);
+      return addedElements;
+    }
+    
+    /** 
+     * Checks if e is already in the vector.
+     * 
+     * @param e - the Element to look for
+     * @param v - the vector to search
+     * @return true if e is in v.
+     */
+    private boolean contains(Vector v, Element e)
+    {
+      if (e == null)
+        return false;
+      
+      int i = v.size();
+      for (int j = 0; j < i; j++)
+        {
+          Element e1 = (Element) v.get(j);
+          if ((e1 != null) && (e1.getAttributes().isEqual(e.getAttributes()))
+              && (e1.getName().equals(e.getName()))
+              && (e1.getStartOffset() == e.getStartOffset())
+              && (e1.getEndOffset() == e.getEndOffset())
+              && (e1.getParentElement().equals(e.getParentElement()))
+              && (e1.getElementCount() == e.getElementCount()))
+            return true;
+        }
+      return false;
+    }
+
+    /**
+     * Adds one Element to the vector of removed Elements.
+     * 
+     * @param e
+     *          the Element to add
+     */
+    public void addRemovedElement(Element e)
+    {
+      if (!contains(removed, e))
+        removed.add(e);
+    }
+
+    /**
+     * Adds each Element in the given array to the vector of removed Elements
+     * 
+     * @param e
+     *          the array containing the Elements to be added
+     */
+    public void addRemovedElements(Element[] e)
+    {
+      if (e == null || e.length == 0)
+        return;
+      for (int i = 0; i < e.length; i++)
+        {
+          if (!contains(removed, e[i]))
+            removed.add(e[i]);
+        }
+    }
+
+    /**
+     * Adds one Element to the vector of added Elements.
+     * 
+     * @param e
+     *          the Element to add
+     */
+    public void addAddedElement(Element e)
+    {
+      if (!contains(added, e))
+        added.add(e);
+    }
+
+    /**
+     * Adds each Element in the given array to the vector of added Elements.
+     * 
+     * @param e
+     *          the array containing the Elements to be added
+     */
+    public void addAddedElements(Element[] e)
+    {
+      if (e == null || e.length == 0)
+        return;
+      for (int i = 0; i < e.length; i++)
+        {
+          if (!contains(added, e[i]))
+            added.add(e[i]);
+        }
+    }
+
+    /**
+     * Creates a new Edit object with the given parameters
+     * 
+     * @param e
+     *          the paragraph Element associated with this Edit
+     * @param i
+     *          the index within the paragraph where changes are started
+     * @param removed
+     *          an array containing Elements that should be removed from the
+     *          paragraph Element
+     * @param added
+     *          an array containing Elements that should be added to the
+     *          paragraph Element
+     */
+    public Edit(Element e, int i, Element[] removed, Element[] added)
+    {
+      this.e = e;
+      this.index = i;
+      addRemovedElements(removed);
+      addAddedElements(added);
+    }
+  }
+
+  /**
+   * An element type for sections. This is a simple BranchElement with a unique
+   * name.
+   */
+  protected class SectionElement extends BranchElement
+  {
+    /**
+     * Creates a new SectionElement.
+     */
+    public SectionElement()
+    {
+      super(null, null);
+    }
+
+    /**
+     * Returns the name of the element. This method always returns
+     * "section".
+     * 
+     * @return the name of the element
+     */
+    public String getName()
+    {
+      return SectionElementName;
+    }
+  }
+
+  /**
+   * Receives notification when any of the document's style changes and calls
+   * {@link DefaultStyledDocument#styleChanged(Style)}.
+   * 
+   * @author Roman Kennke (kennke at aicas.com)
+   */
+  private class StyleChangeListener implements ChangeListener
+  {
+
+    /**
+     * Receives notification when any of the document's style changes and calls
+     * {@link DefaultStyledDocument#styleChanged(Style)}.
+     * 
+     * @param event
+     *          the change event
+     */
+    public void stateChanged(ChangeEvent event)
+    {
+      Style style = (Style) event.getSource();
+      styleChanged(style);
+    }
+  }
+
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 940485415728614849L;
+
+  /**
+   * The default size to use for new content buffers.
+   */
+  public static final int BUFFER_SIZE_DEFAULT = 4096;
+
+  /**
+   * The <code>EditorBuffer</code> that is used to manage to
+   * <code>Element</code> hierarchy.
+   */
+  protected DefaultStyledDocument.ElementBuffer buffer;
+
+  /**
+   * Listens for changes on this document's styles and notifies styleChanged().
+   */
+  private StyleChangeListener styleChangeListener;
+
+  /**
+   * Vector that contains all the edits. Maybe replace by a HashMap.
+   */
+  Vector edits = new Vector();
+
+  /**
+   * Creates a new <code>DefaultStyledDocument</code>.
+   */
+  public DefaultStyledDocument()
+  {
+    this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
+  }
+
+  /**
+   * Creates a new <code>DefaultStyledDocument</code> that uses the specified
+   * {@link StyleContext}.
+   * 
+   * @param context
+   *          the <code>StyleContext</code> to use
+   */
+  public DefaultStyledDocument(StyleContext context)
+  {
+    this(new GapContent(BUFFER_SIZE_DEFAULT), context);
+  }
+
+  /**
+   * Creates a new <code>DefaultStyledDocument</code> that uses the specified
+   * {@link StyleContext} and {@link Content} buffer.
+   * 
+   * @param content
+   *          the <code>Content</code> buffer to use
+   * @param context
+   *          the <code>StyleContext</code> to use
+   */
+  public DefaultStyledDocument(AbstractDocument.Content content,
+                               StyleContext context)
+  {
+    super(content, context);
+    buffer = new ElementBuffer(createDefaultRoot());
+    setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
+  }
+
+  /**
+   * Adds a style into the style hierarchy. Unspecified style attributes can be
+   * resolved in the <code>parent</code> style, if one is specified. While it
+   * is legal to add nameless styles (<code>nm == null</code),
+   * you must be aware that the client application is then responsible
+   * for managing the style hierarchy, since unnamed styles cannot be
+   * looked up by their name.
+   *
+   * @param nm the name of the style or <code>null</code> if the style should
+   *           be unnamed
+   * @param parent the parent in which unspecified style attributes are
+   *           resolved, or <code>null</code> if that is not necessary
+   *
+   * @return the newly created <code>Style</code>
+   */
+  public Style addStyle(String nm, Style parent)
+  {
+    StyleContext context = (StyleContext) getAttributeContext();
+    Style newStyle = context.addStyle(nm, parent);
+
+    // Register change listener.
+    if (styleChangeListener == null)
+      styleChangeListener = new StyleChangeListener();
+    newStyle.addChangeListener(styleChangeListener);
+
+    return newStyle;
+  }
+
+  /**
+   * Create the default root element for this kind of <code>Document</code>.
+   * 
+   * @return the default root element for this kind of <code>Document</code>
+   */
+  protected AbstractDocument.AbstractElement createDefaultRoot()
+  {
+    Element[] tmp;
+    SectionElement section = new SectionElement();
+
+    BranchElement paragraph = new BranchElement(section, null);
+    tmp = new Element[1];
+    tmp[0] = paragraph;
+    section.replace(0, 0, tmp);
+
+    Element leaf = new LeafElement(paragraph, null, 0, 1);
+    tmp = new Element[1];
+    tmp[0] = leaf;
+    paragraph.replace(0, 0, tmp);
+
+    return section;
+  }
+
+  /**
+   * Returns the <code>Element</code> that corresponds to the character at the
+   * specified position.
+   * 
+   * @param position
+   *          the position of which we query the corresponding
+   *          <code>Element</code>
+   * @return the <code>Element</code> that corresponds to the character at the
+   *         specified position
+   */
+  public Element getCharacterElement(int position)
+  {
+    Element element = getDefaultRootElement();
+
+    while (!element.isLeaf())
+      {
+        int index = element.getElementIndex(position);
+        element = element.getElement(index);
+      }
+
+    return element;
+  }
+
+  /**
+   * Extracts a background color from a set of attributes.
+   * 
+   * @param attributes
+   *          the attributes from which to get a background color
+   * @return the background color that correspond to the attributes
+   */
+  public Color getBackground(AttributeSet attributes)
+  {
+    StyleContext context = (StyleContext) getAttributeContext();
+    return context.getBackground(attributes);
+  }
+
+  /**
+   * Returns the default root element.
+   * 
+   * @return the default root element
+   */
+  public Element getDefaultRootElement()
+  {
+    return buffer.getRootElement();
+  }
+
+  /**
+   * Extracts a font from a set of attributes.
+   * 
+   * @param attributes
+   *          the attributes from which to get a font
+   * @return the font that correspond to the attributes
+   */
+  public Font getFont(AttributeSet attributes)
+  {
+    StyleContext context = (StyleContext) getAttributeContext();
+    return context.getFont(attributes);
+  }
+
+  /**
+   * Extracts a foreground color from a set of attributes.
+   * 
+   * @param attributes
+   *          the attributes from which to get a foreground color
+   * @return the foreground color that correspond to the attributes
+   */
+  public Color getForeground(AttributeSet attributes)
+  {
+    StyleContext context = (StyleContext) getAttributeContext();
+    return context.getForeground(attributes);
+  }
+
+  /**
+   * Returns the logical <code>Style</code> for the specified position.
+   * 
+   * @param position
+   *          the position from which to query to logical style
+   * @return the logical <code>Style</code> for the specified position
+   */
+  public Style getLogicalStyle(int position)
+  {
+    Element paragraph = getParagraphElement(position);
+    AttributeSet attributes = paragraph.getAttributes();
+    AttributeSet a = attributes.getResolveParent();
+    // If the resolve parent is not of type Style, we return null.
+    if (a instanceof Style)
+      return (Style) a;
+    return null;
+  }
+
+  /**
+   * Returns the paragraph element for the specified position. If the position
+   * is outside the bounds of the document's root element, then the closest
+   * element is returned. That is the last paragraph if
+   * <code>position >= endIndex</code> or the first paragraph if
+   * <code>position < startIndex</code>.
+   * 
+   * @param position
+   *          the position for which to query the paragraph element
+   * @return the paragraph element for the specified position
+   */
+  public Element getParagraphElement(int position)
+  {
+    Element e = getDefaultRootElement();
+    while (!e.isLeaf())
+      e = e.getElement(e.getElementIndex(position));
+
+    if (e != null)
+      return e.getParentElement();
+    return e;
+  }
+
+  /**
+   * Looks up and returns a named <code>Style</code>.
+   * 
+   * @param nm
+   *          the name of the <code>Style</code>
+   * @return the found <code>Style</code> of <code>null</code> if no such
+   *         <code>Style</code> exists
+   */
+  public Style getStyle(String nm)
+  {
+    StyleContext context = (StyleContext) getAttributeContext();
+    return context.getStyle(nm);
+  }
+
+  /**
+   * Removes a named <code>Style</code> from the style hierarchy.
+   * 
+   * @param nm
+   *          the name of the <code>Style</code> to be removed
+   */
+  public void removeStyle(String nm)
+  {
+    StyleContext context = (StyleContext) getAttributeContext();
+    context.removeStyle(nm);
+  }
+
+  /**
+   * Sets text attributes for the fragment specified by <code>offset</code>
+   * and <code>length</code>.
+   * 
+   * @param offset
+   *          the start offset of the fragment
+   * @param length
+   *          the length of the fragment
+   * @param attributes
+   *          the text attributes to set
+   * @param replace
+   *          if <code>true</code>, the attributes of the current selection
+   *          are overridden, otherwise they are merged
+   */
+  public void setCharacterAttributes(int offset, int length,
+                                     AttributeSet attributes, boolean replace)
+  {
+    // Exit early if length is 0, so no DocumentEvent is created or fired.
+    if (length == 0)
+      return;
+    try
+      {
+        // Must obtain a write lock for this method. writeLock() and
+        // writeUnlock() should always be in try/finally block to make
+        // sure that locking happens in a balanced manner.
+        writeLock();
+        DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
+                                                           length,
+                                                           DocumentEvent.EventType.CHANGE);
+
+        // Modify the element structure so that the interval begins at an
+        // element
+        // start and ends at an element end.
+        buffer.change(offset, length, ev);
+
+        Element root = getDefaultRootElement();
+        // Visit all paragraph elements within the specified interval
+        int end = offset + length;
+        Element curr;
+        for (int pos = offset; pos < end;)
+          {
+            // Get the CharacterElement at offset pos.
+            curr = getCharacterElement(pos);
+            if (pos == curr.getEndOffset())
+              break;
+
+            MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
+            ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
+            // If replace is true, remove all the old attributes.
+            if (replace)
+              a.removeAttributes(a);
+            // Add all the new attributes.
+            a.addAttributes(attributes);
+            // Increment pos so we can check the next CharacterElement.
+            pos = curr.getEndOffset();
+          }
+        fireChangedUpdate(ev);
+        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+      }
+    finally
+      {
+        writeUnlock();
+      }
+  }
+
+  /**
+   * Sets the logical style for the paragraph at the specified position.
+   * 
+   * @param position
+   *          the position at which the logical style is added
+   * @param style
+   *          the style to set for the current paragraph
+   */
+  public void setLogicalStyle(int position, Style style)
+  {
+    Element el = getParagraphElement(position);
+    // getParagraphElement doesn't return null but subclasses might so
+    // we check for null here.
+    if (el == null)
+      return;
+    try
+      {
+        writeLock();
+        if (el instanceof AbstractElement)
+          {
+            AbstractElement ael = (AbstractElement) el;
+            ael.setResolveParent(style);
+            int start = el.getStartOffset();
+            int end = el.getEndOffset();
+            DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
+                                                               end - start,
+                                                               DocumentEvent.EventType.CHANGE);
+            fireChangedUpdate(ev);
+            fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+          }
+        else
+          throw new AssertionError(
+                                   "paragraph elements are expected to be"
+                                       + "instances of AbstractDocument.AbstractElement");
+      }
+    finally
+      {
+        writeUnlock();
+      }
+  }
+
+  /**
+   * Sets text attributes for the paragraph at the specified fragment.
+   * 
+   * @param offset
+   *          the beginning of the fragment
+   * @param length
+   *          the length of the fragment
+   * @param attributes
+   *          the text attributes to set
+   * @param replace
+   *          if <code>true</code>, the attributes of the current selection
+   *          are overridden, otherwise they are merged
+   */
+  public void setParagraphAttributes(int offset, int length,
+                                     AttributeSet attributes, boolean replace)
+  {
+    try
+      {
+        // Must obtain a write lock for this method. writeLock() and
+        // writeUnlock() should always be in try/finally blocks to make
+        // sure that locking occurs in a balanced manner.
+        writeLock();
+
+        // Create a DocumentEvent to use for changedUpdate().
+        DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
+                                                           length,
+                                                           DocumentEvent.EventType.CHANGE);
+
+        // Have to iterate through all the _paragraph_ elements that are
+        // contained or partially contained in the interval
+        // (offset, offset + length).
+        Element rootElement = getDefaultRootElement();
+        int startElement = rootElement.getElementIndex(offset);
+        int endElement = rootElement.getElementIndex(offset + length - 1);
+        if (endElement < startElement)
+          endElement = startElement;
+
+        for (int i = startElement; i <= endElement; i++)
+          {
+            Element par = rootElement.getElement(i);
+            MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
+            // Add the change to the DocumentEvent.
+            ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
+            // If replace is true remove the old attributes.
+            if (replace)
+              a.removeAttributes(a);
+            // Add the new attributes.
+            a.addAttributes(attributes);
+          }
+        fireChangedUpdate(ev);
+        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+      }
+    finally
+      {
+        writeUnlock();
+      }
+  }
+
+  /**
+   * Called in response to content insert actions. This is used to update the
+   * element structure.
+   * 
+   * @param ev
+   *          the <code>DocumentEvent</code> describing the change
+   * @param attr
+   *          the attributes for the change
+   */
+  protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
+  {
+    super.insertUpdate(ev, attr);
+    // If the attribute set is null, use an empty attribute set.
+    if (attr == null)
+      attr = SimpleAttributeSet.EMPTY;
+    int offset = ev.getOffset();
+    int length = ev.getLength();
+    int endOffset = offset + length;
+    AttributeSet paragraphAttributes = getParagraphElement(endOffset).getAttributes();
+    Segment txt = new Segment();
+    try
+      {
+        getText(offset, length, txt);
+      }
+    catch (BadLocationException ex)
+      {
+        AssertionError ae = new AssertionError("Unexpected bad location");
+        ae.initCause(ex);
+        throw ae;
+      }
+
+    int len = 0;
+    Vector specs = new Vector();
+    ElementSpec finalStartTag = null;
+    short finalStartDirection = ElementSpec.OriginateDirection;
+    boolean prevCharWasNewline = false;
+    Element prev = getCharacterElement(offset);
+    Element next = getCharacterElement(endOffset);
+    Element prevParagraph = getParagraphElement(offset);
+    Element paragraph = getParagraphElement(endOffset);
+
+    int segmentEnd = txt.offset + txt.count;
+
+    // Check to see if we're inserting immediately after a newline.
+    if (offset > 0)
+      {
+        try
+          {
+            String s = getText(offset - 1, 1);
+            if (s.equals("\n"))
+              {
+                finalStartDirection = handleInsertAfterNewline(specs, offset,
+                                                               endOffset,
+                                                               prevParagraph,
+                                                               paragraph,
+                                                               paragraphAttributes);
+
+                prevCharWasNewline = true;
+                // Find the final start tag from the ones just created.
+                for (int i = 0; i < specs.size(); i++)
+                  if (((ElementSpec) specs.get(i)).getType() == ElementSpec.StartTagType)
+                    finalStartTag = (ElementSpec) specs.get(i);
+              }
+          }
+        catch (BadLocationException ble)
+          {
+            // This shouldn't happen.
+            AssertionError ae = new AssertionError();
+            ae.initCause(ble);
+            throw ae;
+          }
+      }
+
+    for (int i = txt.offset; i < segmentEnd; ++i)
+      {
+        len++;
+        if (txt.array[i] == '\n')
+          {
+            // Add the ElementSpec for the content.
+            specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
+
+            // Add ElementSpecs for the newline.
+            specs.add(new ElementSpec(null, ElementSpec.EndTagType));
+            finalStartTag = new ElementSpec(paragraphAttributes,
+                                            ElementSpec.StartTagType);
+            specs.add(finalStartTag);
+            len = 0;
+          }
+      }
+
+    // Create last element if last character hasn't been a newline.
+    if (len > 0)
+      specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
+
+    // Set the direction of the last spec of type StartTagType.
+    // If we are inserting after a newline then this value comes from
+    // handleInsertAfterNewline.
+    if (finalStartTag != null)
+      {
+        if (prevCharWasNewline)
+          finalStartTag.setDirection(finalStartDirection);
+        else if (prevParagraph.getEndOffset() != endOffset)
+          finalStartTag.setDirection(ElementSpec.JoinFractureDirection);
+        else
+          {
+            // If there is an element AFTER this one, then set the
+            // direction to JoinNextDirection.
+            Element parent = prevParagraph.getParentElement();
+            int index = parent.getElementIndex(offset);
+            if (index + 1 < parent.getElementCount()
+                && !parent.getElement(index + 1).isLeaf())
+              finalStartTag.setDirection(ElementSpec.JoinNextDirection);
+          }
+      }
+
+    // If we are at the last index, then check if we could probably be
+    // joined with the next element.
+    // This means:
+    // - we must be a ContentTag
+    // - if there is a next Element, we must have the same attributes
+    // - if there is no next Element, but one will be created,
+    // we must have the same attributes as the higher-level run.
+    ElementSpec last = (ElementSpec) specs.lastElement();
+    if (last.getType() == ElementSpec.ContentType)
+      {
+        Element currentRun = prevParagraph.getElement(prevParagraph.getElementIndex(offset));
+        if (currentRun.getEndOffset() == endOffset)
+          {
+            if (endOffset < getLength() && next.getAttributes().isEqual(attr)
+                && last.getType() == ElementSpec.ContentType)
+              last.setDirection(ElementSpec.JoinNextDirection);
+          }
+        else
+          {
+            if (finalStartTag != null
+                && finalStartTag.getDirection() == ElementSpec.JoinFractureDirection
+                && currentRun.getAttributes().isEqual(attr))
+              {
+                last.setDirection(ElementSpec.JoinNextDirection);
+              }
+          }
+      }
+
+    // If we are at the first new element, then check if it could be
+    // joined with the previous element.
+    ElementSpec first = (ElementSpec) specs.firstElement();
+    if (prev.getAttributes().isEqual(attr)
+        && first.getType() == ElementSpec.ContentType)
+      first.setDirection(ElementSpec.JoinPreviousDirection);
+
+    ElementSpec[] elSpecs = (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
+    buffer.insert(offset, length, elSpecs, ev);
+  }
+
+  /**
+   * A helper method to set up the ElementSpec buffer for the special case of an
+   * insertion occurring immediately after a newline.
+   * 
+   * @param specs
+   *          the ElementSpec buffer to initialize.
+   */
+  short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
+                                 Element prevParagraph, Element paragraph,
+                                 AttributeSet a)
+  {
+    if (prevParagraph.getParentElement() == paragraph.getParentElement())
+      {
+        specs.add(new ElementSpec(a, ElementSpec.EndTagType));
+        specs.add(new ElementSpec(a, ElementSpec.StartTagType));
+        if (paragraph.getStartOffset() != endOffset)
+          return ElementSpec.JoinFractureDirection;
+        // If there is an Element after this one, use JoinNextDirection.
+        Element parent = paragraph.getParentElement();
+        if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
+          return ElementSpec.JoinNextDirection;
+      }
+    return ElementSpec.OriginateDirection;
+  }
+
+  /**
+   * Updates the document structure in response to text removal. This is
+   * forwarded to the {@link ElementBuffer} of this document. Any changes to the
+   * document structure are added to the specified document event and sent to
+   * registered listeners.
+   * 
+   * @param ev
+   *          the document event that records the changes to the document
+   */
+  protected void removeUpdate(DefaultDocumentEvent ev)
+  {
+    super.removeUpdate(ev);
+    buffer.remove(ev.getOffset(), ev.getLength(), ev);
+  }
+
+  /**
+   * Returns an enumeration of all style names.
+   * 
+   * @return an enumeration of all style names
+   */
+  public Enumeration getStyleNames()
+  {
+    StyleContext context = (StyleContext) getAttributeContext();
+    return context.getStyleNames();
+  }
+
+  /**
+   * Called when any of this document's styles changes.
+   * 
+   * @param style
+   *          the style that changed
+   */
+  protected void styleChanged(Style style)
+  {
+    // Nothing to do here. This is intended to be overridden by subclasses.
+  }
+
+  /**
+   * Inserts a bulk of structured content at once.
+   * 
+   * @param offset
+   *          the offset at which the content should be inserted
+   * @param data
+   *          the actual content spec to be inserted
+   */
+  protected void insert(int offset, ElementSpec[] data)
+      throws BadLocationException
+  {
+    if (data == null || data.length == 0)
+      return;
+    try
+      {
+        // writeLock() and writeUnlock() should always be in a try/finally
+        // block so that locking balance is guaranteed even if some
+        // exception is thrown.
+        writeLock();
+
+        // First we collect the content to be inserted.
+        StringBuffer contentBuffer = new StringBuffer();
+        for (int i = 0; i < data.length; i++)
+          {
+            // Collect all inserts into one so we can get the correct
+            // ElementEdit
+            ElementSpec spec = data[i];
+            if (spec.getArray() != null && spec.getLength() > 0)
+              contentBuffer.append(spec.getArray(), spec.getOffset(),
+                                   spec.getLength());
+          }
+
+        int length = contentBuffer.length();
+
+        // If there was no content inserted then exit early.
+        if (length == 0)
+          return;
+
+        UndoableEdit edit = content.insertString(offset,
+                                                 contentBuffer.toString());
+
+        // Create the DocumentEvent with the ElementEdit added
+        DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
+                                                           length,
+                                                           DocumentEvent.EventType.INSERT);
+        ev.addEdit(edit);
+
+        // Finally we must update the document structure and fire the insert
+        // update event.
+        buffer.insert(offset, length, data, ev);
+        fireInsertUpdate(ev);
+        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+      }
+    finally
+      {
+        writeUnlock();
+      }
+  }
+
+  /**
+   * Initializes the <code>DefaultStyledDocument</code> with the specified
+   * data.
+   * 
+   * @param data
+   *          the specification of the content with which the document is
+   *          initialized
+   */
+  protected void create(ElementSpec[] data)
+  {
+    writeLock();
+    try
+      {
+        // Clear content if there is some.
+        int len = getLength();
+        if (len > 0)
+          remove(0, len);
+
+        // Now we insert the content.
+        StringBuilder b = new StringBuilder();
+        for (int i = 0; i < data.length; ++i)
+          {
+            ElementSpec el = data[i];
+            if (el.getArray() != null && el.getLength() > 0)
+              b.append(el.getArray(), el.getOffset(), el.getLength());
+          }
+        Content content = getContent();
+        UndoableEdit cEdit = content.insertString(0, b.toString());
+
+        DefaultDocumentEvent ev =
+          new DefaultDocumentEvent(0, b.length(),
+                                   DocumentEvent.EventType.INSERT);
+        ev.addEdit(cEdit);
+
+        // We do a little trick here to get the new structure: We instantiate
+        // a new ElementBuffer with a new root element, insert into that root
+        // and then reparent the newly created elements to the old root
+        // element.
+        BranchElement createRoot =
+          (BranchElement) createBranchElement(null, null);
+        Element dummyLeaf = createLeafElement(createRoot, null, 0, 1);
+        createRoot.replace(0, 0, new Element[]{ dummyLeaf });
+        ElementBuffer createBuffer = new ElementBuffer(createRoot);
+        createBuffer.insert(0, b.length(), data, new DefaultDocumentEvent(0, b.length(), DocumentEvent.EventType.INSERT));
+        // Now the new root is the first child of the createRoot.
+        Element newRoot = createRoot.getElement(0);
+        BranchElement root = (BranchElement) getDefaultRootElement();
+        Element[] added = new Element[newRoot.getElementCount()];
+        for (int i = 0; i < added.length; ++i)
+          {
+            added[i] = newRoot.getElement(i);
+            ((AbstractElement) added[i]).element_parent = root;
+          }
+        Element[] removed = new Element[root.getElementCount()];
+        for (int i = 0; i < removed.length; ++i)
+          removed[i] = root.getElement(i);
+
+        // Replace the old elements in root with the new and update the event.
+        root.replace(0, removed.length, added);
+        ev.addEdit(new ElementEdit(root, 0, removed, added));
+
+        fireInsertUpdate(ev);
+        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+      }
+    catch (BadLocationException ex)
+      {
+        AssertionError err = new AssertionError("Unexpected bad location");
+        err.initCause(ex);
+        throw err;
+      }
+    finally
+      {
+        writeUnlock();
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,62 @@
+/* DefaultTextUI.java -- Deprecated base UI for text components
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import javax.swing.plaf.basic.BasicTextUI;
+
+/**
+ * This class is deprecated and should not be used anymore. The base UI for
+ * all text components is now {@link BasicTextUI}.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ * @deprecated as of 1.5 use {@link BasicTextUI} instead
+ */
+public abstract class DefaultTextUI extends BasicTextUI
+{
+  /**
+   * This class is deprecated and should not be used anymore. The base UI for
+   * all text components is now {@link BasicTextUI}.
+   *
+   * @deprecated use {@link BasicTextUI} instead
+   */
+  public DefaultTextUI()
+  {
+    // Nothing to do here.
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,221 @@
+/* Document.java --
+   Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import javax.swing.event.DocumentListener;
+import javax.swing.event.UndoableEditListener;
+
+/**
+ * A Document is the model that backs up all text components in Swing.
+ * This interface supports different kinds of implementations, from
+ * simple plain text model up to complex styled HTML or RTF models.
+ */
+public interface Document
+{
+  /**
+   * The key for the property that describes the source of a document.
+   */
+  String StreamDescriptionProperty = "stream";
+
+  /**
+   * The key for the property that is the title of a document.
+   */
+  String TitleProperty = "title";
+
+  /**
+   * Adds a {@link DocumentListener} to this document.
+   *
+   * @param listener the DocumentListener to add
+   */
+  void addDocumentListener(DocumentListener listener);
+
+  /**
+   * Adds an {@link UndoableEditListener} to this document.
+   *
+   * @param listener the UndoableEditListener to add
+   */
+  void addUndoableEditListener(UndoableEditListener listener);
+
+  /**
+   * Creates a mark in the character content at the specified offset.
+   *
+   * @param offs the offset where to place the mark
+   *
+   * @return the created Position object
+   *
+   * @throws BadLocationException of the specified offset is not a valid
+   *         position in the documents content
+   */
+  Position createPosition(int offs)
+    throws BadLocationException;
+
+  /**
+   * Returns the default root element. Views should be using this element
+   * unless other mechanisms for assigning views to element structure is
+   * provided.
+   *
+   * @return the default root element
+   */
+  Element getDefaultRootElement();
+
+  /**
+   * Returns the position that marks the end of the document.
+   *
+   * @return the position that marks the end of the document
+   */
+  Position getEndPosition();
+
+  /**
+   * Returns the length of the document content.
+   *
+   * @return the length of the document content
+   */
+  int getLength();
+
+  /**
+   * Returns a document property with the specified key.
+   *
+   * @param key the (non-null) key for the property to fetch
+   *
+   * @return the property for <code>key</code> or null if no such property
+   *         is stored
+   */
+  Object getProperty(Object key);
+
+  /**
+   * Returns the root elements of the document content.
+   *
+   * @return the root elements of the document content
+   */
+  Element[] getRootElements();
+
+  /**
+   * Returns the position that marks the beginning of the document
+   * content.
+   *
+   * @return the start position
+   */
+  Position getStartPosition();
+
+  /**
+   * Returns the textual content starting at <code>offset</code> with
+   * a length of <code>length</code>.
+   *
+   * @param offset the beginning of the text fragment to fetch
+   * @param length the length of the text fragment to fetch
+   *
+   * @return the text fragment starting at <code>offset</code> with
+   *         a length of <code>length</code>
+   *
+   * @throws BadLocationException if <code>offset</code> or <code>length</code>
+   *         are no valid locations in the document content
+   */
+  String getText(int offset, int length)
+    throws BadLocationException;
+
+  /**
+   * Fetch the textual content starting at <code>offset</code> with
+   * a length of <code>length</code> and store it in <code>txt</code>.
+   *
+   * @param offset the beginning of the text fragment to fetch
+   * @param length the length of the text fragment to fetch
+   * @param txt the Segment where to store the text fragment
+   *
+   * @throws BadLocationException if <code>offset</code> or <code>length</code>
+   *         are no valid locations in the document content
+   */
+  void getText(int offset, int length, Segment txt)
+    throws BadLocationException;
+
+  /**
+   * Inserts a piece of text with an AttributeSet at the specified
+   * <code>offset</code>.
+   *
+   * @param offset the location where to insert the content
+   * @param str the textual content to insert
+   * @param a the Attributes associated with the piece of text
+   *
+   * @throws BadLocationException if <code>offset</code>
+   *         is not a valid location in the document content
+   */
+  void insertString(int offset, String str, AttributeSet a)
+    throws BadLocationException;
+
+  /**
+   * Sets a document property.
+   *
+   * @param key the key of the property
+   * @param value the value of the property
+   */
+  void putProperty(Object key, Object value);
+
+  /**
+   * Removes a piece of content.
+   *
+   * @param offs the location of the fragment to remove
+   * @param len the length of the fragment to remove
+   *
+   * @throws BadLocationException if <code>offs</code> or <code>len</code>
+   *         are no valid locations in the document content
+   */
+  void remove(int offs, int len)
+    throws BadLocationException;
+
+  /**
+   * Removes a DocumentListener from this Document.
+   *
+   * @param listener the DocumentListener to remove
+   */
+  void removeDocumentListener(DocumentListener listener);
+
+  /**
+   * Removes an UndoableEditListener from this Document.
+   *
+   * @param listener the UndoableEditListener to remove
+   */
+  void removeUndoableEditListener(UndoableEditListener listener);
+
+  /**
+   * This allows the Document to be rendered safely. It is made sure that
+   * the Runnable can read the document without any changes while reading.
+   * The Runnable is not allowed to change the Document itself.
+   *
+   * @param r the Runnable that renders the Document
+   */
+  void render(Runnable r);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,83 @@
+/* DocumentFilter.java --
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+public class DocumentFilter
+{
+  public abstract static class FilterBypass
+  {
+    public FilterBypass()
+    {
+      // Do nothing here.
+    }
+
+    public abstract Document getDocument();
+    
+    public abstract void insertString(int offset, String string,
+				      AttributeSet attr)
+      throws BadLocationException;
+    
+    public abstract void remove(int offset, int length)
+      throws BadLocationException;
+    
+    public abstract void replace(int offset, int length, String string,
+				 AttributeSet attrs)
+      throws BadLocationException;
+  }
+  
+  public void insertString(DocumentFilter.FilterBypass fb, int offset,
+			   String string, AttributeSet attr)
+    throws BadLocationException
+  {
+    fb.insertString(offset, string, attr);
+  }
+
+  public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
+    throws BadLocationException
+  {
+    fb.remove(offset, length);
+  }
+
+  public void replace(DocumentFilter.FilterBypass fb, int offset, int length,
+		      String text, AttributeSet attr)
+    throws BadLocationException
+  {
+    fb.replace(offset, length, text, attr);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,98 @@
+/* EditorKit.java --
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.Writer;
+
+import javax.swing.Action;
+import javax.swing.JEditorPane;
+
+public abstract class EditorKit implements Cloneable, Serializable
+{
+  private static final long serialVersionUID = -5044124649345887822L;
+  
+  public EditorKit()
+  {
+    // Nothing to do here.
+  }
+
+  public Object clone()
+  {
+    try
+      {
+        return super.clone();
+      }
+    catch (CloneNotSupportedException e)
+      {
+        return null;
+      }
+  }
+
+  /**
+   * Called when the kit is being removed from the JEditorPane.
+   */
+  public void deinstall(JEditorPane c)
+  {
+    // This default implementation does nothing.
+  }
+
+  public void install(JEditorPane c)
+  {
+    // This default implementation does nothing.
+  }
+
+  public abstract Caret createCaret();
+  public abstract Document createDefaultDocument();
+  public abstract Action[] getActions();
+  public abstract String getContentType();
+  public abstract ViewFactory getViewFactory();
+  public abstract void read(InputStream in, Document doc, int pos)
+    throws BadLocationException, IOException;
+  public abstract void read(Reader in, Document doc, int pos)
+    throws BadLocationException, IOException;
+  public abstract void write(OutputStream out, Document doc, int pos, int len)
+    throws BadLocationException, IOException;
+  public abstract void write(Writer out, Document doc, int pos, int len)
+    throws BadLocationException, IOException;
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,54 @@
+/* Element.java -- 
+   Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+
+
+public interface Element
+{
+    AttributeSet getAttributes();
+    Document getDocument();
+    Element getElement(int index);
+    int getElementCount();
+    int getElementIndex(int offset);
+    int getEndOffset();
+    String getName();
+    Element getParentElement();
+    int getStartOffset();
+    boolean isLeaf();
+ }

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,181 @@
+/* ElementIterator.java --
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+/**
+ * This class can be used to iterate over the {@link Element} tree of
+ * a {@link Document} or an {@link Element}.  This iterator performs
+ * an "in-order" traversal -- first it visits a node, then each of the
+ * node's children in order.  No locking is performed during the
+ * iteration; that is up to the caller.
+ */
+public class ElementIterator implements Cloneable
+{
+  // The root element.
+  private Element root;
+  // The current element.
+  private Element currentElement;
+  // The depth to which we have descended in the tree.
+  private int currentDepth;
+
+  // This is at least as big as the current depth, and at index N
+  // contains the index of the child element we're currently
+  // examining.
+  private int[] state;
+
+  // The previous item.
+  private Element previousItem;
+
+  /**
+   * Create a new ElementIterator to iterate over the given document.
+   * @param document the Document over which we iterate
+   */
+  public ElementIterator(Document document)
+  {
+    this.root = document.getDefaultRootElement();
+    this.currentElement = root;
+    this.state = new int[5];
+  }
+
+  /**
+   * Create a new ElementIterator to iterate over the given document.
+   * @param root the Document over which we iterate
+   */
+  public ElementIterator(Element root)
+  {
+    this.root = root;
+    this.currentElement = root;
+    this.state = new int[5];
+  }
+
+  /**
+   * Returns a new ElementIterator which is a clone of this
+   * ElementIterator.
+   */
+  public Object clone()
+  {
+    try
+      {
+	return super.clone();
+      }
+    catch (CloneNotSupportedException _)
+      {
+	// Can't happen.
+	return null;
+      }
+  }
+
+  /**
+   * Returns the current element.
+   */
+  public Element current()
+  {
+    return currentElement;
+  }
+
+  /**
+   * Returns the depth to which we have descended in the tree.
+   */
+  public int depth()
+  {
+    return currentDepth;
+  }
+
+  /**
+   * Returns the first element in the tree.
+   */
+  public Element first()
+  {
+    // Reset the iterator.
+    currentElement = root;
+    currentDepth = 0;
+    previousItem = null;
+    return root;
+  }
+
+  /**
+   * Advance the iterator and return the next element of the tree,
+   * performing an "in-order" traversal.
+   */
+  public Element next()
+  {
+    previousItem = currentElement;
+    if (currentElement == null)
+      return null;
+    if (! currentElement.isLeaf())
+      {
+	++currentDepth;
+	if (currentDepth > state.length)
+	  {
+	    int[] newState = new int[state.length * 2];
+	    System.arraycopy(state, 0, newState, 0, state.length);
+	    state = newState;
+	  }
+	state[currentDepth] = 0;
+	currentElement = currentElement.getElement(0);
+	return currentElement;
+      }
+
+    while (currentDepth > 0)
+      {
+	// At a leaf, or done with a non-leaf's children, so go up a
+	// level.
+	--currentDepth;
+	currentElement = currentElement.getParentElement();
+	++state[currentDepth];
+	if (state[currentDepth] < currentElement.getElementCount())
+	  {
+	    currentElement = currentElement.getElement(state[currentDepth]);
+	    return currentElement;
+	  }
+      }
+
+    currentElement = null;
+    return currentElement;
+  }
+
+  /**
+   * Returns the previous item.  Does not modify the iterator state.
+   */
+  public Element previous()
+  {
+    if (currentElement == null || currentElement == root)
+      return null;
+    return previousItem;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,153 @@
+/* EmptyAttributeSet.java -- An empty attribute set
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+/**
+ * An immutable, empty attribute set.
+ *
+ * @see SimpleAttributeSet#EMPTY
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+final class EmptyAttributeSet
+  implements AttributeSet
+{
+
+  /**
+   * Always return false as this AttributeSet doesn't contain any attributes.
+   */
+  public boolean containsAttribute(Object name, Object value)
+  {
+    return false;
+  }
+
+  /**
+   * Return true only if the attributes argument also contains no attributes.
+   */
+  public boolean containsAttributes(AttributeSet attributes)
+  {
+    return attributes.getAttributeCount() == 0;
+  }
+
+  /**
+   * Return this, as this is immutable.
+   */
+  public AttributeSet copyAttributes()
+  {
+    return this;
+  }
+
+  /**
+   * Always return null as this AttributeSet doesn't contain any attributes.
+   */
+  public Object getAttribute(Object key)
+  {
+    return null;
+  }
+
+  /**
+   * Always return 0.
+   */
+  public int getAttributeCount()
+  {
+    return 0;
+  }
+
+  /**
+   * Returns an empty Enumeration.
+   */
+  public Enumeration getAttributeNames()
+  {
+    return new Enumeration()
+    {
+      public boolean hasMoreElements()
+      {
+        return false;
+      }
+
+      public Object nextElement()
+      {
+        throw new NoSuchElementException("No more elements");
+      }
+      
+    };
+  }
+
+  /**
+   * Always return null as this has no resolve parent.
+   */
+  public AttributeSet getResolveParent()
+  {
+    return null;
+  }
+
+  /**
+   * Always return false as this AttributeSet doesn't contain any attributes.
+   */
+  public boolean isDefined(Object attrName)
+  {
+    return false;
+  }
+
+  /**
+   * Other attribute sets are equal if they are empty too.
+   */
+  public boolean isEqual(AttributeSet attr)
+  {
+    return attr.getAttributeCount() == 0;
+  }
+
+  /**
+   * Other objects are equal if it's the same instance as this, or if
+   * it's another attribute set without attributes.
+   */
+  public boolean equals(Object o)
+  {
+    boolean eq = o == this;
+    if (! eq)
+      {
+        eq = (o instanceof AttributeSet)
+             && ((AttributeSet) o).getAttributeCount() == 0;
+      }
+    return eq;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,312 @@
+/* FieldView.java -- 
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BoundedRangeModel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+
+public class FieldView extends PlainView
+{
+  BoundedRangeModel horizontalVisibility;
+  
+  /** Caches the preferred span of the X axis. It is invalidated by
+   * setting it to -1f. This is done when text in the document
+   * is inserted, removed or changed. The value is corrected as
+   * soon as calculateHorizontalSpan() is called. 
+   */
+  float cachedSpan = -1f;
+
+  public FieldView(Element elem)
+  {
+    super(elem);
+    
+  }
+  
+  /** Checks whether the given container is a JTextField. If so
+   * it retrieves the textfield's horizontalVisibility instance.
+   * 
+   * <p>This method should be only called when the view's container
+   * is valid. Naturally that would be the setParent() method however
+   * that method is not overridden in the RI and that is why we chose
+   * paint() instead.</p>
+   */ 
+  private void checkContainer()
+  {
+    Container c = getContainer();
+    
+    if (c instanceof JTextField)
+      {
+        horizontalVisibility = ((JTextField) c).getHorizontalVisibility();
+        
+        // Provokes a repaint when the BoundedRangeModel's values change
+        // (which is what the RI does).
+        horizontalVisibility.addChangeListener(new ChangeListener(){
+          public void stateChanged(ChangeEvent event) {
+            getContainer().repaint();
+          };
+        });
+
+        // It turned out that the span calculated at this point is wrong
+        // and needs to be recalculated (e.g. a different font setting is
+        // not taken into account).
+        calculateHorizontalSpan();
+        
+        // Initializes the BoundedRangeModel properly.
+        updateVisibility();
+      }
+    
+  }
+  
+  private void updateVisibility()
+  {
+    JTextField tf = (JTextField) getContainer();
+    Insets insets = tf.getInsets();
+
+    int width = tf.getWidth() - insets.left - insets.right;
+        
+    horizontalVisibility.setMaximum(Math.max((int) ((cachedSpan != -1f)
+                                                 ? cachedSpan
+                                                 : calculateHorizontalSpan()),
+                                             width));
+        
+    horizontalVisibility.setExtent(width - 1);
+  }
+
+  protected FontMetrics getFontMetrics()
+  {
+    Component container = getContainer();
+    return container.getFontMetrics(container.getFont());
+  }
+
+  /**
+   * Vertically centers the single line of text within the
+   * bounds of the input shape. The returned Rectangle is centered
+   * vertically within <code>shape</code> and has a height of the
+   * preferred span along the Y axis. Horizontal adjustment is done according
+   * to the horizontalAligment property of the component that is rendered.
+   *
+   * @param shape the shape within which the line is beeing centered
+   */
+  protected Shape adjustAllocation(Shape shape)
+  {
+    // Return null when the original allocation is null (like the RI).
+    if (shape == null)
+      return null;
+    
+    Rectangle rectIn = shape.getBounds();
+    // vertical adjustment
+    int height = (int) getPreferredSpan(Y_AXIS);
+    int y = rectIn.y + (rectIn.height - height) / 2;
+    // horizontal adjustment
+    JTextField textField = (JTextField) getContainer();
+    int width = (int) ((cachedSpan != -1f) ? cachedSpan : calculateHorizontalSpan());
+    int x;
+    if (horizontalVisibility != null && horizontalVisibility.getExtent() < width)
+        x = rectIn.x - horizontalVisibility.getValue();
+    else
+      switch (textField.getHorizontalAlignment())
+        {
+        case JTextField.CENTER:
+          x = rectIn.x + (rectIn.width - width) / 2;
+          break;
+        case JTextField.RIGHT:
+          x = rectIn.x + (rectIn.width - width - 1);
+          break;
+        case JTextField.TRAILING:
+          if (textField.getComponentOrientation().isLeftToRight())
+            x = rectIn.x + (rectIn.width - width - 1);
+          else
+            x = rectIn.x;
+          break;
+        case JTextField.LEADING:
+          if (textField.getComponentOrientation().isLeftToRight())
+            x = rectIn.x;
+          else
+            x = rectIn.x + (rectIn.width - width - 1);
+          break;
+        case JTextField.LEFT:
+        default:
+          x = rectIn.x;
+          break;
+        }
+    
+    return new Rectangle(x, y, width, height);
+  }
+
+  public float getPreferredSpan(int axis)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException();
+
+
+    if (axis == Y_AXIS)
+      return super.getPreferredSpan(axis);
+
+    if (cachedSpan != -1f)
+      return cachedSpan;
+    
+    return calculateHorizontalSpan();
+  }
+  
+  /** Calculates and sets the horizontal span and stores the value
+   * in cachedSpan.
+   */ 
+  private float calculateHorizontalSpan()
+  {
+    Segment s = getLineBuffer();
+    Element elem = getElement();
+
+    try
+      {
+        elem.getDocument().getText(elem.getStartOffset(),
+                                          elem.getEndOffset() - 1,
+                                          s);
+        
+        return cachedSpan = Utilities.getTabbedTextWidth(s, getFontMetrics(), 0, this, s.offset);
+      }
+    catch (BadLocationException e)
+      {
+	// Should never happen
+	AssertionError ae = new AssertionError();
+	ae.initCause(e);
+	throw ae;
+      }
+  }
+
+  public int getResizeWeight(int axis)
+  {
+    return axis = axis == X_AXIS ? 1 : 0;
+  }
+  
+  public Shape modelToView(int pos, Shape a, Position.Bias bias)
+    throws BadLocationException
+  {
+    Shape newAlloc = adjustAllocation(a);
+    return super.modelToView(pos, newAlloc, bias);
+  }
+  
+  public void paint(Graphics g, Shape s)
+  {
+    if (horizontalVisibility == null)
+      checkContainer();
+
+    Shape newAlloc = adjustAllocation(s);
+    
+    Shape clip = g.getClip();
+    if (clip != null)
+      {
+        // Reason for this: The allocation area is always determined by the
+        // size of the component (and its insets) regardless of whether
+        // parts of the component are invisible or not (e.g. when the
+        // component is part of a JScrollPane and partly moved out of
+        // the user-visible range). However the clip of the Graphics
+        // instance may be adjusted properly to that condition but
+        // does not handle insets. By calculating the intersection
+        // we get the correct clip to paint the text in all cases.
+        Rectangle r = s.getBounds();
+        Rectangle cb = clip.getBounds();
+        SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, cb);
+
+        g.setClip(cb);
+      }
+    else
+      g.setClip(s);
+
+    super.paint(g, newAlloc);
+    g.setClip(clip);
+    
+  }
+
+  public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
+  {
+    cachedSpan = -1f;
+    
+    if (horizontalVisibility != null)
+      updateVisibility();
+    
+    Shape newAlloc = adjustAllocation(shape);
+    
+    super.insertUpdate(ev, newAlloc, vf);
+    getContainer().repaint();
+  }
+
+  public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
+  {
+    cachedSpan = -1f;
+    
+    if (horizontalVisibility != null)
+      updateVisibility();
+
+    Shape newAlloc = adjustAllocation(shape);
+    super.removeUpdate(ev, newAlloc, vf);
+    getContainer().repaint();
+  }
+
+  public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
+  {
+    cachedSpan = -1f;
+    
+    if (horizontalVisibility != null)
+      updateVisibility();
+
+    Shape newAlloc = adjustAllocation(shape);
+    super.changedUpdate(ev, newAlloc, vf);
+    getContainer().repaint();
+  }
+
+  public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias)
+  {
+    return super.viewToModel(fx, fy, adjustAllocation(a), bias);
+  }
+  
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,612 @@
+/* FlowView.java -- A composite View
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SizeRequirements;
+import javax.swing.event.DocumentEvent;
+
+/**
+ * A <code>View</code> that can flows it's children into it's layout space.
+ *
+ * The <code>FlowView</code> manages a set of logical views (that are
+ * the children of the {@link #layoutPool} field). These are translated
+ * at layout time into a set of physical views. These are the views that
+ * are managed as the real child views. Each of these child views represents
+ * a row and are laid out within a box using the superclasses behaviour.
+ * The concrete implementation of the rows must be provided by subclasses.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public abstract class FlowView extends BoxView
+{
+  /**
+   * A strategy for translating the logical views of a <code>FlowView</code>
+   * into the real views.
+   */
+  public static class FlowStrategy
+  {
+    /**
+     * Creates a new instance of <code>FlowStragegy</code>.
+     */
+    public FlowStrategy()
+    {
+      // Nothing to do here.
+    }
+
+    /**
+     * Receives notification from a <code>FlowView</code> that some content
+     * has been inserted into the document at a location that the
+     * <code>FlowView</code> is responsible for.
+     *
+     * The default implementation simply calls {@link #layout}.
+     *
+     * @param fv the flow view that sends the notification
+     * @param e the document event describing the change
+     * @param alloc the current allocation of the flow view
+     */
+    public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
+    {
+      // The default implementation does nothing.
+    }
+
+    /**
+     * Receives notification from a <code>FlowView</code> that some content
+     * has been removed from the document at a location that the
+     * <code>FlowView</code> is responsible for.
+     *
+     * The default implementation simply calls {@link #layout}.
+     *
+     * @param fv the flow view that sends the notification
+     * @param e the document event describing the change
+     * @param alloc the current allocation of the flow view
+     */
+    public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
+    {
+      // The default implementation does nothing.
+    }
+
+    /**
+     * Receives notification from a <code>FlowView</code> that some attributes
+     * have changed in the document at a location that the
+     * <code>FlowView</code> is responsible for.
+     *
+     * The default implementation simply calls {@link #layout}.
+     *
+     * @param fv the flow view that sends the notification
+     * @param e the document event describing the change
+     * @param alloc the current allocation of the flow view
+     */
+    public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
+    {
+      // The default implementation does nothing.
+    }
+
+    /**
+     * Returns the logical view of the managed <code>FlowView</code>.
+     *
+     * @param fv the flow view for which to return the logical view
+     *
+     * @return the logical view of the managed <code>FlowView</code>
+     */
+    protected View getLogicalView(FlowView fv)
+    {
+      return fv.layoutPool;
+    }
+
+    /**
+     * Performs the layout for the whole view. By default this rebuilds
+     * all the physical views from the logical views of the managed FlowView.
+     *
+     * This is called by {@link FlowView#layout} to update the layout of
+     * the view.
+     *
+     * @param fv the flow view for which we perform the layout
+     */
+    public void layout(FlowView fv)
+    {
+      fv.removeAll();
+      Element el = fv.getElement();
+
+      int rowStart = el.getStartOffset();
+      int end = el.getEndOffset();
+      int rowIndex = 0;
+      while (rowStart >= 0 && rowStart < end)
+        {
+          View row = fv.createRow();
+          fv.append(row);
+          rowStart = layoutRow(fv, rowIndex, rowStart);
+          rowIndex++;
+        }
+    }
+
+    /**
+     * Lays out one row of the flow view. This is called by {@link #layout} to
+     * fill one row with child views until the available span is exhausted. The
+     * default implementation fills the row by calling
+     * {@link #createView(FlowView, int, int, int)} until the available space is
+     * exhausted, a forced break is encountered or there are no more views in
+     * the logical view. If the available space is exhausted,
+     * {@link #adjustRow(FlowView, int, int, int)} is called to fit the row into
+     * the available span.
+     * 
+     * @param fv the flow view for which we perform the layout
+     * @param rowIndex the index of the row
+     * @param pos the model position for the beginning of the row
+     * @return the start position of the next row
+     */
+    protected int layoutRow(FlowView fv, int rowIndex, int pos)
+    {
+      View row = fv.getView(rowIndex);
+      int axis = fv.getFlowAxis();
+      int span = fv.getFlowSpan(rowIndex);
+      int x = fv.getFlowStart(rowIndex);
+      int offset = pos;
+      View logicalView = getLogicalView(fv);
+      // Special case when span == 0. We need to layout the row as if it had
+      // a span of Integer.MAX_VALUE.
+      if (span == 0)
+        span = Integer.MAX_VALUE;
+
+      Row: while (span > 0)
+        {
+          if (logicalView.getViewIndex(offset, Position.Bias.Forward) == - 1)
+            break;
+          View view = createView(fv, offset, span, rowIndex);
+          if (view == null)
+            break;
+
+          int viewSpan = (int) view.getPreferredSpan(axis);
+          int breakWeight = view.getBreakWeight(axis, x, span);
+
+          row.append(view);
+          offset += (view.getEndOffset() - view.getStartOffset());
+          x += viewSpan;
+          span -= viewSpan;
+
+          // Break if the line if the view does not fit in this row or the
+          // line just must be broken.
+          if (span < 0 || breakWeight >= View.ForcedBreakWeight)
+            {
+              int flowStart = fv.getFlowStart(axis);
+              int flowSpan = fv.getFlowSpan(axis);
+              adjustRow(fv, rowIndex, flowSpan, flowStart);
+              int rowViewCount = row.getViewCount();
+              if (rowViewCount > 0)
+                offset = row.getView(rowViewCount - 1).getEndOffset();
+              else
+                offset = - 1;
+              break Row;
+            }
+        }
+
+      return offset != pos ? offset : - 1;
+    }
+
+    /**
+     * Creates physical views that form the rows of the flow view. This
+     * can be an entire view from the logical view (if it fits within the
+     * available span), a fragment of such a view (if it doesn't fit in the
+     * available span and can be broken down) or <code>null</code> (if it does
+     * not fit in the available span and also cannot be broken down).
+     *
+     * The default implementation fetches the logical view at the specified
+     * <code>startOffset</code>. If that view has a different startOffset than
+     * specified in the argument, a fragment is created using
+     * {@link View#createFragment(int, int)} that has the correct startOffset
+     * and the logical view's endOffset.
+     *
+     * @param fv the flow view
+     * @param startOffset the start offset for the view to be created
+     * @param spanLeft the available span
+     * @param rowIndex the index of the row
+     *
+     * @return a view to fill the row with, or <code>null</code> if there
+     *         is no view or view fragment that fits in the available span
+     */
+    protected View createView(FlowView fv, int startOffset, int spanLeft,
+                              int rowIndex)
+    {
+       View logicalView = getLogicalView(fv);
+       // FIXME: Handle the bias thing correctly.
+       int index = logicalView.getViewIndex(startOffset, Position.Bias.Forward);
+       View retVal = null;
+       if (index >= 0)
+         {
+           retVal = logicalView.getView(index);
+           if (retVal.getStartOffset() != startOffset)
+             retVal = retVal.createFragment(startOffset, retVal.getEndOffset());
+         }
+       return retVal;
+    }
+
+    /**
+     * Tries to adjust the specified row to fit within the desired span. The
+     * default implementation iterates through the children of the specified
+     * row to find the view that has the highest break weight and - if there
+     * is more than one view with such a break weight - which is nearest to
+     * the end of the row. If there is such a view that has a break weight >
+     * {@link View#BadBreakWeight}, this view is broken using the
+     * {@link View#breakView(int, int, float, float)} method and this view and
+     * all views after the now broken view are replaced by the broken view.
+     *
+     * @param fv the flow view
+     * @param rowIndex the index of the row to be adjusted
+     * @param desiredSpan the layout span
+     * @param x the X location at which the row starts
+     */
+    protected void adjustRow(FlowView fv, int rowIndex, int desiredSpan, int x) {
+      // Determine the last view that has the highest break weight.
+      int axis = fv.getFlowAxis();
+      View row = fv.getView(rowIndex);
+      int count = row.getViewCount();
+      int breakIndex = -1;
+      int maxBreakWeight = View.BadBreakWeight;
+      int breakX = x;
+      int breakSpan = desiredSpan;
+      int currentX = x;
+      int currentSpan = desiredSpan;
+      for (int i = 0; i < count; ++i)
+        {
+          View view = row.getView(i);
+          int weight = view.getBreakWeight(axis, currentX, currentSpan);
+          if (weight >= maxBreakWeight)
+            {
+              breakIndex = i;
+              breakX = currentX;
+              breakSpan = currentSpan;
+              maxBreakWeight = weight;
+            }
+          int size = (int) view.getPreferredSpan(axis);
+          currentX += size;
+          currentSpan -= size;
+        }
+
+      // If there is a potential break location found, break the row at
+      // this location.
+      if (breakIndex > -1)
+        {
+          View toBeBroken = row.getView(breakIndex);
+          View brokenView = toBeBroken.breakView(axis,
+                                                 toBeBroken.getStartOffset(),
+                                                 breakX, breakSpan);
+          row.replace(breakIndex, count - breakIndex,
+                      new View[]{brokenView});
+        }
+    }
+  }
+
+  /**
+   * This special subclass of <code>View</code> is used to represent
+   * the logical representation of this view. It does not support any
+   * visual representation, this is handled by the physical view implemented
+   * in the <code>FlowView</code>.
+   */
+  class LogicalView extends BoxView
+  {
+    /**
+     * Creates a new LogicalView instance.
+     */
+    LogicalView(Element el, int axis)
+    {
+      super(el, axis);
+    }
+  }
+
+  /**
+   * The shared instance of FlowStrategy.
+   */
+  static final FlowStrategy sharedStrategy = new FlowStrategy();
+
+  /**
+   * The span of the <code>FlowView</code> that should be flowed.
+   */
+  protected int layoutSpan;
+
+  /**
+   * Represents the logical child elements of this view, encapsulated within
+   * one parent view (an instance of a package private <code>LogicalView</code>
+   * class). These will be translated to a set of real views that are then
+   * displayed on screen. This translation is performed by the inner class
+   * {@link FlowStrategy}.
+   */
+  protected View layoutPool;
+
+  /**
+   * The <code>FlowStrategy</code> to use for translating between the
+   * logical and physical view.
+   */
+  protected FlowStrategy strategy;
+
+  /**
+   * Indicates if the flow should be rebuild during the next layout.
+   */
+  private boolean layoutDirty;
+
+  /**
+   * Creates a new <code>FlowView</code> for the given
+   * <code>Element</code> and <code>axis</code>.
+   *
+   * @param element the element that is rendered by this FlowView
+   * @param axis the axis along which the view is tiled, either
+   *        <code>View.X_AXIS</code> or <code>View.Y_AXIS</code>, the flow
+   *        axis is orthogonal to this one
+   */
+  public FlowView(Element element, int axis)
+  {
+    super(element, axis);
+    strategy = sharedStrategy;
+    layoutDirty = true;
+  }
+
+  /**
+   * Returns the axis along which the view should be flowed. This is
+   * orthogonal to the axis along which the boxes are tiled.
+   *
+   * @return the axis along which the view should be flowed
+   */
+  public int getFlowAxis()
+  {
+    int axis = getAxis();
+    int flowAxis;
+ 
+    if (axis == X_AXIS)
+      flowAxis = Y_AXIS;
+    else
+      flowAxis = X_AXIS;
+
+    return flowAxis;
+
+  }
+
+  /**
+   * Returns the span of the flow for the specified child view. A flow
+   * layout can be shaped by providing different span values for different
+   * child indices. The default implementation returns the entire available
+   * span inside the view.
+   *
+   * @param index the index of the child for which to return the span
+   *
+   * @return the span of the flow for the specified child view
+   */
+  public int getFlowSpan(int index)
+  {
+    return layoutSpan;
+  }
+
+  /**
+   * Returns the location along the flow axis where the flow span starts
+   * given a child view index. The flow can be shaped by providing
+   * different values here.
+   *
+   * @param index the index of the child for which to return the flow location
+   *
+   * @return the location along the flow axis where the flow span starts
+   */
+  public int getFlowStart(int index)
+  {
+    return getLeftInset(); // TODO: Is this correct?
+  }
+
+  /**
+   * Creates a new view that represents a row within a flow.
+   *
+   * @return a view for a new row
+   */
+  protected abstract View createRow();
+
+  /**
+   * Loads the children of this view. The <code>FlowView</code> does not
+   * directly load its children. Instead it creates a logical view
+   * ({@link #layoutPool}) which is filled by the logical child views.
+   * The real children are created at layout time and each represent one
+   * row.
+   *
+   * This method is called by {@link View#setParent} in order to initialize
+   * the view.
+   *
+   * @param vf the view factory to use for creating the child views
+   */
+  protected void loadChildren(ViewFactory vf)
+  {
+    if (layoutPool == null)
+      {
+        layoutPool = new LogicalView(getElement(), getAxis());
+        layoutPool.setParent(this);
+      }
+  }
+
+  /**
+   * Performs the layout of this view. If the span along the flow axis changed,
+   * this first calls {@link FlowStrategy#layout} in order to rebuild the
+   * rows of this view. Then the superclass's behaviour is called to arrange
+   * the rows within the box.
+   *
+   * @param width the width of the view
+   * @param height the height of the view
+   */
+  protected void layout(int width, int height)
+  {
+    int flowAxis = getFlowAxis();
+    if (flowAxis == X_AXIS)
+      {
+        if (layoutSpan != width)
+          {
+            layoutChanged(Y_AXIS);
+            layoutSpan = width;
+          }
+      }
+    else
+      {
+        if (layoutSpan != height)
+          {
+            layoutChanged(X_AXIS);
+            layoutSpan = height;
+          }
+      }
+
+    if (layoutDirty)
+      {
+        strategy.layout(this);
+        layoutDirty = false;
+      }
+
+    if (getPreferredSpan(getAxis()) != height)
+      preferenceChanged(this, false, true);
+
+    super.layout(width, height);
+  }
+
+  /**
+   * Receice notification that some content has been inserted in the region
+   * that this view is responsible for. This calls
+   * {@link FlowStrategy#insertUpdate}.
+   *
+   * @param changes the document event describing the changes
+   * @param a the current allocation of the view
+   * @param vf the view factory that is used for creating new child views
+   */
+  public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
+  {
+    // First we must send the insertUpdate to the logical view so it can
+    // be updated accordingly.
+    layoutPool.insertUpdate(changes, a, vf);
+    strategy.insertUpdate(this, changes, getInsideAllocation(a));
+    layoutDirty = true;
+  }
+
+  /**
+   * Receice notification that some content has been removed from the region
+   * that this view is responsible for. This calls
+   * {@link FlowStrategy#removeUpdate}.
+   *
+   * @param changes the document event describing the changes
+   * @param a the current allocation of the view
+   * @param vf the view factory that is used for creating new child views
+   */
+  public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
+  {
+    layoutPool.removeUpdate(changes, a, vf);
+    strategy.removeUpdate(this, changes, getInsideAllocation(a));
+    layoutDirty = true;
+  }
+
+  /**
+   * Receice notification that some attributes changed in the region
+   * that this view is responsible for. This calls
+   * {@link FlowStrategy#changedUpdate}.
+   *
+   * @param changes the document event describing the changes
+   * @param a the current allocation of the view
+   * @param vf the view factory that is used for creating new child views
+   */
+  public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
+  {
+    layoutPool.changedUpdate(changes, a, vf);
+    strategy.changedUpdate(this, changes, getInsideAllocation(a));
+    layoutDirty = true;
+  }
+
+  /**
+   * Returns the index of the child <code>View</code> for the given model
+   * position.
+   *
+   * This is implemented to iterate over the children of this
+   * view (the rows) and return the index of the first view that contains
+   * the given position.
+   *
+   * @param pos the model position for whicht the child <code>View</code> is
+   *        queried
+   *
+   * @return the index of the child <code>View</code> for the given model
+   *         position
+   */
+  protected int getViewIndexAtPosition(int pos)
+  {
+    // First make sure we have a valid layout.
+    if (!isAllocationValid())
+      layout(getWidth(), getHeight());
+
+    int count = getViewCount();
+    int result = -1;
+
+    for (int i = 0; i < count; ++i)
+      {
+        View child = getView(i);
+        int start = child.getStartOffset();
+        int end = child.getEndOffset();
+        if (start <= pos && end > pos)
+          {
+            result = i;
+            break;
+          }
+      }
+    return result;
+  }
+
+  /**
+   * Calculates the size requirements of this <code>BoxView</code> along
+   * its minor axis, that is the axis opposite to the axis specified in the
+   * constructor.
+   *
+   * This is overridden and forwards the request to the logical view.
+   *
+   * @param axis the axis that is examined
+   * @param r the <code>SizeRequirements</code> object to hold the result,
+   *        if <code>null</code>, a new one is created
+   *
+   * @return the size requirements for this <code>BoxView</code> along
+   *         the specified axis
+   */
+  protected SizeRequirements calculateMinorAxisRequirements(int axis,
+                                                            SizeRequirements r)
+  {
+    SizeRequirements res = r;
+    if (res == null)
+      res = new SizeRequirements();
+    res.minimum = (int) layoutPool.getMinimumSpan(axis);
+    res.preferred = Math.max(res.minimum,
+                             (int) layoutPool.getMinimumSpan(axis));
+    res.maximum = Integer.MAX_VALUE;
+    res.alignment = 0.5F;
+    return res;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,944 @@
+/* GapContent.java --
+   Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+import java.util.WeakHashMap;
+
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * This implementation of {@link AbstractDocument.Content} uses a gapped buffer.
+ * This takes advantage of the fact that text area content is mostly inserted
+ * sequentially. The buffer is a char array that maintains a gap at the current
+ * insertion point. If characters a inserted at gap boundaries, the cost is
+ * minimal (simple array access). The array only 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.
+ */
+public class GapContent
+    implements AbstractDocument.Content, Serializable
+{
+  
+  /**
+   * A {@link Position} implementation for <code>GapContent</code>.
+   */
+  private class GapContentPosition
+    implements Position
+  {
+
+    /**
+     * The index to the positionMarks array entry, which in turn holds the
+     * mark into the buffer array.
+     */
+    Mark mark;
+
+    /**
+     * Creates a new GapContentPosition object.
+     * 
+     * @param offset the offset of this Position
+     */
+    GapContentPosition(int offset)
+    {
+      // Try to find the mark in the positionMarks array, and store the index
+      // to it.
+      synchronized (GapContent.this)
+        {
+          // Try to make space.
+          garbageCollect();
+          Mark m = new Mark(offset);
+          int i = search(marks, m);
+          if (i >= 0) // mark found
+            {
+              m = (Mark) marks.get(i);
+            }
+          else
+            {
+              i = -i - 1;
+              marks.add(i, m);
+            }
+          m.refCount++;
+          mark = m;
+        }
+
+      // Register this position in the death queue, so we can cleanup the marks
+      // when this position object gets GC'ed.
+      new WeakReference(this, queueOfDeath);
+    }
+
+    /**
+     * Returns the current offset of this Position within the content.
+     * 
+     * @return the current offset of this Position within the content.
+     */
+    public int getOffset()
+    {
+      return mark.getOffset();
+    }
+  }
+
+  /**
+   * Holds a mark into the buffer that is used by GapContentPosition to find
+   * the actual offset of the position. This is pulled out of the
+   * GapContentPosition object so that the mark and position can be handled
+   * independently, and most important, so that the GapContentPosition can
+   * be garbage collected while we still hold a reference to the Mark object. 
+   */
+  private class Mark
+    implements Comparable
+  {
+    /**
+     * The actual mark into the buffer.
+     */
+    int mark;
+
+    /**
+     * The number of GapContentPosition object that reference this mark. If
+     * it reaches zero, it get's deleted by {@link GapContent#garbageCollect()}.
+     */
+    int refCount;
+
+    /**
+     * Creates a new Mark object for the specified offset.
+     *
+     * @param offset the offset
+     */
+    Mark(int offset)
+    {
+      mark = offset;
+      if (mark >= gapStart && mark != 0)
+        mark += (gapEnd - gapStart);
+    }
+
+    /**
+     * Returns the offset of the mark.
+     *
+     * @return the offset of the mark
+     */
+    int getOffset()
+    {
+      assert mark == 0 || mark < gapStart || mark >= gapEnd :
+             "Invalid mark: " + mark + ", gapStart: " + gapStart
+             + ", gapEnd: " + gapEnd;
+
+      int res = mark;
+      if (mark >= gapEnd)
+        res -= (gapEnd - gapStart);
+      return res;
+    }
+
+    /**
+     * Implementation of Comparable.
+     */
+    public int compareTo(Object o)
+    {
+      Mark other = (Mark) o;
+      return mark - other.mark;
+    }
+    /**
+     * Adjustment for equals().
+     */
+    public boolean equals(Object o)
+    {
+      if (o == null || !(o instanceof Mark))
+        return false;
+      else
+        return ((Mark) o).mark == mark;
+    }
+  }
+
+  private class InsertUndo extends AbstractUndoableEdit
+  {
+    public int where, length;
+    String text;
+    public InsertUndo(int start, int len)
+    {
+      where = start;
+      length = len;
+    }
+
+    public void undo () throws CannotUndoException
+    {
+      super.undo();
+      try
+      {
+        text = getString(where, length);
+        remove(where, length);
+      }
+      catch (BadLocationException ble)
+      {
+        throw new CannotUndoException();
+      }
+    }
+    
+    public void redo () throws CannotUndoException
+    {
+      super.redo();
+      try
+      {
+        insertString(where, text);
+      }
+      catch (BadLocationException ble)
+      {
+        throw new CannotRedoException();
+      }
+    }
+    
+  }
+  
+  private class UndoRemove extends AbstractUndoableEdit
+  {
+    public int where;
+    String text;
+    public UndoRemove(int start, String removedText)
+    {
+      where = start;
+      text = removedText;
+    }
+
+    public void undo () throws CannotUndoException
+    {
+      super.undo();
+      try
+      {
+        insertString(where, text);
+      }
+      catch (BadLocationException ble)
+      {
+        throw new CannotUndoException();
+      }
+    }
+    
+    public void redo () throws CannotUndoException
+    {
+      super.redo();
+      try
+      {
+        remove(where, text.length());
+      }
+      catch (BadLocationException ble)
+      {
+        throw new CannotRedoException();
+      }
+    }
+    
+  }
+
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = -6226052713477823730L;
+
+  /**
+   * 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 = 10;
+
+  /**
+   * 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;
+
+  // FIXME: We might want to track GC'ed GapContentPositions and remove their
+  // corresponding marks, or alternativly, perform some regular cleanup of
+  // the positionMarks array.
+
+  /**
+   * Holds the marks for positions. These marks are referenced by the
+   * GapContentPosition instances by an index into this array.
+   *
+   * This is package private to avoid accessor synthetic methods.
+   */
+  ArrayList marks;
+
+  WeakHashMap positions;
+
+  /**
+   * Queues all references to GapContentPositions that are about to be
+   * GC'ed. This is used to remove the corresponding marks from the
+   * positionMarks array if the number of references to that mark reaches zero.
+   *
+   * This is package private to avoid accessor synthetic methods.
+   */
+  ReferenceQueue queueOfDeath;
+
+  /**
+   * Creates a new GapContent object.
+   */
+  public GapContent()
+  {
+    this(DEFAULT_BUFSIZE);
+  }
+
+  /**
+   * Creates a new GapContent object with a specified initial size.
+   * 
+   * @param size the initial size of the buffer
+   */
+  public GapContent(int size)
+  {
+    size = Math.max(size, 2);
+    buffer = (char[]) allocateArray(size);
+    gapStart = 1;
+    gapEnd = size;
+    buffer[0] = '\n';
+    positions = new WeakHashMap();
+    marks = new ArrayList();
+    queueOfDeath = new ReferenceQueue();
+  }
+
+  /**
+   * Allocates an array of the specified length that can then be used as
+   * buffer.
+   * 
+   * @param size the size of the array to be allocated
+   * 
+   * @return the allocated array
+   */
+  protected Object allocateArray(int size)
+  {
+    return new char[size];
+  }
+
+  /**
+   * Returns the length of the allocated buffer array.
+   * 
+   * @return the length of the allocated buffer array
+   */
+  protected int getArrayLength()
+  {
+    return buffer.length;
+  }
+
+  /**
+   * Returns the length of the content.
+   * 
+   * @return the length of the content
+   */
+  public int length()
+  {
+    return buffer.length - (gapEnd - gapStart);
+  }
+
+  /**
+   * Inserts a string at the specified position.
+   * 
+   * @param where the position where the string is inserted
+   * @param str the string that is to be inserted
+   * 
+   * @return an UndoableEdit object
+   * 
+   * @throws BadLocationException if <code>where</code> is not a valid
+   *         location in the buffer
+   */
+  public UndoableEdit insertString(int where, String str)
+      throws BadLocationException
+  {
+    // check arguments
+    int length = length();
+    int strLen = str.length();
+
+    if (where < 0)
+      throw new BadLocationException("The where argument cannot be smaller"
+                                     + " than the zero", where);
+
+    if (where > length)
+      throw new BadLocationException("The where argument cannot be greater"
+          + " than the content length", where);
+
+    replace(where, 0, str.toCharArray(), strLen);
+
+    return new InsertUndo(where, strLen);
+  }
+
+  /**
+   * Removes a piece of content at th specified position.
+   * 
+   * @param where the position where the content is to be removed
+   * @param nitems number of characters to be removed
+   * 
+   * @return an UndoableEdit object
+   * 
+   * @throws BadLocationException if <code>where</code> is not a valid
+   *         location in the buffer
+   */
+  public UndoableEdit remove(int where, int nitems) throws BadLocationException
+  {
+    // check arguments
+    int length = length();
+    
+    if ((where + nitems) >= length)
+      throw new BadLocationException("where + nitems cannot be greater"
+          + " than the content length", where + nitems);
+    
+    String removedText = getString(where, nitems);
+    replace(where, nitems, null, 0);
+
+    return new UndoRemove(where, removedText);
+  }
+
+  /**
+   * Returns a piece of content as String.
+   * 
+   * @param where the start location of the fragment
+   * @param len the length of the fragment
+   * 
+   * @throws BadLocationException if <code>where</code> or
+   *         <code>where + len</code> are no valid locations in the buffer
+   */
+  public String getString(int where, int len) throws BadLocationException
+  {
+    Segment seg = new Segment();
+    try
+      {
+        getChars(where, len, seg);
+        return new String(seg.array, seg.offset, seg.count);
+      }
+    catch (StringIndexOutOfBoundsException ex)
+      {
+        int invalid = 0;
+        if (seg.offset < 0 || seg.offset >= seg.array.length)
+          invalid = seg.offset;
+        else
+          invalid = seg.offset + seg.count;
+        throw new BadLocationException("Illegal location: array.length = "
+                                       + seg.array.length + ", offset = "
+                                       + seg.offset + ", count = "
+                                       + seg.count, invalid);
+      }
+  }
+
+  /**
+   * 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
+   * 
+   * @throws BadLocationException if <code>where</code> or
+   *         <code>where + len</code> are no valid locations in the buffer
+   */
+  public void getChars(int where, int len, Segment txt)
+      throws BadLocationException
+  {
+    // check arguments
+    int length = length();
+    if (where < 0)
+      throw new BadLocationException("the where argument may not be below zero", where);
+    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);
+    if (len < 0)
+      throw new BadLocationException("negative length not allowed: ", 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;
+    }
+  }
+
+  /**
+   * 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
+  {
+    // Implementation note: We used to perform explicit check on the offset
+    // here. However, this makes some Mauve and Intel/Harmony tests fail
+    // and luckily enough the GapContent can very well deal with offsets
+    // outside the buffer bounds. So I removed that check.
+
+    // We try to find a GapContentPosition at the specified offset and return
+    // that. Otherwise we must create a new one.
+    GapContentPosition pos = null;
+    Set positionSet = positions.keySet();
+    for (Iterator i = positionSet.iterator(); i.hasNext();)
+      {
+        GapContentPosition p = (GapContentPosition) i.next();
+        if (p.getOffset() == offset)
+          {
+            pos = p;
+            break;
+          }
+      }
+
+    // If none was found, then create and return a new one.
+    if (pos == null)
+      {
+        pos = new GapContentPosition(offset);
+        positions.put(pos, null);
+      }
+
+    return pos;
+  }
+
+  /**
+   * 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)
+  {
+    assert newSize > (gapEnd - gapStart) : "The new gap size must be greater "
+                                           + "than the old gap size";
+
+    int delta = newSize - gapEnd + gapStart;
+    // Update the marks after the gapEnd.
+    adjustPositionsInRange(gapEnd, -1, delta);
+
+    // Copy the data around.
+    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)
+  {
+    if (newGapStart == gapStart)
+      return;
+    int newGapEnd = newGapStart + gapEnd - gapStart;
+    if (newGapStart < gapStart)
+      {
+        // Update the positions between newGapStart and (old) gapStart. The marks
+        // must be shifted by (gapEnd - gapStart).
+        adjustPositionsInRange(newGapStart, gapStart, gapEnd - gapStart);
+        System.arraycopy(buffer, newGapStart, buffer, newGapEnd, gapStart
+                         - newGapStart);
+        gapStart = newGapStart;
+        gapEnd = newGapEnd;
+      }
+    else
+      {
+        // Update the positions between newGapEnd and (old) gapEnd. The marks
+        // must be shifted by (gapEnd - gapStart).
+        adjustPositionsInRange(gapEnd, newGapEnd, -(gapEnd - gapStart));
+        System.arraycopy(buffer, gapEnd, buffer, gapStart, newGapStart
+                         - gapStart);
+        gapStart = newGapStart;
+        gapEnd = newGapEnd;
+      }
+    resetMarksAtZero();
+  }
+
+  /**
+   * Shifts the gap start downwards. This does not affect the content of the
+   * buffer. This only updates the gap start and all the marks that are between
+   * the old gap start and the new gap start. They all are squeezed to the start
+   * of the gap, because their location has been removed.
+   *
+   * @param newGapStart the new gap start
+   */
+  protected void shiftGapStartDown(int newGapStart)
+  {
+    if (newGapStart == gapStart)
+      return;
+
+    assert newGapStart < gapStart : "The new gap start must be less than the "
+                                    + "old gap start.";
+    setPositionsInRange(newGapStart, gapStart, false);
+    gapStart = newGapStart;
+    resetMarksAtZero();
+  }
+
+  /**
+   * Shifts the gap end upwards. This does not affect the content of the
+   * buffer. This only updates the gap end and all the marks that are between
+   * the old gap end and the new end start. They all are squeezed to the end
+   * of the gap, because their location has been removed.
+   *
+   * @param newGapEnd the new gap start
+   */
+  protected void shiftGapEndUp(int newGapEnd)
+  {
+    if (newGapEnd == gapEnd)
+      return;
+
+    assert newGapEnd > gapEnd : "The new gap end must be greater than the "
+                                + "old gap end.";
+    setPositionsInRange(gapEnd, newGapEnd, false);
+    gapEnd = newGapEnd;
+    resetMarksAtZero();
+  }
+
+  /**
+   * Returns the allocated buffer array.
+   * 
+   * @return the allocated buffer array
+   */
+  protected final Object getArray()
+  {
+    return buffer;
+  }
+
+  /**
+   * Replaces a portion of the storage with the specified items.
+   * 
+   * @param position the position at which to remove items
+   * @param rmSize the number of items to remove
+   * @param addItems the items to add at location
+   * @param addSize the number of items to add
+   */
+  protected void replace(int position, int rmSize, Object addItems,
+                         int addSize)
+  {
+    if (gapStart != position)
+      shiftGap(position);
+      
+    // Remove content
+    if (rmSize > 0) 
+      shiftGapEndUp(gapEnd + rmSize);
+
+    // If gap is too small, enlarge the gap.
+    if ((gapEnd - gapStart) <= addSize)
+      shiftEnd((addSize - gapEnd + gapStart + 1) * 2 + gapEnd + DEFAULT_BUFSIZE);
+
+    // Add new items to the buffer.
+    if (addItems != null)
+      {
+        System.arraycopy(addItems, 0, buffer, gapStart, addSize);
+        gapStart += addSize;
+      }
+  }
+
+  /**
+   * Returns the start index of the gap within the buffer array.
+   *
+   * @return the start index of the gap within the buffer array
+   */
+  protected final int getGapStart()
+  {
+    return gapStart;
+  }
+
+  /**
+   * Returns the end index of the gap within the buffer array.
+   *
+   * @return the end index of the gap within the buffer array
+   */
+  protected final int getGapEnd()
+  {
+    return gapEnd;
+  }
+
+  /**
+   * Returns all <code>Position</code>s that are in the range specified by
+   * <code>offset</code> and </code>length</code> within the buffer array.
+   *
+   * @param v the vector to use; if <code>null</code>, a new Vector is allocated
+   * @param offset the start offset of the range to search
+   * @param length the length of the range to search
+   *
+   * @return the positions within the specified range
+   */
+  protected Vector getPositionsInRange(Vector v, int offset, int length)
+  {
+    Vector res = v;
+    if (res == null)
+      res = new Vector();
+    else
+      res.clear();
+
+    int endOffs = offset + length;
+
+    Set positionSet = positions.keySet();
+    for (Iterator i = positionSet.iterator(); i.hasNext();)
+      {
+        GapContentPosition p = (GapContentPosition) i.next();
+        int offs = p.getOffset();
+        if (offs >= offset && offs < endOffs)
+          res.add(p);
+      }
+
+    return res;
+  }
+  
+  /**
+   * Crunches all positions in the specified range to either the start or
+   * end of that interval. The interval boundaries are meant to be inclusive
+   * [start, end].
+   *
+   * @param start the start offset of the range
+   * @param end the end offset of the range
+   * @param toStart a boolean indicating if the positions should be crunched
+   *        to the start (true) or to the end (false)
+   */
+  private void setPositionsInRange(int start, int end, boolean toStart)
+  {
+    synchronized (this)
+      {
+        // Find the start and end indices in the positionMarks array.
+        Mark m = new Mark(0); // For comparison / search only.
+        m.mark = start;
+        int startIndex = search(marks, m);
+        if (startIndex < 0) // Translate to insertion index, if not found.
+          startIndex = - startIndex - 1;
+        m.mark = end;
+        int endIndex = search(marks, m);
+        if (endIndex < 0) // Translate to insertion index - 1, if not found.
+          endIndex = - endIndex - 2;
+
+        // Actually adjust the marks.
+        for (int i = startIndex; i <= endIndex; i++)
+          ((Mark) marks.get(i)).mark = toStart ? start : end;
+      }
+
+  }
+
+  /**
+   * Adjusts the mark of all <code>Position</code>s that are in the range 
+   * specified by <code>offset</code> and </code>length</code> within 
+   * the buffer array by <code>increment</code>
+   *
+   * @param startOffs the start offset of the range to search
+   * @param endOffs the length of the range to search, -1 means all to the end
+   * @param incr the increment
+   */
+  private void adjustPositionsInRange(int startOffs, int endOffs, int incr)
+  {
+    synchronized (this)
+      {
+        // Find the start and end indices in the positionMarks array.
+        Mark m = new Mark(0); // For comparison / search only.
+
+        m.mark = startOffs;
+        int startIndex = search(marks, m);
+        if (startIndex < 0) // Translate to insertion index, if not found.
+          startIndex = - startIndex - 1;
+
+        m.mark = endOffs;
+        int endIndex;
+        if (endOffs == -1)
+          endIndex = marks.size() - 1;
+        else
+          {
+            endIndex = search(marks, m);
+            if (endIndex < 0) // Translate to insertion index - 1, if not found.
+              endIndex = - endIndex - 2;
+          }
+        // Actually adjust the marks.
+        for (int i = startIndex; i <= endIndex; i++) {
+          ((Mark) marks.get(i)).mark += incr;
+        }
+      }
+
+  }
+
+  /**
+   * Resets all <code>Position</code> that have an offset of <code>0</code>,
+   * to also have an array index of <code>0</code>. This might be necessary
+   * after a call to <code>shiftGap(0)</code>, since then the marks at offset
+   * <code>0</code> get shifted to <code>gapEnd</code>.
+   */
+  protected void resetMarksAtZero()
+  {
+    if (gapStart != 0)
+      return;
+
+    for (int i = 0; i < marks.size(); i++)
+      {
+        Mark m = (Mark) marks.get(i);
+        if (m.mark <= gapEnd)
+          m.mark = 0;
+      }
+  }
+
+  /**
+   * @specnote This method is not very well specified and the positions vector
+   *           is implementation specific. The undo positions are managed
+   *           differently in this implementation, this method is only here
+   *           for binary compatibility.
+   */
+  protected void updateUndoPositions(Vector positions, int offset, int length)
+  {
+    // We do nothing here.
+  }
+
+  /**
+   * Outputs debugging info to System.err. It prints out the buffer array,
+   * the gapStart is marked by a < sign, the gapEnd is marked by a >
+   * sign and each position is marked by a # sign.
+   */
+  private void dump()
+  {
+    System.err.println("GapContent debug information");
+    System.err.println("buffer length: " + buffer.length);
+    System.err.println("gap start: " + gapStart);
+    System.err.println("gap end: " + gapEnd);
+    for (int i = 0; i < buffer.length; i++)
+      {
+        if (i == gapStart)
+          System.err.print('<');
+        if (i == gapEnd)
+          System.err.print('>');
+
+        if (!Character.isISOControl(buffer[i]))
+          System.err.print(buffer[i]);
+        else
+          System.err.print('.');
+      }
+    System.err.println();
+  }
+
+  /**
+   * Prints out the position marks.
+   */
+  private void dumpMarks()
+  {
+    System.out.print("positionMarks: ");
+    for (int i = 0; i < marks.size(); i++)
+      System.out.print(((Mark) marks.get(i)).mark + ", ");
+    System.out.println();
+  }
+
+  /**
+   * Polls the queue of death for GapContentPositions, updates the
+   * corresponding reference count and removes the corresponding mark
+   * if the refcount reaches zero.
+   *
+   * This is package private to avoid accessor synthetic methods.
+   */
+  void garbageCollect()
+  {
+    Reference ref = queueOfDeath.poll();
+    while (ref != null)
+      {
+        if (ref != null)
+          {
+            GapContentPosition pos = (GapContentPosition) ref.get();
+            Mark m = pos.mark;
+            m.refCount--;
+            if (m.refCount == 0)
+              marks.remove(m);
+          }
+        ref = queueOfDeath.poll();
+      }
+  }
+
+  /**
+   * Searches the first occurance of object <code>o</code> in list
+   * <code>l</code>. This performs a binary search by calling
+   * {@link Collections#binarySearch(List, Object)} and when an object has been
+   * found, it searches backwards to the first occurance of that object in the
+   * list. The meaning of the return value is the same as in
+   * <code>Collections.binarySearch()</code>.
+   *
+   * @param l the list to search through
+   * @param o the object to be searched
+   *
+   * @return the index of the first occurance of o in l, or -i + 1 if not found
+   */
+  private int search(List l, Object o)
+  {
+    int i = Collections.binarySearch(l, o);
+    while (i > 0)
+      {
+        Object o2 = l.get(i - 1);
+        if (o2.equals(o))
+          i--;
+        else
+          break;
+      }
+    return i;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1078 @@
+/* GlyphView.java -- A view to render styled text
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.text.BreakIterator;
+
+import javax.swing.SwingConstants;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.Position.Bias;
+
+/**
+ * Renders a run of styled text. This {@link View} subclass paints the
+ * characters of the <code>Element</code> it is responsible for using
+ * the style information from that <code>Element</code>.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class GlyphView extends View implements TabableView, Cloneable
+{
+
+  /**
+   * An abstract base implementation for a glyph painter for
+   * <code>GlyphView</code>.
+   */
+  public abstract static class GlyphPainter
+  {
+    /**
+     * Creates a new <code>GlyphPainer</code>.
+     */
+    public GlyphPainter()
+    {
+      // Nothing to do here.
+    }
+
+    /**
+     * Returns the ascent of the font that is used by this glyph painter.
+     *
+     * @param v the glyph view
+     *
+     * @return the ascent of the font that is used by this glyph painter
+     */
+    public abstract float getAscent(GlyphView v);
+
+    /**
+     * Returns the descent of the font that is used by this glyph painter.
+     *
+     * @param v the glyph view
+     *
+     * @return the descent of the font that is used by this glyph painter
+     */
+    public abstract float getDescent(GlyphView v);
+
+    /**
+     * Returns the full height of the rendered text.
+     *
+     * @return the full height of the rendered text
+     */
+    public abstract float getHeight(GlyphView view);
+
+    /**
+     * Determines the model offset, so that the text between <code>p0</code>
+     * and this offset fits within the span starting at <code>x</code> with
+     * the length of <code>len</code>. 
+     *
+     * @param v the glyph view
+     * @param p0 the starting offset in the model
+     * @param x the start location in the view
+     * @param len the length of the span in the view
+     */
+    public abstract int getBoundedPosition(GlyphView v, int p0, float x,
+                                           float len);
+
+    /**
+     * Paints the glyphs.
+     *
+     * @param view the glyph view to paint
+     * @param g the graphics context to use for painting
+     * @param a the allocation of the glyph view
+     * @param p0 the start position (in the model) from which to paint
+     * @param p1 the end position (in the model) to which to paint
+     */
+    public abstract void paint(GlyphView view, Graphics g, Shape a, int p0,
+                               int p1);
+
+    /**
+     * Maps a position in the document into the coordinate space of the View.
+     * The output rectangle usually reflects the font height but has a width
+     * of zero.
+     *
+     * @param view the glyph view
+     * @param pos the position of the character in the model
+     * @param a the area that is occupied by the view
+     * @param b either {@link Position.Bias#Forward} or
+     *        {@link Position.Bias#Backward} depending on the preferred
+     *        direction bias. If <code>null</code> this defaults to
+     *        <code>Position.Bias.Forward</code>
+     *
+     * @return a rectangle that gives the location of the document position
+     *         inside the view coordinate space
+     *
+     * @throws BadLocationException if <code>pos</code> is invalid
+     * @throws IllegalArgumentException if b is not one of the above listed
+     *         valid values
+     */
+    public abstract Shape modelToView(GlyphView view, int pos, Position.Bias b,
+                                      Shape a)
+      throws BadLocationException;
+
+    /**
+     * Maps a visual position into a document location.
+     *
+     * @param v the glyph view
+     * @param x the X coordinate of the visual position
+     * @param y the Y coordinate of the visual position
+     * @param a the allocated region
+     * @param biasRet filled with the bias of the model location on method exit
+     *
+     * @return the model location that represents the specified view location
+     */
+    public abstract int viewToModel(GlyphView v, float x, float y, Shape a,
+                                    Position.Bias[] biasRet);
+
+    /**
+     * Determine the span of the glyphs from location <code>p0</code> to
+     * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
+     * then TABs are expanded using this <code>TabExpander</code>.
+     * The parameter <code>x</code> is the location at which the view is
+     * located (this is important when using TAB expansion).
+     *
+     * @param view the glyph view
+     * @param p0 the starting location in the document model
+     * @param p1 the end location in the document model
+     * @param te the tab expander to use
+     * @param x the location at which the view is located
+     *
+     * @return the span of the glyphs from location <code>p0</code> to
+     *         location <code>p1</code>, possibly using TAB expansion
+     */
+    public abstract float getSpan(GlyphView view, int p0, int p1,
+                                  TabExpander te, float x);
+
+
+    /**
+     * Returns the model location that should be used to place a caret when
+     * moving the caret through the document.
+     *
+     * @param v the glyph view
+     * @param pos the current model location
+     * @param b the bias for <code>p</code>
+     * @param a the allocated region for the glyph view
+     * @param direction the direction from the current position; Must be one of
+     *        {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+     *        {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+     * @param biasRet filled with the bias of the resulting location when method
+     *        returns
+     *
+     * @return the location within the document that should be used to place the
+     *         caret when moving the caret around the document
+     *
+     * @throws BadLocationException if <code>pos</code> is an invalid model
+     *         location
+     * @throws IllegalArgumentException if <code>d</code> is invalid
+     */
+    public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b,
+                                         Shape a, int direction,
+                                         Position.Bias[] biasRet)
+      throws BadLocationException
+
+    {
+      int result = pos;
+      switch (direction)
+      {
+        case SwingConstants.EAST:
+          result = pos + 1;
+          break;
+        case SwingConstants.WEST:
+          result = pos - 1;
+          break;
+        case SwingConstants.NORTH:
+        case SwingConstants.SOUTH:
+        default:
+          // This should be handled in enclosing view, since the glyph view
+          // does not layout vertically.
+          break;
+      }
+      return result;
+    }
+
+    /**
+     * Returns a painter that can be used to render the specified glyph view.
+     * If this glyph painter is stateful, then it should return a new instance.
+     * However, if this painter is stateless it should return itself. The
+     * default behaviour is to return itself.
+     *
+     * @param v the glyph view for which to create a painter
+     * @param p0 the start offset of the rendered area
+     * @param p1 the end offset of the rendered area
+     *
+     * @return a painter that can be used to render the specified glyph view
+     */
+    public GlyphPainter getPainter(GlyphView v, int p0, int p1)
+    {
+      return this;
+    }
+  }
+
+  /**
+   * The default <code>GlyphPainter</code> used in <code>GlyphView</code>.
+   */
+  static class DefaultGlyphPainter extends GlyphPainter
+  {
+    /**
+     * Returns the full height of the rendered text.
+     *
+     * @return the full height of the rendered text
+     */
+    public float getHeight(GlyphView view)
+    {
+      Font font = view.getFont();
+      FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
+      float height = metrics.getHeight();
+      return height;
+    }
+    
+    /**
+     * Paints the glyphs.
+     *
+     * @param view the glyph view to paint
+     * @param g the graphics context to use for painting
+     * @param a the allocation of the glyph view
+     * @param p0 the start position (in the model) from which to paint
+     * @param p1 the end position (in the model) to which to paint
+     */
+    public void paint(GlyphView view, Graphics g, Shape a, int p0,
+                      int p1)
+    {
+      Color oldColor = g.getColor();
+      int height = (int) getHeight(view);
+      Segment txt = view.getText(p0, p1);
+      Rectangle bounds = a.getBounds();
+      TabExpander tabEx = null;
+      View parent = view.getParent();
+      if (parent instanceof TabExpander)
+        tabEx = (TabExpander) parent;
+
+      int width = Utilities.getTabbedTextWidth(txt, g.getFontMetrics(),
+                                               bounds.x, tabEx, txt.offset);
+      // Fill the background of the text run.
+      Color background = view.getBackground();
+      if (background != null)
+        {
+          g.setColor(background);
+          g.fillRect(bounds.x, bounds.y, width, height);
+        }
+      // Draw the actual text.
+      g.setColor(view.getForeground());
+      g.setFont(view.getFont());
+      int ascent = g.getFontMetrics().getAscent();
+      if (view.isSuperscript())
+        // TODO: Adjust font for superscripting.
+        Utilities.drawTabbedText(txt, bounds.x, bounds.y + ascent - height / 2,
+                                 g, tabEx, txt.offset);
+      else if (view.isSubscript())
+        // TODO: Adjust font for subscripting.
+        Utilities.drawTabbedText(txt, bounds.x, bounds.y + ascent + height / 2,
+                                 g, tabEx, txt.offset);
+      else
+        Utilities.drawTabbedText(txt, bounds.x, bounds.y + ascent, g, tabEx,
+                                 txt.offset);
+
+      if (view.isStrikeThrough())
+        {
+          int strikeHeight = (int) (getAscent(view) / 2);
+          g.drawLine(bounds.x, bounds.y + strikeHeight, bounds.height + width,
+                     bounds.y + strikeHeight);
+        }
+      if (view.isUnderline())
+        {
+          int lineHeight = (int) getAscent(view);
+          g.drawLine(bounds.x, bounds.y + lineHeight, bounds.height + width,
+                     bounds.y + lineHeight);
+        }
+      g.setColor(oldColor);
+    }
+
+    /**
+     * Maps a position in the document into the coordinate space of the View.
+     * The output rectangle usually reflects the font height but has a width
+     * of zero.
+     *
+     * @param view the glyph view
+     * @param pos the position of the character in the model
+     * @param a the area that is occupied by the view
+     * @param b either {@link Position.Bias#Forward} or
+     *        {@link Position.Bias#Backward} depending on the preferred
+     *        direction bias. If <code>null</code> this defaults to
+     *        <code>Position.Bias.Forward</code>
+     *
+     * @return a rectangle that gives the location of the document position
+     *         inside the view coordinate space
+     *
+     * @throws BadLocationException if <code>pos</code> is invalid
+     * @throws IllegalArgumentException if b is not one of the above listed
+     *         valid values
+     */
+    public Shape modelToView(GlyphView view, int pos, Position.Bias b,
+                             Shape a)
+      throws BadLocationException
+    {
+      Element el = view.getElement();
+      Font font = view.getFont();
+      FontMetrics fm = view.getContainer().getFontMetrics(font);
+      Segment txt = view.getText(el.getStartOffset(), pos);
+      int width = fm.charsWidth(txt.array, txt.offset, txt.count);
+      int height = fm.getHeight();
+      Rectangle bounds = a.getBounds();
+      Rectangle result = new Rectangle(bounds.x + width, bounds.y,
+                                       bounds.x + width, height);
+      return result;
+    }
+
+    /**
+     * Determine the span of the glyphs from location <code>p0</code> to
+     * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
+     * then TABs are expanded using this <code>TabExpander</code>.
+     * The parameter <code>x</code> is the location at which the view is
+     * located (this is important when using TAB expansion).
+     *
+     * @param view the glyph view
+     * @param p0 the starting location in the document model
+     * @param p1 the end location in the document model
+     * @param te the tab expander to use
+     * @param x the location at which the view is located
+     *
+     * @return the span of the glyphs from location <code>p0</code> to
+     *         location <code>p1</code>, possibly using TAB expansion
+     */
+    public float getSpan(GlyphView view, int p0, int p1,
+                         TabExpander te, float x)
+    {
+      Element el = view.getElement();
+      Font font = view.getFont();
+      FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+      Segment txt = view.getText(p0, p1);
+      int span = Utilities.getTabbedTextWidth(txt, fm, (int) x, te, p0);
+      return span;
+    }
+
+    /**
+     * Returns the ascent of the text run that is rendered by this
+     * <code>GlyphPainter</code>.
+     *
+     * @param v the glyph view
+     *
+     * @return the ascent of the text run that is rendered by this
+     *         <code>GlyphPainter</code>
+     *
+     * @see FontMetrics#getAscent()
+     */
+    public float getAscent(GlyphView v)
+    {
+      Font font = v.getFont();
+      FontMetrics fm = v.getContainer().getFontMetrics(font);
+      return fm.getAscent();
+    }
+
+    /**
+     * Returns the descent of the text run that is rendered by this
+     * <code>GlyphPainter</code>.
+     *
+     * @param v the glyph view
+     *
+     * @return the descent of the text run that is rendered by this
+     *         <code>GlyphPainter</code>
+     *
+     * @see FontMetrics#getDescent()
+     */
+    public float getDescent(GlyphView v)
+    {
+      Font font = v.getFont();
+      FontMetrics fm = v.getContainer().getFontMetrics(font);
+      return fm.getDescent();
+    }
+
+    /**
+     * Determines the model offset, so that the text between <code>p0</code>
+     * and this offset fits within the span starting at <code>x</code> with
+     * the length of <code>len</code>. 
+     *
+     * @param v the glyph view
+     * @param p0 the starting offset in the model
+     * @param x the start location in the view
+     * @param len the length of the span in the view
+     */
+    public int getBoundedPosition(GlyphView v, int p0, float x, float len)
+    {
+      TabExpander te = v.getTabExpander();
+      Segment txt = v.getText(p0, v.getEndOffset());
+      Font font = v.getFont();
+      FontMetrics fm = v.getContainer().getFontMetrics(font);
+      int pos = Utilities.getTabbedTextOffset(txt, fm, (int) x,
+                                              (int) (x + len), te, p0, false);
+      return pos;
+    }
+
+    /**
+     * Maps a visual position into a document location.
+     *
+     * @param v the glyph view
+     * @param x the X coordinate of the visual position
+     * @param y the Y coordinate of the visual position
+     * @param a the allocated region
+     * @param biasRet filled with the bias of the model location on method exit
+     *
+     * @return the model location that represents the specified view location
+     */
+    public int viewToModel(GlyphView v, float x, float y, Shape a,
+                           Bias[] biasRet)
+    {
+      Rectangle b = a.getBounds();
+      int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
+      return pos;
+    }
+  }
+
+  /**
+   * The GlyphPainer used for painting the glyphs.
+   */
+  GlyphPainter glyphPainter;
+
+  /**
+   * The start offset within the document for this view.
+   */
+  private int startOffset;
+
+  /**
+   * The end offset within the document for this view.
+   */
+  private int endOffset;
+
+  /**
+   * Creates a new <code>GlyphView</code> for the given <code>Element</code>.
+   *
+   * @param element the element that is rendered by this GlyphView
+   */
+  public GlyphView(Element element)
+  {
+    super(element);
+    startOffset = -1;
+    endOffset = -1;
+  }
+
+  /**
+   * Returns the <code>GlyphPainter</code> that is used by this
+   * <code>GlyphView</code>. If no <code>GlyphPainer</code> has been installed
+   * <code>null</code> is returned.
+   *
+   * @return the glyph painter that is used by this
+   *         glyph view or <code>null</code> if no glyph painter has been
+   *         installed
+   */
+  public GlyphPainter getGlyphPainter()
+  {
+    return glyphPainter;
+  }
+
+  /**
+   * Sets the {@link GlyphPainter} to be used for this <code>GlyphView</code>.
+   *
+   * @param painter the glyph painter to be used for this glyph view
+   */
+  public void setGlyphPainter(GlyphPainter painter)
+  {
+    glyphPainter = painter;
+  }
+
+  /**
+   * Checks if a <code>GlyphPainer</code> is installed. If this is not the
+   * case, a default painter is installed.
+   */
+  protected void checkPainter()
+  {
+    if (glyphPainter == null)
+      glyphPainter = new DefaultGlyphPainter();
+  }
+
+  /**
+   * Renders the <code>Element</code> that is associated with this
+   * <code>View</code>.
+   *
+   * @param g the <code>Graphics</code> context to render to
+   * @param a the allocated region for the <code>Element</code>
+   */
+  public void paint(Graphics g, Shape a)
+  {
+    Element el = getElement();
+    checkPainter();
+    getGlyphPainter().paint(this, g, a, getStartOffset(), getEndOffset());
+  }
+
+
+  /**
+   * Returns the preferred span of the content managed by this
+   * <code>View</code> along the specified <code>axis</code>.
+   *
+   * @param axis the axis
+   *
+   * @return the preferred span of this <code>View</code>.
+   */
+  public float getPreferredSpan(int axis)
+  {
+    float span = 0;
+    checkPainter();
+    GlyphPainter painter = getGlyphPainter();
+    if (axis == X_AXIS)
+      {
+        Element el = getElement();
+        TabExpander tabEx = null;
+        View parent = getParent();
+        if (parent instanceof TabExpander)
+          tabEx = (TabExpander) parent;
+        span = painter.getSpan(this, getStartOffset(), getEndOffset(),
+                               tabEx, 0.F);
+      }
+    else
+      span = painter.getHeight(this);
+
+    return span;
+  }
+
+  /**
+   * Maps a position in the document into the coordinate space of the View.
+   * The output rectangle usually reflects the font height but has a width
+   * of zero.
+   *
+   * @param pos the position of the character in the model
+   * @param a the area that is occupied by the view
+   * @param b either {@link Position.Bias#Forward} or
+   *        {@link Position.Bias#Backward} depending on the preferred
+   *        direction bias. If <code>null</code> this defaults to
+   *        <code>Position.Bias.Forward</code>
+   *
+   * @return a rectangle that gives the location of the document position
+   *         inside the view coordinate space
+   *
+   * @throws BadLocationException if <code>pos</code> is invalid
+   * @throws IllegalArgumentException if b is not one of the above listed
+   *         valid values
+   */
+  public Shape modelToView(int pos, Shape a, Position.Bias b)
+    throws BadLocationException
+  {
+    GlyphPainter p = getGlyphPainter();
+    return p.modelToView(this, pos, b, a);
+  }
+
+  /**
+   * Maps coordinates from the <code>View</code>'s space into a position
+   * in the document model.
+   *
+   * @param x the x coordinate in the view space
+   * @param y the y coordinate in the view space
+   * @param a the allocation of this <code>View</code>
+   * @param b the bias to use
+   *
+   * @return the position in the document that corresponds to the screen
+   *         coordinates <code>x, y</code>
+   */
+  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+  {
+    checkPainter();
+    GlyphPainter painter = getGlyphPainter();
+    return painter.viewToModel(this, x, y, a, b);
+  }
+
+  /**
+   * Return the {@link TabExpander} to use.
+   *
+   * @return the {@link TabExpander} to use
+   */
+  public TabExpander getTabExpander()
+  {
+    TabExpander te = null;
+    View parent = getParent();
+
+    if (parent instanceof TabExpander)
+      te = (TabExpander) parent;
+    
+    return te;
+  }
+
+  /**
+   * Returns the preferred span of this view for tab expansion.
+   *
+   * @param x the location of the view
+   * @param te the tab expander to use
+   *
+   * @return the preferred span of this view for tab expansion
+   */
+  public float getTabbedSpan(float x, TabExpander te)
+  {
+    Element el = getElement();
+    return getGlyphPainter().getSpan(this, el.getStartOffset(),
+                                     el.getEndOffset(), te, x);
+  }
+
+  /**
+   * Returns the span of a portion of the view. This is used in TAB expansion
+   * for fragments that don't contain TABs.
+   *
+   * @param p0 the start index
+   * @param p1 the end index
+   *
+   * @return the span of the specified portion of the view
+   */
+  public float getPartialSpan(int p0, int p1)
+  {
+    Element el = getElement();
+    Document doc = el.getDocument();
+    Segment seg = new Segment();
+    try
+      {
+        doc.getText(p0, p1 - p0, seg);
+      }
+    catch (BadLocationException ex)
+      {
+	AssertionError ae;
+        ae = new AssertionError("BadLocationException must not be thrown "
+				+ "here");
+	ae.initCause(ex);
+	throw ae;
+      }
+    FontMetrics fm = null; // Fetch font metrics somewhere.
+    return Utilities.getTabbedTextWidth(seg, fm, 0, null, p0);
+  }
+
+  /**
+   * Returns the start offset in the document model of the portion
+   * of text that this view is responsible for.
+   *
+   * @return the start offset in the document model of the portion
+   *         of text that this view is responsible for
+   */
+  public int getStartOffset()
+  {
+    int start = startOffset;
+    if (start < 0)
+      start = super.getStartOffset();
+    return start;
+  }
+
+  /**
+   * Returns the end offset in the document model of the portion
+   * of text that this view is responsible for.
+   *
+   * @return the end offset in the document model of the portion
+   *         of text that this view is responsible for
+   */
+  public int getEndOffset()
+  {
+    int end = endOffset;
+    if (end < 0)
+      end = super.getEndOffset();
+    return end;
+  }
+
+  /**
+   * Returns the text segment that this view is responsible for.
+   *
+   * @param p0 the start index in the document model
+   * @param p1 the end index in the document model
+   *
+   * @return the text segment that this view is responsible for
+   */
+  public Segment getText(int p0, int p1)
+  {
+    Segment txt = new Segment();
+    try
+      {
+        getDocument().getText(p0, p1 - p0, txt);
+      }
+    catch (BadLocationException ex)
+      {
+	AssertionError ae;
+        ae = new AssertionError("BadLocationException should not be "
+				+ "thrown here. p0 = " + p0 + ", p1 = " + p1);
+	ae.initCause(ex);
+	throw ae;
+      }
+
+    return txt;
+  }
+
+  /**
+   * Returns the font for the text run for which this <code>GlyphView</code>
+   * is responsible.
+   *
+   * @return the font for the text run for which this <code>GlyphView</code>
+   *         is responsible
+   */
+  public Font getFont()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    String family = StyleConstants.getFontFamily(atts);
+    int size = StyleConstants.getFontSize(atts);
+    int style = Font.PLAIN;
+    if (StyleConstants.isBold(atts))
+        style |= Font.BOLD;
+    if (StyleConstants.isItalic(atts))
+      style |= Font.ITALIC;
+    Font font = new Font(family, style, size);
+    return font;
+  }
+
+  /**
+   * Returns the foreground color which should be used to paint the text.
+   * This is fetched from the associated element's text attributes using
+   * {@link StyleConstants#getForeground}.
+   *
+   * @return the foreground color which should be used to paint the text
+   */
+  public Color getForeground()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    return StyleConstants.getForeground(atts);
+  }
+
+  /**
+   * Returns the background color which should be used to paint the text.
+   * This is fetched from the associated element's text attributes using
+   * {@link StyleConstants#getBackground}.
+   *
+   * @return the background color which should be used to paint the text
+   */
+  public Color getBackground()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    // We cannot use StyleConstants.getBackground() here, because that returns
+    // BLACK as default (when background == null). What we need is the
+    // background setting of the text component instead, which is what we get
+    // when background == null anyway.
+    return (Color) atts.getAttribute(StyleConstants.Background);
+  }
+
+  /**
+   * Determines whether the text should be rendered strike-through or not. This
+   * is determined using the method
+   * {@link StyleConstants#isStrikeThrough(AttributeSet)} on the element of
+   * this view.
+   *
+   * @return whether the text should be rendered strike-through or not
+   */
+  public boolean isStrikeThrough()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    return StyleConstants.isStrikeThrough(atts);
+  }
+
+  /**
+   * Determines whether the text should be rendered as subscript or not. This
+   * is determined using the method
+   * {@link StyleConstants#isSubscript(AttributeSet)} on the element of
+   * this view.
+   *
+   * @return whether the text should be rendered as subscript or not
+   */
+  public boolean isSubscript()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    return StyleConstants.isSubscript(atts);
+  }
+
+  /**
+   * Determines whether the text should be rendered as superscript or not. This
+   * is determined using the method
+   * {@link StyleConstants#isSuperscript(AttributeSet)} on the element of
+   * this view.
+   *
+   * @return whether the text should be rendered as superscript or not
+   */
+  public boolean isSuperscript()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    return StyleConstants.isSuperscript(atts);
+  }
+
+  /**
+   * Determines whether the text should be rendered as underlined or not. This
+   * is determined using the method
+   * {@link StyleConstants#isUnderline(AttributeSet)} on the element of
+   * this view.
+   *
+   * @return whether the text should be rendered as underlined or not
+   */
+  public boolean isUnderline()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    return StyleConstants.isUnderline(atts);
+  }
+
+  /**
+   * Creates and returns a shallow clone of this GlyphView. This is used by
+   * the {@link #createFragment} and {@link #breakView} methods.
+   *
+   * @return a shallow clone of this GlyphView
+   */
+  protected final Object clone()
+  {
+    try
+      {
+        return super.clone();
+      }
+    catch (CloneNotSupportedException ex)
+      {
+        AssertionError err = new AssertionError("CloneNotSupportedException "
+                                                + "must not be thrown here");
+        err.initCause(ex);
+        throw err;
+      }
+  }
+
+  /**
+   * Tries to break the view near the specified view span <code>len</code>.
+   * The glyph view can only be broken in the X direction. For Y direction it
+   * returns itself.
+   *
+   * @param axis the axis for breaking, may be {@link View#X_AXIS} or
+   *        {@link View#Y_AXIS}
+   * @param p0 the model location where the fragment should start
+   * @param pos the view position along the axis where the fragment starts
+   * @param len the desired length of the fragment view
+   *
+   * @return the fragment view, or <code>this</code> if breaking was not
+   *         possible
+   */
+  public View breakView(int axis, int p0, float pos, float len)
+  {
+    if (axis == Y_AXIS)
+      return this;
+
+    checkPainter();
+    GlyphPainter painter = getGlyphPainter();
+
+    // Try to find a suitable line break.
+    BreakIterator lineBreaker = BreakIterator.getLineInstance();
+    Segment txt = new Segment();
+    try
+      {
+        int start = getStartOffset();
+        int length = getEndOffset() - start;
+        getDocument().getText(start, length, txt);
+      }
+    catch (BadLocationException ex)
+      {
+        AssertionError err = new AssertionError("BadLocationException must not "
+                                                + "be thrown here.");
+        err.initCause(ex);
+        throw err;
+      }
+    int breakLocation =
+      Utilities.getBreakLocation(txt, getContainer().getFontMetrics(getFont()),
+                                 (int) pos, (int) (pos + len),
+                                 getTabExpander(), p0);
+    View brokenView = createFragment(p0, breakLocation);
+    return brokenView;
+  }
+
+  /**
+   * Determines how well the specified view location is suitable for inserting
+   * a line break. If <code>axis</code> is <code>View.Y_AXIS</code>, then
+   * this method forwards to the superclass, if <code>axis</code> is
+   * <code>View.X_AXIS</code> then this method returns
+   * {@link View#ExcellentBreakWeight} if there is a suitable break location
+   * (usually whitespace) within the specified view span, or
+   * {@link View#GoodBreakWeight} if not.
+   *
+   * @param axis the axis along which the break weight is requested
+   * @param pos the starting view location
+   * @param len the length of the span at which the view should be broken
+   *
+   * @return the break weight
+   */
+  public int getBreakWeight(int axis, float pos, float len)
+  {
+    int weight;
+    if (axis == Y_AXIS)
+      weight = super.getBreakWeight(axis, pos, len);
+    else
+      {
+        // FIXME: Commented out because the Utilities.getBreakLocation method
+        // is still buggy. The GoodBreakWeight is a reasonable workaround for
+        // now.
+//        int startOffset = getStartOffset();
+//        int endOffset = getEndOffset() - 1;
+//        Segment s = getText(startOffset, endOffset);
+//        Container c = getContainer();
+//        FontMetrics fm = c.getFontMetrics(c.getFont());
+//        int x0 = (int) pos;
+//        int x = (int) (pos + len);
+//        int breakLoc = Utilities.getBreakLocation(s, fm, x0, x,
+//                                                  getTabExpander(),
+//                                                  startOffset);
+//        if (breakLoc == startOffset || breakLoc == endOffset)
+//          weight = GoodBreakWeight;
+//        else
+//          weight = ExcellentBreakWeight;
+        weight = GoodBreakWeight;
+      }
+    return weight;
+  }
+
+  /**
+   * Receives notification that some text attributes have changed within the
+   * text fragment that this view is responsible for. This calls
+   * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+   * both width and height.
+   *
+   * @param e the document event describing the change; not used here
+   * @param a the view allocation on screen; not used here
+   * @param vf the view factory; not used here
+   */
+  public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+  {
+    preferenceChanged(this, true, true);
+  }
+
+  /**
+   * Receives notification that some text has been inserted within the
+   * text fragment that this view is responsible for. This calls
+   * {@link View#preferenceChanged(View, boolean, boolean)} for the
+   * direction in which the glyphs are rendered.
+   *
+   * @param e the document event describing the change; not used here
+   * @param a the view allocation on screen; not used here
+   * @param vf the view factory; not used here
+   */
+  public void insertUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+  {
+    preferenceChanged(this, true, false);
+  }
+
+  /**
+   * Receives notification that some text has been removed within the
+   * text fragment that this view is responsible for. This calls
+   * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+   * width.
+   *
+   * @param e the document event describing the change; not used here
+   * @param a the view allocation on screen; not used here
+   * @param vf the view factory; not used here
+   */
+  public void removeUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+  {
+    preferenceChanged(this, true, false);
+  }
+
+  /**
+   * Creates a fragment view of this view that starts at <code>p0</code> and
+   * ends at <code>p1</code>.
+   *
+   * @param p0 the start location for the fragment view
+   * @param p1 the end location for the fragment view
+   *
+   * @return the fragment view
+   */
+  public View createFragment(int p0, int p1)
+  {
+    GlyphView fragment = (GlyphView) clone();
+    if (p0 != getStartOffset())
+      fragment.startOffset = p0;
+    if (p1 != getEndOffset())
+      fragment.endOffset = p1;
+    return fragment;
+  }
+
+  /**
+   * Returns the alignment of this view along the specified axis. For the Y
+   * axis this is <code>(height - descent) / height</code> for the used font,
+   * so that it is aligned along the baseline.
+   * For the X axis the superclass is called.
+   */
+  public float getAlignment(int axis)
+  {
+    float align;
+    if (axis == Y_AXIS)
+      {
+        checkPainter();
+        GlyphPainter painter = getGlyphPainter();
+        float height = painter.getHeight(this);
+        float descent = painter.getDescent(this);
+        align = (height - descent) / height; 
+      }
+    else
+      align = super.getAlignment(axis);
+
+    return align;
+  }
+
+  /**
+   * Returns the model location that should be used to place a caret when
+   * moving the caret through the document.
+   *
+   * @param pos the current model location
+   * @param bias the bias for <code>p</code>
+   * @param a the allocated region for the glyph view
+   * @param direction the direction from the current position; Must be one of
+   *        {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+   *        {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+   * @param biasRet filled with the bias of the resulting location when method
+   *        returns
+   *
+   * @return the location within the document that should be used to place the
+   *         caret when moving the caret around the document
+   *
+   * @throws BadLocationException if <code>pos</code> is an invalid model
+   *         location
+   * @throws IllegalArgumentException if <code>d</code> is invalid
+   */
+  public int getNextVisualPositionFrom(int pos, Position.Bias bias, Shape a,
+                                       int direction, Position.Bias[] biasRet)
+    throws BadLocationException
+  {
+    checkPainter();
+    GlyphPainter painter = getGlyphPainter();
+    return painter.getNextVisualPositionFrom(this, pos, bias, a, direction,
+                                             biasRet);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,79 @@
+/* Highlighter.java --
+   Copyright (C) 2004  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Shape;
+
+
+public interface Highlighter
+{
+  public interface Highlight
+  {
+    int getEndOffset();
+
+    int getStartOffset();
+
+    HighlightPainter getPainter();
+  }
+
+  public interface HighlightPainter
+  {
+    void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c);
+  }
+  
+  void install(JTextComponent c);
+
+  void deinstall(JTextComponent c);
+
+  Object addHighlight(int p0, int p1, HighlightPainter p)
+    throws BadLocationException;
+
+  void removeAllHighlights();
+
+  void removeHighlight(Object tag);
+
+  void changeHighlight(Object tag, int p0, int p1)
+    throws BadLocationException;
+
+  Highlight[] getHighlights();
+
+  void paint(Graphics g);
+}
+

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,175 @@
+/* IconView.java -- A view to render icons
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.Icon;
+import javax.swing.JTextPane;
+
+/**
+ * A View that can render an icon. This view is created by the
+ * {@link StyledEditorKit}'s view factory for all elements that have name
+ * {@link StyleConstants#IconElementName}. This is usually created by
+ * inserting an icon into <code>JTextPane</code> using
+ * {@link JTextPane#insertIcon(Icon)}
+ *
+ * The icon is determined using the attribute
+ * {@link StyleConstants#IconAttribute}, which's value must be an {@link Icon}.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+public class IconView
+  extends View
+{
+
+  /**
+   * Creates a new <code>IconView</code> for the given <code>Element</code>.
+   *
+   * @param element the element that is rendered by this IconView
+   */
+  public IconView(Element element)
+  {
+    super(element);
+  }
+
+  /**
+   * Renders the <code>Element</code> that is associated with this
+   * <code>View</code>.
+   *
+   * @param g the <code>Graphics</code> context to render to
+   * @param a the allocated region for the <code>Element</code>
+   */
+  public void paint(Graphics g, Shape a)
+  {
+    Icon icon = StyleConstants.getIcon(getElement().getAttributes());
+    Rectangle b = a.getBounds();
+    icon.paintIcon(getContainer(), g, b.x, b.y);
+  }
+
+  /**
+   * Returns the preferred span of the content managed by this
+   * <code>View</code> along the specified <code>axis</code>.
+   *
+   * @param axis the axis
+   *
+   * @return the preferred span of this <code>View</code>.
+   */
+  public float getPreferredSpan(int axis)
+  {
+    Icon icon = StyleConstants.getIcon(getElement().getAttributes());
+    float span;
+    if (axis == X_AXIS)
+      span = icon.getIconWidth();
+    else if (axis == Y_AXIS)
+      span = icon.getIconHeight();
+    else
+      throw new IllegalArgumentException();
+    return span;
+  }
+
+  /**
+   * Maps a position in the document into the coordinate space of the View.
+   * The output rectangle usually reflects the font height but has a width
+   * of zero.
+   *
+   * @param pos the position of the character in the model
+   * @param a the area that is occupied by the view
+   * @param b either {@link Position.Bias#Forward} or
+   *        {@link Position.Bias#Backward} depending on the preferred
+   *        direction bias. If <code>null</code> this defaults to
+   *        <code>Position.Bias.Forward</code>
+   *
+   * @return a rectangle that gives the location of the document position
+   *         inside the view coordinate space
+   *
+   * @throws BadLocationException if <code>pos</code> is invalid
+   * @throws IllegalArgumentException if b is not one of the above listed
+   *         valid values
+   */
+  public Shape modelToView(int pos, Shape a, Position.Bias b)
+    throws BadLocationException
+  {
+    Element el = getElement();
+    Rectangle r = a.getBounds();
+    Icon icon = StyleConstants.getIcon(el.getAttributes());
+    return new Rectangle(r.x, r.y, icon.getIconWidth(), icon.getIconHeight());
+  }
+
+  /**
+   * Maps coordinates from the <code>View</code>'s space into a position
+   * in the document model.
+   *
+   * @param x the x coordinate in the view space
+   * @param y the y coordinate in the view space
+   * @param a the allocation of this <code>View</code>
+   * @param b the bias to use
+   *
+   * @return the position in the document that corresponds to the screen
+   *         coordinates <code>x, y</code>
+   */
+  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+  {
+    // The element should only have one character position and it is clear
+    // that this position is the position that best matches the given screen
+    // coordinates, simply because this view has only this one position.
+    Element el = getElement();
+    return el.getStartOffset();
+  }
+
+  /**
+   * Returns the alignment for this view. This will be 1.0 for the Y_AXIS,
+   * and the super behaviour for the X_AXIS.
+   *
+   * @param axis the axis for which to calculate the alignment
+   *
+   * @return the alignment
+   */
+  public float getAlignment(int axis)
+  {
+    float align;
+    if (axis == Y_AXIS)
+      align = 1.0F;
+    else
+      align = super.getAlignment(axis);
+    return align;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,357 @@
+/* InternationalFormatter.java --
+Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.text.AttributedCharacterIterator;
+import java.text.Format;
+import java.text.ParseException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.Action;
+import javax.swing.JFormattedTextField;
+
+/**
+ * This extends {@link DefaultFormatter} so that the value to string
+ * conversion is done via a {@link Format} object. This allows
+ * various additional formats to be handled by JFormattedField.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class InternationalFormatter
+  extends DefaultFormatter
+{
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 2436068675711756856L;
+
+  /** The format that handles value to string conversion. */
+  Format format;
+
+  /** The minimal permissable value. */
+  Comparable minimum;
+
+  /** The maximal permissable value. */
+  Comparable maximum;
+
+  /**
+   * Creates a new InternationalFormatter with no Format specified.
+   */
+  public InternationalFormatter()
+  {
+    super();
+    minimum = null;
+    maximum = null;
+    format = null;
+    setCommitsOnValidEdit(false);
+    setOverwriteMode(false);
+  }
+
+  /**
+   * Creates a new InternationalFormatter that uses the specified
+   * Format object for value to string conversion.
+   *
+   * @param format the Format object to use for value to string conversion
+   */
+  public InternationalFormatter(Format format)
+  {
+    this();
+    setFormat(format);
+  }
+
+  /**
+   * Sets the Format object that is used to convert values to strings.
+   *
+   * @param format the Format to use for value to string conversion
+   *
+   * @see Format
+   */
+  public void setFormat(Format format)
+  {
+    this.format = format;
+  }
+
+  /**
+   * Returns the currently used Format object that is used to format
+   * the JFormattedField.
+   *
+   * @return the current Format
+   */
+  public Format getFormat()
+  {
+    return format;
+  }
+
+  /**
+   * Sets the minimum value that is allowed by this Formatter. The minimum
+   * value is given as an object that implements the {@link Comparable}
+   * interface.
+   *
+   * If <code>minValue</code> is null, then the Formatter has no restrictions
+   * at the lower end.
+   *
+   * If value class is not yet specified and <code>minValue</code> is not
+   * null, then <code>valueClass</code> is set to the class of the minimum
+   * value.
+   *
+   * @param minValue the minimum permissable value
+   *
+   * @see Comparable
+   */
+  public void setMinimum(Comparable minValue)
+  {
+    minimum = minValue;
+    if (valueClass == null && minValue != null)
+      valueClass = minValue.getClass();
+  }
+
+  /**
+   * Returns the minimal value that is allowed by this Formatter.
+   *
+   * A <code>null</code> value means that there is no restriction.
+   *
+   * @return the minimal value that is allowed by this Formatter or
+   *     <code>null</code> if there is no restriction
+   */
+  public Comparable getMinimum()
+  {
+    return minimum;
+  }
+
+  /**
+   * Sets the maximum value that is allowed by this Formatter. The maximum
+   * value is given as an object that implements the {@link Comparable}
+   * interface.
+   *
+   * If <code>maxValue</code> is null, then the Formatter has no restrictions
+   * at the upper end.
+   *
+   * If value class is not yet specified and <code>maxValue</code> is not
+   * null, then <code>valueClass</code> is set to the class of the maximum
+   * value.
+   *
+   * @param maxValue the maximum permissable value
+   *
+   * @see Comparable
+   */
+  public void setMaximum(Comparable maxValue)
+  {
+    maximum = maxValue;
+    if (valueClass == null && maxValue != null)
+      valueClass = maxValue.getClass();
+  }
+
+  /**
+   * Returns the maximal value that is allowed by this Formatter.
+   *
+   * A <code>null</code> value means that there is no restriction.
+   *
+   * @return the maximal value that is allowed by this Formatter or
+   *     <code>null</code> if there is no restriction
+   */
+  public Comparable getMaximum()
+  {
+    return maximum;
+  }
+
+  /**
+   * Installs the formatter on the specified {@link JFormattedTextField}.
+   *
+   * This method does the following things:
+   * <ul>
+   * <li>Display the value of #valueToString in the
+   *  <code>JFormattedTextField</code></li>
+   * <li>Install the Actions from #getActions on the <code>JTextField</code>
+   * </li>
+   * <li>Install the DocumentFilter returned by #getDocumentFilter</li>
+   * <li>Install the NavigationFilter returned by #getNavigationFilter</li>
+   * </ul>
+   *
+   * This method is typically not overridden by subclasses. Instead override
+   * one of the mentioned methods in order to customize behaviour.
+   *
+   * @param ftf the {@link JFormattedTextField} in which this formatter
+   *     is installed 
+   */
+  public void install(JFormattedTextField ftf)
+  {
+    super.install(ftf);
+  }
+
+  /**
+   * Converts a value object into a String. This is done by invoking
+   * {@link Format#format(Object)} on the specified <code>Format</code> object.
+   * If no format is set, then {@link DefaultFormatter#valueToString(Object)}
+   * is called as a fallback.
+   *
+   * @param value the value to be converted
+   *
+   * @return the string representation of the value
+   *
+   * @throws ParseException if the value cannot be converted
+   */
+  public String valueToString(Object value)
+    throws ParseException
+  {
+    if (value == null)
+      return "";
+    if (format != null)
+      return format.format(value);
+    else
+      return super.valueToString(value);
+  }
+
+  /**
+   * Converts a String (from the JFormattedTextField input) to a value.
+   * This is achieved by invoking {@link Format#parseObject(String)} on
+   * the specified <code>Format</code> object.
+   *
+   * This implementation differs slightly from {@link DefaultFormatter},
+   * it does:
+   * <ol>
+   * <li>Convert the string to an <code>Object</code> using the
+   *   <code>Formatter</code>.</li>
+   * <li>If a <code>valueClass</code> has been set, this object is passed to
+   *   {@link DefaultFormatter#stringToValue(String)} so that the value
+   *   has the correct type. This may or may not work correctly, depending on
+   *   the implementation of toString() in the value class and if the class
+   *   implements a constructor that takes one String as argument.</li>
+   * <li>If no {@link ParseException} has been thrown so far, we check if the
+   *   value exceeds either <code>minimum</code> or <code>maximum</code> if
+   *   one of those has been specified and throw a <code>ParseException</code>
+   *   if it does.</li>
+   * <li>Return the value.</li>
+   * </ol>
+   *
+   * If no format has been specified, then
+   * {@link DefaultFormatter#stringToValue(String)} is invoked as fallback.
+   *
+   * @param string the string to convert
+   *
+   * @return the value for the string
+   *
+   * @throws ParseException if the string cannot be converted into
+   *     a value object (e.g. invalid input)
+   */
+  public Object stringToValue(String string)
+    throws ParseException
+  {
+    if (format != null)
+      {
+        Object o = format.parseObject(string);
+
+        // If a value class has been set, call super in order to get
+        // the class right. That is what the JDK API docs suggest, so we do
+        // it that way.
+        if (valueClass != null)
+          o = super.stringToValue(o.toString());
+
+        // Check for minimum and maximum bounds
+        if (minimum != null && minimum.compareTo(o) > 0)
+          throw new ParseException("The value may not be less than the"
+                                    + " specified minimum", 0);
+        if (maximum != null && minimum.compareTo(o) < 0)
+          throw new ParseException("The value may not be greater than the"
+                                    + " specified maximum", 0);
+        return o;
+      }
+    else
+      return super.stringToValue(string);
+  }
+
+  /**
+   * Returns the {@link Format.Field} constants that are associated with
+   * the specified position in the text.
+   *
+   * If <code>offset</code> is not a valid location in the input field,
+   * an empty array of fields is returned.
+   *
+   * @param offset the position in the text from which we want to fetch
+   *     the fields constants
+   *
+   * @return the field values associated with the specified position in
+   *     the text
+   */
+  public Format.Field[] getFields(int offset)
+  {
+    // TODO: don't know if this is correct
+    AttributedCharacterIterator aci = format.formatToCharacterIterator
+                                         (getFormattedTextField().getValue());
+    aci.setIndex(offset);
+    Map atts = aci.getAttributes();
+    Set keys = atts.keySet();
+    Format.Field[] fields = new Format.Field[keys.size()];
+    int index = 0;
+    for (Iterator i = keys.iterator(); i.hasNext(); index++)
+      fields[index] = (Format.Field) i.next();
+    return fields;
+  }
+
+  /**
+   * This creates and returns a clone of this Formatter.
+   *
+   * @return a clone of this formatter
+   *
+   * @throws CloneNotSupportedException not thrown here, since cloning is
+   *     supported
+   * XXX - FIXME - Whole method disabled as workaround for gcj bug #22060.
+  public Object clone()
+    throws CloneNotSupportedException
+  {
+    // TODO: it has to be considered, if we should return a deep or shallow
+    // clone here. for now we return a shallow clone
+    Object clone = super.clone();
+    return clone;
+  }
+   */
+
+  /**
+   * Returns the Actions that are supported by this Formatter.
+   *
+   * @specnote the JDK API docs say here: <cite>If
+   *     <code>getSupportsIncrement</code> returns true, this returns two
+   *     Actions suitable for incrementing/decrementing the value.</cite>
+   *     The questsion is, which method <code>getSupportsIncrement</code>?
+   *     There is no such method in the whole API! So we just call
+   *     super.getActions here.
+   */
+  protected Action[] getActions()
+  {
+    return super.getActions();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1905 @@
+/* JTextComponent.java --
+   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import gnu.classpath.NotImplementedException;
+
+import java.awt.AWTEvent;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleEditableText;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
+import javax.swing.Action;
+import javax.swing.ActionMap;
+import javax.swing.InputMap;
+import javax.swing.JComponent;
+import javax.swing.JViewport;
+import javax.swing.KeyStroke;
+import javax.swing.Scrollable;
+import javax.swing.SwingConstants;
+import javax.swing.TransferHandler;
+import javax.swing.UIManager;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.plaf.ActionMapUIResource;
+import javax.swing.plaf.InputMapUIResource;
+import javax.swing.plaf.TextUI;
+
+public abstract class JTextComponent extends JComponent
+  implements Scrollable, Accessible
+{
+  /**
+   * AccessibleJTextComponent implements accessibility hooks for
+   * JTextComponent.  It allows an accessibility driver to read and
+   * manipulate the text component's contents as well as update UI
+   * elements such as the caret.
+   */
+  public class AccessibleJTextComponent extends AccessibleJComponent implements
+      AccessibleText, CaretListener, DocumentListener, AccessibleAction,
+      AccessibleEditableText
+  {
+    private static final long serialVersionUID = 7664188944091413696L;
+
+    /**
+     * The caret's offset.
+     */
+    int dot = 0;
+
+    /**
+     * The current JTextComponent.
+     */
+    JTextComponent textComp = JTextComponent.this;
+
+    /**
+     * Construct an AccessibleJTextComponent.
+     */
+    public AccessibleJTextComponent()
+    {
+      super();
+      textComp.addCaretListener(this);
+    }
+
+    /**
+     * Retrieve the current caret position.  The index of the first
+     * caret position is 0.
+     *
+     * @return caret position
+     */
+    public int getCaretPosition()
+    {
+      dot = textComp.getCaretPosition();
+      return dot;
+    }
+
+    /**
+     * Retrieve the current text selection.  If no text is selected
+     * this method returns null.
+     *
+     * @return the currently selected text or null
+     */
+    public String getSelectedText()
+    {
+      return textComp.getSelectedText();
+    }
+
+    /**
+     * Retrieve the index of the first character in the current text
+     * selection.  If there is no text in the text component, this
+     * method returns 0.  If there is text in the text component, but
+     * there is no selection, this method returns the current caret
+     * position.
+     *
+     * @return the index of the first character in the selection, the
+     * current caret position or 0
+     */
+    public int getSelectionStart()
+    {
+      if (getSelectedText() == null || (textComp.getText().equals("")))
+        return 0;
+      return textComp.getSelectionStart();
+    }
+
+    /**
+     * Retrieve the index of the last character in the current text
+     * selection.  If there is no text in the text component, this
+     * method returns 0.  If there is text in the text component, but
+     * there is no selection, this method returns the current caret
+     * position.
+     *
+     * @return the index of the last character in the selection, the
+     * current caret position or 0
+     */
+    public int getSelectionEnd()
+    {
+      if (getSelectedText() == null || (textComp.getText().equals("")))
+        return 0;
+      return textComp.getSelectionEnd();
+    }
+
+    /**
+     * Handle a change in the caret position and fire any applicable
+     * property change events.
+     *
+     * @param e - the caret update event
+     */
+    public void caretUpdate(CaretEvent e)
+      throws NotImplementedException
+    {
+      // TODO: fire appropriate event.
+      dot = e.getDot();
+    }
+
+    /**
+     * Retreive the accessible state set of this component.
+     *
+     * @return the accessible state set of this component
+     */
+    public AccessibleStateSet getAccessibleStateSet()
+      throws NotImplementedException
+    {
+      AccessibleStateSet state = super.getAccessibleStateSet();
+      // TODO: Figure out what state must be added here to the super's state.
+      return state;
+    }
+
+    /**
+     * Retrieve the accessible role of this component.
+     *
+     * @return the accessible role of this component
+     *
+     * @see AccessibleRole
+     */
+    public AccessibleRole getAccessibleRole()
+    {
+      return AccessibleRole.TEXT;
+    }
+
+    /**
+     * Retrieve an AccessibleEditableText object that controls this
+     * text component.
+     *
+     * @return this
+     */
+    public AccessibleEditableText getAccessibleEditableText()
+    {
+      return this;
+    }
+
+    /**
+     * Retrieve an AccessibleText object that controls this text
+     * component.
+     *
+     * @return this
+     *
+     * @see AccessibleText
+     */
+    public AccessibleText getAccessibleText()
+    {
+      return this;
+    }
+    
+    /**
+     * Handle a text insertion event and fire an
+     * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
+     * event.
+     *
+     * @param e - the insertion event
+     */
+    public void insertUpdate(DocumentEvent e)
+      throws NotImplementedException
+    {
+      // TODO
+    }
+
+    /**
+     * Handle a text removal event and fire an
+     * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
+     * event.
+     *
+     * @param e - the removal event
+     */
+    public void removeUpdate(DocumentEvent e)
+      throws NotImplementedException
+    {
+      // TODO
+    }
+
+    /**
+     * Handle a text change event and fire an
+     * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
+     * event.
+     *
+     * @param e - text change event
+     */
+    public void changedUpdate(DocumentEvent e)
+      throws NotImplementedException
+    {
+      // TODO
+    }
+
+    /**
+     * Get the index of the character at the given point, in component
+     * pixel co-ordinates.  If the point argument is invalid this
+     * method returns -1.
+     *
+     * @param p - a point in component pixel co-ordinates
+     *
+     * @return a character index, or -1
+     */
+    public int getIndexAtPoint(Point p)
+      throws NotImplementedException
+    {
+      return 0; // TODO
+    }
+
+    /**
+     * Calculate the bounding box of the character at the given index.
+     * The returned x and y co-ordinates are relative to this text
+     * component's top-left corner.  If the index is invalid this
+     * method returns null.
+     *
+     * @param index - the character index
+     *
+     * @return a character's bounding box, or null
+     */
+    public Rectangle getCharacterBounds(int index)
+      throws NotImplementedException
+    {
+      return null; // TODO
+    }
+
+    /**
+     * Return the length of the text in this text component.
+     *
+     * @return a character length
+     */
+    public int getCharCount()
+    {
+      return textComp.getText().length();
+    }
+
+   /** 
+    * Gets the character attributes of the character at index. If
+    * the index is out of bounds, null is returned.
+    *
+    * @param index - index of the character
+    * 
+    * @return the character's attributes
+    */
+    public AttributeSet getCharacterAttribute(int index)
+      throws NotImplementedException
+    {
+      return null; // TODO
+    }
+
+    /**
+     * Gets the text located at index. null is returned if the index
+     * or part is invalid.
+     * 
+     * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
+     * @param index - index of the part
+     * 
+     * @return the part of text at that index, or null
+     */
+    public String getAtIndex(int part, int index)
+      throws NotImplementedException
+    {
+      return null; // TODO
+    }
+    
+    /**
+     * Gets the text located after index. null is returned if the index
+     * or part is invalid.
+     * 
+     * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
+     * @param index - index after the part
+     * 
+     * @return the part of text after that index, or null
+     */
+    public String getAfterIndex(int part, int index)
+      throws NotImplementedException
+    {
+      return null; // TODO
+    }
+
+    /**
+     * Gets the text located before index. null is returned if the index
+     * or part is invalid.
+     * 
+     * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
+     * @param index - index before the part
+     * 
+     * @return the part of text before that index, or null
+     */
+    public String getBeforeIndex(int part, int index)
+      throws NotImplementedException
+    {
+      return null; // TODO
+    }
+    
+    /**
+     * Returns the number of actions for this object. The zero-th
+     * object represents the default action.
+     * 
+     * @return the number of actions (0-based).
+     */
+    public int getAccessibleActionCount()
+      throws NotImplementedException
+    {
+      return 0; // TODO
+    }
+    
+    /**
+     * Returns the description of the i-th action. Null is returned if
+     * i is out of bounds.
+     * 
+     * @param i - the action to get the description for
+     * 
+     * @return description of the i-th action
+     */
+    public String getAccessibleActionDescription(int i)
+      throws NotImplementedException
+    {
+      // TODO: Not implemented fully
+      return super.getAccessibleDescription();
+    }
+    
+    /**
+     * Performs the i-th action. Nothing happens if i is 
+     * out of bounds.
+     *
+     * @param i - the action to perform
+     * 
+     * @return true if the action was performed successfully
+     */
+    public boolean doAccessibleAction(int i)
+      throws NotImplementedException
+    {
+      return false; // TODO
+    }
+    
+    /**
+     * Sets the text contents.
+     *
+     * @param s - the new text contents.
+     */
+    public void setTextContents(String s)
+      throws NotImplementedException
+    {
+      // TODO
+    }
+
+    /**
+     * Inserts the text at the given index.
+     *
+     * @param index - the index to insert the new text at.
+     * @param s - the new text
+     */
+    public void insertTextAtIndex(int index, String s)
+      throws NotImplementedException
+    {
+      replaceText(index, index, s);
+    }
+
+    /**
+     * Gets the text between two indexes.
+     *
+     * @param start - the starting index (inclusive)
+     * @param end - the ending index (exclusive)
+     */
+    public String getTextRange(int start, int end)
+    {
+      try
+      {
+        return textComp.getText(start, end - start);
+      }
+      catch (BadLocationException ble)
+      {
+        return "";
+      }
+    }
+
+    /**
+     * Deletes the text between two indexes.
+     *
+     * @param start - the starting index (inclusive)
+     * @param end - the ending index (exclusive)
+     */
+    public void delete(int start, int end)
+    {
+      replaceText(start, end, "");
+    }
+
+    /**
+     * Cuts the text between two indexes. The text is put
+     * into the system clipboard.
+     *
+     * @param start - the starting index (inclusive)
+     * @param end - the ending index (exclusive)
+     */
+    public void cut(int start, int end)
+    {
+      textComp.select(start, end);
+      textComp.cut();
+    }
+
+    /**
+     * Pastes the text from the system clipboard to the given index.
+     *
+     * @param start - the starting index
+     */
+    public void paste(int start)
+    {
+      textComp.setCaretPosition(start);
+      textComp.paste();
+    }
+
+    /**
+     * Replaces the text between two indexes with the given text.
+     *
+     *
+     * @param start - the starting index (inclusive)
+     * @param end - the ending index (exclusive)
+     * @param s - the text to paste
+     */
+    public void replaceText(int start, int end, String s)
+    {
+      textComp.select(start, end);
+      textComp.replaceSelection(s);
+    }
+
+    /**
+     * Selects the text between two indexes.
+     *
+     * @param start - the starting index (inclusive)
+     * @param end - the ending index (exclusive)
+     */
+    public void selectText(int start, int end)
+    {
+      textComp.select(start, end);
+    }
+
+    /**
+     * Sets the attributes of all the text between two indexes.
+     *
+     * @param start - the starting index (inclusive)
+     * @param end - the ending index (exclusive)
+     * @param s - the new attribute set for the text in the range
+     */
+    public void setAttributes(int start, int end, AttributeSet s)
+      throws NotImplementedException
+    {
+      // TODO
+    }
+  }
+
+  public static class KeyBinding
+  {
+    public KeyStroke key;
+    public String actionName;
+
+    /**
+     * Creates a new <code>KeyBinding</code> instance.
+     *
+     * @param key a <code>KeyStroke</code> value
+     * @param actionName a <code>String</code> value
+     */
+    public KeyBinding(KeyStroke key, String actionName)
+    {
+      this.key = key;
+      this.actionName = actionName;
+    }
+  }
+
+  /**
+   * According to <a
+   * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this
+   * report</a>, a pair of private classes wraps a {@link
+   * javax.swing.text.Keymap} in the new {@link InputMap} / {@link
+   * ActionMap} interfaces, such that old Keymap-using code can make use of
+   * the new framework.
+   *
+   * <p>A little bit of experimentation with these classes reveals the following
+   * structure:
+   *
+   * <ul>
+   *
+   * <li>KeymapWrapper extends {@link InputMap} and holds a reference to
+   * the underlying {@link Keymap}.</li>
+   *
+   * <li>KeymapWrapper maps {@link KeyStroke} objects to {@link Action}
+   * objects, by delegation to the underlying {@link Keymap}.</li>
+   *
+   * <li>KeymapActionMap extends {@link ActionMap} also holds a reference to
+   * the underlying {@link Keymap} but only appears to use it for listing 
+   * its keys. </li>
+   *
+   * <li>KeymapActionMap maps all {@link Action} objects to
+   * <em>themselves</em>, whether they exist in the underlying {@link
+   * Keymap} or not, and passes other objects to the parent {@link
+   * ActionMap} for resolving.
+   *
+   * </ul>
+   */
+
+  private class KeymapWrapper extends InputMap
+  {
+    Keymap map;
+
+    public KeymapWrapper(Keymap k)
+    {
+      map = k;
+    }
+
+    public int size()
+    {
+      return map.getBoundKeyStrokes().length + super.size();
+    }
+
+    public Object get(KeyStroke ks)
+    {
+      Action mapped = null;
+      Keymap m = map;
+      while(mapped == null && m != null)
+        {
+          mapped = m.getAction(ks);
+          if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED)
+            mapped = m.getDefaultAction();
+          if (mapped == null)
+            m = m.getResolveParent();
+        }
+
+      if (mapped == null)
+        return super.get(ks);
+      else
+        return mapped;
+    }
+
+    public KeyStroke[] keys()
+    {
+      KeyStroke[] superKeys = super.keys();
+      KeyStroke[] mapKeys = map.getBoundKeyStrokes(); 
+      KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length];
+      for (int i = 0; i < superKeys.length; ++i)
+        bothKeys[i] = superKeys[i];
+      for (int i = 0; i < mapKeys.length; ++i)
+        bothKeys[i + superKeys.length] = mapKeys[i];
+      return bothKeys;
+    }
+
+    public KeyStroke[] allKeys()
+    {
+      KeyStroke[] superKeys = super.allKeys();
+      KeyStroke[] mapKeys = map.getBoundKeyStrokes();
+      int skl = 0;
+      int mkl = 0;
+      if (superKeys != null)
+        skl = superKeys.length;
+      if (mapKeys != null)
+        mkl = mapKeys.length;
+      KeyStroke[] bothKeys = new KeyStroke[skl + mkl];
+      for (int i = 0; i < skl; ++i)
+        bothKeys[i] = superKeys[i];
+      for (int i = 0; i < mkl; ++i)
+        bothKeys[i + skl] = mapKeys[i];
+      return bothKeys;
+    }
+  }
+
+  private class KeymapActionMap extends ActionMap
+  {
+    Keymap map;
+
+    public KeymapActionMap(Keymap k)
+    {
+      map = k;
+    }
+
+    public Action get(Object cmd)
+    {
+      if (cmd instanceof Action)
+        return (Action) cmd;
+      else
+        return super.get(cmd);
+    }
+
+    public int size()
+    {
+      return map.getBoundKeyStrokes().length + super.size();
+    }
+
+    public Object[] keys() 
+    {
+      Object[] superKeys = super.keys();
+      Object[] mapKeys = map.getBoundKeyStrokes(); 
+      Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
+      for (int i = 0; i < superKeys.length; ++i)
+        bothKeys[i] = superKeys[i];
+      for (int i = 0; i < mapKeys.length; ++i)
+        bothKeys[i + superKeys.length] = mapKeys[i];
+      return bothKeys;      
+    }
+
+    public Object[] allKeys()
+    {
+      Object[] superKeys = super.allKeys();
+      Object[] mapKeys = map.getBoundKeyStrokes(); 
+      Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
+      for (int i = 0; i < superKeys.length; ++i)
+        bothKeys[i] = superKeys[i];
+      for (int i = 0; i < mapKeys.length; ++i)
+        bothKeys[i + superKeys.length] = mapKeys[i];
+      return bothKeys;
+    }
+
+  }
+
+  static class DefaultKeymap implements Keymap
+  {
+    String name;
+    Keymap parent;
+    Hashtable map;
+    Action defaultAction;
+
+    public DefaultKeymap(String name)
+    {
+      this.name = name;
+      this.map = new Hashtable();
+    }
+
+    public void addActionForKeyStroke(KeyStroke key, Action a)
+    {
+      map.put(key, a);
+    }
+
+    /**
+     * Looks up a KeyStroke either in the current map or the parent Keymap;
+     * does <em>not</em> return the default action if lookup fails.
+     *
+     * @param key The KeyStroke to look up an Action for.
+     *
+     * @return The mapping for <code>key</code>, or <code>null</code>
+     * if no mapping exists in this Keymap or any of its parents.
+     */
+    public Action getAction(KeyStroke key)
+    {
+      if (map.containsKey(key))
+        return (Action) map.get(key);
+      else if (parent != null)
+        return parent.getAction(key);
+      else
+        return null;
+    }
+
+    public Action[] getBoundActions()
+    {
+      Action [] ret = new Action[map.size()];
+      Enumeration e = map.elements();
+      int i = 0;
+      while (e.hasMoreElements())
+        {
+          ret[i++] = (Action) e.nextElement();
+        }
+      return ret;
+    }
+
+    public KeyStroke[] getBoundKeyStrokes()
+    {
+      KeyStroke [] ret = new KeyStroke[map.size()];
+      Enumeration e = map.keys();
+      int i = 0;
+      while (e.hasMoreElements())
+        {
+          ret[i++] = (KeyStroke) e.nextElement();
+        }
+      return ret;
+    }
+
+    public Action getDefaultAction()
+    {
+      return defaultAction;
+    }
+
+    public KeyStroke[] getKeyStrokesForAction(Action a)
+    {
+      int i = 0;
+      Enumeration e = map.keys();
+      while (e.hasMoreElements())
+        {
+          if (map.get(e.nextElement()).equals(a))
+            ++i;
+        }
+      KeyStroke [] ret = new KeyStroke[i];
+      i = 0;
+      e = map.keys();
+      while (e.hasMoreElements())
+        {          
+          KeyStroke k = (KeyStroke) e.nextElement();
+          if (map.get(k).equals(a))
+            ret[i++] = k;            
+        }
+      return ret;
+    }
+
+    public String getName()
+    {
+      return name;
+    }
+
+    public Keymap getResolveParent()
+    {
+      return parent;
+    }
+
+    public boolean isLocallyDefined(KeyStroke key)
+    {
+      return map.containsKey(key);
+    }
+
+    public void removeBindings()
+    {
+      map.clear();
+    }
+
+    public void removeKeyStrokeBinding(KeyStroke key)
+    {
+      map.remove(key);
+    }
+
+    public void setDefaultAction(Action a)
+    {
+      defaultAction = a;
+    }
+
+    public void setResolveParent(Keymap p)
+    {
+      parent = p;
+    }
+  }
+
+  class DefaultTransferHandler extends TransferHandler
+  {
+    public boolean canImport(JComponent component, DataFlavor[] flavors)
+    {
+      JTextComponent textComponent = (JTextComponent) component;
+      
+      if (! (textComponent.isEnabled()
+	     && textComponent.isEditable()
+	     && flavors != null))
+        return false;
+
+      for (int i = 0; i < flavors.length; ++i)
+	if (flavors[i].equals(DataFlavor.stringFlavor))
+	   return true;
+
+      return false;
+    }
+    
+    public void exportToClipboard(JComponent component, Clipboard clipboard,
+				  int action)
+    {
+      JTextComponent textComponent = (JTextComponent) component;
+      int start = textComponent.getSelectionStart();
+      int end = textComponent.getSelectionEnd();
+
+      if (start == end)
+        return;
+
+      try
+        {
+          // Copy text to clipboard.
+          String data = textComponent.getDocument().getText(start, end);
+          StringSelection selection = new StringSelection(data);
+          clipboard.setContents(selection, null);
+
+          // Delete selected text on cut action.
+          if (action == MOVE)
+            doc.remove(start, end - start);
+        }
+      catch (BadLocationException e)
+        {
+          // Ignore this and do nothing.
+        }
+    }
+    
+    public int getSourceActions()
+    {
+      return NONE;
+    }
+
+    public boolean importData(JComponent component, Transferable transferable)
+    {
+      DataFlavor flavor = null;
+      DataFlavor[] flavors = transferable.getTransferDataFlavors();
+
+      if (flavors == null)
+        return false;
+
+      for (int i = 0; i < flavors.length; ++i)
+        if (flavors[i].equals(DataFlavor.stringFlavor))
+          flavor = flavors[i];
+      
+      if (flavor == null)
+        return false;
+
+      try
+        {
+          JTextComponent textComponent = (JTextComponent) component;
+          String data = (String) transferable.getTransferData(flavor);
+          textComponent.replaceSelection(data);
+          return true;
+        }
+      catch (IOException e)
+        {
+          // Ignored.
+        }
+      catch (UnsupportedFlavorException e)
+        {
+          // Ignored.
+        }
+
+      return false;
+    }
+  }
+
+  private static final long serialVersionUID = -8796518220218978795L;
+  
+  public static final String DEFAULT_KEYMAP = "default";
+  public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey";
+  
+  private static DefaultTransferHandler defaultTransferHandler;
+  private static Hashtable keymaps = new Hashtable();
+  private Keymap keymap;
+  private char focusAccelerator = '\0';
+  private NavigationFilter navigationFilter;
+
+  /**
+   * Get a Keymap from the global keymap table, by name.
+   *
+   * @param n The name of the Keymap to look up
+   *
+   * @return A Keymap associated with the provided name, or
+   * <code>null</code> if no such Keymap exists
+   *
+   * @see #addKeymap
+   * @see #removeKeymap
+   * @see #keymaps
+   */
+  public static Keymap getKeymap(String n)
+  {
+    return (Keymap) keymaps.get(n);
+  }
+
+  /**
+   * Remove a Keymap from the global Keymap table, by name.
+   *
+   * @param n The name of the Keymap to remove
+   *
+   * @return The keymap removed from the global table
+   *
+   * @see #addKeymap
+   * @see #getKeymap()
+   * @see #keymaps
+   */  
+  public static Keymap removeKeymap(String n)
+  {
+    Keymap km = (Keymap) keymaps.get(n);
+    keymaps.remove(n);
+    return km;
+  }
+
+  /**
+   * Create a new Keymap with a specific name and parent, and add the new
+   * Keymap to the global keymap table. The name may be <code>null</code>,
+   * in which case the new Keymap will <em>not</em> be added to the global
+   * Keymap table. The parent may also be <code>null</code>, which is
+   * harmless.
+   * 
+   * @param n The name of the new Keymap, or <code>null</code>
+   * @param parent The parent of the new Keymap, or <code>null</code>
+   *
+   * @return The newly created Keymap
+   *
+   * @see #removeKeymap
+   * @see #getKeymap()
+   * @see #keymaps
+   */
+  public static Keymap addKeymap(String n, Keymap parent)
+  {
+    Keymap k = new DefaultKeymap(n);
+    k.setResolveParent(parent);
+    if (n != null)
+      keymaps.put(n, k);
+    return k;
+  }
+
+  /**
+   * Get the current Keymap of this component.
+   *
+   * @return The component's current Keymap
+   *
+   * @see #setKeymap
+   * @see #keymap
+   */
+  public Keymap getKeymap() 
+  {
+    return keymap;
+  }
+
+  /**
+   * Set the current Keymap of this component, installing appropriate
+   * {@link KeymapWrapper} and {@link KeymapActionMap} objects in the
+   * {@link InputMap} and {@link ActionMap} parent chains, respectively,
+   * and fire a property change event with name <code>"keymap"</code>.
+   *
+   * @see #getKeymap()
+   * @see #keymap
+   */
+  public void setKeymap(Keymap k) 
+  {
+
+    // phase 1: replace the KeymapWrapper entry in the InputMap chain.
+    // the goal here is to always maintain the following ordering:
+    //
+    //   [InputMap]? -> [KeymapWrapper]? -> [InputMapUIResource]*
+    // 
+    // that is to say, component-specific InputMaps need to remain children
+    // of Keymaps, and Keymaps need to remain children of UI-installed
+    // InputMaps (and the order of each group needs to be preserved, of
+    // course).
+    
+    KeymapWrapper kw = (k == null ? null : new KeymapWrapper(k));
+    InputMap childInputMap = getInputMap(JComponent.WHEN_FOCUSED);
+    if (childInputMap == null)
+      setInputMap(JComponent.WHEN_FOCUSED, kw);
+    else
+      {
+        while (childInputMap.getParent() != null 
+               && !(childInputMap.getParent() instanceof KeymapWrapper)
+               && !(childInputMap.getParent() instanceof InputMapUIResource))
+          childInputMap = childInputMap.getParent();
+
+        // option 1: there is nobody to replace at the end of the chain
+        if (childInputMap.getParent() == null)
+          childInputMap.setParent(kw);
+        
+        // option 2: there is already a KeymapWrapper in the chain which
+        // needs replacing (possibly with its own parents, possibly without)
+        else if (childInputMap.getParent() instanceof KeymapWrapper)
+          {
+            if (kw == null)
+              childInputMap.setParent(childInputMap.getParent().getParent());
+            else
+              {
+                kw.setParent(childInputMap.getParent().getParent());
+                childInputMap.setParent(kw);
+              }
+          }
+
+        // option 3: there is an InputMapUIResource in the chain, which marks
+        // the place where we need to stop and insert ourselves
+        else if (childInputMap.getParent() instanceof InputMapUIResource)
+          {
+            if (kw != null)
+              {
+                kw.setParent(childInputMap.getParent());
+                childInputMap.setParent(kw);
+              }
+          }
+      }
+
+    // phase 2: replace the KeymapActionMap entry in the ActionMap chain
+
+    KeymapActionMap kam = (k == null ? null : new KeymapActionMap(k));
+    ActionMap childActionMap = getActionMap();
+    if (childActionMap == null)
+      setActionMap(kam);
+    else
+      {
+        while (childActionMap.getParent() != null 
+               && !(childActionMap.getParent() instanceof KeymapActionMap)
+               && !(childActionMap.getParent() instanceof ActionMapUIResource))
+          childActionMap = childActionMap.getParent();
+
+        // option 1: there is nobody to replace at the end of the chain
+        if (childActionMap.getParent() == null)
+          childActionMap.setParent(kam);
+        
+        // option 2: there is already a KeymapActionMap in the chain which
+        // needs replacing (possibly with its own parents, possibly without)
+        else if (childActionMap.getParent() instanceof KeymapActionMap)
+          {
+            if (kam == null)
+              childActionMap.setParent(childActionMap.getParent().getParent());
+            else
+              {
+                kam.setParent(childActionMap.getParent().getParent());
+                childActionMap.setParent(kam);
+              }
+          }
+
+        // option 3: there is an ActionMapUIResource in the chain, which marks
+        // the place where we need to stop and insert ourselves
+        else if (childActionMap.getParent() instanceof ActionMapUIResource)
+          {
+            if (kam != null)
+              {
+                kam.setParent(childActionMap.getParent());
+                childActionMap.setParent(kam);
+              }
+          }
+      }
+
+    // phase 3: update the explicit keymap field
+
+    Keymap old = keymap;
+    keymap = k;
+    firePropertyChange("keymap", old, k);
+  }
+
+  /**
+   * Resolves a set of bindings against a set of actions and inserts the
+   * results into a {@link Keymap}. Specifically, for each provided binding
+   * <code>b</code>, if there exists a provided action <code>a</code> such
+   * that <code>a.getValue(Action.NAME) == b.ActionName</code> then an
+   * entry is added to the Keymap mapping <code>b</code> to
+   * <code>a</code>.
+   *
+   * @param map The Keymap to add new mappings to
+   * @param bindings The set of bindings to add to the Keymap
+   * @param actions The set of actions to resolve binding names against
+   *
+   * @see Action#NAME
+   * @see Action#getValue
+   * @see KeyBinding#actionName
+   */
+  public static void loadKeymap(Keymap map, 
+                                JTextComponent.KeyBinding[] bindings, 
+                                Action[] actions)
+  {
+    Hashtable acts = new Hashtable(actions.length);
+    for (int i = 0; i < actions.length; ++i)
+      acts.put(actions[i].getValue(Action.NAME), actions[i]);
+      for (int i = 0; i < bindings.length; ++i)
+      if (acts.containsKey(bindings[i].actionName))
+        map.addActionForKeyStroke(bindings[i].key, (Action) acts.get(bindings[i].actionName));
+  }
+
+  /**
+   * Returns the set of available Actions this component's associated
+   * editor can run.  Equivalent to calling
+   * <code>getUI().getEditorKit().getActions()</code>. This set of Actions
+   * is a reasonable value to provide as a parameter to {@link
+   * #loadKeymap}, when resolving a set of {@link KeyBinding} objects
+   * against this component.
+   *
+   * @return The set of available Actions on this component's {@link EditorKit}
+   *
+   * @see TextUI#getEditorKit
+   * @see EditorKit#getActions()
+   */
+  public Action[] getActions()
+  {
+    return getUI().getEditorKit(this).getActions();
+  }
+    
+  // These are package-private to avoid an accessor method.
+  Document doc;
+  Caret caret;
+  boolean editable;
+  
+  private Highlighter highlighter;
+  private Color caretColor;
+  private Color disabledTextColor;
+  private Color selectedTextColor;
+  private Color selectionColor;
+  private Insets margin;
+  private boolean dragEnabled;
+
+  /**
+   * Creates a new <code>JTextComponent</code> instance.
+   */
+  public JTextComponent()
+  {
+    Keymap defkeymap = getKeymap(DEFAULT_KEYMAP);
+    if (defkeymap == null)
+      {
+        defkeymap = addKeymap(DEFAULT_KEYMAP, null);
+        defkeymap.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction());
+      }
+
+    setFocusable(true);
+    setEditable(true);
+    enableEvents(AWTEvent.KEY_EVENT_MASK);
+    setOpaque(true);
+    updateUI();
+  }
+
+  public void setDocument(Document newDoc)
+  {
+    Document oldDoc = doc;
+    try
+      {
+        if (oldDoc instanceof AbstractDocument)
+          ((AbstractDocument) oldDoc).readLock();
+
+        doc = newDoc;
+        firePropertyChange("document", oldDoc, newDoc);
+      }
+    finally
+      {
+        if (oldDoc instanceof AbstractDocument)
+          ((AbstractDocument) oldDoc).readUnlock();
+      }
+    revalidate();
+    repaint();
+  }
+
+  public Document getDocument()
+  {
+    return doc;
+  }
+
+  /**
+   * Get the <code>AccessibleContext</code> of this object.
+   *
+   * @return an <code>AccessibleContext</code> object
+   */
+  public AccessibleContext getAccessibleContext()
+  {
+    return new AccessibleJTextComponent();
+  }
+
+  public void setMargin(Insets m)
+  {
+    margin = m;
+  }
+
+  public Insets getMargin()
+  {
+    return margin;
+  }
+
+  public void setText(String text)
+  {
+    try
+      {
+        if (doc instanceof AbstractDocument)
+          ((AbstractDocument) doc).replace(0, doc.getLength(), text, null);
+        else
+          {
+            doc.remove(0, doc.getLength());
+            doc.insertString(0, text, null);
+          }
+      }
+    catch (BadLocationException e)
+      {
+        // This can never happen.
+        throw (InternalError) new InternalError().initCause(e);
+      }
+  }
+
+  /**
+   * Retrieves the current text in this text document.
+   *
+   * @return the text
+   *
+   * @exception NullPointerException if the underlaying document is null
+   */
+  public String getText()
+  {
+    if (doc == null)
+      return null;
+
+    try
+      {
+        return doc.getText(0, doc.getLength());
+      }
+    catch (BadLocationException e)
+      {
+        // This should never happen.
+        return "";
+      }
+  }
+
+  /**
+   * Retrieves a part of the current text in this document.
+   *
+   * @param offset the postion of the first character
+   * @param length the length of the text to retrieve
+   *
+   * @return the text
+   *
+   * @exception BadLocationException if arguments do not hold pre-conditions
+   */
+  public String getText(int offset, int length)
+    throws BadLocationException
+  {
+    return getDocument().getText(offset, length);
+  }
+
+  /**
+   * Retrieves the currently selected text in this text document.
+   *
+   * @return the selected text
+   *
+   * @exception NullPointerException if the underlaying document is null
+   */
+  public String getSelectedText()
+  {
+    int start = getSelectionStart();
+    int offset = getSelectionEnd() - start;
+    
+    if (offset <= 0)
+      return null;
+    
+    try
+      {
+        return doc.getText(start, offset);
+      }
+    catch (BadLocationException e)
+      {
+        // This should never happen.
+        return null;
+      }
+  }
+
+  /**
+   * Returns a string that specifies the name of the Look and Feel class
+   * that renders this component.
+   *
+   * @return the string "TextComponentUI"
+   */
+  public String getUIClassID()
+  {
+    return "TextComponentUI";
+  }
+
+  /**
+   * Returns a string representation of this JTextComponent.
+   */
+  protected String paramString()
+  {
+    // TODO: Do something useful here.
+    return super.paramString();
+  }
+
+  /**
+   * This method returns the label's UI delegate.
+   *
+   * @return The label's UI delegate.
+   */
+  public TextUI getUI()
+  {
+    return (TextUI) ui;
+  }
+
+  /**
+   * This method sets the label's UI delegate.
+   *
+   * @param newUI The label's UI delegate.
+   */
+  public void setUI(TextUI newUI)
+  {
+    super.setUI(newUI);
+  }
+
+  /**
+   * This method resets the label's UI delegate to the default UI for the
+   * current look and feel.
+   */
+  public void updateUI()
+  {
+    setUI((TextUI) UIManager.getUI(this));
+  }
+
+  public Dimension getPreferredScrollableViewportSize()
+  {
+    return getPreferredSize();
+  }
+
+  public int getScrollableUnitIncrement(Rectangle visible, int orientation,
+                                        int direction)
+  {
+    // We return 1/10 of the visible area as documented in Sun's API docs.
+    if (orientation == SwingConstants.HORIZONTAL)
+      return visible.width / 10;
+    else if (orientation == SwingConstants.VERTICAL)
+      return visible.height / 10;
+    else
+      throw new IllegalArgumentException("orientation must be either "
+                                      + "javax.swing.SwingConstants.VERTICAL "
+                                      + "or "
+                                      + "javax.swing.SwingConstants.HORIZONTAL"
+                                         );
+  }
+
+  public int getScrollableBlockIncrement(Rectangle visible, int orientation,
+                                         int direction)
+  {
+    // We return the whole visible area as documented in Sun's API docs.
+    if (orientation == SwingConstants.HORIZONTAL)
+      return visible.width;
+    else if (orientation == SwingConstants.VERTICAL)
+      return visible.height;
+    else
+      throw new IllegalArgumentException("orientation must be either "
+                                      + "javax.swing.SwingConstants.VERTICAL "
+                                      + "or "
+                                      + "javax.swing.SwingConstants.HORIZONTAL"
+                                         );
+  }
+
+  /**
+   * Checks whether this text component it editable.
+   *
+   * @return true if editable, false otherwise
+   */
+  public boolean isEditable()
+  {
+    return editable;
+  }
+
+  /**
+   * Enables/disabled this text component's editability.
+   *
+   * @param newValue true to make it editable, false otherwise.
+   */
+  public void setEditable(boolean newValue)
+  {
+    if (editable == newValue)
+      return;
+    
+    boolean oldValue = editable;
+    editable = newValue;
+    firePropertyChange("editable", oldValue, newValue);
+  }
+
+  /**
+   * The <code>Caret</code> object used in this text component.
+   *
+   * @return the caret object
+   */
+  public Caret getCaret()
+  {
+    return caret;
+  }
+
+  /**
+   * Sets a new <code>Caret</code> for this text component.
+   *
+   * @param newCaret the new <code>Caret</code> to set
+   */
+  public void setCaret(Caret newCaret)
+  {
+    if (caret != null)
+      caret.deinstall(this);
+    
+    Caret oldCaret = caret;
+    caret = newCaret;
+
+    if (caret != null)
+      caret.install(this);
+    
+    firePropertyChange("caret", oldCaret, newCaret);
+  }
+
+  public Color getCaretColor()
+  {
+    return caretColor;
+  }
+
+  public void setCaretColor(Color newColor)
+  {
+    Color oldCaretColor = caretColor;
+    caretColor = newColor;
+    firePropertyChange("caretColor", oldCaretColor, newColor);
+  }
+
+  public Color getDisabledTextColor()
+  {
+    return disabledTextColor;
+  }
+
+  public void setDisabledTextColor(Color newColor)
+  {
+    Color oldColor = disabledTextColor;
+    disabledTextColor = newColor;
+    firePropertyChange("disabledTextColor", oldColor, newColor);
+  }
+
+  public Color getSelectedTextColor()
+  {
+    return selectedTextColor;
+  }
+
+  public void setSelectedTextColor(Color newColor)
+  {
+    Color oldColor = selectedTextColor;
+    selectedTextColor = newColor;
+    firePropertyChange("selectedTextColor", oldColor, newColor);
+  }
+
+  public Color getSelectionColor()
+  {
+    return selectionColor;
+  }
+
+  public void setSelectionColor(Color newColor)
+  {
+    Color oldColor = selectionColor;
+    selectionColor = newColor;
+    firePropertyChange("selectionColor", oldColor, newColor);
+  }
+
+  /**
+   * Retrisves the current caret position.
+   *
+   * @return the current position
+   */
+  public int getCaretPosition()
+  {
+    return caret.getDot();
+  }
+
+  /**
+   * Sets the caret to a new position.
+   *
+   * @param position the new position
+   */
+  public void setCaretPosition(int position)
+  {
+    if (doc == null)
+      return;
+
+    if (position < 0 || position > doc.getLength())
+      throw new IllegalArgumentException();
+
+    caret.setDot(position);
+  }
+
+  /**
+   * Moves the caret to a given position. This selects the text between
+   * the old and the new position of the caret.
+   */
+  public void moveCaretPosition(int position)
+  {
+    if (doc == null)
+      return;
+
+    if (position < 0 || position > doc.getLength())
+      throw new IllegalArgumentException();
+
+    caret.moveDot(position);
+  }
+
+  public Highlighter getHighlighter()
+  {
+    return highlighter;
+  }
+
+  public void setHighlighter(Highlighter newHighlighter)
+  {
+    if (highlighter != null)
+      highlighter.deinstall(this);
+    
+    Highlighter oldHighlighter = highlighter;
+    highlighter = newHighlighter;
+
+    if (highlighter != null)
+      highlighter.install(this);
+    
+    firePropertyChange("highlighter", oldHighlighter, newHighlighter);
+  }
+
+  /**
+   * Returns the start postion of the currently selected text.
+   *
+   * @return the start postion
+   */
+  public int getSelectionStart()
+  {
+    return Math.min(caret.getDot(), caret.getMark());
+  }
+
+  /**
+   * Selects the text from the given postion to the selection end position.
+   *
+   * @param start the start positon of the selected text.
+   */
+  public void setSelectionStart(int start)
+  {
+    select(start, getSelectionEnd());
+  }
+
+  /**
+   * Returns the end postion of the currently selected text.
+   *
+   * @return the end postion
+   */
+  public int getSelectionEnd()
+  {
+    return Math.max(caret.getDot(), caret.getMark());
+  }
+
+  /**
+   * Selects the text from the selection start postion to the given position.
+   *
+   * @param end the end positon of the selected text.
+   */
+  public void setSelectionEnd(int end)
+  {
+    select(getSelectionStart(), end);
+  }
+
+  /**
+   * Selects a part of the content of the text component.
+   *
+   * @param start the start position of the selected text
+   * @param end the end position of the selected text
+   */
+  public void select(int start, int end)
+  {
+    int length = doc.getLength();
+    
+    start = Math.max(start, 0);
+    start = Math.min(start, length);
+
+    end = Math.max(end, start);
+    end = Math.min(end, length);
+
+    setCaretPosition(start);
+    moveCaretPosition(end);
+  }
+
+  /**
+   * Selects the whole content of the text component.
+   */
+  public void selectAll()
+  {
+    select(0, doc.getLength());
+  }
+
+  public synchronized void replaceSelection(String content)
+  {
+    int dot = caret.getDot();
+    int mark = caret.getMark();
+
+    // If content is empty delete selection.
+    if (content == null)
+      {
+        caret.setDot(dot);
+        return;
+      }
+
+    try
+      {
+        int start = getSelectionStart();
+        int end = getSelectionEnd();
+
+        // Remove selected text.
+        if (dot != mark)
+          doc.remove(start, end - start);
+
+        // Insert new text.
+        doc.insertString(start, content, null);
+
+        // Set dot to new position,
+        dot = start + content.length();
+        setCaretPosition(dot);
+        
+        // and update it's magic position.
+        caret.setMagicCaretPosition(modelToView(dot).getLocation());
+      }
+    catch (BadLocationException e)
+      {
+        // This should never happen.
+      }
+  }
+
+  public boolean getScrollableTracksViewportHeight()
+  {
+    if (getParent() instanceof JViewport)
+      return getParent().getHeight() > getPreferredSize().height;
+
+    return false;
+  }
+
+  public boolean getScrollableTracksViewportWidth()
+  {
+    boolean res = false;;
+    Container c = getParent();
+    if (c instanceof JViewport)
+      res = ((JViewport) c).getExtentSize().width > getPreferredSize().width;
+
+    return res;
+  }
+
+  /**
+   * Adds a <code>CaretListener</code> object to this text component.
+   *
+   * @param listener the listener to add
+   */
+  public void addCaretListener(CaretListener listener)
+  {
+    listenerList.add(CaretListener.class, listener);
+  }
+
+  /**
+   * Removed a <code>CaretListener</code> object from this text component.
+   *
+   * @param listener the listener to remove
+   */
+  public void removeCaretListener(CaretListener listener)
+  {
+    listenerList.remove(CaretListener.class, listener);
+  }
+
+  /**
+   * Returns all added <code>CaretListener</code> objects.
+   *
+   * @return an array of listeners
+   */
+  public CaretListener[] getCaretListeners()
+  {
+    return (CaretListener[]) getListeners(CaretListener.class);
+  }
+
+  /**
+   * Notifies all registered <code>CaretListener</code> objects that the caret
+   * was updated.
+   *
+   * @param event the event to send
+   */
+  protected void fireCaretUpdate(CaretEvent event)
+  {
+    CaretListener[] listeners = getCaretListeners();
+
+    for (int index = 0; index < listeners.length; ++index)
+      listeners[index].caretUpdate(event);
+  }
+
+  /**
+   * Adds an <code>InputListener</code> object to this text component.
+   *
+   * @param listener the listener to add
+   */
+  public void addInputMethodListener(InputMethodListener listener)
+  {
+    listenerList.add(InputMethodListener.class, listener);
+  }
+
+  /**
+   * Removes an <code>InputListener</code> object from this text component.
+   *
+   * @param listener the listener to remove
+   */
+  public void removeInputMethodListener(InputMethodListener listener)
+  {
+    listenerList.remove(InputMethodListener.class, listener);
+  }
+
+  /**
+   * Returns all added <code>InputMethodListener</code> objects.
+   *
+   * @return an array of listeners
+   */
+  public InputMethodListener[] getInputMethodListeners()
+  {
+    return (InputMethodListener[]) getListeners(InputMethodListener.class);
+  }
+
+  public Rectangle modelToView(int position) throws BadLocationException
+  {
+    return getUI().modelToView(this, position);
+  }
+
+  public boolean getDragEnabled()
+  {
+    return dragEnabled;
+  }
+
+  public void setDragEnabled(boolean enabled)
+  {
+    dragEnabled = enabled;
+  }
+
+  public int viewToModel(Point pt)
+  {
+    return getUI().viewToModel(this, pt);
+  }
+
+  public void copy()
+  {
+    if (isEnabled())
+    doTransferAction("copy", TransferHandler.getCopyAction());
+  }
+
+  public void cut()
+  {
+    if (editable && isEnabled())
+      doTransferAction("cut", TransferHandler.getCutAction());
+  }
+
+  public void paste()
+  {
+    if (editable && isEnabled())
+      doTransferAction("paste", TransferHandler.getPasteAction());
+  }
+
+  private void doTransferAction(String name, Action action)
+  {
+    // Install default TransferHandler if none set.
+    if (getTransferHandler() == null)
+      {
+        if (defaultTransferHandler == null)
+          defaultTransferHandler = new DefaultTransferHandler();
+
+        setTransferHandler(defaultTransferHandler);
+      }
+
+    // Perform action.
+    ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
+                                        action.getValue(Action.NAME).toString());
+    action.actionPerformed(event);
+  }
+
+  public void setFocusAccelerator(char newKey)
+  {
+    if (focusAccelerator == newKey)
+      return;
+
+    char oldKey = focusAccelerator;
+    focusAccelerator = newKey;
+    firePropertyChange(FOCUS_ACCELERATOR_KEY, oldKey, newKey);
+  }
+  
+  public char getFocusAccelerator()
+  {
+    return focusAccelerator;
+  }
+
+  /**
+   * @since 1.4
+   */
+  public NavigationFilter getNavigationFilter()
+  {
+    return navigationFilter;
+  }
+
+  /**
+   * @since 1.4
+   */
+  public void setNavigationFilter(NavigationFilter filter)
+  {
+    navigationFilter = filter;
+  }
+  
+  /**
+   * Read and set the content this component. If not overridden, the
+   * method reads the component content as a plain text.
+   *
+   * The second parameter of this method describes the input stream. It can
+   * be String, URL, File and so on. If not null, this object is added to
+   * the properties of the associated document under the key
+   * {@link Document#StreamDescriptionProperty}.
+   *
+   * @param input an input stream to read from.
+   * @param streamDescription an object, describing the stream.
+   *
+   * @throws IOException if the reader throws it.
+   *
+   * @see #getDocument()
+   * @see Document#getProperty(Object)
+   */
+  public void read(Reader input, Object streamDescription)
+            throws IOException
+  {
+    if (streamDescription != null)
+      {
+        Document d = getDocument();
+        if (d != null)
+          d.putProperty(Document.StreamDescriptionProperty, streamDescription);
+      }
+
+    StringBuffer b = new StringBuffer();
+    int c;
+
+    // Read till -1 (EOF).
+    while ((c = input.read()) >= 0)
+      b.append((char) c);
+
+    setText(b.toString());
+  }
+
+  /**
+   * Write the content of this component to the given stream. If not
+   * overridden, the method writes the component content as a plain text.
+   *
+   * @param output the writer to write into.
+   *
+   * @throws IOException if the writer throws it.
+   */
+  public void write(Writer output)
+             throws IOException
+  {
+    output.write(getText());
+  }
+
+  /**
+   * Returns the tooltip text for this text component for the given mouse
+   * event. This forwards the call to
+   * {@link TextUI#getToolTipText(JTextComponent, Point)}.
+   *
+   * @param ev the mouse event
+   *
+   * @return the tooltip text for this text component for the given mouse
+   *         event
+   */
+  public String getToolTipText(MouseEvent ev)
+  {
+    return getUI().getToolTipText(this, ev.getPoint());
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,60 @@
+/* Keymap.java -- 
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import javax.swing.Action;
+import javax.swing.KeyStroke;
+
+public interface Keymap
+{
+    void addActionForKeyStroke(KeyStroke key, Action a); 
+    Action getAction(KeyStroke key); 
+    Action[] getBoundActions(); 
+    KeyStroke[] getBoundKeyStrokes(); 
+    Action getDefaultAction(); 
+    KeyStroke[] getKeyStrokesForAction(Action a); 
+    String getName(); 
+    Keymap getResolveParent(); 
+    boolean isLocallyDefined(KeyStroke key); 
+    void removeBindings(); 
+    void removeKeyStrokeBinding(KeyStroke keys); 
+    void setDefaultAction(Action a); 
+    void setResolveParent(Keymap parent);
+}
+
+

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,294 @@
+/* LabelView.java -- A view to render styled text
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Shape;
+
+import javax.swing.event.DocumentEvent;
+
+/**
+ * A {@link GlyphView} that caches the textattributes for most effective
+ * rendering.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+public class LabelView extends GlyphView
+{
+
+  /**
+   * The background color.
+   */
+  Color background;
+
+  /**
+   * The foreground color.
+   */
+  Color foreground;
+
+  /**
+   * The background color.
+   */
+  Font font;
+
+  /**
+   * The strikethrough flag.
+   */
+  boolean strikeThrough;
+
+  /**
+   * The underline flag.
+   */
+  boolean underline;
+
+  /**
+   * The subscript flag.
+   */
+  boolean subscript;
+
+  /**
+   * The superscript flag.
+   */
+  boolean superscript;
+
+  /**
+   * Creates a new <code>GlyphView</code> for the given <code>Element</code>.
+   *
+   * @param element the element that is rendered by this GlyphView
+   */
+  public LabelView(Element element)
+  {
+    super(element);
+    setPropertiesFromAttributes();
+  }
+
+  /**
+   * Loads the properties of this label view from the element's text
+   * attributes. This method is called from the constructor and the
+   * {@link #changedUpdate} method
+   */
+  protected void setPropertiesFromAttributes()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    // We cannot use StyleConstants.getBackground() here, because that returns
+    // BLACK as default (when background == null). What we need is the
+    // background setting of the text component instead, which is what we get
+    // when background == null anyway.
+    background = (Color) atts.getAttribute(StyleConstants.Background);
+    foreground = StyleConstants.getForeground(atts);
+    strikeThrough = StyleConstants.isStrikeThrough(atts);
+    subscript = StyleConstants.isSubscript(atts);
+    superscript = StyleConstants.isSuperscript(atts);
+    underline = StyleConstants.isUnderline(atts);
+
+    // Determine the font.
+    String family = StyleConstants.getFontFamily(atts);
+    int size = StyleConstants.getFontSize(atts);
+    int style = Font.PLAIN;
+    if (StyleConstants.isBold(atts))
+        style |= Font.BOLD;
+    if (StyleConstants.isItalic(atts))
+      style |= Font.ITALIC;
+    font = new Font(family, style, size);
+  }
+
+  /**
+   * Receives notification when text attributes change in the chunk of
+   * text that this view is responsible for. This simply calls
+   * {@link #setPropertiesFromAttributes()}.
+   *
+   * @param e the document event
+   * @param a the allocation of this view
+   * @param vf the view factory to use for creating new views
+   */
+  public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+  {
+    setPropertiesFromAttributes();
+  }
+
+  /**
+   * Returns the background color for the glyphs.
+   *
+   * @return the background color for the glyphs
+   */
+  public Color getBackground()
+  {
+    return background;
+  }
+
+  /**
+   * Sets the background color for the glyphs. A value of <code>null</code>
+   * means the background of the parent view should shine through.
+   *
+   * @param bg the background to set or <code>null</code>
+   *
+   * @since 1.5
+   */
+  protected void setBackground(Color bg)
+  {
+    background = bg;
+  }
+
+  /**
+   * Returns the foreground color for the glyphs.
+   *
+   * @return the foreground color for the glyphs
+   */
+  public Color getForeground()
+  {
+    return foreground;
+  }
+
+  /**
+   * Returns the font for the glyphs.
+   *
+   * @return the font for the glyphs
+   */
+  public Font getFont()
+  {
+    return font;
+  }
+
+  /**
+   * Returns the font metrics of the current font.
+   *
+   * @return the font metrics of the current font
+   *
+   * @deprecated this is not used anymore
+   */
+  protected FontMetrics getFontMetrics()
+  {
+    return getContainer().getGraphics().getFontMetrics(font);
+  }
+
+  /**
+   * Returns <code>true</code> if the glyphs are rendered underlined,
+   * <code>false</code> otherwise.
+   *
+   * @return <code>true</code> if the glyphs are rendered underlined,
+   *         <code>false</code> otherwise
+   */
+  public boolean isUnderline()
+  {
+    return underline;
+  }
+
+  /**
+   * Sets the underline flag.
+   *
+   * @param flag <code>true</code> if the glyphs are rendered underlined,
+   *             <code>false</code> otherwise
+   */
+  protected void setUnderline(boolean flag)
+  {
+    underline = flag;
+  }
+
+  /**
+   * Returns <code>true</code> if the glyphs are rendered as subscript,
+   * <code>false</code> otherwise.
+   *
+   * @return <code>true</code> if the glyphs are rendered as subscript,
+   *         <code>false</code> otherwise
+   */
+  public boolean isSubscript()
+  {
+    return subscript;
+  }
+
+  /**
+   * Sets the subscript flag.
+   *
+   * @param flag <code>true</code> if the glyphs are rendered as subscript,
+   *             <code>false</code> otherwise
+   */
+  protected void setSubscript(boolean flag)
+  {
+    subscript = flag;
+  }
+
+  /**
+   * Returns <code>true</code> if the glyphs are rendered as superscript,
+   * <code>false</code> otherwise.
+   *
+   * @return <code>true</code> if the glyphs are rendered as superscript,
+   *         <code>false</code> otherwise
+   */
+  public boolean isSuperscript()
+  {
+    return superscript;
+  }
+
+  /**
+   * Sets the superscript flag.
+   *
+   * @param flag <code>true</code> if the glyphs are rendered as superscript,
+   *             <code>false</code> otherwise
+   */
+  protected void setSuperscript(boolean flag)
+  {
+    superscript = flag;
+  }
+
+  /**
+   * Returns <code>true</code> if the glyphs are rendered strike-through,
+   * <code>false</code> otherwise.
+   *
+   * @return <code>true</code> if the glyphs are rendered strike-through,
+   *         <code>false</code> otherwise
+   */
+  public boolean isStrikeThrough()
+  {
+    return strikeThrough;
+  }
+
+  /**
+   * Sets the strike-through flag.
+   *
+   * @param flag <code>true</code> if the glyphs are rendered strike-through,
+   *             <code>false</code> otherwise
+   */
+  protected void setStrikeThrough(boolean flag)
+  {
+    strikeThrough = flag;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,57 @@
+/* LayeredHighlighter.java --
+   Copyright (C) 2004  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Shape;
+
+public abstract class LayeredHighlighter
+  implements Highlighter
+{
+  public abstract static class LayerPainter
+    implements Highlighter.HighlightPainter
+  {
+    public abstract Shape paintLayer(Graphics g, int p0, int p1,
+				     Shape viewBounds, JTextComponent editor,
+				     View view);
+  }
+  
+  public abstract void paintLayeredHighlights(Graphics g, int p0, int p1,
+                                              Shape viewBounds,
+                                              JTextComponent editor, View view);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,116 @@
+/* LayoutQueue.java --
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.util.LinkedList;
+
+/**
+ * This is a queue which holds {@link Runnable} objects.  It is
+ * intended for deferring layout operations.
+ */
+public class LayoutQueue
+{
+  // The default layout queue.
+  private static LayoutQueue defaultQueue = new LayoutQueue();
+
+  // The queue of tasks.
+  private LinkedList list = new LinkedList();
+
+  /**
+   * Create a new layout queue.
+   */
+  public LayoutQueue()
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * Add a layout task to the queue.
+   */
+  public void addTask(Runnable task)
+  {
+    synchronized (list)
+      {
+	list.addLast(task);
+	list.notify();
+      }
+  }
+
+  /**
+   * Called by a worker thread to retrieve the next layout task.  This
+   * will block until a new task is available.  This method will
+   * return null if the thread is interrupted while waiting.
+   */
+  protected Runnable waitForWork()
+  {
+    synchronized (list)
+      {
+	while (list.size() == 0)
+	  {
+	    try
+	      {
+		list.wait();
+	      }
+	    catch (InterruptedException _)
+	      {
+		// This seemed like a good idea, but it has not been
+		// tested on the JDK.
+		return null;
+	      }
+	  }
+	return (Runnable) list.removeFirst();
+      }
+  }
+
+  /**
+   * Return the default layout queue.
+   */
+  public static synchronized LayoutQueue getDefaultQueue()
+  {
+    return defaultQueue;
+  }
+
+  /**
+   * Set the default layout queue.
+   */
+  public static synchronized void setDefaultQueue(LayoutQueue q)
+  {
+    defaultQueue = q;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,583 @@
+/* MaskFormatter.java -- 
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.text.ParseException;
+
+import javax.swing.JFormattedTextField;
+
+/**
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ *
+ */
+public class MaskFormatter extends DefaultFormatter
+{
+  // The declaration of the valid mask characters
+  private static final char NUM_CHAR = '#';
+  private static final char ESCAPE_CHAR = '\'';
+  private static final char UPPERCASE_CHAR = 'U';
+  private static final char LOWERCASE_CHAR = 'L';
+  private static final char ALPHANUM_CHAR = 'A';
+  private static final char LETTER_CHAR = '?';
+  private static final char ANYTHING_CHAR = '*';
+  private static final char HEX_CHAR = 'H';
+  
+  /** The mask for this MaskFormatter **/
+  private String mask;
+  
+  /** 
+   * A String made up of the characters that are not valid for input for 
+   * this MaskFormatter. 
+   */
+  private String invalidChars;
+  
+  /** 
+   * A String made up of the characters that are valid for input for 
+   * this MaskFormatter. 
+   */
+  private String validChars;
+  
+  /** A String used in place of missing chracters if the value does not 
+   * completely fill in the spaces in the mask.
+   */
+  private String placeHolder;
+  
+  /** A character used in place of missing characters if the value does 
+   * not completely fill in the spaces in the mask.
+   */
+  private char placeHolderChar = ' ';
+  
+  /**
+   * Whether or not stringToValue should return literal characters in the mask.
+   */
+  private boolean valueContainsLiteralCharacters = true;
+  
+  /** A String used for easy access to valid HEX characters **/
+  private static String hexString = "0123456789abcdefABCDEF";
+  
+  /** An int to hold the length of the mask, accounting for escaped characters **/
+  int maskLength = 0;
+  
+  public MaskFormatter ()
+  {
+    // Override super's default behaviour, in MaskFormatter the default
+    // is not to allow invalid values
+    setAllowsInvalid(false);
+  }
+  
+  /**
+   * Creates a MaskFormatter with the specified mask.
+   * @specnote doesn't actually throw a ParseException although it 
+   * is declared to do so
+   * @param mask
+   * @throws java.text.ParseException
+   */
+  public MaskFormatter (String mask) throws java.text.ParseException
+  {
+    // Override super's default behaviour, in MaskFormatter the default
+    // is not to allow invalid values
+    setAllowsInvalid(false);
+    setMask (mask);
+  }
+  
+  /**
+   * Returns the mask used in this MaskFormatter.
+   * @return the mask used in this MaskFormatter.
+   */
+  public String getMask()
+  {
+    return mask;
+  }
+  
+  /**
+   * Returns a String containing the characters that are not valid for input
+   * for this MaskFormatter.
+   * @return a String containing the invalid characters.
+   */
+  public String getInvalidCharacters()
+  {
+    return invalidChars;
+  }
+  
+  /**
+   * Sets characters that are not valid for input. If
+   * <code>invalidCharacters</code> is non-null then no characters contained
+   * in it will be allowed to be input.
+   * 
+   * @param invalidCharacters the String specifying invalid characters.
+   */
+  public void setInvalidCharacters (String invalidCharacters)
+  {
+    this.invalidChars = invalidCharacters;
+  }
+  
+  /**
+   * Returns a String containing the characters that are valid for input
+   * for this MaskFormatter.
+   * @return a String containing the valid characters.
+   */
+  public String getValidCharacters()
+  {
+    return validChars;
+  }
+  
+  /**
+   * Sets characters that are valid for input. If
+   * <code>validCharacters</code> is non-null then no characters that are
+   * not contained in it will be allowed to be input.
+   * 
+   * @param validCharacters the String specifying valid characters.
+   */
+  public void setValidCharacters (String validCharacters)
+  {
+    this.validChars = validCharacters;
+  }
+
+  /**
+   * Returns the place holder String that is used in place of missing 
+   * characters when the value doesn't completely fill in the spaces
+   * in the mask.
+   * @return the place holder String.
+   */
+  public String getPlaceholder()
+  {
+    return placeHolder;
+  }
+  
+  /**
+   * Sets the string to use if the value does not completely fill in the mask.
+   * If this is null, the place holder character will be used instead.
+   * @param placeholder the String to use if the value doesn't completely 
+   * fill in the mask.
+   */
+  public void setPlaceholder (String placeholder)
+  {
+    this.placeHolder = placeholder;
+  }
+  
+  /**
+   * Returns the character used in place of missing characters when the
+   * value doesn't completely fill the mask.
+   * @return the place holder character
+   */
+  public char getPlaceholderCharacter()
+  {
+    return placeHolderChar;
+  }
+  
+  /**
+   * Sets the char  to use if the value does not completely fill in the mask.
+   * This is only used if the place holder String has not been set or does 
+   * not completely fill in the mask.
+   * @param placeholder the char to use if the value doesn't completely 
+   * fill in the mask.
+   */
+  public void setPlaceholderCharacter (char placeholder)
+  {
+    this.placeHolderChar = placeholder;
+  }
+  
+  /**
+   * Returns true if stringToValue should return the literal 
+   * characters in the mask.
+   * @return true if stringToValue should return the literal 
+   * characters in the mask
+   */
+  public boolean getValueContainsLiteralCharacters()
+  {
+    return valueContainsLiteralCharacters;
+  }
+  
+  /**
+   * Determines whether stringToValue will return literal characters or not.
+   * @param containsLiteralChars if true, stringToValue will return the 
+   * literal characters in the mask, otherwise it will not.
+   */
+  public void setValueContainsLiteralCharacters (boolean containsLiteralChars)
+  {
+    this.valueContainsLiteralCharacters = containsLiteralChars;
+  }
+  
+  /**
+   * Sets the mask for this MaskFormatter.  
+   * @specnote doesn't actually throw a ParseException even though it is
+   * declared to do so
+   * @param mask the new mask for this MaskFormatter
+   * @throws ParseException if <code>mask</code> is not valid.
+   */
+  public void setMask (String mask) throws ParseException
+  {
+    this.mask = mask;
+
+    // Update the cached maskLength.
+    int end = mask.length() - 1;
+    maskLength = 0;    
+    for (int i = 0; i <= end; i++)
+      {
+        // Handle escape characters properly - they don't add to the maskLength
+        // but 2 escape characters in a row is really one escape character and
+        // one literal single quote, so that does add 1 to the maskLength.
+        if (mask.charAt(i) == '\'')
+          {            
+            // Escape characters at the end of the mask don't do anything.
+            if (i != end)
+              maskLength++;
+            i++;
+          }
+        else
+          maskLength++;
+      }
+  }
+  
+  /**
+   * Installs this MaskFormatter on the JFormattedTextField.
+   * Invokes valueToString to convert the current value from the 
+   * JFormattedTextField to a String, then installs the Actions from
+   * getActions, the DocumentFilter from getDocumentFilter, and the 
+   * NavigationFilter from getNavigationFilter.
+   * 
+   * If valueToString throws a ParseException, this method sets the text
+   * to an empty String and marks the JFormattedTextField as invalid.
+   */
+  public void install (JFormattedTextField ftf)
+  {
+    super.install(ftf);
+    if (ftf != null)
+      {
+        try
+        {
+          valueToString(ftf.getValue());
+        }
+        catch (ParseException pe)
+        {
+          // Set the text to an empty String and mark the JFormattedTextField
+          // as invalid.
+          ftf.setText("");
+          setEditValid(false);
+        }
+      }
+  }
+  
+  /**
+   * Parses the text using the mask, valid characters, and invalid characters
+   * to determine the appropriate Object to return.  This strips the literal
+   * characters if necessary and invokes super.stringToValue.  If the paramter
+   * is invalid for the current mask and valid/invalid character sets this 
+   * method will throw a ParseException.
+   * 
+   * @param value the String to parse
+   * @throws ParseException if value doesn't match the mask and valid/invalid
+   * character sets
+   */
+  public Object stringToValue (String value) throws ParseException
+  {
+    int vLength = value.length();
+    
+    // For value to be a valid it must be the same length as the mask
+    // note this doesn't take into account symbols that occupy more than 
+    // one character, this is something we may possibly need to fix.
+    if (maskLength != vLength)
+      throw new ParseException ("stringToValue passed invalid value", vLength);
+    
+    // Check if the value is valid according to the mask and valid/invalid 
+    // sets.
+    try
+    {
+      convertValue(value, false);      
+    }
+    catch (ParseException pe)
+    {
+      throw new ParseException("stringToValue passed invalid value",
+                                 pe.getErrorOffset());
+    }
+    
+    if (!getValueContainsLiteralCharacters())
+      value = stripLiterals(value);
+    return super.stringToValue(value);
+  }
+  
+  /**
+   * Strips the literal characters from the given String.
+   * @param value the String to strip
+   * @return the stripped String
+   */
+  String stripLiterals(String value)
+  {
+    StringBuffer result = new StringBuffer();
+    for (int i = 0; i < value.length(); i++)
+      {
+        // Only append the characters that don't correspond to literal
+        // characters in the mask.
+        switch (mask.charAt(i))
+          {
+          case NUM_CHAR:
+          case UPPERCASE_CHAR:
+          case LOWERCASE_CHAR:
+          case ALPHANUM_CHAR:
+          case LETTER_CHAR:
+          case HEX_CHAR:
+          case ANYTHING_CHAR:
+            result.append(value.charAt(i));
+            break;
+          default:
+          }
+      }
+    return result.toString();
+  }
+  
+  /**
+   * Returns a String representation of the Object value based on the mask.
+   * 
+   * @param value the value to convert
+   * @throws ParseException if value is invalid for this mask and valid/invalid
+   * character sets
+   */
+  public String valueToString (Object value) throws ParseException
+  {
+    String result = super.valueToString(value);
+    int rLength = result.length();
+    
+    // If value is longer than the mask, truncate it.  Note we may need to 
+    // account for symbols that are more than one character long.
+    if (rLength > maskLength)
+      result = result.substring(0, maskLength);
+    
+    // Verify the validity and convert to upper/lowercase as needed.
+    result = convertValue(result, true);        
+    if (rLength < maskLength)
+      return pad(result, rLength);    
+    return result;
+  }
+  
+  /**
+   * This method takes in a String and runs it through the mask to make
+   * sure that it is valid.  If <code>convert</code> is true, it also
+   * converts letters to upper/lowercase as required by the mask.
+   * @param value the String to convert
+   * @param convert true if we should convert letters to upper/lowercase
+   * @return the converted String
+   * @throws ParseException if the given String isn't valid for the mask
+   */
+  String convertValue(String value, boolean convert) throws ParseException
+  {
+    StringBuffer result = new StringBuffer(value);
+    char markChar;
+    char resultChar;
+    boolean literal;
+
+    // this boolean is specifically to avoid calling the isCharValid method
+    // when neither invalidChars or validChars has been set
+    boolean checkCharSets = (invalidChars != null || validChars != null);
+
+    for (int i = 0, j = 0; i < value.length(); i++, j++)
+      {
+        literal = false;
+        resultChar = result.charAt(i);
+        // This switch block on the mask character checks that the character 
+        // within <code>value</code> at that point is valid according to the
+        // mask and also converts to upper/lowercase as needed.
+        switch (mask.charAt(j))
+          {
+          case NUM_CHAR:
+            if (!Character.isDigit(resultChar))
+              throw new ParseException("Number expected", i);
+            break;
+          case UPPERCASE_CHAR:
+            if (!Character.isLetter(resultChar))
+              throw new ParseException("Letter expected", i);
+            if (convert)
+              result.setCharAt(i, Character.toUpperCase(resultChar));
+            break;
+          case LOWERCASE_CHAR:
+            if (!Character.isLetter(resultChar))
+              throw new ParseException("Letter expected", i);
+            if (convert)
+              result.setCharAt(i, Character.toLowerCase(resultChar));
+            break;
+          case ALPHANUM_CHAR:
+            if (!Character.isLetterOrDigit(resultChar))
+              throw new ParseException("Letter or number expected", i);
+            break;
+          case LETTER_CHAR:
+            if (!Character.isLetter(resultChar))
+              throw new ParseException("Letter expected", i);
+            break;
+          case HEX_CHAR:
+            if (hexString.indexOf(resultChar) == -1)
+              throw new ParseException("Hexadecimal character expected", i);
+            break;
+          case ANYTHING_CHAR:
+            break;
+          case ESCAPE_CHAR:
+            // Escape character, check the next character to make sure that 
+            // the literals match
+            j++;
+            literal = true;
+            if (resultChar != mask.charAt(j))
+              throw new ParseException ("Invalid character: "+resultChar, i);
+            break;
+          default:
+            literal = true;
+            if (!getValueContainsLiteralCharacters() && convert)
+              throw new ParseException ("Invalid character: "+resultChar, i);
+            else if (resultChar != mask.charAt(j))
+              throw new ParseException ("Invalid character: "+resultChar, i);
+          }
+        // If necessary, check if the character is valid.
+        if (!literal && checkCharSets && !isCharValid(resultChar))
+          throw new ParseException("invalid character: "+resultChar, i);
+
+      }
+    return result.toString();
+  }
+  
+  /**
+   * Convenience method used by many other methods to check if a character is 
+   * valid according to the mask, the validChars, and the invalidChars.  To
+   * be valid a character must:
+   * 1. be allowed by the mask
+   * 2. be present in any non-null validChars String
+   * 3. not be present in any non-null invalidChars String
+   * @param testChar the character to test
+   * @return true if the character is valid
+   */
+  boolean isCharValid(char testChar)
+  {
+    char lower = Character.toLowerCase(testChar);
+    char upper = Character.toUpperCase(testChar);
+    // If validChars isn't null, the character must appear in it.
+    if (validChars != null)
+      if (validChars.indexOf(lower) == -1 && validChars.indexOf(upper) == -1)
+        return false;
+    // If invalidChars isn't null, the character must not appear in it.
+    if (invalidChars != null)
+      if (invalidChars.indexOf(lower) != -1
+          || invalidChars.indexOf(upper) != -1)
+        return false;
+    return true;
+  }
+  
+  /**
+   * Pads the value with literals, the placeholder String and/or placeholder
+   * character as appropriate.
+   * @param value the value to pad
+   * @param currLength the current length of the value
+   * @return the padded String
+   */
+  String pad (String value, int currLength)
+  {
+    StringBuffer result = new StringBuffer(value);
+    int index = currLength;
+    while (result.length() < maskLength)
+      {
+        // The character used to pad may be a literal, a character from the 
+        // place holder string, or the place holder character.  getPadCharAt
+        // will find the proper one for us.
+        result.append (getPadCharAt(index));
+        index++;
+      }
+    return result.toString();
+  }
+
+  /**
+   * Returns the character with which to pad the value at the given index
+   * position.  If the mask has a literal at this position, this is returned
+   * otherwise if the place holder string is initialized and is longer than 
+   * <code>i</code> characters then the character at position <code>i</code>
+   * from this String is returned.  Else, the place holder character is 
+   * returned.
+   * @param i the index at which we want to pad the value
+   * @return the character with which we should pad the value
+   */
+  char getPadCharAt(int i)
+  {
+    boolean escaped = false;
+    int target = i;
+    char maskChar;
+    int holderLength = placeHolder == null ? -1 : placeHolder.length();
+    // We must iterate through the mask from the beginning, because the given
+    // index doesn't account for escaped characters.  For example, with the 
+    // mask "1A'A''A1" index 2 refers to the literalized A, not to the 
+    // single quotation.
+    for (int n = 0; n < mask.length(); n++)
+      {
+        maskChar = mask.charAt(n);
+        if (maskChar == ESCAPE_CHAR && !escaped)
+          {
+            target++;
+            escaped = true;
+          }
+        else if (escaped == true)
+          {
+            // Check if target == n which means we've come to the character
+            // we want to return and since it is a literal (because escaped 
+            // is true), we return it.
+            if (target == n)
+              return maskChar;
+            escaped = false;
+          }
+        if (target == n)
+          {
+            // We've come to the character we want to return.  It wasn't
+            // escaped so if it isn't a literal we should return either
+            // the character from place holder string or the place holder
+            // character, depending on whether or not the place holder
+            // string is long enough.
+            switch (maskChar)
+            {
+            case NUM_CHAR:
+            case UPPERCASE_CHAR:
+            case LOWERCASE_CHAR:
+            case ALPHANUM_CHAR:
+            case LETTER_CHAR:
+            case HEX_CHAR:
+            case ANYTHING_CHAR:
+              if (holderLength > i)
+                return placeHolder.charAt(i);
+              else
+                return placeHolderChar;
+            default:
+              return maskChar;
+            }
+          }
+      }
+    // This shouldn't happen
+    throw new AssertionError("MaskFormatter.getMaskCharAt failed");
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,117 @@
+/* MutableAttributeSet.java --
+   Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.util.Enumeration;
+
+/**
+ * An {@link AttributeSet} that supports modification of the stored 
+ * attributes.
+ * 
+ * @author	Andrew Selkirk
+ * @since 1.2
+ */
+public interface MutableAttributeSet extends AttributeSet
+{
+  /**
+   * Adds an attribute with the given <code>name</code> and <code>value</code>
+   * to the set.  If the set already contains an attribute with the given
+   * <code>name</code>, the attribute value is updated.
+   * 
+   * @param name  the attribute name (<code>null</code> not permitted).
+   * @param value  the value (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   */
+  void addAttribute(Object name, Object value);
+
+  /**
+   * Adds all the attributes from <code>attributes</code> to this set.
+   * 
+   * @param attributes  the set of attributes to add (<code>null</code> not
+   *                    permitted).
+   *                    
+   * @throws NullPointerException if <code>attributes</code> is 
+   *         <code>null</code>.
+   */
+  void addAttributes(AttributeSet attributes);
+
+  /**
+   * Removes the attribute with the specified <code>name</code>, if this 
+   * attribute is defined.  This method will only remove an attribute from
+   * this set, not from the resolving parent.
+   * 
+   * @param name  the attribute name (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>name</code> is <code>null</code>.
+   */
+  void removeAttribute(Object name);
+
+  /**
+   * Removes the attributes listed in <code>names</code>.
+   * 
+   * @param names  the attribute names (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>names</code> is <code>null</code> 
+   *         or contains any <code>null</code> values.
+   */
+  void removeAttributes(Enumeration names);
+
+  /**
+   * Removes attributes from this set if they are found in the 
+   * given set.  Only attributes whose key AND value are removed.
+   * Removes attributes only from this set, not from the resolving parent.  
+   * Since the resolving parent is stored as an attribute, if 
+   * <code>attributes</code> has the same resolving parent as this set, the
+   * parent will be removed from this set.
+   * 
+   * @param attributes  the attributes (<code>null</code> not permitted).
+   */
+  void removeAttributes(AttributeSet attributes);
+
+  /**
+   * Sets the reolving parent for this set.  When looking up an attribute, if
+   * it is not found in this set, then the resolving parent is also used for
+   * the lookup. 
+   * 
+   * @param parent  the parent attribute set (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>parent</code> is <code>null</code>.
+   */
+  void setResolveParent(AttributeSet parent);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,98 @@
+/* NavigationFilter.java --
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+public class NavigationFilter
+{
+  public abstract static class FilterBypass
+  {
+    public FilterBypass()
+    {
+      // Do nothing here.
+    }
+
+    public abstract Caret getCaret();
+    public abstract void moveDot(int dot, Position.Bias bias);
+    public abstract void setDot(int dot, Position.Bias bias);
+  }
+  
+  public NavigationFilter()
+  {
+    // Do nothing here.
+  }
+
+  public void moveDot(NavigationFilter.FilterBypass fb, int dot,
+		      Position.Bias bias)
+  {
+    fb.moveDot(dot, bias);
+  }
+
+  public void setDot(NavigationFilter.FilterBypass fb, int dot,
+		     Position.Bias bias)
+  {
+    fb.setDot(dot, bias);
+  }
+
+  /**
+   * Returns the next visual position in the specified direction at which one
+   * would place a caret. The default implementation forwards to the text
+   * component's root view. Subclasses may wish to restrict that more.
+   *
+   * @param c the text component
+   * @param pos the current model position
+   * @param bias the bias of <code>pos</code>
+   * @param dir the direction, one of {@link javax.swing.SwingConstants#NORTH},
+   *        {@link javax.swing.SwingConstants#SOUTH},
+   *        {@link javax.swing.SwingConstants#WEST} or
+   *        {@link javax.swing.SwingConstants#EAST}
+   * @param retBias the bias of the returned position
+   *
+   * @return the next model location to place the caret
+   *
+   * @throws BadLocationException when <code>pos</code> is not a valid model
+   *         position
+   */
+  public int getNextVisualPositionFrom(JTextComponent c, int pos,
+                                       Position.Bias bias, int dir,
+                                       Position.Bias[] retBias)
+    throws BadLocationException
+  {
+    return c.getUI().getNextVisualPositionFrom(c, pos, bias, dir, retBias);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,86 @@
+/* NumberFormatter.java -- 
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.text.Format;
+import java.text.NumberFormat;
+
+/**
+ * <code>NumberFormatter</code> is an {@link InternationalFormatter}
+ * that implements value to string and string to value conversion via
+ * an instance of {@link NumberFormat}.
+ * 
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ * @since 1.4
+ */
+public class NumberFormatter extends InternationalFormatter
+{
+  
+  /**
+   * Creates a NumberFormatter with the default NumberFormat from 
+   * NumberFormat.getNumberInstance().   
+   */
+  public NumberFormatter ()
+  {
+    this (NumberFormat.getNumberInstance());
+  }
+  
+  /**
+   * Creates a NumberFormatter with the specified NumberFormat.
+   * @param format the NumberFormat to use for this NumberFormatter.
+   */
+  public NumberFormatter (NumberFormat format)
+  {
+    super(format);
+    setFormat(format);
+  }
+  
+  /**
+   * Sets the NumberFormat that this NumberFormatter will use to determine
+   * legal values for editing and displaying.
+   * 
+   * @param format the Format to use to determine legal values.
+   */
+  public void setFormat (Format format)
+  {
+    // TODO: This should be different from the super implementation
+    // but I don't yet know how.
+    super.setFormat(format);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,456 @@
+/* ParagraphView.java -- A composite View
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Shape;
+
+import javax.swing.event.DocumentEvent;
+
+/**
+ * A {@link FlowView} that flows it's children horizontally and boxes the rows
+ * vertically.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class ParagraphView extends FlowView implements TabExpander
+{
+  /**
+   * A specialized horizontal <code>BoxView</code> that represents exactly
+   * one row in a <code>ParagraphView</code>.
+   */
+  class Row extends BoxView
+  {
+    /**
+     * Creates a new instance of <code>Row</code>.
+     */
+    Row(Element el)
+    {
+      super(el, X_AXIS);
+    }
+
+    public float getAlignment(int axis)
+    {
+      float align;
+      if (axis == X_AXIS)
+        align = 0.0F; // TODO: Implement according to justification
+      else
+        align = super.getAlignment(axis);
+      return align;
+    }
+
+    /**
+     * Allows rows to span the whole parent view.
+     */
+    public float getMaximumSpan(int axis)
+    {
+      float max;
+      if (axis == X_AXIS)
+        max = Float.MAX_VALUE;
+      else
+        max = super.getMaximumSpan(axis);
+      return max;
+    }
+
+    /**
+     * Overridden because child views are not necessarily laid out in model
+     * order.
+     */
+    protected int getViewIndexAtPosition(int pos)
+    {
+      int index = -1;
+      if (pos >= getStartOffset() && pos < getEndOffset())
+        {
+          int nviews = getViewCount();
+          for (int i = 0; i < nviews && index == -1; i++)
+            {
+              View child = getView(i);
+              if (pos >= child.getStartOffset() && pos < child.getEndOffset())
+                index = i;
+            }
+        }
+      return index;
+    }
+
+    protected void loadChildren(ViewFactory vf)
+    {
+      // Do nothing here. The children are added while layouting.
+    }
+  }
+
+  /**
+   * The indentation of the first line of the paragraph.
+   */
+  protected int firstLineIndent;
+
+  /**
+   * The justification of the paragraph.
+   */
+  private int justification;
+
+  /**
+   * The line spacing of this paragraph.
+   */
+  private float lineSpacing;
+
+  /**
+   * The TabSet of this paragraph.
+   */
+  private TabSet tabSet;
+
+  /**
+   * Creates a new <code>ParagraphView</code> for the given
+   * <code>Element</code>.
+   *
+   * @param element the element that is rendered by this ParagraphView
+   */
+  public ParagraphView(Element element)
+  {
+    super(element, Y_AXIS);
+  }
+
+  public float nextTabStop(float x, int tabOffset)
+  {
+    throw new InternalError("Not implemented yet");
+  }
+
+  /**
+   * Creates a new view that represents a row within a flow.
+   *
+   * @return a view for a new row
+   */
+  protected View createRow()
+  {
+    return new Row(getElement());
+  }
+
+  /**
+   * Returns the alignment for this paragraph view for the specified axis.
+   * For the X_AXIS the paragraph view will be aligned at it's left edge
+   * (0.0F). For the Y_AXIS the paragraph view will be aligned at the
+   * center of it's first row.
+   *
+   * @param axis the axis which is examined
+   *
+   * @return the alignment for this paragraph view for the specified axis
+   */
+  public float getAlignment(int axis)
+  {
+    float align;
+    if (axis == X_AXIS)
+      align = 0.5F;
+    else if (getViewCount() > 0)
+      {
+        float prefHeight = getPreferredSpan(Y_AXIS);
+        float firstRowHeight = getView(0).getPreferredSpan(Y_AXIS);
+        align = (firstRowHeight / 2.F) / prefHeight;
+      }
+    else
+      align = 0.5F;
+    return align;
+  }
+
+  /**
+   * Receives notification when some attributes of the displayed element
+   * changes. This triggers a refresh of the cached attributes of this
+   * paragraph.
+   *
+   * @param ev the document event
+   * @param a the allocation of this view
+   * @param fv the view factory to use for creating new child views
+   */
+  public void changedUpdate(DocumentEvent ev, Shape a, ViewFactory fv)
+  {
+    setPropertiesFromAttributes();
+  }
+
+  /**
+   * Fetches the cached properties from the element's attributes.
+   */
+  protected void setPropertiesFromAttributes()
+  {
+    Element el = getElement();
+    AttributeSet atts = el.getAttributes();
+    setFirstLineIndent(StyleConstants.getFirstLineIndent(atts));
+    setLineSpacing(StyleConstants.getLineSpacing(atts));
+    setJustification(StyleConstants.getAlignment(atts));
+    tabSet = StyleConstants.getTabSet(atts);
+  }
+
+  /**
+   * Sets the indentation of the first line of the paragraph.
+   *
+   * @param i the indentation to set
+   */
+  protected void setFirstLineIndent(float i)
+  {
+    firstLineIndent = (int) i;
+  }
+
+  /**
+   * Sets the justification of the paragraph.
+   *
+   * @param j the justification to set 
+   */
+  protected void setJustification(int j)
+  {
+    justification = j;
+  }
+
+  /**
+   * Sets the line spacing for this paragraph.
+   *
+   * @param s the line spacing to set
+   */
+  protected void setLineSpacing(float s)
+  {
+    lineSpacing = s;
+  }
+
+  /**
+   * Returns the i-th view from the logical views, before breaking into rows.
+   *
+   * @param i the index of the logical view to return
+   *
+   * @return the i-th view from the logical views, before breaking into rows
+   */
+  protected View getLayoutView(int i)
+  {
+    return layoutPool.getView(i);
+  }
+
+  /**
+   * Returns the number of logical child views.
+   *
+   * @return the number of logical child views
+   */
+  protected int getLayoutViewCount()
+  {
+    return layoutPool.getViewCount();
+  }
+
+  /**
+   * Returns the TabSet used by this ParagraphView.
+   *
+   * @return the TabSet used by this ParagraphView
+   */
+  protected TabSet getTabSet()
+  {
+    return tabSet;
+  }
+
+  /**
+   * Finds the next offset in the document that has one of the characters
+   * specified in <code>string</code>. If there is no such character found,
+   * this returns -1.
+   *
+   * @param string the characters to search for
+   * @param start the start offset
+   *
+   * @return the next offset in the document that has one of the characters
+   *         specified in <code>string</code>
+   */
+  protected int findOffsetToCharactersInString(char[] string, int start)
+  {
+    int offset = -1;
+    Document doc = getDocument();
+    Segment text = new Segment();
+    try
+      {
+        doc.getText(start, doc.getLength() - start, text);
+        int index = start;
+
+        searchLoop:
+        while (true)
+          {
+            char ch = text.next();
+            if (ch == Segment.DONE)
+              break;
+
+            for (int j = 0; j < string.length; ++j)
+              {
+                if (string[j] == ch)
+                  {
+                    offset = index;
+                    break searchLoop;
+                  }
+              }
+            index++;
+          }
+      }
+    catch (BadLocationException ex)
+      {
+        // Ignore this and return -1.
+      }
+    return offset;
+  }
+
+  protected int getClosestPositionTo(int pos, Position.Bias bias, Shape a,
+                                     int direction, Position.Bias[] biasRet,
+                                     int rowIndex, int x)
+    throws BadLocationException
+  {
+    // FIXME: Implement this properly. However, this looks like it might
+    // have been replaced by viewToModel.
+    return pos;
+  }
+
+  /**
+   * Returns the size that is used by this view (or it's child views) between
+   * <code>startOffset</code> and <code>endOffset</code>. If the child views
+   * implement the {@link TabableView} interface, then this is used to
+   * determine the span, otherwise we use the preferred span of the child
+   * views.
+   *
+   * @param startOffset the start offset
+   * @param endOffset the end offset
+   *
+   * @return the span used by the view between <code>startOffset</code> and
+   *         <code>endOffset</cod>
+   */
+  protected float getPartialSize(int startOffset, int endOffset)
+  {
+    int startIndex = getViewIndex(startOffset, Position.Bias.Backward);
+    int endIndex = getViewIndex(endOffset, Position.Bias.Forward);
+    float span;
+    if (startIndex == endIndex)
+      {
+        View child = getView(startIndex);
+        if (child instanceof TabableView)
+          {
+            TabableView tabable = (TabableView) child;
+            span = tabable.getPartialSpan(startOffset, endOffset);
+          }
+        else
+          span = child.getPreferredSpan(X_AXIS);
+      }
+    else if (endIndex - startIndex == 1)
+      {
+        View child1 = getView(startIndex);
+        if (child1 instanceof TabableView)
+          {
+            TabableView tabable = (TabableView) child1;
+            span = tabable.getPartialSpan(startOffset, child1.getEndOffset());
+          }
+        else
+          span = child1.getPreferredSpan(X_AXIS);
+        View child2 = getView(endIndex);
+        if (child2 instanceof TabableView)
+          {
+            TabableView tabable = (TabableView) child2;
+            span += tabable.getPartialSpan(child2.getStartOffset(), endOffset);
+          }
+        else
+          span += child2.getPreferredSpan(X_AXIS);
+      }
+    else
+      {
+        // Start with the first view.
+        View child1 = getView(startIndex);
+        if (child1 instanceof TabableView)
+          {
+            TabableView tabable = (TabableView) child1;
+            span = tabable.getPartialSpan(startOffset, child1.getEndOffset());
+          }
+        else
+          span = child1.getPreferredSpan(X_AXIS);
+
+        // Add up the view spans between the start and the end view.
+        for (int i = startIndex + 1; i < endIndex; i++)
+          {
+            View child = getView(i);
+            span += child.getPreferredSpan(X_AXIS);
+          }
+
+        // Add the span of the last view.
+        View child2 = getView(endIndex);
+        if (child2 instanceof TabableView)
+          {
+            TabableView tabable = (TabableView) child2;
+            span += tabable.getPartialSpan(child2.getStartOffset(), endOffset);
+          }
+        else
+          span += child2.getPreferredSpan(X_AXIS);
+      }
+    return span;
+  }
+
+  /**
+   * Returns the location where the tabs are calculated from. This returns
+   * <code>0.0F</code> by default.
+   *
+   * @return the location where the tabs are calculated from
+   */
+  protected float getTabBase()
+  {
+    return 0.0F;
+  }
+
+  /**
+   * @specnote This method is specified to take a Row parameter, which is a
+   *           private inner class of that class, which makes it unusable from
+   *           application code. Also, this method seems to be replaced by
+   *           {@link FlowStrategy#adjustRow(FlowView, int, int, int)}.
+   *
+   */
+  protected void adjustRow(Row r, int desiredSpan, int x)
+  {
+  }
+
+  /**
+   * @specnote This method's signature differs from the one defined in
+   *           {@link View} and is therefore never called. It is probably there
+   *           for historical reasons.
+   */
+  public View breakView(int axis, float len, Shape a)
+  {
+    // This method is not used.
+    return null;
+  }
+
+  /**
+   * @specnote This method's signature differs from the one defined in
+   *           {@link View} and is therefore never called. It is probably there
+   *           for historical reasons.
+   */
+  public int getBreakWeight(int axis, float len)
+  {
+    // This method is not used.
+    return 0;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,254 @@
+/* PasswordView.java -- 
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.JPasswordField;
+
+public class PasswordView
+  extends FieldView
+{
+  /**
+   * Buffer for putting the echo char into it and
+   * then using it to draw it into the view.
+   */
+  private char[] oneCharBuffer = new char[1];
+
+  public PasswordView(Element elem)
+  {
+    super(elem);
+  }
+
+  /**
+   * Draws one echo character at a given position.
+   *
+   * @param g the <code>Graphics</code> object to draw to
+   * @param x the x-position
+   * @param y the y-position
+   * @param ch the echo character
+   *
+   * @return the next x position right of the drawn character
+   */
+  protected int drawEchoCharacter(Graphics g, int x, int y, char ch)
+  {
+    // Update font metrics.
+    updateMetrics();
+
+    // Draw character.
+    oneCharBuffer[0] = ch;
+    g.drawChars(oneCharBuffer, 0, 1, x, y);
+
+    // Return new x position right of drawn character.
+    return x + metrics.charWidth(ch);
+  }
+
+  private char getEchoChar()
+  {
+    char ch = ((JPasswordField) getContainer()).getEchoChar();
+
+    if (ch == 0)
+      ch = '*';
+
+    return ch;
+  }
+
+  /**
+   * Draws selected text at a given position.
+   *
+   * @param g the <code>Graphics</code> object to draw to
+   * @param x the x-position
+   * @param y the y-position
+   * @param p0 the position of the first character to draw
+   * @param p1 the position of the first character not to draw
+   *
+   * @return the next x position right of the drawn character
+   */
+  protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
+    throws BadLocationException
+  {
+    // Update font metrics.
+    updateMetrics();
+
+    // Get echo character.
+    char ch = getEchoChar();
+
+    // Set color for selected text.
+    g.setColor(selectedColor);
+    g.setColor(Color.BLACK);
+
+    // Draw echo character using drawEchoCharacter() method.
+    for (int index = p0; index < p1; ++index)
+      x = drawEchoCharacter(g, x, y, ch);
+    return x;
+  }
+
+  /**
+   * Draws unselected text at a given position.
+   *
+   * @param g the <code>Graphics</code> object to draw to
+   * @param x the x-position of the start of the baseline
+   * @param y the y-position of the start of the baseline
+   * @param p0 the position of the first character to draw
+   * @param p1 the position of the first character not to draw
+   *
+   * @return the next x position right of the drawn character
+   */
+  protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
+    throws BadLocationException
+  {
+    // Update font metrics.
+    updateMetrics();
+
+    // Get echo character.
+    char ch = getEchoChar();
+
+    // Set color for unselected text.
+    g.setColor(unselectedColor);
+    g.setColor(Color.BLACK);
+
+    // Draw echo character using drawEchoCharacter() method.
+    for (int index = p0; index < p1; ++index)
+      x = drawEchoCharacter(g, x, y, ch);
+    return x;
+  }
+
+  /**
+   * Determines the preferred span for this view along an axis.
+   * 
+   * @param axis to get the preferred span of
+   * @return the preferred span of the axis
+   */
+  public float getPreferredSpan(int axis)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException();
+
+    FontMetrics fm = getFontMetrics();
+
+    if (axis == Y_AXIS)
+        return fm.getHeight();
+
+    String text;
+    Element elem = getElement();
+
+    try
+      {
+        text = elem.getDocument().getText(elem.getStartOffset(),
+                                          elem.getEndOffset());
+      }
+    catch (BadLocationException e)
+      {
+        // This should never happen.
+        text = "";
+      }
+    return fm.stringWidth(text);
+  }
+
+  /**
+   * Provides a mapping from the document model coordinate space to the
+   * coordinate space of the view mapped to it.
+   *
+   * This method is overridden to provide a correct mapping with respect to the
+   * echo char and not to the real content.
+   *
+   * @param pos - the position to convert >= 0
+   * @param a - the allocated region to render into
+   * @param b - typesafe enumeration to indicate bias to a position in the model.
+   * @return the bounding box of the given position
+   * @throws BadLocationException if the given position does not 
+   * represent a valid location in the associated document
+   */
+  public Shape modelToView(int pos, Shape a, Position.Bias b)
+    throws BadLocationException
+  {
+    Shape newAlloc = adjustAllocation(a);
+
+    // Ensure metrics are up-to-date.
+    updateMetrics();
+    
+    // Get rectangle of the line containing position.
+    int lineIndex = getElement().getElementIndex(pos);
+    Rectangle rect = lineToRect(newAlloc, lineIndex);
+
+    // Get the rectangle for position.
+    Element line = getElement().getElement(lineIndex);
+    int lineStart = line.getStartOffset();
+    Segment segment = getLineBuffer();
+    segment.array = new char[pos - lineStart];
+    char echoChar = getEchoChar();
+    for (int i = 0; i < segment.array.length; ++i)
+      segment.array[i] = echoChar;
+    segment.offset = 0;
+    segment.count = segment.array.length;
+
+    int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
+                           this, lineStart);
+
+    // Calc the real rectangle.
+    rect.x += xoffset;
+    rect.width = 1;
+    rect.height = metrics.getHeight();
+
+    return rect;
+  }
+
+  /**
+   * Provides a mapping from the view coordinate space to the logical 
+   * coordinate space of the model.
+   * 
+   * @param fx - the X coordinate >= 0.0f
+   * @param fy - the Y coordinate >= 0.0f
+   * @param a - the allocated region to render into 
+   * @param bias - typesafe enumeration to indicate bias to a position in the model.
+   * @return the location within the model that best represents 
+   * the given point in the view
+   * 
+   */
+  public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias)
+  {
+    // FIXME: This only provides a view->model mapping for the real text
+    // content and does not respect the echo char.
+    return super.viewToModel(fx, fy, a, bias);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,292 @@
+/* PlainDocument.java --
+   Copyright (C) 2002, 2004, 2006  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.util.ArrayList;
+
+/**
+ * A simple document class which maps lines to {@link Element}s.
+ *
+ * @author Anthony Balkissoon (abalkiss at redhat.com)
+ * @author Graydon Hoare (graydon at redhat.com)
+ * @author Roman Kennke (roman at kennke.org)
+ * @author Michael Koch (konqueror at gmx.de)
+ * @author Robert Schuster (robertschuster at fsfe.org)
+ */
+public class PlainDocument extends AbstractDocument
+{
+  private static final long serialVersionUID = 4758290289196893664L;
+    
+  public static final String lineLimitAttribute = "lineLimit";
+  public static final String tabSizeAttribute = "tabSize";
+
+  /**
+   * The default root element of this document. This is made type Element
+   * because the RI seems to accept other types of elements as well from
+   * createDefaultRoot() (when overridden by a subclass).
+   */
+  private Element rootElement;
+  
+  public PlainDocument()
+  {
+    this(new GapContent());
+  }
+
+  public PlainDocument(AbstractDocument.Content content)
+  {
+    super(content);
+    rootElement = createDefaultRoot();
+
+    // This property has been determined using a Mauve test.
+    putProperty("tabSize", new Integer(8));
+  }
+
+  private void reindex()
+  {
+    Element[] lines;
+    try 
+      {
+        String str = content.getString(0, content.length());
+
+        ArrayList elts = new ArrayList();
+        int j = 0;
+        for (int i = str.indexOf('\n', 0); i != -1; i = str.indexOf('\n', i + 1))
+          {
+            elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, i + 1));
+            j = i + 1;
+          }
+        
+        if (j < content.length())
+          elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, content.length()));
+        
+        lines = new Element[elts.size()];
+        for (int i = 0; i < elts.size(); ++i)
+          lines[i] = (Element) elts.get(i);
+      }
+    catch (BadLocationException e)
+      {
+        lines = new Element[1];
+        lines[0] = createLeafElement(rootElement, SimpleAttributeSet.EMPTY, 0, 1);
+      }
+
+    ((BranchElement) rootElement).replace(0, rootElement.getElementCount(), lines);
+  }
+
+  protected AbstractDocument.AbstractElement createDefaultRoot()
+  {
+    BranchElement root =
+      (BranchElement) createBranchElement(null, null);
+
+    Element[] array = new Element[1];
+    array[0] = createLeafElement(root, null, 0, 1);
+    root.replace(0, 0, array);
+    
+    return root;
+  }
+
+  protected void insertUpdate(DefaultDocumentEvent event,
+                              AttributeSet attributes)
+  {
+
+    String text = null;
+    int offset = event.getOffset();
+    int length = event.getLength();
+    try
+      {
+        text = getText(offset, length);
+      }
+    catch (BadLocationException ex)
+      {
+        AssertionError err = new AssertionError();
+        err.initCause(ex);
+        throw err;
+      }
+
+    boolean hasLineBreak = text.indexOf('\n') != -1;
+    boolean prevCharIsLineBreak = false;
+    try
+      {
+        prevCharIsLineBreak =
+          offset > 0 && getText(offset - 1, 1).charAt(0) == '\n';
+      }
+    catch (BadLocationException ex)
+      {
+        AssertionError err = new AssertionError();
+        err.initCause(ex);
+        throw err;
+      }
+    boolean lastCharIsLineBreak = text.charAt(text.length() - 1) == '\n';
+    int lineIndex = -1;
+    int lineStart = -1;
+    int lineEnd = -1;
+    Element[] removed = null;
+    BranchElement root = (BranchElement) rootElement;
+    boolean updateStructure = true;
+
+    if (prevCharIsLineBreak && ! lastCharIsLineBreak)
+      {
+        // We must fix the structure a little if the previous char
+        // is a linebreak and the last char isn't.
+        lineIndex = root.getElementIndex(offset - 1);
+        Element prevLine = root.getElement(lineIndex);
+        Element nextLine = root.getElement(lineIndex + 1);
+        lineStart = prevLine.getStartOffset();
+        lineEnd = nextLine.getEndOffset();
+        removed = new Element[]{ prevLine, nextLine };
+      }
+    else if (hasLineBreak)
+      {
+        lineIndex = root.getElementIndex(offset);
+        Element line = root.getElement(lineIndex);
+        lineStart = line.getStartOffset();
+        lineEnd = line.getEndOffset();
+        removed = new Element[]{ line };
+      }
+    else
+      {
+        updateStructure = false;
+      }
+
+    if (updateStructure)
+      {
+        // Break the lines between lineStart and lineEnd.
+        ArrayList lines = new ArrayList();
+        int len = lineEnd - lineStart;
+        try
+          {
+            text = getText(lineStart, len);
+          }
+        catch (BadLocationException ex)
+          {
+            AssertionError err = new AssertionError();
+            err.initCause(ex);
+            throw err;
+          }
+        int prevLineBreak = 0;
+        int lineBreak = text.indexOf('\n');
+        do
+          {
+            lineBreak++;
+            lines.add(createLeafElement(root, null, lineStart + prevLineBreak,
+                                        lineStart + lineBreak));
+            prevLineBreak = lineBreak;
+            lineBreak = text.indexOf('\n', prevLineBreak);
+          } while (prevLineBreak < len);
+
+        // Update the element structure and prepare document event.
+        Element[] added = (Element[]) lines.toArray(new Element[lines.size()]);
+        event.addEdit(new ElementEdit(root, lineIndex, removed, added));
+        root.replace(lineIndex, removed.length, added);
+      }
+    super.insertUpdate(event, attributes);
+  }
+
+  protected void removeUpdate(DefaultDocumentEvent event)
+  {
+    super.removeUpdate(event);
+
+    // added and removed are Element arrays used to add an ElementEdit
+    // to the DocumentEvent if there were entire lines added or removed
+    // from the Document
+    Element[] added = new Element[1];
+    Element[] removed;
+    int p0 = event.getOffset();
+
+    // check if we must collapse some elements
+    int i1 = rootElement.getElementIndex(p0);
+    int i2 = rootElement.getElementIndex(p0 + event.getLength());
+    if (i1 != i2)
+      {
+        // If there were lines removed then we have to add an ElementEdit
+        // to the DocumentEvent so we set it up now by filling the Element
+        // arrays "removed" and "added" appropriately
+        removed = new Element [i2 - i1 + 1];
+        for (int i = i1; i <= i2; i++)
+          removed[i-i1] = rootElement.getElement(i);
+        
+        int start = rootElement.getElement(i1).getStartOffset();
+        int end = rootElement.getElement(i2).getEndOffset();        
+        added[0] = createLeafElement(rootElement,
+                                          SimpleAttributeSet.EMPTY,
+                                          start, end);
+
+        // Now create and add the ElementEdit
+        ElementEdit e = new ElementEdit(rootElement, i1, removed, added);
+        event.addEdit(e);
+
+        // collapse elements if the removal spans more than 1 line
+        ((BranchElement) rootElement).replace(i1, i2 - i1 + 1, added);
+      }
+  }
+
+  public Element getDefaultRootElement()
+  {
+    return rootElement;
+  }
+
+  public Element getParagraphElement(int pos)
+  {
+    Element root = getDefaultRootElement();
+    return root.getElement(root.getElementIndex(pos));
+  }
+
+  /**
+   * Inserts a string into the document. If the document property
+   * '<code>filterNewLines</code>' is set to <code>Boolean.TRUE</code>, then
+   * all newlines in the inserted string are replaced by space characters,
+   * otherwise the superclasses behaviour is executed.
+   *
+   * Inserting content causes a write lock to be acquired during this method
+   * call.
+   *
+   * @param offs the offset at which to insert the string
+   * @param str the string to be inserted
+   * @param atts the text attributes of the string to be inserted
+   *
+   * @throws BadLocationException
+   */
+  public void insertString(int offs, String str, AttributeSet atts)
+    throws BadLocationException
+  {
+    String string = str;
+    if (str != null && Boolean.TRUE.equals(getProperty("filterNewlines")))
+      string = str.replaceAll("\n", " ");
+    super.insertString(offs, string, atts);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,661 @@
+/* PlainView.java -- 
+   Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SwingUtilities;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentEvent.ElementChange;
+
+public class PlainView extends View implements TabExpander
+{
+  Color selectedColor;
+  Color unselectedColor;
+
+  /**
+   * The color that is used to draw disabled text fields.
+   */
+  Color disabledColor;
+  
+  /**
+   * While painting this is the textcomponent's current start index
+   * of the selection.
+   */
+  int selectionStart;
+
+  /**
+   * While painting this is the textcomponent's current end index
+   * of the selection.
+   */
+  int selectionEnd;
+
+  Font font;
+  
+  /** The length of the longest line in the Document **/
+  float maxLineLength = -1;
+  
+  /** The longest line in the Document **/
+  Element longestLine = null;
+  
+  protected FontMetrics metrics;
+
+  /**
+   * The instance returned by {@link #getLineBuffer()}.
+   */
+  private transient Segment lineBuffer;
+
+  public PlainView(Element elem)
+  {
+    super(elem);
+  }
+
+  /**
+   * @since 1.4
+   */
+  protected void updateMetrics()
+  {
+    Component component = getContainer();
+    Font font = component.getFont();
+
+    if (this.font != font)
+      {
+	this.font = font;
+	metrics = component.getFontMetrics(font);
+      }
+  }
+  
+  /**
+   * @since 1.4
+   */
+  protected Rectangle lineToRect(Shape a, int line)
+  {
+    // Ensure metrics are up-to-date.
+    updateMetrics();
+    
+    Rectangle rect = a.getBounds();
+    int fontHeight = metrics.getHeight();
+    return new Rectangle(rect.x, rect.y + (line * fontHeight),
+			 rect.width, fontHeight);
+  }
+
+  public Shape modelToView(int position, Shape a, Position.Bias b)
+    throws BadLocationException
+  {
+    // Ensure metrics are up-to-date.
+    updateMetrics();
+    
+    Document document = getDocument();
+
+    // Get rectangle of the line containing position.
+    int lineIndex = getElement().getElementIndex(position);
+    Rectangle rect = lineToRect(a, lineIndex);
+
+    // Get the rectangle for position.
+    Element line = getElement().getElement(lineIndex);
+    int lineStart = line.getStartOffset();
+    Segment segment = getLineBuffer();
+    document.getText(lineStart, position - lineStart, segment);
+    int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
+					       this, lineStart);
+
+    // Calc the real rectangle.
+    rect.x += xoffset;
+    rect.width = 1;
+    rect.height = metrics.getHeight();
+
+    return rect;
+  }
+  
+  /**
+   * Draws a line of text. The X and Y coordinates specify the start of
+   * the <em>baseline</em> of the line.
+   *
+   * @param lineIndex the index of the line
+   * @param g the graphics to use for drawing the text
+   * @param x the X coordinate of the baseline
+   * @param y the Y coordinate of the baseline
+   */
+  protected void drawLine(int lineIndex, Graphics g, int x, int y)
+  {
+    try
+      {
+        Element line = getElement().getElement(lineIndex);
+        int startOffset = line.getStartOffset();
+        int endOffset = line.getEndOffset() - 1;
+        
+        if (selectionStart <= startOffset)
+          // Selection starts before the line ...
+          if (selectionEnd <= startOffset)
+            {
+              // end ends before the line: Draw completely unselected text.
+              drawUnselectedText(g, x, y, startOffset, endOffset);
+            }
+          else if (selectionEnd <= endOffset)
+            {
+              // and ends within the line: First part is selected,
+              // second is not.
+              x = drawSelectedText(g, x, y, startOffset, selectionEnd);
+              drawUnselectedText(g, x, y, selectionEnd, endOffset);
+            }
+          else
+            // and ends behind the line: Draw completely selected text.
+            drawSelectedText(g, x, y, startOffset, endOffset);
+        else if (selectionStart < endOffset)
+          // Selection starts within the line ..
+          if (selectionEnd < endOffset)
+            {
+              // and ends within it: First part unselected, second part
+              // selected, third part unselected.
+              x = drawUnselectedText(g, x, y, startOffset, selectionStart);
+              x = drawSelectedText(g, x, y, selectionStart, selectionEnd);
+              drawUnselectedText(g, x, y, selectionEnd, endOffset);
+            }
+          else
+            {
+              // and ends behind the line: First part unselected, second
+              // part selected.
+              x = drawUnselectedText(g, x, y, startOffset, selectionStart);
+              drawSelectedText(g, x, y, selectionStart, endOffset);
+            }
+        else
+          // Selection is behind this line: Draw completely unselected text.
+          drawUnselectedText(g, x, y, startOffset, endOffset);
+      }
+    catch (BadLocationException e)
+    {
+      AssertionError ae = new AssertionError("Unexpected bad location");
+      ae.initCause(e);
+      throw ae;
+    }
+  }
+
+  protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
+    throws BadLocationException
+  {
+    g.setColor(selectedColor);
+    Segment segment = getLineBuffer();
+    getDocument().getText(p0, p1 - p0, segment);
+    return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
+  }
+
+  /**
+   * Draws a chunk of unselected text.
+   *
+   * @param g the graphics to use for drawing the text
+   * @param x the X coordinate of the baseline
+   * @param y the Y coordinate of the baseline
+   * @param p0 the start position in the text model
+   * @param p1 the end position in the text model
+   *
+   * @return the X location of the end of the range
+   *
+   * @throws BadLocationException if <code>p0</code> or <code>p1</code> are
+   *         invalid
+   */
+  protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
+    throws BadLocationException
+  {
+    JTextComponent textComponent = (JTextComponent) getContainer();
+    if (textComponent.isEnabled())
+      g.setColor(unselectedColor);
+    else
+      g.setColor(disabledColor);
+
+    Segment segment = getLineBuffer();
+    getDocument().getText(p0, p1 - p0, segment);
+    return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
+  }
+
+  public void paint(Graphics g, Shape s)
+  {
+    // Ensure metrics are up-to-date.
+    updateMetrics();
+    
+    JTextComponent textComponent = (JTextComponent) getContainer();
+
+    selectedColor = textComponent.getSelectedTextColor();
+    unselectedColor = textComponent.getForeground();
+    disabledColor = textComponent.getDisabledTextColor();
+    selectionStart = textComponent.getSelectionStart();
+    selectionEnd = textComponent.getSelectionEnd();
+
+    Rectangle rect = s.getBounds();
+
+    // FIXME: Text may be scrolled.
+    Document document = textComponent.getDocument();
+    Element root = document.getDefaultRootElement();
+    int y = rect.y + metrics.getAscent();
+    int height = metrics.getHeight();
+    
+    int count = root.getElementCount();
+    for (int i = 0; i < count; i++)
+      {
+        drawLine(i, g, rect.x, y);
+        y += height;
+      }
+  }
+
+  /**
+   * Returns the tab size of a tab.  Checks the Document's
+   * properties for PlainDocument.tabSizeAttribute and returns it if it is
+   * defined, otherwise returns 8.
+   * 
+   * @return the tab size.
+   */
+  protected int getTabSize()
+  {
+    Object tabSize = getDocument().getProperty(PlainDocument.tabSizeAttribute);
+    if (tabSize == null)
+      return 8;
+    return ((Integer)tabSize).intValue();
+  }
+
+  /**
+   * Returns the next tab stop position after a given reference position.
+   *
+   * This implementation ignores the <code>tabStop</code> argument.
+   * 
+   * @param x the current x position in pixels
+   * @param tabStop the position within the text stream that the tab occured at
+   */
+  public float nextTabStop(float x, int tabStop)
+  {
+    float tabSizePixels = getTabSize() * metrics.charWidth('m');
+    return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
+  }
+
+  /**
+   * Returns the length of the longest line, used for getting the span
+   * @return the length of the longest line
+   */
+  float determineMaxLineLength()
+  {
+    // if the longest line is cached, return the cached value
+    if (maxLineLength != -1)
+      return maxLineLength;
+    
+    // otherwise we have to go through all the lines and find it
+    Element el = getElement();
+    Segment seg = getLineBuffer();
+    float span = 0;
+    for (int i = 0; i < el.getElementCount(); i++)
+      {
+        Element child = el.getElement(i);
+        int start = child.getStartOffset();
+        int end = child.getEndOffset() - 1;
+        try
+          {
+            el.getDocument().getText(start, end - start, seg);
+          }
+        catch (BadLocationException ex)
+          {
+            AssertionError ae = new AssertionError("Unexpected bad location");
+	    ae.initCause(ex);
+	    throw ae;
+          }
+        
+        if (seg == null || seg.array == null || seg.count == 0)
+          continue;
+        
+        int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
+        if (width > span)
+          {
+            longestLine = child;
+            span = width;
+          }
+      }
+    maxLineLength = span;
+    return maxLineLength;
+  }
+  
+  public float getPreferredSpan(int axis)
+  {
+    if (axis != X_AXIS && axis != Y_AXIS)
+      throw new IllegalArgumentException();
+
+    // make sure we have the metrics
+    updateMetrics();
+
+    Element el = getElement();
+    float span;
+
+    switch (axis)
+      {
+      case X_AXIS:
+        span = determineMaxLineLength();
+        break;
+      case Y_AXIS:
+      default:
+        span = metrics.getHeight() * el.getElementCount();
+        break;
+      }
+    
+    return span;
+  }
+
+  /**
+   * Maps coordinates from the <code>View</code>'s space into a position
+   * in the document model.
+   *
+   * @param x the x coordinate in the view space
+   * @param y the y coordinate in the view space
+   * @param a the allocation of this <code>View</code>
+   * @param b the bias to use
+   *
+   * @return the position in the document that corresponds to the screen
+   *         coordinates <code>x, y</code>
+   */
+  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+  {
+    Rectangle rec = a.getBounds();
+    Document doc = getDocument();
+    Element root = doc.getDefaultRootElement();
+    
+    // PlainView doesn't support line-wrapping so we can find out which
+    // Element was clicked on just by the y-position.    
+    // Since the coordinates may be outside of the coordinate space
+    // of the allocation area (e.g. user dragged mouse outside
+    // the component) we have to limit the values.
+    // This has the nice effect that the user can drag the
+    // mouse above or below the component and it will still
+    // react to the x values (e.g. when selecting).
+    int lineClicked
+      = Math.min(Math.max((int) (y - rec.y) / metrics.getHeight(), 0),
+                          root.getElementCount() - 1);
+    
+    Element line = root.getElement(lineClicked);
+    
+    Segment s = getLineBuffer();
+    int start = line.getStartOffset();
+    // We don't want the \n at the end of the line.
+    int end = line.getEndOffset() - 1;
+    try
+      {
+        doc.getText(start, end - start, s);
+      }
+    catch (BadLocationException ble)
+      {
+        AssertionError ae = new AssertionError("Unexpected bad location");
+        ae.initCause(ble);
+        throw ae;
+      }
+    
+    int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start);
+    return Math.max (0, pos);
+  }     
+  
+  /**
+   * Since insertUpdate and removeUpdate each deal with children
+   * Elements being both added and removed, they both have to perform
+   * the same checks.  So they both simply call this method.
+   * @param changes the DocumentEvent for the changes to the Document.
+   * @param a the allocation of the View.
+   * @param f the ViewFactory to use for rebuilding.
+   */
+  protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f)
+  {
+    // This happens during initialization.
+    if (metrics == null)
+      {
+        updateMetrics();
+        preferenceChanged(null, true, true);
+        return;
+      }
+
+    Element element = getElement();
+
+    // Find longest line if it hasn't been initialized yet.
+    if (longestLine == null)
+      findLongestLine(0, element.getElementCount() - 1);
+
+    ElementChange change = changes.getChange(element);
+    if (changes.getType() == DocumentEvent.EventType.INSERT)
+      {
+        // Handles character/line insertion.
+
+        // Determine if lines have been added. In this case we repaint
+        // differently.
+        boolean linesAdded = true;
+        if (change == null)
+          linesAdded = false;
+
+        // Determine the start line.
+        int start;
+        if (linesAdded)
+          start = change.getIndex();
+        else
+          start = element.getElementIndex(changes.getOffset());
+
+        // Determine the length of the updated region.
+        int length = 0;
+        if (linesAdded)
+          length = change.getChildrenAdded().length - 1;
+
+        // Update the longest line and length.
+        int oldMaxLength = (int) maxLineLength;
+        if (longestLine.getEndOffset() < changes.getOffset()
+            || longestLine.getStartOffset() > changes.getOffset()
+                                             + changes.getLength())
+          {
+            findLongestLine(start, start + length);
+          }
+        else
+          {
+            findLongestLine(0, element.getElementCount() - 1);
+          }
+
+        // Trigger a preference change so that the layout gets updated
+        // correctly.
+        preferenceChanged(null, maxLineLength != oldMaxLength, linesAdded);
+
+        // Damage the updated line range.
+        int endLine = start;
+        if (linesAdded)
+          endLine = element.getElementCount() - 1;
+        damageLineRange(start, endLine, a, getContainer());
+
+      }
+    else
+      {
+        // Handles character/lines removals.
+
+        // Update the longest line and length and trigger preference changed.
+        int oldMaxLength = (int) maxLineLength;
+        if (change != null)
+          {
+            // Line(s) have been removed.
+            findLongestLine(0, element.getElementCount() - 1);
+            preferenceChanged(null, maxLineLength != oldMaxLength, true);
+          }
+        else
+          {
+            // No line has been removed.
+            int lineNo = getElement().getElementIndex(changes.getOffset());
+            Element line = getElement().getElement(lineNo);
+            if (longestLine == line)
+              {
+                findLongestLine(0, element.getElementCount() - 1);
+                preferenceChanged(null, maxLineLength != oldMaxLength, false);
+            }
+            damageLineRange(lineNo, lineNo, a, getContainer());
+        }
+      }
+  }
+
+  /**
+   * This method is called when something is inserted into the Document
+   * that this View is displaying.
+   * 
+   * @param changes the DocumentEvent for the changes.
+   * @param a the allocation of the View
+   * @param f the ViewFactory used to rebuild
+   */
+  public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+  {
+    updateDamage(changes, a, f);
+  }
+
+  /**
+   * This method is called when something is removed from the Document
+   * that this View is displaying.
+   * 
+   * @param changes the DocumentEvent for the changes.
+   * @param a the allocation of the View
+   * @param f the ViewFactory used to rebuild
+   */
+  public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+  {
+    updateDamage(changes, a, f);
+  }
+  
+  /**
+   * This method is called when attributes were changed in the 
+   * Document in a location that this view is responsible for.
+   */
+  public void changedUpdate (DocumentEvent changes, Shape a, ViewFactory f)
+  {
+    updateDamage(changes, a, f);
+  }
+  
+  /**
+   * Repaint the given line range.  This is called from insertUpdate,
+   * changedUpdate, and removeUpdate when no new lines were added 
+   * and no lines were removed, to repaint the line that was 
+   * modified.
+   * 
+   * @param line0 the start of the range
+   * @param line1 the end of the range
+   * @param a the rendering region of the host
+   * @param host the Component that uses this View (used to call repaint
+   * on that Component)
+   * 
+   * @since 1.4
+   */
+  protected void damageLineRange (int line0, int line1, Shape a, Component host)
+  {
+    if (a == null)
+      return;
+
+    Rectangle rec0 = lineToRect(a, line0);
+    Rectangle rec1 = lineToRect(a, line1);
+
+    if (rec0 == null || rec1 == null)
+      // something went wrong, repaint the entire host to be safe
+      host.repaint();
+    else
+      {
+        Rectangle repaintRec = SwingUtilities.computeUnion(rec0.x, rec0.y,
+                                                           rec0.width,
+                                                           rec0.height, rec1);
+        host.repaint(repaintRec.x, repaintRec.y, repaintRec.width,
+                     repaintRec.height);
+      }    
+  }
+
+  /**
+   * Provides a {@link Segment} object, that can be used to fetch text from
+   * the document.
+   *
+   * @returna {@link Segment} object, that can be used to fetch text from
+   *          the document
+   */
+  protected final Segment getLineBuffer()
+  {
+    if (lineBuffer == null)
+      lineBuffer = new Segment();
+    return lineBuffer;
+  }
+
+  /**
+   * Finds and updates the longest line in the view inside an interval of
+   * lines.
+   *
+   * @param start the start of the search interval
+   * @param end the end of the search interval
+   */
+  private void findLongestLine(int start, int end)
+  {
+    for (int i = start; i <= end; i++)
+      {
+        int w = getLineLength(i);
+        if (w > maxLineLength)
+          {
+            maxLineLength = w;
+            longestLine = getElement().getElement(i);
+          }
+      }
+  }
+
+  /**
+   * Determines the length of the specified line.
+   *
+   * @param line the number of the line
+   *
+   * @return the length of the line in pixels
+   */
+  private int getLineLength(int line)
+  {
+    Element lineEl = getElement().getElement(line);
+    Segment buffer = getLineBuffer();
+    try
+      {
+        Document doc = getDocument();
+        doc.getText(lineEl.getStartOffset(),
+                    lineEl.getEndOffset() - lineEl.getStartOffset() - 1,
+                    buffer);
+      }
+    catch (BadLocationException ex)
+      {
+        AssertionError err = new AssertionError("Unexpected bad location");
+        err.initCause(ex);
+        throw err;
+      }
+
+    return Utilities.getTabbedTextWidth(buffer, metrics, 0, this,
+                                        lineEl.getStartOffset());
+  }
+}
+

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,62 @@
+/* Position.java -- 
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+
+public interface Position
+{
+  static final class Bias
+  {
+    public static final Bias Backward = new Bias("backward");
+    public static final Bias Forward = new Bias("forward");
+
+    private String name;
+    
+    private Bias(String n)
+    {
+      name = n;
+    }
+
+    public String toString()
+    {
+      return name;
+    }
+  }
+    
+  int getOffset();
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,297 @@
+/* Segment.java --
+   Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.text.CharacterIterator;
+
+/**
+ * A text fragment represented by a sequence of characters stored in an array.
+ */
+public class Segment implements Cloneable, CharacterIterator
+{
+  private boolean partialReturn;
+  
+  /** The current index. */
+  private int current;
+  
+  /** Storage for the characters (may contain additional characters). */
+  public char[] array;
+  
+  /** The number of characters in the segment. */
+  public int count;
+  
+  /** The offset of the first character in the segment. */
+  public int offset;
+
+  /**
+   * Creates a new <code>Segment</code>.
+   */
+  public Segment()
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * Creates a new <code>Segment</code>.
+   * 
+   * @param array  the underlying character data.
+   * @param offset  the offset of the first character in the segment.
+   * @param count  the number of characters in the segment.
+   */
+  public Segment(char[] array, int offset, int count)
+  {
+    this.array = array;
+    this.offset = offset;
+    this.count = count;
+  }
+  
+  /**
+   * Clones the segment (note that the underlying character array is not cloned,
+   * just the reference to it).
+   * 
+   * @return A clone of the segment.
+   */
+  public Object clone()
+  {
+    try
+      {
+	return super.clone();
+      }
+    catch (CloneNotSupportedException e)
+      {
+	return null;
+      }
+  }
+
+  /**
+   * Returns the character at the current index.  If the segment consists of
+   * zero characters, or the current index has passed the end of the 
+   * characters in the segment, this method returns {@link #DONE}.
+   * 
+   * @return The character at the current index.
+   */
+  public char current()
+  {
+    if (count == 0
+	|| current >= getEndIndex())
+      return DONE;
+    
+    return array[current];
+  }
+
+  /**
+   * Sets the current index to the first character in the segment and returns
+   * that character.  If the segment contains zero characters, this method
+   * returns {@link #DONE}.
+   * 
+   * @return The first character in the segment, or {@link #DONE} if the 
+   *         segment contains zero characters.
+   */
+  public char first()
+  {
+    if (count == 0)
+      return DONE;
+
+    current = getBeginIndex();
+    return array[current];
+  }
+
+  /**
+   * Returns the index of the first character in the segment.
+   * 
+   * @return The index of the first character.
+   */
+  public int getBeginIndex()
+  {
+    return offset;
+  }
+
+  /**
+   * Returns the end index for the segment (one position beyond the last 
+   * character in the segment - note that this can be outside the range of the 
+   * underlying character array).
+   * 
+   * @return The end index for the segment.
+   */
+  public int getEndIndex()
+  {
+    return offset + count;
+  }
+
+  /**
+   * Returns the index of the current character in the segment.
+   * 
+   * @return The index of the current character.
+   */
+  public int getIndex()
+  {
+    return current;
+  }
+
+  /**
+   * Sets the current index to point to the last character in the segment and 
+   * returns that character.  If the segment contains zero characters, the 
+   * current index is set to {@link #getEndIndex()} and this method returns 
+   * {@link #DONE}.
+   * 
+   * @return The last character in the segment, or {@link #DONE} if the 
+   *         segment contains zero characters.
+   */
+  public char last()
+  {
+    if (count == 0)
+      {
+        current = getEndIndex();
+        return DONE;
+      }
+    
+    current = getEndIndex() - 1;
+    return array[current];
+  }
+
+  /**
+   * Sets the current index to point to the next character in the segment and 
+   * returns that character.  If the next character position is past the end of
+   * the segment, the index is set to {@link #getEndIndex()} and the method
+   * returns {@link #DONE}.  If the segment contains zero characters, this 
+   * method returns {@link #DONE}.
+   * 
+   * @return The next character in the segment or {@link #DONE} (if the next
+   *         character position is past the end of the segment or if the 
+   *         segment contains zero characters).
+   */
+  public char next()
+  {
+    if (count == 0)
+      return DONE;
+
+    if ((current + 1) >= getEndIndex())
+      {
+	current = getEndIndex();
+	return DONE;
+      }
+    
+    current++;
+    return array[current];
+  }
+
+  /**
+   * Sets the current index to point to the previous character in the segment 
+   * and returns that character.  If the current index is equal to 
+   * {@link #getBeginIndex()}, or if the segment contains zero characters, this 
+   * method returns {@link #DONE}.
+   * 
+   * @return The previous character in the segment or {@link #DONE} (if the 
+   *         current character position is at the beginning of the segment or 
+   *         if the segment contains zero characters).
+   */
+  public char previous()
+  {
+    if (count == 0
+	|| current == getBeginIndex())
+      return DONE;
+    
+    current--;
+    return array[current];
+  }
+
+  /**
+   * Sets the current index and returns the character at that position (or
+   * {@link #DONE} if the index is equal to {@link #getEndIndex()}.
+   * 
+   * @param position  the current position.
+   * 
+   * @return The character at the specified <code>position</code>, or
+   *         {@link #DONE} if <code>position</code> is equal to 
+   *         {@link #getEndIndex()}.
+   *         
+   * @throws IllegalArgumentException if <code>position</code> is not in the
+   *         range {@link #getBeginIndex()} to {@link #getEndIndex()}.
+   */
+  public char setIndex(int position)
+  {
+    if (position < getBeginIndex()
+	|| position > getEndIndex())
+      throw new IllegalArgumentException("position: " + position
+                                         + ", beginIndex: " + getBeginIndex()
+                                         + ", endIndex: " + getEndIndex()
+                                         + ", text: " + toString());
+
+    current = position;
+
+    if (position == getEndIndex())
+      return DONE;
+    
+    return array[current];
+  }
+
+  /**
+   * Returns a <code>String</code> containing the same characters as this 
+   * <code>Segment</code>.
+   * 
+   * @return A <code>String</code> containing the same characters as this 
+   *         <code>Segment</code>.
+   */
+  public String toString()
+  {
+    return (array != null) ? new String(array, offset, count) : "";
+  }
+
+  /**
+   * Sets the partial return flag.
+   * 
+   * @param p  the new value of the flag.
+   * 
+   * @since 1.4
+   */
+  public void setPartialReturn(boolean p)
+  {
+    partialReturn = p;
+  }
+  
+  /**
+   * Returns the partial return flag.
+   * 
+   * @return The partial return flag.
+   * @since 1.4
+   */
+  public boolean isPartialReturn()
+  {
+    return partialReturn;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,407 @@
+/* SimpleAttributeSet.java --
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * A set of attributes.
+ */
+public class SimpleAttributeSet
+  implements MutableAttributeSet, Serializable, Cloneable
+{
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 8267656273837665219L;
+
+  /**
+   * An empty attribute set.
+   */
+  public static final AttributeSet EMPTY = new EmptyAttributeSet();
+
+  /** Storage for the attributes. */
+  Hashtable tab;
+
+  /**
+   * Creates a new attribute set that is initially empty.
+   */
+  public SimpleAttributeSet()
+  {
+    tab = new Hashtable();
+  }
+  
+  /**
+   * Creates a new <code>SimpleAttributeSet</code> with the same attributes
+   * and resolve parent as the specified set.
+   * 
+   * @param a  the attributes (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   */
+  public SimpleAttributeSet(AttributeSet a)
+  {
+    tab = new Hashtable();
+    addAttributes(a);
+  }
+
+  /**
+   * Adds an attribute with the given <code>name</code> and <code>value</code>
+   * to the set.  If the set already contains an attribute with the given
+   * <code>name</code>, the attribute value is updated.
+   * 
+   * @param name  the attribute name (<code>null</code> not permitted).
+   * @param value  the value (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   */
+  public void addAttribute(Object name, Object value)
+  {
+    tab.put(name, value);
+  }
+
+  /**
+   * Adds all the attributes from <code>attributes</code> to this set.
+   * 
+   * @param attributes  the set of attributes to add (<code>null</code> not
+   *                    permitted).
+   *                    
+   * @throws NullPointerException if <code>attributes</code> is 
+   *         <code>null</code>.
+   */
+  public void addAttributes(AttributeSet attributes)
+  {
+    Enumeration e = attributes.getAttributeNames();
+    while (e.hasMoreElements())
+      {
+        Object name = e.nextElement();
+        Object val = attributes.getAttribute(name);
+        tab.put(name, val);
+      }
+  }
+
+  /**
+   * Returns a clone of the attribute set.
+   * 
+   * @return A clone of the attribute set.
+   */
+  public Object clone()
+  {
+    SimpleAttributeSet s = new SimpleAttributeSet();
+    s.tab = (Hashtable) tab.clone();
+    return s;
+  }
+
+  /**
+   * Returns true if the given name and value represent an attribute
+   * found either in this AttributeSet or in its resolve parent hierarchy.
+   * @param name the key for the attribute
+   * @param value the value for the attribute
+   * @return true if the attribute is found here or in this set's resolve
+   * parent hierarchy
+   */
+  public boolean containsAttribute(Object name, Object value)
+  {
+    if (value == null)
+      throw new NullPointerException("Null 'value' argument.");
+    if (tab.containsKey(name))
+      return tab.get(name).equals(value);
+    else
+      {
+        AttributeSet p = getResolveParent();
+        if (p != null)
+          return p.containsAttribute(name, value);
+        else
+          return false;
+      }
+  }
+  
+  /**
+   * Returns true if the given name and value are found in this AttributeSet.
+   * Does not check the resolve parent.
+   * @param name the key for the attribute
+   * @param value the value for the attribute
+   * @return true if the attribute is found in this AttributeSet
+   */
+  boolean containsAttributeLocally(Object name, Object value)
+  {
+    return tab.containsKey(name) 
+      && tab.get(name).equals(value);
+  }
+
+  /**
+   * Returns <code>true</code> of this <code>AttributeSet</code> contains all
+   * of the specified <code>attributes</code>.
+   *
+   * @param attributes the requested attributes
+   *
+   * @return <code>true</code> of this <code>AttributeSet</code> contains all
+   *         of the specified <code>attributes</code>
+   */
+  public boolean containsAttributes(AttributeSet attributes)
+  {
+    Enumeration e = attributes.getAttributeNames();
+    while (e.hasMoreElements())
+      {
+        Object name = e.nextElement();
+        Object val = attributes.getAttribute(name);
+        if (! containsAttribute(name, val))
+          return false;		
+      }
+    return true;
+  }
+
+  /**
+   * Creates and returns a copy of this <code>AttributeSet</code>.
+   *
+   * @return a copy of this <code>AttributeSet</code>
+   */
+  public AttributeSet copyAttributes()
+  {
+    return (AttributeSet) clone();
+  }
+
+  /**
+   * Checks this set for equality with an arbitrary object.
+   * 
+   * @param obj  the object (<code>null</code> permitted).
+   * 
+   * @return <code>true</code> if this set is equal to <code>obj</code>, and
+   *         <code>false</code> otherwise. 
+   */
+  public boolean equals(Object obj)
+  {
+    return 
+      (obj instanceof AttributeSet)
+      && this.isEqual((AttributeSet) obj);
+  }
+
+  /**
+   * Returns the value of the specified attribute, or <code>null</code> if 
+   * there is no attribute with that name.  If the attribute is not defined
+   * directly in this set, the parent hierarchy (if there is one) will be
+   * used.
+   * 
+   * @param name  the attribute (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>name</code> is <code>null</code>.
+   */
+  public Object getAttribute(Object name)
+  {
+    Object val = tab.get(name);
+    if (val != null) 
+      return val;
+
+    AttributeSet p = getResolveParent();
+    if (p != null)
+      return p.getAttribute(name);
+
+    return null;
+  }
+
+  /**
+   * Returns the number of attributes stored in this set, plus 1 if a parent
+   * has been specified (the reference to the parent is stored as a special 
+   * attribute).  The attributes stored in the parent do NOT contribute
+   * to the count.
+   * 
+   * @return The attribute count.
+   */
+  public int getAttributeCount()
+  {
+    return tab.size();
+  }
+
+  /**
+   * Returns an enumeration of the attribute names.
+   * 
+   * @return An enumeration of the attribute names.
+   */
+  public Enumeration getAttributeNames()
+  {
+    return tab.keys();
+  }
+
+  /**
+   * Returns the resolving parent.
+   * 
+   * @return The resolving parent (possibly <code>null</code>).
+   * 
+   * @see #setResolveParent(AttributeSet)
+   */
+  public AttributeSet getResolveParent()
+  {
+    return (AttributeSet) tab.get(ResolveAttribute);
+  }
+
+  /**
+   * Returns a hash code for this instance.
+   * 
+   * @return A hash code.
+   */
+  public int hashCode()
+  {
+    return tab.hashCode();
+  }
+
+  /**
+   * Returns <code>true</code> if the given attribute is defined in this set,
+   * and <code>false</code> otherwise.  The parent attribute set is not
+   * checked.
+   * 
+   * @param attrName  the attribute name (<code>null</code> not permitted).
+   */
+  public boolean isDefined(Object attrName)
+  {
+    return tab.containsKey(attrName);
+  }
+
+  /**
+   * Returns <code>true</code> if the set contains no attributes, and 
+   * <code>false</code> otherwise.  Note that the resolving parent is 
+   * stored as an attribute, so this method will return <code>false</code> if 
+   * a resolving parent is set.
+   * 
+   * @return <code>true</code> if the set contains no attributes, and 
+   * <code>false</code> otherwise.
+   */
+  public boolean isEmpty()
+  {
+    return tab.isEmpty();	
+  }
+
+  /**
+   * Returns true if the given set has the same number of attributes
+   * as this set and <code>containsAttributes(attr)</code> returns
+   * <code>true</code>.
+   * 
+   * @param attr  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return A boolean.
+   * 
+   * @throws NullPointerException if <code>attr</code> is <code>null</code>.
+   */
+  public boolean isEqual(AttributeSet attr)
+  {
+    return getAttributeCount() == attr.getAttributeCount()
+      && this.containsAttributes(attr);
+  }
+    
+  /**
+   * Removes the attribute with the specified <code>name</code>, if this 
+   * attribute is defined.  This method will only remove an attribute from
+   * this set, not from the resolving parent.
+   * 
+   * @param name  the attribute name (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>name</code> is <code>null</code>.
+   */
+  public void removeAttribute(Object name)
+  {
+    tab.remove(name);
+  }
+
+  /**
+   * Removes attributes from this set if they are found in the 
+   * given set.  Only attributes whose key AND value are removed.
+   * Removes attributes only from this set, not from the resolving parent.  
+   * Since the resolving parent is stored as an attribute, if 
+   * <code>attributes</code> has the same resolving parent as this set, the
+   * parent will be removed from this set.
+   * 
+   * @param attributes  the attributes (<code>null</code> not permitted).
+   */
+  public void removeAttributes(AttributeSet attributes)
+  {
+    Enumeration e = attributes.getAttributeNames();
+    while (e.hasMoreElements())
+      {
+        Object name = e.nextElement();
+        Object val = attributes.getAttribute(name);
+        if (containsAttributeLocally(name, val))
+          removeAttribute(name);     
+      }
+  }
+
+  /**
+   * Removes the attributes listed in <code>names</code>.
+   * 
+   * @param names  the attribute names (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>names</code> is <code>null</code> 
+   *         or contains any <code>null</code> values.
+   */
+  public void removeAttributes(Enumeration names)
+  {
+    while (names.hasMoreElements())
+      {
+        removeAttribute(names.nextElement());
+      }	
+  }
+
+  /**
+   * Sets the reolving parent for this set.  When looking up an attribute, if
+   * it is not found in this set, then the resolving parent is also used for
+   * the lookup.
+   * <p>
+   * Note that the parent is stored as an attribute, and will contribute 1 to 
+   * the count returned by {@link #getAttributeCount()}. 
+   * 
+   * @param parent  the parent attribute set (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if <code>parent</code> is <code>null</code>.
+   * 
+   * @see #setResolveParent(AttributeSet)
+   */
+  public void setResolveParent(AttributeSet parent)
+  {
+    addAttribute(ResolveAttribute, parent);
+  }
+  
+  /**
+   * Returns a string representation of this instance, typically used for
+   * debugging purposes.
+   * 
+   * @return A string representation of this instance.
+   */
+  public String toString()
+  {
+    return tab.toString();
+  }    
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,410 @@
+/* StringContent.java --
+   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * An implementation of the <code>AbstractDocument.Content</code>
+ * interface useful for small documents or debugging. The character
+ * content is a simple character array. It's not really efficient.
+ * 
+ * <p>Do not use this class for large size.</p>
+ */
+public final class StringContent 
+  implements AbstractDocument.Content, Serializable
+{
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 4755994433709540381L;
+
+  // This is package-private to avoid an accessor method.
+  char[] content;
+
+  private int count;
+
+  private Vector positions = new Vector();
+
+  private class InsertUndo extends AbstractUndoableEdit
+  {
+    private int start;
+    
+    private int length;
+
+    private String redoContent;
+
+    public InsertUndo(int start, int length)
+    {
+      super();
+      this.start = start;
+      this.length = length;
+    }
+
+    public void undo()
+    {
+      super.undo();
+      try
+        {
+          StringContent.this.checkLocation(this.start, this.length);
+          this.redoContent = new String(StringContent.this.content, this.start,
+              this.length);
+          StringContent.this.remove(this.start, this.length);
+        }
+      catch (BadLocationException b)
+        {
+          throw new CannotUndoException();
+        }
+    }
+    
+    public void redo()
+    {
+      super.redo();
+      try
+        {
+          StringContent.this.insertString(this.start, this.redoContent);
+        }
+      catch (BadLocationException b)
+        {
+          throw new CannotRedoException();
+        }
+    }
+  }
+
+  private class RemoveUndo extends AbstractUndoableEdit
+  {
+    private int start;
+
+    private String undoString;
+
+    public RemoveUndo(int start, String str)
+    {
+      super();
+      this.start = start;
+      this.undoString = str;
+    }
+
+    public void undo()
+    {
+      super.undo();
+      try
+        {
+          StringContent.this.insertString(this.start, this.undoString);
+        }
+      catch (BadLocationException bad)
+        {
+          throw new CannotUndoException();
+        }
+    }
+
+    public void redo()
+    {
+      super.redo();
+      try
+        {
+          int end = this.undoString.length();
+          StringContent.this.remove(this.start, end);
+        }
+      catch (BadLocationException bad)
+        {
+          throw new CannotRedoException();
+        }
+    }
+  }
+
+  private class StickyPosition implements Position
+  {
+    private int offset = -1;
+
+    public StickyPosition(int offset)
+    {
+      this.offset = offset;
+    }
+
+    // This is package-private to avoid an accessor method.
+    void setOffset(int offset)
+    {
+      this.offset = this.offset >= 0 ? offset : -1;
+    }
+
+    /**
+     * Should be >=0.
+     */
+    public int getOffset()
+    {
+      return offset < 0 ? 0 : offset;
+    }
+  }
+
+  /**
+   * Creates a new instance containing the string "\n".  This is equivalent
+   * to calling {@link #StringContent(int)} with an <code>initialLength</code>
+   * of 10.
+   */
+  public StringContent()
+  {
+    this(10);
+  }
+
+  /**
+   * Creates a new instance containing the string "\n".
+   * 
+   * @param initialLength  the initial length of the underlying character 
+   *                       array used to store the content.
+   */
+  public StringContent(int initialLength)
+  {
+    super();
+    if (initialLength < 1)
+      initialLength = 1;
+    this.content = new char[initialLength];
+    this.content[0] = '\n';
+    this.count = 1;
+  }
+
+  protected Vector getPositionsInRange(Vector v,
+                                       int offset,
+                                       int length)
+  {
+    Vector refPos = new Vector();
+    Iterator iter = this.positions.iterator();
+    while(iter.hasNext())
+      {
+        Position p = (Position) iter.next();
+        if ((offset <= p.getOffset())
+            && (p.getOffset() <= (offset + length)))
+          refPos.add(p);
+      }
+    return refPos;
+  }
+
+  /**
+   * Creates a position reference for the character at the given offset.  The
+   * position offset will be automatically updated when new characters are
+   * inserted into or removed from the content.
+   * 
+   * @param offset  the character offset.
+   * 
+   * @throws BadLocationException if offset is outside the bounds of the 
+   *         content.
+   */
+  public Position createPosition(int offset) throws BadLocationException
+  {
+    if (offset < this.count || offset > this.count)
+      checkLocation(offset, 0);
+    StickyPosition sp = new StickyPosition(offset);
+    this.positions.add(sp);
+    return sp;
+  }
+  
+  /**
+   * Returns the length of the string content, including the '\n' character at
+   * the end.
+   * 
+   * @return The length of the string content.
+   */
+  public int length()
+  {
+    return this.count;
+  }
+  
+  /**
+   * Inserts <code>str</code> at the given position and returns an 
+   * {@link UndoableEdit} that enables undo/redo support.
+   * 
+   * @param where  the insertion point (must be less than 
+   *               <code>length()</code>).
+   * @param str  the string to insert (<code>null</code> not permitted).
+   * 
+   * @return An object that can undo the insertion.
+   */
+  public UndoableEdit insertString(int where, String str)
+    throws BadLocationException
+  {
+    checkLocation(where, 0);
+    if (where == this.count)
+      throw new BadLocationException("Invalid location", 1);
+    if (str == null)
+      throw new NullPointerException();
+    char[] insert = str.toCharArray();
+    char[] temp = new char[this.content.length + insert.length];
+    this.count += insert.length;
+    // Copy array and insert the string.
+    if (where > 0)
+      System.arraycopy(this.content, 0, temp, 0, where);
+    System.arraycopy(insert, 0, temp, where, insert.length);
+    System.arraycopy(this.content, where, temp, (where + insert.length), 
+        (temp.length - where - insert.length));
+    if (this.content.length < temp.length)
+      this.content = new char[temp.length];
+    // Copy the result in the original char array.
+    System.arraycopy(temp, 0, this.content, 0, temp.length);
+    // Move all the positions.
+    Vector refPos = getPositionsInRange(this.positions, where, 
+                                        temp.length - where);
+    Iterator iter = refPos.iterator();
+    while (iter.hasNext())
+      {
+        StickyPosition p = (StickyPosition)iter.next();
+        p.setOffset(p.getOffset() + str.length());
+      }
+    InsertUndo iundo = new InsertUndo(where, insert.length);
+    return iundo;
+  }
+  
+  /**
+   * Removes the specified range of characters and returns an 
+   * {@link UndoableEdit} that enables undo/redo support.
+   * 
+   * @param where  the starting index.
+   * @param nitems  the number of characters.
+   * 
+   * @return An object that can undo the removal.
+   * 
+   * @throws BadLocationException if the character range extends outside the
+   *         bounds of the content OR includes the last character.
+   */
+  public UndoableEdit remove(int where, int nitems) throws BadLocationException
+  {
+    checkLocation(where, nitems + 1);
+    char[] temp = new char[(this.content.length - nitems)];
+    this.count = this.count - nitems;
+    RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where, 
+        nitems));
+    // Copy array.
+    System.arraycopy(this.content, 0, temp, 0, where);
+    System.arraycopy(this.content, where + nitems, temp, where, 
+        this.content.length - where - nitems);
+    this.content = new char[temp.length];
+    // Then copy the result in the original char array.
+    System.arraycopy(temp, 0, this.content, 0, this.content.length);
+    // Move all the positions.
+    Vector refPos = getPositionsInRange(this.positions, where, 
+        this.content.length + nitems - where);
+    Iterator iter = refPos.iterator();
+    while (iter.hasNext())
+      {
+        StickyPosition p = (StickyPosition)iter.next();
+        int result = p.getOffset() - nitems;
+        p.setOffset(result);
+        if (result < 0)
+          this.positions.remove(p);
+      }
+    return rundo;
+  }
+  
+  /**
+   * Returns a new <code>String</code> containing the characters in the 
+   * specified range.
+   * 
+   * @param where  the start index.
+   * @param len  the number of characters.
+   * 
+   * @return A string.
+   * 
+   * @throws BadLocationException if the requested range of characters extends 
+   *         outside the bounds of the content.
+   */
+  public String getString(int where, int len) throws BadLocationException
+  {
+    checkLocation(where, len);
+    return new String(this.content, where, len);
+  }
+  
+  /**
+   * Updates <code>txt</code> to contain a direct reference to the underlying 
+   * character array.
+   * 
+   * @param where  the index of the first character.
+   * @param len  the number of characters.
+   * @param txt  a carrier for the return result (<code>null</code> not 
+   *             permitted).
+   *             
+   * @throws BadLocationException if the requested character range is not 
+   *                              within the bounds of the content.
+   * @throws NullPointerException if <code>txt</code> is <code>null</code>.
+   */
+  public void getChars(int where, int len, Segment txt) 
+    throws BadLocationException
+  {
+    checkLocation(where, len);
+    txt.array = this.content;
+    txt.offset = where;
+    txt.count = len;
+  }
+
+
+  /**
+   * @specnote This method is not very well specified and the positions vector
+   *           is implementation specific. The undo positions are managed
+   *           differently in this implementation, this method is only here
+   *           for binary compatibility.
+   */
+  protected void updateUndoPositions(Vector positions)
+  {
+    // We do nothing here.
+  }
+
+  /** 
+   * A utility method that checks the validity of the specified character
+   * range.
+   * 
+   * @param where  the first character in the range.
+   * @param len  the number of characters in the range.
+   * 
+   * @throws BadLocationException if the specified range is not within the
+   *         bounds of the content.
+   */
+  void checkLocation(int where, int len) throws BadLocationException
+  {
+    if (where < 0)
+      throw new BadLocationException("Invalid location", 1);
+    else if (where > this.count)
+      throw new BadLocationException("Invalid location", this.count);
+    else if ((where + len) > this.count)
+      throw new BadLocationException("Invalid range", this.count);
+  }
+  
+}
+

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,64 @@
+/* Style.java -- 
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import javax.swing.event.ChangeListener;
+
+public interface Style extends MutableAttributeSet
+{
+  /**
+   * Returns the name of the style.
+   *
+   * @return the name
+   */
+  String getName();
+
+  /**
+   * Adds a <code>ChangeListener</code> object to the style.
+   *
+   * @param listener the listener object to add
+   */
+  void addChangeListener(ChangeListener listener);
+
+  /**
+   * Removes a <code>ChangeListener</code> from to the style.
+   *
+   * @param listener the listener object to remove,
+   */
+  void removeChangeListener(ChangeListener listener);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1072 @@
+/* StyleConstants.java --
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Component;
+
+import javax.swing.Icon;
+
+/**
+ * Represents standard attribute keys.  This class also contains a set of 
+ * useful static utility methods for querying and populating an 
+ * {@link AttributeSet}.
+ * 
+ * @since 1.2
+ */
+public class StyleConstants
+{
+  /** 
+   * A value representing left alignment for the 
+   * {@link ParagraphConstants#Alignment} attribute. 
+   */
+  public static final int ALIGN_LEFT = 0;
+
+  /** 
+   * A value representing center alignment for the 
+   * {@link ParagraphConstants#Alignment} attribute. 
+   */
+  public static final int ALIGN_CENTER = 1;
+
+  /** 
+   * A value representing right alignment for the 
+   * {@link ParagraphConstants#Alignment} attribute. 
+   */
+  public static final int ALIGN_RIGHT = 2;
+
+  /** 
+   * A value representing ful justification for the 
+   * {@link ParagraphConstants#Alignment} attribute. 
+   */
+  public static final int ALIGN_JUSTIFIED = 3;
+
+  /** An alias for {@link CharacterConstants#Background}. */
+  public static final Object Background = CharacterConstants.Background;
+
+  /** An alias for {@link CharacterConstants#BidiLevel}. */
+  public static final Object BidiLevel = CharacterConstants.BidiLevel;
+  
+  /** An alias for {@link CharacterConstants#Bold}. */
+  public static final Object Bold = CharacterConstants.Bold;
+  
+  /** An alias for {@link CharacterConstants#ComponentAttribute}. */
+  public static final Object ComponentAttribute 
+      = CharacterConstants.ComponentAttribute;
+  
+  /** An alias for {@link CharacterConstants#Family}. */
+  public static final Object Family = CharacterConstants.Family;
+  
+  /** An alias for {@link CharacterConstants#Family}. */
+  public static final Object FontFamily = CharacterConstants.Family;  
+  
+  /** An alias for {@link CharacterConstants#Size}. */
+  public static final Object FontSize = CharacterConstants.Size;
+  
+  /** An alias for {@link CharacterConstants#Foreground}. */
+  public static final Object Foreground = CharacterConstants.Foreground;
+  
+  /** An alias for {@link CharacterConstants#IconAttribute}. */
+  public static final Object IconAttribute = CharacterConstants.IconAttribute;
+  
+  /** An alias for {@link CharacterConstants#Italic}. */
+  public static final Object Italic = CharacterConstants.Italic;
+  
+  /** An alias for {@link CharacterConstants#Size}. */
+  public static final Object Size = CharacterConstants.Size;
+  
+  /** An alias for {@link CharacterConstants#StrikeThrough}. */
+  public static final Object StrikeThrough = CharacterConstants.StrikeThrough;
+  
+  /** An alias for {@link CharacterConstants#Subscript}. */
+  public static final Object Subscript = CharacterConstants.Subscript;
+  
+  /** An alias for {@link CharacterConstants#Superscript}. */
+  public static final Object Superscript = CharacterConstants.Superscript;
+  
+  /** An alias for {@link CharacterConstants#Underline}. */
+  public static final Object Underline = CharacterConstants.Underline;
+
+  /** An alias for {@link ParagraphConstants#Alignment}. */
+  public static final Object Alignment = ParagraphConstants.Alignment;
+  
+  /** An alias for {@link ParagraphConstants#FirstLineIndent}. */
+  public static final Object FirstLineIndent 
+      = ParagraphConstants.FirstLineIndent;
+  
+  /** An alias for {@link ParagraphConstants#LeftIndent}. */
+  public static final Object LeftIndent = ParagraphConstants.LeftIndent;
+  
+  /** An alias for {@link ParagraphConstants#LineSpacing}. */
+  public static final Object LineSpacing = ParagraphConstants.LineSpacing;
+  
+  /** An alias for {@link ParagraphConstants#Orientation}. */
+  public static final Object Orientation = ParagraphConstants.Orientation;
+  
+  /** An alias for {@link ParagraphConstants#RightIndent}. */
+  public static final Object RightIndent = ParagraphConstants.RightIndent;
+  
+  /** An alias for {@link ParagraphConstants#SpaceAbove}. */
+  public static final Object SpaceAbove = ParagraphConstants.SpaceAbove;
+  
+  /** An alias for {@link ParagraphConstants#SpaceBelow}. */
+  public static final Object SpaceBelow = ParagraphConstants.SpaceBelow;
+  
+  /** An alias for {@link ParagraphConstants#TabSet}. */
+  public static final Object TabSet = ParagraphConstants.TabSet;
+
+  public static final String ComponentElementName = "component";
+
+  public static final String IconElementName = "icon";
+
+  public static final Object ComposedTextAttribute 
+      = new StyleConstants("composed text");
+  
+  public static final Object ModelAttribute = new StyleConstants("model");
+  
+  public static final Object NameAttribute = new StyleConstants("name");
+  
+  public static final Object ResolveAttribute = new StyleConstants("resolver");
+
+  String keyname;
+
+  // Package-private to avoid accessor constructor for use by
+  // subclasses.
+  StyleConstants(String k) 
+  {
+    keyname = k;
+  }
+
+  /**
+   * Returns a string representation of the attribute key.
+   * 
+   * @return A string representation of the attribute key.
+   */
+  public String toString()
+  {
+    return keyname;
+  }
+
+  /**
+   * Returns the alignment specified in the given attributes, or 
+   * {@link #ALIGN_LEFT} if no alignment is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The alignment (typically one of {@link #ALIGN_LEFT}, 
+   *         {@link #ALIGN_RIGHT}, {@link #ALIGN_CENTER} or 
+   *         {@link #ALIGN_JUSTIFIED}).
+   *         
+   * @see #setAlignment(MutableAttributeSet, int)
+   */
+  public static int getAlignment(AttributeSet a)
+  {
+    Integer i = (Integer) a.getAttribute(Alignment);
+    if (i != null)
+      return i.intValue();
+    else
+      return ALIGN_LEFT;      
+  } 
+
+  /**
+   * Returns the background color specified in the given attributes, or
+   * {@link Color#BLACK} if no background color is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The background color.
+   * 
+   * @see #setBackground(MutableAttributeSet, Color)
+   */
+  public static Color getBackground(AttributeSet a)
+  {
+    Color c = (Color) a.getAttribute(Background);
+    if (c != null) 
+      return c;
+    else
+      return Color.BLACK;
+  } 
+
+  /**
+   * Returns the bidi level specified in the given attributes, or 
+   * <code>0</code> if no bidi level is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The bidi level.
+   * 
+   * @see #setBidiLevel(MutableAttributeSet, int)
+   */  
+  public static int getBidiLevel(AttributeSet a)
+  {
+    Integer i = (Integer) a.getAttribute(BidiLevel);
+    if (i != null)
+      return i.intValue();
+    else
+      return 0;
+  } 
+
+  /**
+   * Returns the component specified in the given attributes, or 
+   * <code>null</code> if no component is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The component (possibly <code>null</code>).
+   * 
+   * @see #setComponent(MutableAttributeSet, Component)
+   */    
+  public static Component getComponent(AttributeSet a)
+  {
+    Component c = (Component) a.getAttribute(ComponentAttribute);
+    if (c != null)
+      return c;
+    else
+      return null;
+  } 
+
+  /**
+   * Returns the indentation specified in the given attributes, or 
+   * <code>0.0f</code> if no indentation is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The indentation.
+   * 
+   * @see #setFirstLineIndent(MutableAttributeSet, float)
+   */    
+  public static float getFirstLineIndent(AttributeSet a)
+  {
+    Float f = (Float) a.getAttribute(FirstLineIndent);
+    if (f != null)
+      return f.floatValue();
+    else
+      return 0.0f;
+  } 
+
+  /**
+   * Returns the font family specified in the given attributes, or 
+   * <code>Monospaced</code> if no font family is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The font family.
+   * 
+   * @see #setFontFamily(MutableAttributeSet, String)
+   */    
+  public static String getFontFamily(AttributeSet a)
+  {
+    String ff = (String) a.getAttribute(FontFamily);
+    if (ff != null)
+      return ff;
+    else
+      return "Monospaced";
+  } 
+
+  /**
+   * Returns the font size specified in the given attributes, or 
+   * <code>12</code> if no font size is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The font size.
+   * 
+   * @see #setFontSize(MutableAttributeSet, int)
+   */  
+  public static int getFontSize(AttributeSet a)
+  {
+    Integer i = (Integer) a.getAttribute(FontSize);
+    if (i != null)
+      return i.intValue();
+    else
+      return 12;
+  } 
+
+  /**
+   * Returns the foreground color specified in the given attributes, or
+   * {@link Color#BLACK} if no foreground color is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The foreground color.
+   * 
+   * @see #setForeground(MutableAttributeSet, Color)
+   */
+  public static Color getForeground(AttributeSet a)
+  {
+    Color c = (Color) a.getAttribute(Foreground);
+    if (c != null)
+      return c;
+    else
+      return Color.BLACK;
+  } 
+
+  /**
+   * Returns the icon specified in the given attributes, or 
+   * <code>null</code> if no icon is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The icon (possibly <code>null</code>).
+   * 
+   * @see #setIcon(MutableAttributeSet, Icon)
+   */    
+  public static Icon getIcon(AttributeSet a)
+  {
+    return (Icon) a.getAttribute(IconAttribute);
+  } 
+
+  /**
+   * Returns the left indentation specified in the given attributes, or 
+   * <code>0.0f</code> if no left indentation is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The left indentation.
+   * 
+   * @see #setLeftIndent(MutableAttributeSet, float)
+   */    
+  public static float getLeftIndent(AttributeSet a)
+  {
+    Float f = (Float) a.getAttribute(LeftIndent);
+    if (f != null)
+      return f.floatValue();
+    else
+      return 0.0f;
+  } 
+
+  /**
+   * Returns the line spacing specified in the given attributes, or 
+   * <code>0.0f</code> if no line spacing is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The line spacing.
+   * 
+   * @see #setLineSpacing(MutableAttributeSet, float)
+   */    
+  public static float getLineSpacing(AttributeSet a)
+  {
+    Float f = (Float) a.getAttribute(LineSpacing);
+    if (f != null)
+      return f.floatValue();
+    else
+      return 0.0f;
+  } 
+
+  /**
+   * Returns the right indentation specified in the given attributes, or 
+   * <code>0.0f</code> if no right indentation is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The right indentation.
+   * 
+   * @see #setRightIndent(MutableAttributeSet, float)
+   */    
+  public static float getRightIndent(AttributeSet a)
+  {
+    Float f = (Float) a.getAttribute(RightIndent);
+    if (f != null)
+      return f.floatValue();
+    else
+      return 0.0f;
+  } 
+
+  /**
+   * Returns the 'space above' specified in the given attributes, or 
+   * <code>0.0f</code> if no 'space above' is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The 'space above'.
+   * 
+   * @see #setSpaceAbove(MutableAttributeSet, float)
+   */    
+  public static float getSpaceAbove(AttributeSet a)
+  {
+    Float f = (Float) a.getAttribute(SpaceAbove);
+    if (f != null)
+      return f.floatValue();
+    else 
+      return 0.0f;
+  } 
+
+  /**
+   * Returns the 'space below' specified in the given attributes, or 
+   * <code>0.0f</code> if no 'space below' is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The 'space below'.
+   * 
+   * @see #setSpaceBelow(MutableAttributeSet, float)
+   */    
+  public static float getSpaceBelow(AttributeSet a)
+  {
+    Float f = (Float) a.getAttribute(SpaceBelow);
+    if (f != null)
+      return f.floatValue();
+    else
+      return 0.0f;
+  } 
+
+  /**
+   * Returns the tab set specified in the given attributes, or 
+   * <code>null</code> if no tab set is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The tab set.
+   * 
+   * @see #setTabSet(MutableAttributeSet, javax.swing.text.TabSet)
+   */    
+  public static javax.swing.text.TabSet getTabSet(AttributeSet a)
+  {
+    // I'm guessing that the fully qualified class name is to differentiate
+    // between the TabSet class and the TabSet (attribute) instance on some
+    // compiler...
+    return (javax.swing.text.TabSet) a.getAttribute(StyleConstants.TabSet);
+  } 
+
+  /**
+   * Returns the value of the bold flag in the given attributes, or 
+   * <code>false</code> if no bold flag is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The bold flag.
+   * 
+   * @see #setBold(MutableAttributeSet, boolean)
+   */
+  public static boolean isBold(AttributeSet a)
+  {
+    Boolean b = (Boolean) a.getAttribute(Bold);
+    if (b != null)
+      return b.booleanValue();
+    else
+      return false;
+  } 
+
+  /**
+   * Returns the value of the italic flag in the given attributes, or 
+   * <code>false</code> if no italic flag is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The italic flag.
+   * 
+   * @see #setItalic(MutableAttributeSet, boolean)
+   */
+  public static boolean isItalic(AttributeSet a)
+  {
+    Boolean b = (Boolean) a.getAttribute(Italic);
+    if (b != null)
+      return b.booleanValue();
+    else
+      return false;
+  } 
+
+  /**
+   * Returns the value of the strike-through flag in the given attributes, or 
+   * <code>false</code> if no strike-through flag is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The strike-through flag.
+   * 
+   * @see #setStrikeThrough(MutableAttributeSet, boolean)
+   */
+  public static boolean isStrikeThrough(AttributeSet a)
+  {
+    Boolean b = (Boolean) a.getAttribute(StrikeThrough);
+    if (b != null)
+      return b.booleanValue();
+    else
+      return false;
+  } 
+
+  /**
+   * Returns the value of the subscript flag in the given attributes, or 
+   * <code>false</code> if no subscript flag is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The subscript flag.
+   * 
+   * @see #setSubscript(MutableAttributeSet, boolean)
+   */
+  public static boolean isSubscript(AttributeSet a)
+  {
+    Boolean b = (Boolean) a.getAttribute(Subscript);
+    if (b != null)
+      return b.booleanValue();
+    else
+      return false;
+  } 
+
+  /**
+   * Returns the value of the superscript flag in the given attributes, or 
+   * <code>false</code> if no superscript flag is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The superscript flag.
+   * 
+   * @see #setSuperscript(MutableAttributeSet, boolean)
+   */
+  public static boolean isSuperscript(AttributeSet a)
+  {
+    Boolean b = (Boolean) a.getAttribute(Superscript);
+    if (b != null)
+      return b.booleanValue();
+    else 
+      return false;
+  } 
+
+  /**
+   * Returns the value of the underline flag in the given attributes, or 
+   * <code>false</code> if no underline flag is specified.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * 
+   * @return The underline flag.
+   * 
+   * @see #setUnderline(MutableAttributeSet, boolean)
+   */
+  public static boolean isUnderline(AttributeSet a)
+  {
+    Boolean b = (Boolean) a.getAttribute(Underline);
+    if (b != null)
+      return b.booleanValue();
+    else
+      return false;
+  } 
+
+  /**
+   * Adds an alignment attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param align  the alignment (typically one of 
+   *               {@link StyleConstants#ALIGN_LEFT}, 
+   *               {@link StyleConstants#ALIGN_RIGHT}, 
+   *               {@link StyleConstants#ALIGN_CENTER} or 
+   *               {@link StyleConstants#ALIGN_JUSTIFIED}).
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getAlignment(AttributeSet)
+   */
+  public static void setAlignment(MutableAttributeSet a, int align)
+  {
+    a.addAttribute(Alignment, new Integer(align));
+  } 
+
+  /**
+   * Adds a background attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param bg  the background (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   * 
+   * @see #getBackground(AttributeSet)
+   */
+  public static void setBackground(MutableAttributeSet a, Color bg)
+  {
+    a.addAttribute(Background, bg);
+  } 
+
+  /**
+   * Adds a bidi-level attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param lev  the level.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getBidiLevel(AttributeSet)
+   */
+  public static void setBidiLevel(MutableAttributeSet a, int lev)
+  {
+    a.addAttribute(BidiLevel, new Integer(lev));
+  } 
+
+  /**
+   * Adds a bold attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param b  the new value of the bold attribute.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #isBold(AttributeSet)
+   */
+  public static void setBold(MutableAttributeSet a, boolean b)
+  {
+    a.addAttribute(Bold, Boolean.valueOf(b));
+  } 
+  
+  /**
+   * Adds a component attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param c  the component (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   * 
+   * @see #getComponent(AttributeSet)
+   */
+  public static void setComponent(MutableAttributeSet a, Component c)
+  {
+    a.addAttribute(ComponentAttribute, c);
+  } 
+
+  /**
+   * Adds a first line indentation attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param i  the indentation.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getFirstLineIndent(AttributeSet)
+   */
+  public static void setFirstLineIndent(MutableAttributeSet a, float i)
+  {
+    a.addAttribute(FirstLineIndent, new Float(i));
+  } 
+
+  /**
+   * Adds a font family attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param fam  the font family name (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   * 
+   * @see #getFontFamily(AttributeSet)
+   */
+  public static void setFontFamily(MutableAttributeSet a, String fam)
+  {
+    a.addAttribute(FontFamily, fam);
+  } 
+
+  /**
+   * Adds a font size attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param s  the font size (in points).
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getFontSize(AttributeSet)
+   */
+  public static void setFontSize(MutableAttributeSet a, int s)
+  {
+    a.addAttribute(FontSize, new Integer(s));
+  } 
+
+  /**
+   * Adds a foreground color attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param fg  the foreground color (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   * 
+   * @see #getForeground(AttributeSet)
+   */
+  public static void setForeground(MutableAttributeSet a, Color fg)
+  {
+    a.addAttribute(Foreground, fg);
+  }
+
+  /**
+   * Adds an icon attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param c  the icon (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   * 
+   * @see #getIcon(AttributeSet)
+   */
+  public static void setIcon(MutableAttributeSet a, Icon c)
+  {
+    a.addAttribute(IconAttribute, c);
+  }
+ 
+  /**
+   * Adds an italic attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param b  the new value of the italic attribute.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #isItalic(AttributeSet)
+   */
+  public static void setItalic(MutableAttributeSet a, boolean b)
+  {
+    a.addAttribute(Italic, Boolean.valueOf(b));
+  }
+ 
+  /**
+   * Adds a left indentation attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param i  the indentation.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getLeftIndent(AttributeSet)
+   */
+  public static void setLeftIndent(MutableAttributeSet a, float i)
+  {
+    a.addAttribute(LeftIndent, new Float(i));
+  } 
+
+  /**
+   * Adds a line spacing attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param i  the line spacing.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getLineSpacing(AttributeSet)
+   */
+  public static void setLineSpacing(MutableAttributeSet a, float i)
+  {
+    a.addAttribute(LineSpacing, new Float(i));
+  } 
+
+  /**
+   * Adds a right indentation attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param i  the right indentation.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getRightIndent(AttributeSet)
+   */
+  public static void setRightIndent(MutableAttributeSet a, float i)
+  {
+    a.addAttribute(RightIndent, new Float(i));
+  } 
+
+  /**
+   * Adds a 'space above' attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param i  the space above attribute value.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getSpaceAbove(AttributeSet)
+   */
+  public static void setSpaceAbove(MutableAttributeSet a, float i)
+  {
+    a.addAttribute(SpaceAbove, new Float(i));
+  } 
+
+  /**
+   * Adds a 'space below' attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param i  the space below attribute value.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #getSpaceBelow(AttributeSet)
+   */
+  public static void setSpaceBelow(MutableAttributeSet a, float i)
+  {
+    a.addAttribute(SpaceBelow, new Float(i));
+  } 
+
+  /**
+   * Adds a strike-through attribue to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param b  the strike-through attribute value.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #isStrikeThrough(AttributeSet)
+   */
+  public static void setStrikeThrough(MutableAttributeSet a, boolean b)
+  {
+    a.addAttribute(StrikeThrough, Boolean.valueOf(b));
+  } 
+
+  /**
+   * Adds a subscript attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param b  the subscript attribute value.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #isSubscript(AttributeSet)
+   */
+  public static void setSubscript(MutableAttributeSet a, boolean b)
+  {
+    a.addAttribute(Subscript, Boolean.valueOf(b));
+  } 
+
+  /**
+   * Adds a superscript attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param b  the superscript attribute value.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #isSuperscript(AttributeSet)
+   */
+  public static void setSuperscript(MutableAttributeSet a, boolean b)
+  {
+    a.addAttribute(Superscript, Boolean.valueOf(b));
+  } 
+
+  /**
+   * Adds a {@link TabSet} attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param tabs  the tab set (<code>null</code> not permitted).
+   * 
+   * @throws NullPointerException if either argument is <code>null</code>.
+   * 
+   * @see #getTabSet(AttributeSet)
+   */
+  public static void setTabSet(MutableAttributeSet a, 
+                               javax.swing.text.TabSet tabs)
+  {
+    a.addAttribute(StyleConstants.TabSet, tabs);
+  } 
+
+  /**
+   * Adds an underline attribute to the specified set.
+   * 
+   * @param a  the attribute set (<code>null</code> not permitted).
+   * @param b  the underline attribute value.
+   * 
+   * @throws NullPointerException if <code>a</code> is <code>null</code>.
+   * 
+   * @see #isUnderline(AttributeSet)
+   */
+  public static void setUnderline(MutableAttributeSet a, boolean b)
+  {
+    a.addAttribute(Underline, Boolean.valueOf(b));
+  } 
+
+  // The remainder are so-called "typesafe enumerations" which 
+  // alias subsets of the above constants.
+
+  /**
+   * A set of keys for attributes that apply to characters.
+   */
+  public static class CharacterConstants
+    extends StyleConstants
+    implements AttributeSet.CharacterAttribute
+  {
+    /**
+     * Private constructor prevents new instances being created.
+     * 
+     * @param k  the key name.
+     */
+    private CharacterConstants(String k) 
+    {
+      super(k);
+    }
+    
+    /** An alias for {@link ColorConstants#Background}. */
+    public static final Object Background = ColorConstants.Background;
+    
+    /** A key for the bidi level character attribute. */
+    public static final Object BidiLevel = new CharacterConstants("bidiLevel");
+    
+    /** An alias for {@link FontConstants#Bold}. */
+    public static final Object Bold = FontConstants.Bold;
+    
+    /** A key for the component character attribute. */
+    public static final Object ComponentAttribute 
+        = new CharacterConstants("component");
+    
+    /** An alias for {@link FontConstants#Family}. */
+    public static final Object Family = FontConstants.Family;
+    
+    /** An alias for {@link FontConstants#Size}. */
+    public static final Object Size = FontConstants.Size;
+    
+    /** An alias for {@link ColorConstants#Foreground}. */
+    public static final Object Foreground = ColorConstants.Foreground;
+    
+    /** A key for the icon character attribute. */
+    public static final Object IconAttribute = new CharacterConstants("icon");
+    
+    /** A key for the italic character attribute. */
+    public static final Object Italic = FontConstants.Italic;
+    
+    /** A key for the strike through character attribute. */
+    public static final Object StrikeThrough 
+        = new CharacterConstants("strikethrough");
+    
+    /** A key for the subscript character attribute. */
+    public static final Object Subscript = new CharacterConstants("subscript");
+    
+    /** A key for the superscript character attribute. */
+    public static final Object Superscript 
+        = new CharacterConstants("superscript");
+    
+    /** A key for the underline character attribute. */
+    public static final Object Underline = new CharacterConstants("underline");
+  
+  }
+
+  /**
+   * A set of keys for attributes that relate to colors.
+   */
+  public static class ColorConstants
+    extends StyleConstants
+    implements AttributeSet.ColorAttribute, AttributeSet.CharacterAttribute
+  {
+    /**
+     * Private constructor prevents new instances being created.
+     * 
+     * @param k  the key name.
+     */
+    private ColorConstants(String k) 
+    {
+      super(k);
+    }
+    
+    /** A key for the foreground color attribute. */
+    public static final Object Foreground = new ColorConstants("foreground");
+
+    /** A key for the background color attribute. */
+    public static final Object Background = new ColorConstants("background");
+  }
+
+  /**
+   * A set of keys for attributes that apply to fonts.
+   */
+  public static class FontConstants
+    extends StyleConstants
+    implements AttributeSet.FontAttribute, AttributeSet.CharacterAttribute
+  {
+    /**
+     * Private constructor prevents new instances being created.
+     * 
+     * @param k  the key name.
+     */
+    private FontConstants(String k) 
+    {
+      super(k);
+    }
+    
+    /** A key for the bold font attribute. */
+    public static final Object Bold = new FontConstants("bold");
+
+    /** A key for the family font attribute. */
+    public static final Object Family = new FontConstants("family");
+    
+    /** A key for the italic font attribute. */
+    public static final Object Italic = new FontConstants("italic");
+    
+    /** A key for the size font attribute. */
+    public static final Object Size = new FontConstants("size");
+  }
+
+  /**
+   * A set of keys for attributes that apply to paragraphs.
+   */
+  public static class ParagraphConstants
+    extends StyleConstants
+    implements AttributeSet.ParagraphAttribute
+  {
+    /**
+     * Private constructor prevents new instances being created.
+     * 
+     * @param k  the key name.
+     */
+    private ParagraphConstants(String k) 
+    {
+      super(k);
+    }
+    
+    /** A key for the alignment paragraph attribute. */
+    public static final Object Alignment = new ParagraphConstants("Alignment");
+
+    /** A key for the first line indentation paragraph attribute. */
+    public static final Object FirstLineIndent 
+        = new ParagraphConstants("FirstLineIndent");
+    
+    /** A key for the left indentation paragraph attribute. */
+    public static final Object LeftIndent 
+        = new ParagraphConstants("LeftIndent");
+    
+    /** A key for the line spacing paragraph attribute. */
+    public static final Object LineSpacing 
+        = new ParagraphConstants("LineSpacing");
+    
+    /** A key for the orientation paragraph attribute. */
+    public static final Object Orientation 
+        = new ParagraphConstants("Orientation");
+    
+    /** A key for the right indentation paragraph attribute. */
+    public static final Object RightIndent 
+        = new ParagraphConstants("RightIndent");
+    
+    /** A key for the 'space above' paragraph attribute. */
+    public static final Object SpaceAbove 
+        = new ParagraphConstants("SpaceAbove");
+    
+    /** A key for the 'space below' paragraph attribute. */
+    public static final Object SpaceBelow 
+        = new ParagraphConstants("SpaceBelow");
+    
+    /** A key for the tabset paragraph attribute. */
+    public static final Object TabSet = new ParagraphConstants("TabSet");
+    
+  }
+
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,840 @@
+/* StyleContext.java --
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Toolkit;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Hashtable;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.EventListenerList;
+
+public class StyleContext 
+    implements Serializable, AbstractDocument.AttributeContext
+{
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 8042858831190784241L;
+
+  public class NamedStyle
+    implements Serializable, Style
+  {
+    /** The serialization UID (compatible with JDK1.5). */
+    private static final long serialVersionUID = -6690628971806226374L;
+
+    protected ChangeEvent changeEvent;
+    protected EventListenerList listenerList;
+      
+    AttributeSet attributes;
+    String name;
+
+    public NamedStyle()
+    {
+      this(null, null);
+    }
+
+    public NamedStyle(Style parent)
+    {
+      this(null, parent);
+    }
+
+    public NamedStyle(String name, Style parent)
+    {
+      this.name = name;
+      this.attributes = getEmptySet();
+      this.changeEvent = new ChangeEvent(this);
+      this.listenerList = new EventListenerList();
+      setResolveParent(parent);
+    }
+
+    public String getName()
+    {
+      return name;
+    }
+
+    public void setName(String n)
+    {
+      name = n;
+      fireStateChanged();
+    }
+
+    public void addChangeListener(ChangeListener l)
+    {
+      listenerList.add(ChangeListener.class, l);
+    }
+      
+    public void removeChangeListener(ChangeListener l)
+    {
+      listenerList.remove(ChangeListener.class, l);
+    }
+      
+    public EventListener[] getListeners(Class listenerType)
+    {
+      return listenerList.getListeners(listenerType);
+    }
+
+    public ChangeListener[] getChangeListeners()
+    {
+      return (ChangeListener[]) getListeners(ChangeListener.class);
+    }
+
+    protected  void fireStateChanged()
+    {
+      ChangeListener[] listeners = getChangeListeners();
+      for (int i = 0; i < listeners.length; ++i)
+        {
+          listeners[i].stateChanged(changeEvent);
+        }
+    }
+
+    public void addAttribute(Object name, Object value)
+    {
+      attributes = StyleContext.this.addAttribute(attributes, name, value);
+      fireStateChanged();
+    }
+
+    public void addAttributes(AttributeSet attr)
+    {
+      attributes = StyleContext.this.addAttributes(attributes, attr);
+      fireStateChanged();
+    }
+
+    public boolean containsAttribute(Object name, Object value)
+    {
+      return attributes.containsAttribute(name, value);
+    }
+      
+    public boolean containsAttributes(AttributeSet attrs)
+    {
+      return attributes.containsAttributes(attrs);
+    }
+
+    public AttributeSet copyAttributes()
+    {
+      return attributes.copyAttributes();
+    }
+            
+    public Object getAttribute(Object attrName)
+    {
+      return attributes.getAttribute(attrName);
+    }
+
+    public int getAttributeCount()
+    {
+      return attributes.getAttributeCount();
+    }
+
+    public Enumeration getAttributeNames()
+    {
+      return attributes.getAttributeNames();
+    }
+      
+    public boolean isDefined(Object attrName)
+    {
+      return attributes.isDefined(attrName);        
+    }
+
+    public boolean isEqual(AttributeSet attr)
+    {
+      return attributes.isEqual(attr);
+    }
+
+    public void removeAttribute(Object name)
+    {
+      attributes = StyleContext.this.removeAttribute(attributes, name);
+      fireStateChanged();
+    }
+
+    public void removeAttributes(AttributeSet attrs)
+    {
+      attributes = StyleContext.this.removeAttributes(attributes, attrs);
+      fireStateChanged();
+    }
+
+    public void removeAttributes(Enumeration names)
+    {
+      attributes = StyleContext.this.removeAttributes(attributes, names);
+      fireStateChanged();
+    }
+
+
+    public AttributeSet getResolveParent()
+    {
+      return attributes.getResolveParent();        
+    }
+
+    public void setResolveParent(AttributeSet parent)
+    {
+      if (parent != null)
+        {
+          attributes = StyleContext.this.addAttribute
+            (attributes, ResolveAttribute, parent);
+        }
+      fireStateChanged();
+    }
+      
+    public String toString()
+    {
+      return ("[NamedStyle: name=" + name + ", attrs=" + attributes.toString() + "]");
+    }      
+  }
+  
+  public class SmallAttributeSet
+    implements AttributeSet
+  {
+    final Object [] attrs;
+    public SmallAttributeSet(AttributeSet a)
+    {
+      if (a == null)
+        attrs = new Object[0];
+      else
+        {
+          int n = a.getAttributeCount();
+          int i = 0;
+          attrs = new Object[n * 2];
+          Enumeration e = a.getAttributeNames();
+          while (e.hasMoreElements())
+            {
+              Object name = e.nextElement();
+              attrs[i++] = name;
+              attrs[i++] = a.getAttribute(name);
+            }
+        }
+    }
+
+    public SmallAttributeSet(Object [] a)
+    {
+      if (a == null)
+        attrs = new Object[0];
+      else
+        {
+          attrs = new Object[a.length];
+          System.arraycopy(a, 0, attrs, 0, a.length);
+        }
+    }
+
+    public Object clone()
+    {
+      return new SmallAttributeSet(this.attrs);
+    }
+
+    public boolean containsAttribute(Object name, Object value)
+    {
+      for (int i = 0; i < attrs.length; i += 2)
+        {
+          if (attrs[i].equals(name) &&
+              attrs[i+1].equals(value))
+            return true;
+        }
+      return false;
+    }
+
+    public boolean containsAttributes(AttributeSet a)
+    {
+      Enumeration e = a.getAttributeNames();
+      while (e.hasMoreElements())
+        {
+          Object name = e.nextElement();
+          Object val = a.getAttribute(name);
+          if (!containsAttribute(name, val))
+            return false;
+        }
+      return true;			
+    }
+
+    public AttributeSet copyAttributes()
+    {
+      return (AttributeSet) clone();
+    }
+
+    public boolean equals(Object obj)
+    {
+      return 
+        (obj instanceof AttributeSet)
+        && this.isEqual((AttributeSet)obj);
+    }
+ 
+    public Object getAttribute(Object key)
+    {
+      for (int i = 0; i < attrs.length; i += 2)
+        {
+          if (attrs[i].equals(key))
+            return attrs[i+1];
+        }
+            
+      // Check the resolve parent, unless we're looking for the 
+      // ResolveAttribute, which would cause an infinite loop
+      if (!(key.equals(ResolveAttribute)))
+          {
+            Object p = getResolveParent();
+            if (p != null && p instanceof AttributeSet)
+              return (((AttributeSet)p).getAttribute(key));
+          }
+      
+      return null;
+    }
+
+    public int getAttributeCount()
+    {
+      return attrs.length / 2;
+    }
+
+    public Enumeration getAttributeNames()
+    {      
+      return new Enumeration() 
+        {
+          int i = 0;
+          public boolean hasMoreElements() 
+          { 
+            return i < attrs.length; 
+          }
+          public Object nextElement() 
+          { 
+            i += 2; 
+            return attrs[i-2]; 
+          }
+        };
+    }
+
+    public AttributeSet getResolveParent()
+    {
+      return (AttributeSet) getAttribute(ResolveAttribute);
+    }
+
+    public int hashCode()
+    {
+      return java.util.Arrays.asList(attrs).hashCode();
+    }
+
+    public boolean isDefined(Object key)
+    {
+      for (int i = 0; i < attrs.length; i += 2)
+        {
+          if (attrs[i].equals(key))
+            return true;
+        }
+      return false;
+    }
+	
+    public boolean isEqual(AttributeSet attr)
+    {
+      return getAttributeCount() == attr.getAttributeCount()
+             && this.containsAttributes(attr);
+    }
+	
+    public String toString()
+    {
+      StringBuffer sb = new StringBuffer();
+      sb.append("[StyleContext.SmallattributeSet:");
+      for (int i = 0; i < attrs.length - 1; ++i)
+        {
+          sb.append(" (");
+          sb.append(attrs[i].toString());
+          sb.append("=");
+          sb.append(attrs[i+1].toString());
+          sb.append(")");
+        }
+      sb.append("]");
+      return sb.toString();
+    }
+  }
+
+  // FIXME: official javadocs suggest that these might be more usefully
+  // implemented using a WeakHashMap, but not sure if that works most
+  // places or whether it really matters anyways.
+  //
+  // FIXME: also not sure if these tables ought to be static (singletons),
+  // shared across all StyleContexts. I think so, but it's not clear in
+  // docs. revert to non-shared if you think it matters.
+  
+  /**
+   * The name of the default style.
+   */
+  public static final String DEFAULT_STYLE = "default";
+  
+  /**
+   * The default style for this style context.
+   */
+  NamedStyle defaultStyle = new NamedStyle(DEFAULT_STYLE, null);
+  
+  static Hashtable sharedAttributeSets = new Hashtable();
+  static Hashtable sharedFonts = new Hashtable();
+
+  static StyleContext defaultStyleContext = new StyleContext();
+  static final int compressionThreshold = 9;
+
+  /**
+   * These attribute keys are handled specially in serialization.
+   */
+  private static Hashtable staticAttributeKeys = new Hashtable();
+
+  EventListenerList listenerList;
+  Hashtable styleTable;
+  
+  /**
+   * Creates a new instance of the style context. Add the default style
+   * to the style table.
+   */
+  public StyleContext()
+  {
+    listenerList = new EventListenerList();
+    styleTable = new Hashtable();
+    styleTable.put(DEFAULT_STYLE, defaultStyle);
+  }
+
+  protected SmallAttributeSet createSmallAttributeSet(AttributeSet a)
+  {
+    return new SmallAttributeSet(a);
+  }
+  
+  protected MutableAttributeSet createLargeAttributeSet(AttributeSet a)
+  {
+    return new SimpleAttributeSet(a);
+  }
+
+  public void addChangeListener(ChangeListener listener)
+  {
+    listenerList.add(ChangeListener.class, listener);
+  }
+
+  public void removeChangeListener(ChangeListener listener)
+  {
+    listenerList.remove(ChangeListener.class, listener);
+  }
+
+  public ChangeListener[] getChangeListeners()
+  {
+    return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
+  }
+    
+  public Style addStyle(String name, Style parent)
+  {
+    Style newStyle = new NamedStyle(name, parent);
+    if (name != null)
+      styleTable.put(name, newStyle);
+    return newStyle;
+  }
+
+  public void removeStyle(String name)
+  {
+    styleTable.remove(name);
+  }
+
+  /**
+   * Get the style from the style table. If the passed name
+   * matches {@link #DEFAULT_STYLE}, returns the default style.
+   * Otherwise returns the previously defined style of
+   * <code>null</code> if the style with the given name is not defined.
+   *
+   * @param name the name of the style.
+   *
+   * @return the style with the given name or null if no such defined.
+   */
+  public Style getStyle(String name)
+  {
+    return (Style) styleTable.get(name);
+  }
+  
+  /**
+   * Get the names of the style. The returned enumeration always
+   * contains at least one member, the default style.
+   */
+  public Enumeration getStyleNames()
+  {
+    return styleTable.keys();
+  }
+
+  //
+  // StyleContexts only understand the "simple" model of fonts present in
+  // pre-java2d systems: fonts are a family name, a size (integral number
+  // of points), and a mask of style parameters (plain, bold, italic, or
+  // bold|italic). We have an inner class here called SimpleFontSpec which
+  // holds such triples.
+  //
+  // A SimpleFontSpec can be built for *any* AttributeSet because the size,
+  // family, and style keys in an AttributeSet have default values (defined
+  // over in StyleConstants).
+  //
+  // We keep a static cache mapping SimpleFontSpecs to java.awt.Fonts, so
+  // that we reuse Fonts between styles and style contexts.
+  // 
+
+  private static class SimpleFontSpec
+  {
+    String family;
+    int style;
+    int size;
+    public SimpleFontSpec(String family,
+                          int style,
+                          int size)
+    {
+      this.family = family;
+      this.style = style;
+      this.size = size;
+    }
+    public boolean equals(Object obj)
+    {
+      return (obj != null)
+        && (obj instanceof SimpleFontSpec)
+        && (((SimpleFontSpec)obj).family.equals(this.family))
+        && (((SimpleFontSpec)obj).style == this.style)
+        && (((SimpleFontSpec)obj).size == this.size);
+    }
+    public int hashCode()
+    {
+      return family.hashCode() + style + size;
+    }
+  }
+  
+  public Font getFont(AttributeSet attr)
+  {
+    String family = StyleConstants.getFontFamily(attr);
+    int style = Font.PLAIN;
+    if (StyleConstants.isBold(attr))
+      style += Font.BOLD;
+    if (StyleConstants.isItalic(attr))
+      style += Font.ITALIC;      
+    int size = StyleConstants.getFontSize(attr);
+    return getFont(family, style, size);
+  }
+
+  public Font getFont(String family, int style, int size)
+  {
+    SimpleFontSpec spec = new SimpleFontSpec(family, style, size);
+    if (sharedFonts.containsKey(spec))
+      return (Font) sharedFonts.get(spec);
+    else
+      {
+        Font tmp = new Font(family, style, size);
+        sharedFonts.put(spec, tmp);
+        return tmp;
+      }
+  }
+  
+  public FontMetrics getFontMetrics(Font f)
+  {
+    return Toolkit.getDefaultToolkit().getFontMetrics(f);
+  }
+
+  public Color getForeground(AttributeSet a)
+  {
+    return StyleConstants.getForeground(a);
+  }
+
+  public Color getBackground(AttributeSet a)
+  {
+    return StyleConstants.getBackground(a);
+  }
+
+  protected int getCompressionThreshold() 
+  {
+    return compressionThreshold;
+  }
+
+  public static StyleContext getDefaultStyleContext()
+  {
+    return defaultStyleContext;
+  }
+
+  public AttributeSet addAttribute(AttributeSet old, Object name, Object value)
+  {
+    if (old instanceof MutableAttributeSet)
+      {
+        ((MutableAttributeSet)old).addAttribute(name, value);
+        return old;
+      }
+    else 
+      {
+        MutableAttributeSet mutable = createLargeAttributeSet(old);
+        mutable.addAttribute(name, value);
+        if (mutable.getAttributeCount() >= getCompressionThreshold())
+          return mutable;
+        else
+          {
+            SmallAttributeSet small = createSmallAttributeSet(mutable);
+            if (sharedAttributeSets.containsKey(small))
+              small = (SmallAttributeSet) sharedAttributeSets.get(small);
+            else
+              sharedAttributeSets.put(small,small);
+            return small;
+          }
+      }
+  }
+
+  public AttributeSet addAttributes(AttributeSet old, AttributeSet attributes)
+  {
+    if (old instanceof MutableAttributeSet)
+      {
+        ((MutableAttributeSet)old).addAttributes(attributes);
+        return old;
+      }
+    else 
+      {
+        MutableAttributeSet mutable = createLargeAttributeSet(old);
+        mutable.addAttributes(attributes);
+        if (mutable.getAttributeCount() >= getCompressionThreshold())
+          return mutable;
+        else
+          {
+            SmallAttributeSet small = createSmallAttributeSet(mutable);
+            if (sharedAttributeSets.containsKey(small))
+              small = (SmallAttributeSet) sharedAttributeSets.get(small);
+            else
+              sharedAttributeSets.put(small,small);
+            return small;
+          }
+      }
+  }
+
+  public AttributeSet getEmptySet()
+  {
+    AttributeSet e = createSmallAttributeSet(null);
+    if (sharedAttributeSets.containsKey(e))
+      e = (AttributeSet) sharedAttributeSets.get(e);
+    else
+      sharedAttributeSets.put(e, e);
+    return e;
+  }
+
+  public void reclaim(AttributeSet attributes)
+  {
+    if (sharedAttributeSets.containsKey(attributes))
+      sharedAttributeSets.remove(attributes);
+  }
+
+  public AttributeSet removeAttribute(AttributeSet old, Object name)
+  {
+    if (old instanceof MutableAttributeSet)
+      {
+        ((MutableAttributeSet)old).removeAttribute(name);
+        if (old.getAttributeCount() < getCompressionThreshold())
+          {
+            SmallAttributeSet small = createSmallAttributeSet(old);
+            if (!sharedAttributeSets.containsKey(small))
+              sharedAttributeSets.put(small,small);
+            old = (AttributeSet) sharedAttributeSets.get(small);
+          }
+        return old;
+      }
+    else 
+      {          
+        MutableAttributeSet mutable = createLargeAttributeSet(old);
+        mutable.removeAttribute(name);
+        SmallAttributeSet small = createSmallAttributeSet(mutable);
+        if (sharedAttributeSets.containsKey(small))
+          small = (SmallAttributeSet) sharedAttributeSets.get(small);
+        else
+          sharedAttributeSets.put(small,small);
+        return small;
+      }
+  }
+
+  public AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes)
+  {
+    return removeAttributes(old, attributes.getAttributeNames());
+  }
+
+  public AttributeSet removeAttributes(AttributeSet old, Enumeration names)
+  {
+    if (old instanceof MutableAttributeSet)
+      {
+        ((MutableAttributeSet)old).removeAttributes(names);
+        if (old.getAttributeCount() < getCompressionThreshold())
+          {
+            SmallAttributeSet small = createSmallAttributeSet(old);
+            if (!sharedAttributeSets.containsKey(small))
+              sharedAttributeSets.put(small,small);
+            old = (AttributeSet) sharedAttributeSets.get(small);
+          }
+        return old;
+      }
+    else 
+      {          
+        MutableAttributeSet mutable = createLargeAttributeSet(old);
+        mutable.removeAttributes(names);
+        SmallAttributeSet small = createSmallAttributeSet(mutable);
+        if (sharedAttributeSets.containsKey(small))
+          small = (SmallAttributeSet) sharedAttributeSets.get(small);
+        else
+          sharedAttributeSets.put(small,small);
+        return small;
+      }	
+  }
+
+  /**
+   * Gets the object previously registered with registerStaticAttributeKey.
+   * 
+   * @param key - the key that was registered.
+   * @return the object previously registered with registerStaticAttributeKey.
+   */
+  public static Object getStaticAttribute(Object key)
+  {
+    if (key == null)
+      return null;
+    return staticAttributeKeys.get(key);
+  }
+  
+  /**
+   * Returns the String that key will be registered with
+   * registerStaticAttributeKey.
+   * 
+   * @param key - the key that will be registered.
+   * @return the string the key will be registered with.
+   */
+  public static Object getStaticAttributeKey(Object key)
+  {
+    return key.getClass().getName() + "." + key.toString();
+  }
+
+  /**
+   * Reads a set of attributes from the given object input stream. This will
+   * attempt to restore keys that were static objects by considering only the
+   * keys that have were registered with registerStaticAttributeKey. The
+   * attributes retrieved will be placed into the given set.
+   * 
+   * @param in - the stream to read from
+   * @param a - the set of attributes
+   * @throws ClassNotFoundException - may be encountered when reading from
+   *           stream
+   * @throws IOException - any I/O error
+   */
+  public static void readAttributeSet(ObjectInputStream in, MutableAttributeSet a)
+    throws ClassNotFoundException, IOException
+  {
+    if (in == null || a == null)
+      return;
+    
+    Object key = in.readObject();
+    Object val = in.readObject();
+    while (key != null && val != null)
+      {
+        Object staticKey = staticAttributeKeys.get(key);
+        Object staticVal = staticAttributeKeys.get(val);
+        
+        if (staticKey != null)
+          key = staticKey;
+        if (staticVal != null)
+          val = staticVal;
+        
+        a.addAttribute(key, val);
+        key = in.readObject();
+        val = in.readObject();
+      }
+  }
+  
+  /**
+   * Serialize an attribute set in a way that is compatible with it
+   * being read in again by {@link #readAttributeSet(ObjectInputStream, MutableAttributeSet)}.
+   * In particular registered static keys are transformed properly.
+   * 
+   * @param out - stream to write to
+   * @param a - the attribute set
+   * @throws IOException - any I/O error
+   */
+  public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a)
+    throws IOException
+  {
+    Enumeration e = a.getAttributeNames();
+    while (e.hasMoreElements())
+      {
+        Object oldKey = e.nextElement();
+        Object newKey = getStaticAttribute(oldKey);
+        Object key = (newKey == null) ? oldKey : newKey;
+ 
+        out.writeObject(key);
+        out.writeObject(a.getAttribute(oldKey));
+      }
+    out.writeObject(null);
+    out.writeObject(null);
+  }
+
+  /**
+   * Handles reading in the attributes. 
+   * @see #readAttributeSet(ObjectInputStream, MutableAttributeSet)
+   * 
+   * @param in - the stream to read from
+   * @param a - the set of attributes
+   * @throws ClassNotFoundException - may be encountered when reading from stream
+   * @throws IOException - any I/O error
+   */
+  public void readAttributes(ObjectInputStream in, MutableAttributeSet a)
+    throws ClassNotFoundException, IOException
+  {
+    readAttributeSet(in, a);
+  }
+
+  /**
+   * Handles writing of the given attributes.
+   * @see #writeAttributeSet(ObjectOutputStream, AttributeSet)
+   * 
+   * @param out - stream to write to
+   * @param a - the attribute set
+   * @throws IOException - any I/O error
+   */
+  public void writeAttributes(ObjectOutputStream out, AttributeSet a)
+    throws IOException
+  {
+    writeAttributeSet(out, a);
+  }
+
+  /**
+   * Registers an attribute key as a well-known keys. When an attribute with
+   * such a key is written to a stream, a special syntax is used so that it
+   * can be recognized when it is read back in. All attribute keys defined
+   * in <code>StyleContext</code> are registered as static keys. If you define
+   * additional attribute keys that you want to exist as nonreplicated objects,
+   * then you should register them using this method.
+   *
+   * @param key the key to register as static attribute key
+   */
+  public static void registerStaticAttributeKey(Object key)
+  {
+    if (key != null)
+      staticAttributeKeys.put(key.getClass().getName() + "." + key.toString(),
+                              key);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,140 @@
+/* StyledDcoument.java --
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+
+/**
+ * StyledDocument
+ * @author	Andrew Selkirk
+ * @version	1.0
+ */
+public interface StyledDocument extends Document
+{
+  /**
+   * addStyle
+   * @param nm TODO
+   * @param parent TODO
+   * @returns Style
+   */
+  Style addStyle(String nm, Style parent);
+
+  /**
+   * removeStyle
+   * @param nm TODO
+   */
+  void removeStyle(String nm);
+
+  /**
+   * getStyle
+   * @param nm TODO
+   * @returns Style
+   */
+  Style getStyle(String nm);
+
+  /**
+   * setCharacterAttributes
+   * @param offset TODO
+   * @param length TODO
+   * @param set TODO
+   * @param replace TODO
+   */
+  void setCharacterAttributes(int offset, int length, AttributeSet set,
+                              boolean replace);
+
+  /**
+   * setParagraphAttributes
+   * @param offset TODO
+   * @param length TODO
+   * @param set TODO
+   * @param replace TODO
+   */
+  void setParagraphAttributes(int offset, int length, AttributeSet set,
+                              boolean replace);
+
+  /**
+   * getLogicalStyle
+   * @param position TODO
+   * @returns Style
+   */
+  Style getLogicalStyle(int position);
+
+  /**
+   * setLogicalStyle
+   * @param position TODO
+   * @param style TODO
+   */
+  void setLogicalStyle(int position, Style style);
+
+  /**
+   * getParagraphElement
+   * @param position TODO
+   * @returns Element
+   */
+  Element getParagraphElement(int position);
+
+  /**
+   * getCharacterElement
+   * @param position TODO
+   * @returns Element
+   */
+  Element getCharacterElement(int position);
+
+  /**
+   * getForeground
+   * @param set TODO
+   * @returns Color
+   */
+  Color getForeground(AttributeSet set);
+
+  /**
+   * getBackground
+   * @param set TODO
+   * @returns Color
+   */
+  Color getBackground(AttributeSet set);
+
+  /**
+   * getFont
+   * @param set TODO
+   * @returns Font
+   */
+  Font getFont(AttributeSet set);
+
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,721 @@
+/* StyledEditorKit.java --
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+
+import javax.swing.Action;
+import javax.swing.JEditorPane;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+
+/**
+ * An {@link EditorKit} that supports editing styled text.
+ *
+ * @author Andrew Selkirk
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class StyledEditorKit extends DefaultEditorKit
+{
+  /** The serialVersionUID. */
+  private static final long serialVersionUID = 7002391892985555948L;
+
+  /**
+   * Toggles the underline attribute for the selected text.
+   */
+  public static class UnderlineAction extends StyledEditorKit.StyledTextAction
+  {
+    /**
+     * Creates an instance of <code>UnderlineAction</code>.
+     */
+    public UnderlineAction()
+    {
+      super("font-underline");
+    }
+
+    /**
+     * Performs the action.
+     *
+     * @param event the <code>ActionEvent</code> that describes the action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      JEditorPane editor = getEditor(event);
+      StyledDocument doc = getStyledDocument(editor);
+      Element el = doc.getCharacterElement(editor.getSelectionStart());
+      boolean isUnderline = StyleConstants.isUnderline(el.getAttributes());
+      SimpleAttributeSet atts = new SimpleAttributeSet();
+      StyleConstants.setUnderline(atts, ! isUnderline);
+      setCharacterAttributes(editor, atts, false);
+    }
+  }
+
+  /**
+   * Toggles the italic attribute for the selected text.
+   */
+  public static class ItalicAction extends StyledEditorKit.StyledTextAction
+  {
+    /**
+     * Creates an instance of <code>ItalicAction</code>.
+     */
+    public ItalicAction()
+    {
+      super("font-italic");
+    }
+
+    /**
+     * Performs the action.
+     *
+     * @param event the <code>ActionEvent</code> that describes the action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      JEditorPane editor = getEditor(event);
+      StyledDocument doc = getStyledDocument(editor);
+      Element el = doc.getCharacterElement(editor.getSelectionStart());
+      boolean isItalic = StyleConstants.isItalic(el.getAttributes());
+      SimpleAttributeSet atts = new SimpleAttributeSet();
+      StyleConstants.setItalic(atts, ! isItalic);
+      setCharacterAttributes(editor, atts, false);
+    }
+  }
+
+  /**
+   * Toggles the bold attribute for the selected text.
+   */
+  public static class BoldAction extends StyledEditorKit.StyledTextAction
+  {
+    /**
+     * Creates an instance of <code>BoldAction</code>.
+     */
+    public BoldAction()
+    {
+      super("font-bold");
+    }
+
+    /**
+     * Performs the action.
+     *
+     * @param event the <code>ActionEvent</code> that describes the action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      JEditorPane editor = getEditor(event);
+      StyledDocument doc = getStyledDocument(editor);
+      Element el = doc.getCharacterElement(editor.getSelectionStart());
+      boolean isBold = StyleConstants.isBold(el.getAttributes());
+      SimpleAttributeSet atts = new SimpleAttributeSet();
+      StyleConstants.setItalic(atts, ! isBold);
+      setCharacterAttributes(editor, atts, false);
+    }
+  }
+
+  /**
+   * Sets the alignment attribute on the selected text.
+   */
+  public static class AlignmentAction extends StyledEditorKit.StyledTextAction
+  {
+    /**
+     * The aligment to set.
+     */
+    private int a;
+
+    /**
+     * Creates a new instance of <code>AlignmentAction</code> to set the
+     * alignment to <code>a</code>.
+     *
+     * @param nm the name of the Action
+     * @param a the alignment to set
+     */
+    public AlignmentAction(String nm, int a)
+    {
+      super(nm);
+      this.a = a;
+    }
+
+    /**
+     * Performs the action.
+     *
+     * @param event the <code>ActionEvent</code> that describes the action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      SimpleAttributeSet atts = new SimpleAttributeSet();
+      StyleConstants.setAlignment(atts, a);
+      setParagraphAttributes(getEditor(event), atts, false);
+    }
+  }
+
+  /**
+   * Sets the foreground color attribute on the selected text.
+   */
+  public static class ForegroundAction extends StyledEditorKit.StyledTextAction
+  {
+    /**
+     * The foreground color to set.
+     */
+    private Color fg;
+
+    /**
+     * Creates a new instance of <code>ForegroundAction</code> to set the
+     * foreground color to <code>fg</code>.
+     *
+     * @param nm the name of the Action
+     * @param fg the foreground color to set
+     */
+    public ForegroundAction(String nm, Color fg)
+    {
+      super(nm);
+      this.fg = fg;
+    }
+
+    /**
+     * Performs the action.
+     *
+     * @param event the <code>ActionEvent</code> that describes the action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      SimpleAttributeSet atts = new SimpleAttributeSet();
+      StyleConstants.setForeground(atts, fg);
+      setCharacterAttributes(getEditor(event), atts, false);
+    }
+  }
+
+  /**
+   * Sets the font size attribute on the selected text.
+   */
+  public static class FontSizeAction extends StyledEditorKit.StyledTextAction
+  {
+    /**
+     * The font size to set.
+     */
+    private int size;
+
+    /**
+     * Creates a new instance of <code>FontSizeAction</code> to set the
+     * font size to <code>size</code>.
+     *
+     * @param nm the name of the Action
+     * @param size the font size to set
+     */
+    public FontSizeAction(String nm, int size)
+    {
+      super(nm);
+      this.size = size;
+    }
+
+    /**
+     * Performs the action.
+     *
+     * @param event the <code>ActionEvent</code> that describes the action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      SimpleAttributeSet atts = new SimpleAttributeSet();
+      StyleConstants.setFontSize(atts, size);
+      setCharacterAttributes(getEditor(event), atts, false);
+    }
+  }
+
+  /**
+   * Sets the font family attribute on the selected text.
+   */
+  public static class FontFamilyAction extends StyledEditorKit.StyledTextAction
+  {
+    /**
+     * The font family to set.
+     */
+    private String family;
+
+    /**
+     * Creates a new instance of <code>FontFamilyAction</code> to set the
+     * font family to <code>family</code>.
+     *
+     * @param nm the name of the Action
+     * @param family the font family to set
+     */
+    public FontFamilyAction(String nm, String family)
+    {
+      super(nm);
+      this.family = family;
+    }
+
+    /**
+     * Performs the action.
+     *
+     * @param event the <code>ActionEvent</code> that describes the action
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+      SimpleAttributeSet atts = new SimpleAttributeSet();
+      StyleConstants.setFontFamily(atts, family);
+      setCharacterAttributes(getEditor(event), atts, false);
+    }
+  }
+
+  /**
+   * The abstract superclass of all styled TextActions. This class
+   * provides some useful methods to manipulate the text attributes.
+   */
+  public abstract static class StyledTextAction extends TextAction
+  {
+    /**
+     * Creates a new instance of <code>StyledTextAction</code>.
+     *
+     * @param nm the name of the <code>StyledTextAction</code>
+     */
+    public StyledTextAction(String nm)
+    {
+      super(nm);
+    }
+
+    /**
+     * Returns the <code>JEditorPane</code> component from which the
+     * <code>ActionEvent</code> originated.
+     *
+     * @param event the <code>ActionEvent</code>
+     * @return the <code>JEditorPane</code> component from which the
+     *         <code>ActionEvent</code> originated
+     */
+    protected final JEditorPane getEditor(ActionEvent event)
+    {
+      return (JEditorPane) getTextComponent(event);
+    }
+
+    /**
+     * Sets the specified character attributes on the currently selected
+     * text of <code>editor</code>. If <code>editor</code> does not have
+     * a selection, then the attributes are used as input attributes
+     * for newly inserted content.
+     *
+     * @param editor the <code>JEditorPane</code> component
+     * @param atts the text attributes to set
+     * @param replace if <code>true</code> the current attributes of the
+     *        selection are replaces, otherwise they are merged
+     */
+    protected final void setCharacterAttributes(JEditorPane editor,
+                                                AttributeSet atts,
+                                                boolean replace)
+    {
+      Document doc = editor.getDocument();
+      if (doc instanceof StyledDocument)
+	{
+	  StyledDocument styleDoc = (StyledDocument) editor.getDocument();
+	  EditorKit kit = editor.getEditorKit();
+	  if (!(kit instanceof StyledEditorKit))
+	    {
+	      StyledEditorKit styleKit = (StyledEditorKit) kit;
+	      int start = editor.getSelectionStart();
+	      int end = editor.getSelectionEnd();
+	      int dot = editor.getCaret().getDot();
+	      if (start == dot && end == dot)
+		{
+		  // If there is no selection, then we only update the
+		  // input attributes.
+		  MutableAttributeSet inputAttributes =
+		    styleKit.getInputAttributes();
+		  inputAttributes.addAttributes(atts);
+		}
+	      else
+		styleDoc.setCharacterAttributes(start, end, atts, replace);
+	    }
+	  else
+	    throw new AssertionError("The EditorKit for StyledTextActions "
+				     + "is expected to be a StyledEditorKit");
+	}
+      else
+	throw new AssertionError("The Document for StyledTextActions is "
+				 + "expected to be a StyledDocument.");
+    }
+
+    /**
+     * Returns the {@link StyledDocument} that is used by <code>editor</code>.
+     *
+     * @param editor the <code>JEditorPane</code> from which to get the
+     *        <code>StyledDocument</code>
+     *
+     * @return the {@link StyledDocument} that is used by <code>editor</code>
+     */
+    protected final StyledDocument getStyledDocument(JEditorPane editor)
+    {
+      Document doc = editor.getDocument();
+      if (!(doc instanceof StyledDocument))
+	throw new AssertionError("The Document for StyledEditorKits is "
+				 + "expected to be a StyledDocument.");
+
+      return (StyledDocument) doc;
+    }
+
+    /**
+     * Returns the {@link StyledEditorKit} that is used by <code>editor</code>.
+     *
+     * @param editor the <code>JEditorPane</code> from which to get the
+     *        <code>StyledEditorKit</code>
+     *
+     * @return the {@link StyledEditorKit} that is used by <code>editor</code>
+     */
+    protected final StyledEditorKit getStyledEditorKit(JEditorPane editor)
+    {
+      EditorKit kit = editor.getEditorKit();
+      if (!(kit instanceof StyledEditorKit))
+	throw new AssertionError("The EditorKit for StyledDocuments is "
+				 + "expected to be a StyledEditorKit.");
+
+      return (StyledEditorKit) kit;
+    }
+
+    /**
+     * Sets the specified character attributes on the paragraph that
+     * contains the currently selected
+     * text of <code>editor</code>. If <code>editor</code> does not have
+     * a selection, then the attributes are set on the paragraph that
+     * contains the current caret position.
+     *
+     * @param editor the <code>JEditorPane</code> component
+     * @param atts the text attributes to set
+     * @param replace if <code>true</code> the current attributes of the
+     *        selection are replaces, otherwise they are merged
+     */
+    protected final void setParagraphAttributes(JEditorPane editor,
+                                                AttributeSet atts,
+                                                boolean replace)
+    {
+      Document doc = editor.getDocument();
+      if (doc instanceof StyledDocument)
+	{
+	  StyledDocument styleDoc = (StyledDocument) editor.getDocument();
+	  EditorKit kit = editor.getEditorKit();
+	  if (!(kit instanceof StyledEditorKit))
+	    {
+	      StyledEditorKit styleKit = (StyledEditorKit) kit;
+	      int start = editor.getSelectionStart();
+	      int end = editor.getSelectionEnd();
+	      int dot = editor.getCaret().getDot();
+	      if (start == dot && end == dot)
+		{
+		  // If there is no selection, then we only update the
+		  // input attributes.
+		  MutableAttributeSet inputAttributes =
+		    styleKit.getInputAttributes();
+		  inputAttributes.addAttributes(atts);
+		}
+	      else
+		styleDoc.setParagraphAttributes(start, end, atts, replace);
+	    }
+	  else
+	    throw new AssertionError("The EditorKit for StyledTextActions "
+				     + "is expected to be a StyledEditorKit");
+	}
+      else
+	throw new AssertionError("The Document for StyledTextActions is "
+				 + "expected to be a StyledDocument.");
+    }
+  }
+
+  /**
+   * A {@link ViewFactory} that is able to create {@link View}s for
+   * the <code>Element</code>s that are supported by
+   * <code>StyledEditorKit</code>, namely the following types of Elements:
+   *
+   * <ul>
+   * <li>{@link AbstractDocument#ContentElementName}</li>
+   * <li>{@link AbstractDocument#ParagraphElementName}</li>
+   * <li>{@link AbstractDocument#SectionElementName}</li>
+   * <li>{@link StyleConstants#ComponentElementName}</li>
+   * <li>{@link StyleConstants#IconElementName}</li>
+   * </ul>
+   */
+  static class StyledViewFactory
+    implements ViewFactory
+  {
+    /**
+     * Creates a {@link View} for the specified <code>Element</code>.
+     *
+     * @param element the <code>Element</code> to create a <code>View</code>
+     *        for
+     * @return the <code>View</code> for the specified <code>Element</code>
+     *         or <code>null</code> if the type of <code>element</code> is
+     *         not supported
+     */
+    public View create(Element element)
+    {
+      String name = element.getName();
+      View view = null;
+      if (name.equals(AbstractDocument.ContentElementName))
+	view = new LabelView(element);
+      else if (name.equals(AbstractDocument.ParagraphElementName))
+	view = new ParagraphView(element);
+      else if (name.equals(AbstractDocument.SectionElementName))
+	view = new BoxView(element, View.Y_AXIS);
+      else if (name.equals(StyleConstants.ComponentElementName))
+	view = new ComponentView(element);
+      else if (name.equals(StyleConstants.IconElementName))
+	view = new IconView(element);
+      else
+        throw new AssertionError("Unknown Element type: "
+                                 + element.getClass().getName() + " : "
+                                 + name);
+      return view;
+    }
+  }
+
+  /**
+   * Keeps track of the caret position and updates the currentRun
+   * <code>Element</code> and the <code>inputAttributes</code>.
+   */
+  class CaretTracker
+    implements CaretListener
+  {
+    /**
+     * Notifies an update of the caret position.
+     *
+     * @param ev the event for the caret update
+     */
+    public void caretUpdate(CaretEvent ev)
+    {
+      Object source = ev.getSource();
+      if (!(source instanceof JTextComponent))
+	throw new AssertionError("CaretEvents are expected to come from a"
+				 + "JTextComponent.");
+
+      JTextComponent text = (JTextComponent) source;
+      Document doc = text.getDocument();
+      if (!(doc instanceof StyledDocument))
+	throw new AssertionError("The Document used by StyledEditorKits is"
+				 + "expected to be a StyledDocument");
+
+      StyledDocument styleDoc = (StyledDocument) doc;
+      currentRun = styleDoc.getCharacterElement(ev.getDot());
+      createInputAttributes(currentRun, inputAttributes);
+    }
+  }
+
+  /**
+   * Stores the <code>Element</code> at the current caret position. This
+   * is updated by {@link CaretTracker}.
+   */
+  Element currentRun;
+
+  /**
+   * The current input attributes. This is updated by {@link CaretTracker}.
+   */
+  MutableAttributeSet inputAttributes;
+
+  /**
+   * The CaretTracker that keeps track of the current input attributes, and
+   * the current character run Element.
+   */
+  CaretTracker caretTracker;
+
+  /**
+   * The ViewFactory for StyledEditorKits.
+   */
+  StyledViewFactory viewFactory;
+
+  /**
+   * Creates a new instance of <code>StyledEditorKit</code>.
+   */
+  public StyledEditorKit()
+  {
+    inputAttributes = new SimpleAttributeSet();
+  }
+
+  /**
+   * Creates an exact copy of this <code>StyledEditorKit</code>.
+   *
+   * @return an exact copy of this <code>StyledEditorKit</code>
+   */
+  public Object clone()
+  {
+    StyledEditorKit clone = (StyledEditorKit) super.clone();
+    // FIXME: Investigate which fields must be copied.
+    return clone;
+  }
+
+  /**
+   * Returns the <code>Action</code>s supported by this {@link EditorKit}.
+   * This includes the {@link BoldAction}, {@link ItalicAction} and
+   * {@link UnderlineAction} as well as the <code>Action</code>s supported
+   * by {@link DefaultEditorKit}.
+   *
+   * The other <code>Action</code>s of <code>StyledEditorKit</code> are not
+   * returned here, since they require a parameter and thus custom
+   * instantiation.
+   *
+   * @return the <code>Action</code>s supported by this {@link EditorKit}
+   */
+  public Action[] getActions()
+  {
+    Action[] actions1 = super.getActions();
+    Action[] myActions = new Action[] { 
+      new FontSizeAction("font-size-8", 8),
+      new FontSizeAction("font-size-10", 10),
+      new FontSizeAction("font-size-12", 12),
+      new FontSizeAction("font-size-14", 14),
+      new FontSizeAction("font-size-16", 16),
+      new FontSizeAction("font-size-18", 18),
+      new FontSizeAction("font-size-24", 24),
+      new FontSizeAction("font-size-36", 36),
+      new FontSizeAction("font-size-48", 48),
+      new FontFamilyAction("font-family-Serif", "Serif"),
+      new FontFamilyAction("font-family-Monospaced", "Monospaced"),
+      new FontFamilyAction("font-family-SansSerif", "SansSerif"),
+      new AlignmentAction("left-justify", StyleConstants.ALIGN_LEFT),
+      new AlignmentAction("center-justify", StyleConstants.ALIGN_CENTER),
+      new AlignmentAction("right-justify", StyleConstants.ALIGN_RIGHT),
+      new BoldAction(),
+      new ItalicAction(),
+      new UnderlineAction()
+    };
+    return TextAction.augmentList(actions1, myActions);
+  }
+
+  /**
+   * Returns the current input attributes. These are automatically set on
+   * any newly inserted content, if not specified otherwise.
+   *
+   * @return the current input attributes
+   */
+  public MutableAttributeSet getInputAttributes()
+  {
+    return inputAttributes;
+  }
+
+  /**
+   * Returns the {@link Element} that represents the character run at the
+   * current caret position.
+   *
+   * @return the {@link Element} that represents the character run at the
+   *         current caret position
+   */
+  public Element getCharacterAttributeRun()
+  {
+    return currentRun;
+  }
+
+  /**
+   * Creates the default {@link Document} supported by this
+   * <code>EditorKit</code>. This is an instance of
+   * {@link DefaultStyledDocument} in this case but may be overridden by
+   * subclasses.
+   *
+   * @return an instance of <code>DefaultStyledDocument</code>
+   */
+  public Document createDefaultDocument()
+  {
+    return new DefaultStyledDocument();
+  }
+
+  /**
+   * Installs this <code>EditorKit</code> on the specified {@link JEditorPane}.
+   * This basically involves setting up required listeners on the
+   * <code>JEditorPane</code>.
+   *
+   * @param component the <code>JEditorPane</code> to install this
+   *        <code>EditorKit</code> on
+   */
+  public void install(JEditorPane component)
+  {
+    CaretTracker tracker = new CaretTracker();
+    component.addCaretListener(tracker);
+  }
+
+  /**
+   * Deinstalls this <code>EditorKit</code> from the specified
+   * {@link JEditorPane}. This basically involves removing all listeners from
+   * <code>JEditorPane</code> that have been set up by this
+   * <code>EditorKit</code>.
+   *
+   * @param component the <code>JEditorPane</code> from which to deinstall this
+   *        <code>EditorKit</code>
+   */
+  public void deinstall(JEditorPane component)
+  {
+    CaretTracker t = caretTracker;
+    if (t != null)
+      component.removeCaretListener(t);
+    caretTracker = null;
+  }
+
+  /**
+   * Returns a {@link ViewFactory} that is able to create {@link View}s
+   * for {@link Element}s that are supported by this <code>EditorKit</code>,
+   * namely the following types of <code>Element</code>s:
+   *
+   * <ul>
+   * <li>{@link AbstractDocument#ContentElementName}</li>
+   * <li>{@link AbstractDocument#ParagraphElementName}</li>
+   * <li>{@link AbstractDocument#SectionElementName}</li>
+   * <li>{@link StyleConstants#ComponentElementName}</li>
+   * <li>{@link StyleConstants#IconElementName}</li>
+   * </ul>
+   *
+   * @return a {@link ViewFactory} that is able to create {@link View}s
+   *          for {@link Element}s that are supported by this <code>EditorKit</code>
+   */
+  public ViewFactory getViewFactory()
+  {
+    if (viewFactory == null)
+      viewFactory = new StyledViewFactory();
+    return viewFactory;
+  }
+
+  /**
+   * Copies the text attributes from <code>element</code> to <code>set</code>.
+   * This is called everytime when the caret position changes to keep
+   * track of the current input attributes. The attributes in <code>set</code>
+   * are cleaned before adding the attributes of <code>element</code>.
+   *
+   * This method filters out attributes for element names, <code>Icon</code>s
+   * and <code>Component</code>s.
+   *
+   * @param element the <code>Element</code> from which to copy the text
+   *         attributes
+   * @param set the inputAttributes to copy the attributes to
+   */
+  protected void createInputAttributes(Element element,
+				       MutableAttributeSet set)
+  {
+    // FIXME: Filter out component, icon and element name attributes.
+    set.removeAttributes(set);
+    set.addAttributes(element.getAttributes());
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,43 @@
+/* TabExpander.java --
+   Copyright (C) 2004  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+public interface TabExpander
+{
+  float nextTabStop(float x, int tabOffset);
+}
\ No newline at end of file

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,208 @@
+/* TabSet.java --
+   Copyright (C) 2004, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.Serializable;
+
+/**
+ * A set of tab stops.  Instances of this class are immutable.
+ */
+public class TabSet implements Serializable
+{
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = 2367703481999080593L;
+
+  /** Storage for the tab stops. */
+  TabStop[] tabs;
+
+  /**
+   * Creates a new <code>TabSet</code> containing the specified tab stops.
+   * 
+   * @param t  the tab stops (<code>null</code> permitted).
+   */
+  public TabSet(TabStop[] t) 
+  {
+    if (t != null)
+      tabs = (TabStop[]) t.clone();
+    else 
+      tabs = new TabStop[0];
+  }
+ 
+  /**
+   * Returns the tab stop with the specified index.
+   * 
+   * @param i  the index.
+   * 
+   * @return The tab stop.
+   * 
+   * @throws IllegalArgumentException if <code>i</code> is not in the range 
+   *     <code>0</code> to <code>getTabCount() - 1</code>.
+   */
+  public TabStop getTab(int i) 
+  {
+    if (i < 0 || i >= tabs.length)
+      throw new IllegalArgumentException("Index out of bounds.");
+    return tabs[i];
+  }
+
+  /**
+   * Returns the tab following the specified location.
+   * 
+   * @param location  the location.
+   * 
+   * @return The tab following the specified location (or <code>null</code>).
+   */
+  public TabStop getTabAfter(float location) 
+  {
+    int idx = getTabIndexAfter(location);
+    if (idx == -1)
+      return null;
+    else
+      return tabs[idx];        
+  }
+
+  /**
+   * Returns the number of tab stops in this tab set.
+   * 
+   * @return The number of tab stops in this tab set.
+   */
+  public int getTabCount() 
+  {
+    return tabs.length;
+  }
+
+  /**
+   * Returns the index of the specified tab, or -1 if the tab is not found.
+   * 
+   * @param tab  the tab (<code>null</code> permitted).
+   * 
+   * @return The index of the specified tab, or -1.
+   */
+  public int getTabIndex(TabStop tab) 
+  {
+    for (int i = 0; i < tabs.length; ++i)
+      if (tabs[i] == tab)
+        return i;
+    return -1;
+  }
+
+  /**
+   * Returns the index of the tab at or after the specified location.
+   * 
+   * @param location  the tab location.
+   * 
+   * @return The index of the tab stop, or -1.
+   */
+  public int getTabIndexAfter(float location) 
+  {
+    for (int i = 0; i < tabs.length; i++)
+      {
+        if (location <= tabs[i].getPosition())
+          return i;
+      }
+    return -1;
+  }
+  
+  /**
+   * Tests this <code>TabSet</code> for equality with an arbitrary object.
+   * 
+   * @param obj  the object (<code>null</code> permitted).
+   * 
+   * @return <code>true</code> if this <code>TabSet</code> is equal to
+   *     <code>obj</code>, and <code>false</code> otherwise.
+   *     
+   * @since 1.5
+   */
+  public boolean equals(Object obj)
+  {
+    if (obj == this)
+      return true;
+    if (!(obj instanceof TabSet))
+      return false;
+    TabSet that = (TabSet) obj;
+    int tabCount = getTabCount();
+    if (tabCount != that.getTabCount())
+      return false;
+    for (int i = 0; i < tabCount; i++)
+      {
+        if (!this.getTab(i).equals(that.getTab(i)))
+          return false;
+      }
+    return true;
+  }
+  
+  /**
+   * Returns a hash code for this <code>TabSet</code>.
+   * 
+   * @return A hash code.
+   * 
+   * @since 1.5
+   */
+  public int hashCode() 
+  {
+    // this hash code won't match Sun's, but that shouldn't matter...
+    int result = 193;
+    int tabs = getTabCount();
+    for (int i = 0; i < tabs; i++)
+      {
+        TabStop t = getTab(i);
+        if (t != null)
+          result = 37 * result + t.hashCode();
+      }
+    return result;
+  }
+
+  /**
+   * Returns a string representation of this <code>TabSet</code>.
+   * 
+   * @return A string representation of this <code>TabSet</code>.
+   */
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("[ ");
+    for (int i = 0; i < tabs.length; ++i)
+      {
+        if (i != 0)
+          sb.append(" - ");
+        sb.append(tabs[i].toString());
+      }
+    sb.append(" ]");
+    return sb.toString();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,190 @@
+/* TabStop.java --
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.Serializable;
+
+/**
+ * Represents a tab position in some text.
+ */
+public class TabStop implements Serializable
+{
+  /** The serialization UID (compatible with JDK1.5). */
+  private static final long serialVersionUID = -5381995917363605058L;
+
+  public static final int ALIGN_LEFT = 0;
+  public static final int ALIGN_RIGHT = 1;
+  public static final int ALIGN_CENTER = 2;
+  public static final int ALIGN_DECIMAL = 4;
+  public static final int ALIGN_BAR = 5;
+
+  public static final int LEAD_NONE = 0;
+  public static final int LEAD_DOTS = 1;
+  public static final int LEAD_HYPHENS = 2;
+  public static final int LEAD_UNDERLINE = 3;
+  public static final int LEAD_THICKLINE = 4;
+  public static final int LEAD_EQUALS = 5;
+
+  float pos;
+  int align;
+  int leader;
+
+  /**
+   * Creates a new <code>TabStop</code> for the specified tab position.
+   * 
+   * @param pos  the tab position.
+   */
+  public TabStop(float pos) 
+  {
+    this(pos, ALIGN_LEFT, LEAD_NONE);
+  }
+  
+  /**
+   * Creates a new <code>TabStop</code> with the specified attributes.
+   * 
+   * @param pos  the tab position.
+   * @param align  the alignment (one of {@link #ALIGN_LEFT}, 
+   *     {@link #ALIGN_CENTER}, {@link #ALIGN_RIGHT}, {@link #ALIGN_DECIMAL} 
+   *     or {@link #ALIGN_BAR}).
+   * @param leader  the leader (one of {@link #LEAD_NONE}, {@link #LEAD_DOTS}, 
+   *     {@link #LEAD_EQUALS}, {@link #LEAD_HYPHENS}, {@link #LEAD_THICKLINE} 
+   *     or {@link #LEAD_UNDERLINE}).
+   */
+  public TabStop(float pos, int align, int leader)
+  {
+    this.pos = pos;
+    this.align = align;
+    this.leader = leader;
+  }
+  
+  /**
+   * Tests this <code>TabStop</code> for equality with an arbitrary object.
+   * 
+   * @param other  the other object (<code>null</code> permitted).
+   * 
+   * @return <code>true</code> if this <code>TabStop</code> is equal to 
+   *     the specified object, and <code>false</code> otherwise.
+   */
+  public boolean equals(Object other) 
+  {
+    return (other != null)
+      && (other instanceof TabStop)
+      && (((TabStop)other).getPosition() == this.getPosition())
+      && (((TabStop)other).getLeader() == this.getLeader())
+      && (((TabStop)other).getAlignment() == this.getAlignment());
+  }
+
+  /**
+   * Returns the tab alignment.  This should be one of {@link #ALIGN_LEFT}, 
+   * {@link #ALIGN_CENTER}, {@link #ALIGN_RIGHT}, {@link #ALIGN_DECIMAL} or 
+   * {@link #ALIGN_BAR}.
+   * 
+   * @return The tab alignment.
+   */
+  public int getAlignment() 
+  {
+    return align;
+  }
+
+  /**
+   * Returns the leader type.  This should be one of {@link #LEAD_NONE}, 
+   * {@link #LEAD_DOTS}, {@link #LEAD_EQUALS}, {@link #LEAD_HYPHENS}, 
+   * {@link #LEAD_THICKLINE} or {@link #LEAD_UNDERLINE}.
+   * 
+   * @return The leader type.
+   */
+  public int getLeader() 
+  {
+    return leader;
+  }
+
+  /**
+   * Returns the tab position.
+   * 
+   * @return The tab position.
+   */
+  public float getPosition() 
+  {
+    return pos;
+  }
+
+  /**
+   * Returns a hash code for this <code>TabStop</code>.
+   * 
+   * @return A hash code.
+   */
+  public int hashCode() 
+  {
+    return (int) pos + (int) leader + (int) align;
+  }
+
+  /**
+   * Returns a string describing this <code>TabStop</code>.
+   * 
+   * @return A string describing this <code>TabStop</code>.
+   */
+  public String toString() 
+  {
+    String prefix = "";
+    switch (align)
+      {
+      case ALIGN_RIGHT:
+        prefix = "right ";
+        break;
+
+      case ALIGN_CENTER:
+        prefix = "center ";
+        break;
+
+      case ALIGN_DECIMAL:
+        prefix = "decimal ";
+        break;
+        
+      case ALIGN_BAR:
+        prefix = "bar ";
+        break;
+
+      default:
+        break;
+      }
+    
+    return prefix + "tab @" + pos 
+        + ((leader == LEAD_NONE) ? "" : " (w/leaders)");
+  }
+
+}





More information about the llvm-commits mailing list