/* 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@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@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@aicas.com)
   * @author Audrius Meskauskas (AudriusA@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@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@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@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);
  }
  
}
