/* Toolkit.java -- AWT Toolkit superclass
   Copyright (C) 1999, 2000, 2001, 2002, 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 java.awt;

import gnu.classpath.SystemProperties;
import gnu.java.awt.peer.GLightweightPeer;

import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.AWTEventListener;
import java.awt.event.AWTEventListenerProxy;
import java.awt.event.KeyEvent;
import java.awt.im.InputMethodHighlight;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.peer.ButtonPeer;
import java.awt.peer.CanvasPeer;
import java.awt.peer.CheckboxMenuItemPeer;
import java.awt.peer.CheckboxPeer;
import java.awt.peer.ChoicePeer;
import java.awt.peer.DialogPeer;
import java.awt.peer.FileDialogPeer;
import java.awt.peer.FontPeer;
import java.awt.peer.FramePeer;
import java.awt.peer.LabelPeer;
import java.awt.peer.LightweightPeer;
import java.awt.peer.ListPeer;
import java.awt.peer.MenuBarPeer;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;
import java.awt.peer.MouseInfoPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.PopupMenuPeer;
import java.awt.peer.ScrollPanePeer;
import java.awt.peer.ScrollbarPeer;
import java.awt.peer.TextAreaPeer;
import java.awt.peer.TextFieldPeer;
import java.awt.peer.WindowPeer;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

/**
 * The AWT system uses a set of native peer objects to implement its
 * widgets.  These peers are provided by a peer toolkit, that is accessed
 * via a subclass of this superclass.  The system toolkit is retrieved
 * by the static methods <code>getDefaultToolkit</code>.  This method
 * determines the system toolkit by examining the system property
 * <code>awt.toolkit</code>.  That property is set to the name of the
 * <code>Toolkit</code> subclass for the specified peer set.  If the
 * <code>awt.toolkit</code> property is not set, then the default
 * toolkit <code>gnu.java.awt.peer.gtk.GtkToolkit</code> is used.  This
 * toolkit creates its peers using the GTK+ toolkit.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 */
public abstract class Toolkit
{
  /** The default toolkit name. */
  private static String default_toolkit_name
    = gnu.classpath.Configuration.default_awt_peer_toolkit;

  /**
   * The toolkit in use.  Once we load it, we don't ever change it
   * if the awt.toolkit property is set.
   */
  private static Toolkit toolkit;

  /** The toolkit properties. */
  private static Properties props = new Properties();

  protected final Map desktopProperties = new Properties();

  protected final PropertyChangeSupport desktopPropsSupport
    = new PropertyChangeSupport(this);

  /**
   * All registered AWTEventListener objects. This is package private, so the
   * event queue can efficiently access this list.
   */
  AWTEventListenerProxy[] awtEventListeners;

  /**
   * Default constructor for subclasses.
   */
  public Toolkit()
  {
    awtEventListeners = new AWTEventListenerProxy[0];
  }

  /**
   * Creates a peer object for the specified <code>Button</code>.
   *
   * @param target The <code>Button</code> to create the peer for.
   * 
   * @return The peer for the specified <code>Button</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract ButtonPeer createButton(Button target);

  /**
   * Creates a peer object for the specified <code>TextField</code>.
   *
   * @param target The <code>TextField</code> to create the peer for.
   *
   * @return The peer for the specified <code>TextField</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract TextFieldPeer createTextField(TextField target);

  /**
   * Creates a peer object for the specified <code>Label</code>.
   *
   * @param target The <code>Label</code> to create the peer for.
   *
   * @return The peer for the specified <code>Label</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract LabelPeer createLabel(Label target);

  /**
   * Creates a peer object for the specified <code>List</code>.
   *
   * @param target The <code>List</code> to create the peer for.
   *
   * @return The peer for the specified <code>List</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract ListPeer createList(List target);

  /**
   * Creates a peer object for the specified <code>Checkbox</code>.
   *
   * @param target The <code>Checkbox</code> to create the peer for.
   *
   * @return The peer for the specified <code>Checkbox</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract CheckboxPeer createCheckbox(Checkbox target);

  /**
   * Creates a peer object for the specified <code>Scrollbar</code>.
   *
   * @param target The <code>Scrollbar</code> to create the peer for.
   *
   * @return The peer for the specified <code>Scrollbar</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract ScrollbarPeer createScrollbar(Scrollbar target);

  /**
   * Creates a peer object for the specified <code>ScrollPane</code>.
   *
   * @param target The <code>ScrollPane</code> to create the peer for.
   *
   * @return The peer for the specified <code>ScrollPane</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract ScrollPanePeer createScrollPane(ScrollPane target);

  /**
   * Creates a peer object for the specified <code>TextArea</code>.
   *
   * @param target The <code>TextArea</code> to create the peer for.
   *
   * @return The peer for the specified <code>TextArea</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract TextAreaPeer createTextArea(TextArea target);

  /**
   * Creates a peer object for the specified <code>Choice</code>.
   *
   * @param target The <code>Choice</code> to create the peer for.
   *
   * @return The peer for the specified <code>Choice</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract ChoicePeer createChoice(Choice target);

  /**
   * Creates a peer object for the specified <code>Frame</code>.
   *
   * @param target The <code>Frame</code> to create the peer for.
   *
   * @return The peer for the specified <code>Frame</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract FramePeer createFrame(Frame target);

  /**
   * Creates a peer object for the specified <code>Canvas</code>.
   *
   * @param target The <code>Canvas</code> to create the peer for.
   *
   * @return The peer for the specified <code>Canvas</code> object.
   */
  protected abstract CanvasPeer createCanvas(Canvas target);

  /**
   * Creates a peer object for the specified <code>Panel</code>.
   *
   * @param target The <code>Panel</code> to create the peer for.
   *
   * @return The peer for the specified <code>Panel</code> object.
   */
  protected abstract PanelPeer createPanel(Panel target);

  /**
   * Creates a peer object for the specified <code>Window</code>.
   *
   * @param target The <code>Window</code> to create the peer for.
   *
   * @return The peer for the specified <code>Window</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract WindowPeer createWindow(Window target);

  /**
   * Creates a peer object for the specified <code>Dialog</code>.
   *
   * @param target The dialog to create the peer for
   *
   * @return The peer for the specified font name.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract DialogPeer createDialog(Dialog target);

  /**
   * Creates a peer object for the specified <code>MenuBar</code>.
   *
   * @param target The <code>MenuBar</code> to create the peer for.
   *
   * @return The peer for the specified <code>MenuBar</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract MenuBarPeer createMenuBar(MenuBar target);

  /**
   * Creates a peer object for the specified <code>Menu</code>.
   *
   * @param target The <code>Menu</code> to create the peer for.
   *
   * @return The peer for the specified <code>Menu</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract MenuPeer createMenu(Menu target);

  /**
   * Creates a peer object for the specified <code>PopupMenu</code>.
   *
   * @param target The <code>PopupMenu</code> to create the peer for.
   *
   * @return The peer for the specified <code>PopupMenu</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract PopupMenuPeer createPopupMenu(PopupMenu target);

  /**
   * Creates a peer object for the specified <code>MenuItem</code>.
   *
   * @param target The <code>MenuItem</code> to create the peer for.
   *
   * @return The peer for the specified <code>MenuItem</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract MenuItemPeer createMenuItem(MenuItem target);

  /**
   * Returns a MouseInfoPeer. 
   * The default implementation of this method throws
   * UnsupportedOperationException.
   *
   * Toolkit implementations should overload this if possible, however.
   */
  protected MouseInfoPeer getMouseInfoPeer()
  {
    throw new UnsupportedOperationException("No mouse info peer.");
  }

  /**
   * Creates a peer object for the specified <code>FileDialog</code>.
   *
   * @param target The <code>FileDialog</code> to create the peer for.
   *
   * @return The peer for the specified <code>FileDialog</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract FileDialogPeer createFileDialog(FileDialog target);

  /**
   * Creates a peer object for the specified <code>CheckboxMenuItem</code>.
   *
   * @param target The <code>CheckboxMenuItem</code> to create the peer for.
   *
   * @return The peer for the specified <code>CheckboxMenuItem</code> object.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected abstract CheckboxMenuItemPeer
    createCheckboxMenuItem(CheckboxMenuItem target);

  /**
   * Creates a peer object for the specified <code>Component</code>.  The
   * peer returned by this method is not a native windowing system peer
   * with its own native window.  Instead, this method allows the component
   * to draw on its parent window as a "lightweight" widget.
   *
   * @param target The <code>Component</code> to create the peer for.
   *
   * @return The peer for the specified <code>Component</code> object.
   */
  protected LightweightPeer createComponent(Component target)
  {
    return new GLightweightPeer(target);
  }

  /**
   * Creates a peer object for the specified font name.
   *
   * @param name The font to create the peer for.
   * @param style The font style to create the peer for.
   *
   * @return The peer for the specified font name.
   *
   * @deprecated
   */
  protected abstract FontPeer getFontPeer(String name, int style);

  /**
   * Copies the current system colors into the specified array.  This is
   * the interface used by the <code>SystemColor</code> class.  Although
   * this method fills in the array with some default colors a real Toolkit
   * should override this method and provide real system colors for the
   * native GUI platform.
   *
   * @param systemColors The array to copy the system colors into.
   * It must be at least 26 elements.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   *
   * @see java.awt.SystemColor
   */
  protected void loadSystemColors(int systemColors[])
  {
    systemColors[SystemColor.DESKTOP]                 = 0xFF005C5C;
    systemColors[SystemColor.ACTIVE_CAPTION]          = 0xFF000080;
    systemColors[SystemColor.ACTIVE_CAPTION_TEXT]     = 0xFFFFFFFF;
    systemColors[SystemColor.ACTIVE_CAPTION_BORDER]   = 0xFFC0C0C0;
    systemColors[SystemColor.INACTIVE_CAPTION]        = 0xFF808080;
    systemColors[SystemColor.INACTIVE_CAPTION_TEXT]   = 0xFFC0C0C0;
    systemColors[SystemColor.INACTIVE_CAPTION_BORDER] = 0xFFC0C0C0;
    systemColors[SystemColor.WINDOW]                  = 0xFFFFFFFF;
    systemColors[SystemColor.WINDOW_BORDER]           = 0xFF000000;
    systemColors[SystemColor.WINDOW_TEXT]             = 0xFF000000;
    systemColors[SystemColor.MENU]                    = 0xFFC0C0C0;
    systemColors[SystemColor.MENU_TEXT]               = 0xFF000000;
    systemColors[SystemColor.TEXT]                    = 0xFFC0C0C0;
    systemColors[SystemColor.TEXT_TEXT]               = 0xFF000000;
    systemColors[SystemColor.TEXT_HIGHLIGHT]          = 0xFF000090;
    systemColors[SystemColor.TEXT_HIGHLIGHT_TEXT]     = 0xFFFFFFFF;
    systemColors[SystemColor.TEXT_INACTIVE_TEXT]      = 0xFF808080;
    systemColors[SystemColor.CONTROL]                 = 0xFFC0C0C0;
    systemColors[SystemColor.CONTROL_TEXT]            = 0xFF000000;
    systemColors[SystemColor.CONTROL_HIGHLIGHT]       = 0xFFFFFFFF;
    systemColors[SystemColor.CONTROL_LT_HIGHLIGHT]    = 0xFFE0E0E0;
    systemColors[SystemColor.CONTROL_SHADOW]          = 0xFF808080;
    systemColors[SystemColor.CONTROL_DK_SHADOW]       = 0xFF000000;
    systemColors[SystemColor.SCROLLBAR]               = 0xFFE0E0E0;
    systemColors[SystemColor.INFO]                    = 0xFFE0E000;
    systemColors[SystemColor.INFO_TEXT]               = 0xFF000000;
  }

  /**
   * @since 1.4
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public void setDynamicLayout(boolean dynamic)
  {
  }

  /**
   * @since 1.4
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  protected boolean isDynamicLayoutSet()
  {
    return false;
  }

  /**
   * @since 1.4
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public boolean isDynamicLayoutActive()
  {
    return false;
  }

  /**
   * Returns the dimensions of the screen in pixels.
   *
   * @return The dimensions of the screen in pixels.
   * 
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public abstract Dimension getScreenSize();

  /**
   * Returns the screen resolution in dots per square inch.
   *
   * @return The screen resolution in dots per square inch.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public abstract int getScreenResolution();

  /**
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   *
   * @since 1.4
   */
  public Insets getScreenInsets(GraphicsConfiguration gc)
  {
    return new Insets(0, 0, 0, 0);
  }

  /**
   * Returns the color model of the screen.
   *
   * @return The color model of the screen.
   * 
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public abstract ColorModel getColorModel();

  /**
   * Returns the names of the available fonts.
   *
   * @return The names of the available fonts.
   *
   * @deprecated
   */
  public abstract String[] getFontList();

  /**
   * Return the font metrics for the specified font
   *
   * @param name The name of the font to return metrics for.
   *
   * @return The requested font metrics.
   *
   * @deprecated
   */
  public abstract FontMetrics getFontMetrics(Font name);

  /**
   * Flushes any buffered data to the screen so that it is in sync with
   * what the AWT system has drawn to it.
   */
  public abstract void sync();

  /**
   * Returns an instance of the default toolkit.  The default toolkit is
   * the subclass of <code>Toolkit</code> specified in the system property
   * <code>awt.toolkit</code>, or <code>gnu.java.awt.peer.gtk.GtkToolkit</code>
   * if the property is not set.
   *
   * @return An instance of the system default toolkit.
   *
   * @throws AWTError If the toolkit cannot be loaded.
   */
  public static Toolkit getDefaultToolkit()
  {
    if (toolkit != null)
      return toolkit;
    String toolkit_name = SystemProperties.getProperty("awt.toolkit",
                                                       default_toolkit_name);
    try
      {
        ClassLoader cl;
        cl = (ClassLoader) AccessController.doPrivileged
        (new PrivilegedAction()
          {
            public Object run()
              {
                return ClassLoader.getSystemClassLoader();
              }
          });
        Class cls = Class.forName(toolkit_name, true, cl);
        Object obj = cls.newInstance();
        if (!(obj instanceof Toolkit))
          throw new AWTError(toolkit_name + " is not a subclass of " +
                             "java.awt.Toolkit");
        toolkit = (Toolkit) obj;

        initAccessibility();
        return toolkit;
      }
    catch (ThreadDeath death)
      {
        throw death;
      }
    catch (Throwable t)
      {
	AWTError e = new AWTError("Cannot load AWT toolkit: " + toolkit_name);
	throw (AWTError) e.initCause(t);
      }
  }

  /**
   * Returns an image from the specified file, which must be in a
   * recognized format.  Supported formats vary from toolkit to toolkit.
   *
   * @return name The name of the file to read the image from.
   */
  public abstract Image getImage(String name);

  /**
   * Returns an image from the specified URL, which must be in a
   * recognized format.  Supported formats vary from toolkit to toolkit.
   *
   * @return url The URl to read the image from.
   */
  public abstract Image getImage(URL url);

  public abstract Image createImage(String filename);

  public abstract Image createImage(URL url);

  /**
   * Readies an image to be rendered on the screen.  The width and height
   * values can be set to the default sizes for the image by passing -1
   * in those parameters.
   *
   * @param image The image to prepare for rendering.
   * @param width The width of the image.
   * @param height The height of the image.
   * @param observer The observer to receive events about the preparation
   * process.
   *
   * @return <code>true</code> if the image is already prepared for rendering,
   * <code>false</code> otherwise.
   */
  public abstract boolean prepareImage(Image image, int width, int height,
                                       ImageObserver observer);

  /**
   * Checks the status of specified image as it is being readied for
   * rendering.
   *
   * @param image The image to prepare for rendering.
   * @param width The width of the image.
   * @param height The height of the image.
   * @param observer The observer to receive events about the preparation
   * process.
   *
   * @return A union of the bitmasks from
   * <code>java.awt.image.ImageObserver</code> that indicates the current
   * state of the imaging readying process.
   */
  public abstract int checkImage(Image image, int width, int height,
                                 ImageObserver observer);

  /**
   * Creates an image using the specified <code>ImageProducer</code>
   *
   * @param producer The <code>ImageProducer</code> to create the image from.
   *
   * @return The created image.
   */
  public abstract Image createImage(ImageProducer producer);

  /**
   * Creates an image from the specified byte array. The array must be in
   * a recognized format.  Supported formats vary from toolkit to toolkit.
   *
   * @param data The raw image data.
   *
   * @return The created image.
   */
  public Image createImage(byte[] data)
  {
    return createImage(data, 0, data.length);
  }

  /**
   * Creates an image from the specified portion of the byte array passed.
   * The array must be in a recognized format.  Supported formats vary from
   * toolkit to toolkit.
   *
   * @param data The raw image data.
   * @param offset The offset into the data where the image data starts.
   * @param len The length of the image data.
   *
   * @return The created image.
   */
  public abstract Image createImage(byte[] data, int offset, int len);

  /**
   * Returns a instance of <code>PrintJob</code> for the specified
   * arguments.
   *
   * @param frame The window initiating the print job.
   * @param title The print job title.
   * @param props The print job properties.
   *
   * @return The requested print job, or <code>null</code> if the job
   * was cancelled.
   *
   * @exception NullPointerException If frame is null,
   * or GraphicsEnvironment.isHeadless() returns true.
   * @exception SecurityException If this thread is not allowed to initiate
   * a print job request.
   */
  public abstract PrintJob getPrintJob(Frame frame, String title,
                                       Properties props);

  /**
   * Returns a instance of <code>PrintJob</code> for the specified
   * arguments.
   *
   * @param frame The window initiating the print job.
   * @param title The print job title.
   * @param jobAttr A set of job attributes which will control the print job.
   * @param pageAttr A set of page attributes which will control the print job.
   *
   * @exception NullPointerException If frame is null, and either jobAttr is null
   * or jobAttr.getDialog() returns JobAttributes.DialogType.NATIVE.
   * @exception IllegalArgumentException If pageAttrspecifies differing cross
   * feed and feed resolutions, or when GraphicsEnvironment.isHeadless() returns
   * true.
   * @exception SecurityException If this thread is not allowed to initiate
   * a print job request.
   *
   * @since 1.3
   */
  public PrintJob getPrintJob(Frame frame, String title,
                              JobAttributes jobAttr, PageAttributes pageAttr)
  {
    // FIXME: it is possible this check may be removed
    // if this method, when written, always delegates to
    // getPrintJob(Frame, String, Properties).
    SecurityManager sm;
    sm = System.getSecurityManager();
    if (sm != null)
      sm.checkPrintJobAccess();

    return null;
  }

  /**
   * Causes a "beep" tone to be generated.
   */
  public abstract void beep();

  /**
   * Returns the system clipboard.
   *
   * @return THe system clipboard.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public abstract Clipboard getSystemClipboard();

  /**
   * Gets the singleton instance of the system selection as a
   * Clipboard object. The system selection contains the selected text
   * of the last component/widget that had focus and a text selection.
   * The default implementation returns null.
   *
   * @return The Clipboard holding the system (text) selection or null
   * if the Toolkit or system doesn't support a selection clipboard.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless()
   * is true.
   * @exception SecurityException If the current security manager
   * checkSystemClipboardAccess() doesn't allow access.
   *
   * @since 1.4
   */
  public Clipboard getSystemSelection()
  {
    return null;
  }

  /**
   * Returns the accelerator key mask for menu shortcuts. The default is
   * <code>Event.CTRL_MASK</code>.  A toolkit must override this method
   * to change the default.
   *
   * @return The key mask for the menu accelerator key.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public int getMenuShortcutKeyMask()
  {
    return Event.CTRL_MASK;
  }

  /**
   * Returns whether the given locking key on the keyboard is currently in its
   * "on" state.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   * @exception IllegalArgumentException If keyCode is not one of the valid keys.
   * @exception UnsupportedOperationException If the host system doesn't allow
   * getting the state of this key programmatically, or if the keyboard doesn't
   * have this key.
   */
  public boolean getLockingKeyState(int keyCode)
  {
    if (keyCode != KeyEvent.VK_CAPS_LOCK
        && keyCode != KeyEvent.VK_NUM_LOCK
        && keyCode != KeyEvent.VK_SCROLL_LOCK)
      throw new IllegalArgumentException();
    
    throw new UnsupportedOperationException();
  }

  /**
   * Sets the state of the given locking key on the keyboard.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   * @exception IllegalArgumentException If keyCode is not one of the valid keys.
   * @exception UnsupportedOperationException If the host system doesn't allow
   * getting the state of this key programmatically, or if the keyboard doesn't
   * have this key.
   */
  public void setLockingKeyState(int keyCode, boolean on)
  {
    if (keyCode != KeyEvent.VK_CAPS_LOCK
        && keyCode != KeyEvent.VK_NUM_LOCK
        && keyCode != KeyEvent.VK_SCROLL_LOCK)
      throw new IllegalArgumentException();
    
    throw new UnsupportedOperationException();
  }

  /**
   * Returns the native container object of the specified component.  This
   * method is necessary because the parent component might be a lightweight
   * component.
   *
   * @param component The component to fetch the native container for.
   *
   * @return The native container object for this component.
   */
  protected static Container getNativeContainer(Component component)
  {
    component = component.getParent();
    while (true)
      {
        if (component == null)
          return null;
        if (! (component instanceof Container))
          {
            component = component.getParent();
            continue;
          }
        if (component.getPeer() instanceof LightweightPeer)
          {
            component = component.getParent();
            continue;
          }
        return (Container) component;
      }
  }

  /**
   * Creates a new custom cursor object.
   *
   * @exception IndexOutOfBoundsException If the hotSpot values are outside
   * the bounds of the cursor.
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
  {
    // Presumably the only reason this isn't abstract is for backwards
    // compatibility? FIXME?
    if (GraphicsEnvironment.isHeadless())
      throw new HeadlessException("No custom cursor in an headless graphics "
                                  + "environment.");
    return null;
  }

  /**
   * Returns the supported cursor dimension which is closest to the
   * desired sizes.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public Dimension getBestCursorSize(int preferredWidth, int preferredHeight)
  {
    if (GraphicsEnvironment.isHeadless())
      throw new HeadlessException("No best cursor size in an headless "
                                  + "graphics environment.");
    return new Dimension (0,0);
  }

  /**
   * Returns the maximum number of colors the Toolkit supports in a custom
   * cursor palette.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public int getMaximumCursorColors()
  {
    return 0;
  }

  /**
   * Returns whether Toolkit supports this state for Frames.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   * 
   * @since 1.4
   */
  public boolean isFrameStateSupported(int state)
  {
    return false;
  }

  /**
   * Returns the value of the property with the specified name, or the
   * default value if the property does not exist.
   *
   * @param key The name of the property to retrieve.
   * @param def The default value of the property.
   */
  public static String getProperty(String key, String def)
  {
    return props.getProperty(key, def);
  }


  /**
   * Returns the event queue that is suitable for the calling context.
   *
   * <p>Despite the word &#x201c;System&#x201d; in the name of this
   * method, a toolkit may provide different event queues for each
   * applet. There is no guarantee that the same queue is shared
   * system-wide.
   *
   * <p>The implementation first checks whether a
   * SecurityManager has been installed. If so, its {@link
   * java.lang.SecurityManager#checkAwtEventQueueAccess()} method gets
   * called. The security manager will throw a SecurityException if it
   * does not grant the permission to access the event queue.
   *
   * <p>Next, the call is delegated to {@link
   * #getSystemEventQueueImpl()}.
   *
   * @return The event queue for this applet (or application).
   *
   * @throws SecurityException if a security manager has been
   * installed, and it does not grant the permission to access the
   * event queue.
   */
  public final EventQueue getSystemEventQueue()
  {
    SecurityManager sm;

    sm = System.getSecurityManager();
    if (sm != null)
      sm.checkAwtEventQueueAccess();

    return getSystemEventQueueImpl();
  }


  /**
   * Returns the event queue that is suitable for the calling context.
   *
   * <p>Despite the word &#x201c;System&#x201d; in the name of this
   * method, a toolkit may provide different event queues for each
   * applet. There is no guarantee that the same queue is shared
   * system-wide.
   *
   * <p>No security checks are performed, which is why this method
   * may only be called by Toolkits.
   *
   * @see #getSystemEventQueue()
   */
  protected abstract EventQueue getSystemEventQueueImpl();


  /**
   * @since 1.3
   */
  public abstract DragSourceContextPeer
    createDragSourceContextPeer(DragGestureEvent e);

  /**
   * @since 1.3
   */
  public DragGestureRecognizer
    createDragGestureRecognizer(Class recognizer, DragSource ds,
                                Component comp, int actions,
                                DragGestureListener l)
  {
    return null;
  }

  public final Object getDesktopProperty(String propertyName)
  {
    return desktopProperties.get(propertyName);
  }

  protected final void setDesktopProperty(String name, Object newValue)
  {
    Object oldValue = getDesktopProperty(name);
    desktopProperties.put(name, newValue);
    desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
  }

  protected Object lazilyLoadDesktopProperty(String name)
  {
    // FIXME - what is this??
    return null;
  }

  protected void initializeDesktopProperties()
  {
    // Overridden by toolkit implementation?
  }

  public void addPropertyChangeListener(String name,
                                        PropertyChangeListener pcl)
  {
    desktopPropsSupport.addPropertyChangeListener(name, pcl);
  }

  public void removePropertyChangeListener(String name,
                                           PropertyChangeListener pcl)
  {
    desktopPropsSupport.removePropertyChangeListener(name, pcl);
  }

  /**
   * @since 1.4
   */
  public PropertyChangeListener[] getPropertyChangeListeners()
  {
    return desktopPropsSupport.getPropertyChangeListeners();
  }

  /**
   * @since 1.4
   */
  public PropertyChangeListener[] getPropertyChangeListeners(String name)
  {
    return desktopPropsSupport.getPropertyChangeListeners(name);
  }

  /**
   * Adds an AWTEventListener to this toolkit. This listener is informed about
   * all events that pass the eventqueue that match the specified
   * <code>evenMask</code>. The <code>eventMask</code> is an ORed combination
   * of event masks as defined in {@link AWTEvent}.
   *
   * If a security manager is installed, it is asked first if an
   * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
   * This may result in a <code>SecurityException</code> beeing thrown.
   *
   * It is not recommended to use this kind of notification for normal
   * applications. It is intended solely for the purpose of debugging and to
   * support special facilities.
   *
   * @param listener the listener to add
   * @param eventMask the event mask of event types which the listener is
   *        interested in
   *
   * @since 1.2
   *
   * @throws SecurityException if there is a <code>SecurityManager</code> that
   *         doesn't grant
   *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
   *
   * @see #getAWTEventListeners()
   * @see #getAWTEventListeners(long)
   * @see #removeAWTEventListener(AWTEventListener)
   */
  public void addAWTEventListener(AWTEventListener listener, long eventMask)
  {
    // First we must check the security permissions.
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkPermission(new AWTPermission("listenToAllAWTEvents"));

    // Go through the list and check if the requested listener is already
    // registered.
    boolean found = false;
    for (int i = 0; i < awtEventListeners.length; ++i)
      {
        AWTEventListenerProxy proxy = awtEventListeners[i];
        if (proxy.getListener() == listener)
          {
            found = true;
            // Modify the proxies event mask to include the new event mask.
            AWTEventListenerProxy newProxy =
              new AWTEventListenerProxy(proxy.getEventMask() | eventMask,
                                        listener);
            awtEventListeners[i] = newProxy;
            break;
          }
      }

    // If that listener was not found, then add it.
    if (! found)
      {
        AWTEventListenerProxy proxy =
          new AWTEventListenerProxy(eventMask, listener);
        AWTEventListenerProxy[] newArray =
          new AWTEventListenerProxy[awtEventListeners.length + 1];
        System.arraycopy(awtEventListeners, 0, newArray, 0,
                         awtEventListeners.length);
        newArray[newArray.length - 1] = proxy;
        awtEventListeners = newArray;
      }
  }

  /**
   * Removes an AWT event listener from this toolkit. This listener is no
   * longer informed of any event types it was registered in.
   *
   * If a security manager is installed, it is asked first if an
   * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
   * This may result in a <code>SecurityException</code> beeing thrown.
   *
   * It is not recommended to use this kind of notification for normal
   * applications. It is intended solely for the purpose of debugging and to
   * support special facilities.
   *
   * @param listener the listener to remove
   *
   * @throws SecurityException if there is a <code>SecurityManager</code> that
   *         doesn't grant
   *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
   *
   * @since 1.2
   *
   * @see #addAWTEventListener(AWTEventListener, long)
   * @see #getAWTEventListeners()
   * @see #getAWTEventListeners(long)
   */
  public void removeAWTEventListener(AWTEventListener listener)
  {
    // First we must check the security permissions.
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkPermission(new AWTPermission("listenToAllAWTEvents"));


    // Find the index of the listener.
    int index = -1;
    for (int i = 0; i < awtEventListeners.length; ++i)
      {
        AWTEventListenerProxy proxy = awtEventListeners[i];
        if (proxy.getListener() == listener)
          {
            index = i;
            break;
          }
      }

    // Copy over the arrays and leave out the removed element.
    if (index != -1)
      {
        AWTEventListenerProxy[] newArray =
          new AWTEventListenerProxy[awtEventListeners.length - 1];
        if (index > 0)
          System.arraycopy(awtEventListeners, 0, newArray, 0, index);
        if (index < awtEventListeners.length - 1)
          System.arraycopy(awtEventListeners, index + 1, newArray, index,
                           awtEventListeners.length - index - 1);
        awtEventListeners = newArray;
      }
  }

  /**
   * Returns all registered AWT event listeners. This method returns a copy of
   * the listener array, so that application cannot trash the listener list.
   *
   * If a security manager is installed, it is asked first if an
   * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
   * This may result in a <code>SecurityException</code> beeing thrown.
   *
   * It is not recommended to use this kind of notification for normal
   * applications. It is intended solely for the purpose of debugging and to
   * support special facilities.
   *
   * @return all registered AWT event listeners
   *
   * @throws SecurityException if there is a <code>SecurityManager</code> that
   *         doesn't grant
   *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
   *
   * @since 1.4
   *
   * @see #addAWTEventListener(AWTEventListener, long)
   * @see #removeAWTEventListener(AWTEventListener)
   * @see #getAWTEventListeners(long)
   */
  public AWTEventListener[] getAWTEventListeners()
  {
    // First we must check the security permissions.
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkPermission(new AWTPermission("listenToAllAWTEvents"));

    // Create a copy of the array.
    AWTEventListener[] copy = new AWTEventListener[awtEventListeners.length];
    System.arraycopy(awtEventListeners, 0, copy, 0, awtEventListeners.length);
    return copy;
  }

  /**
   * Returns all registered AWT event listeners that listen for events with
   * the specified <code>eventMask</code>. This method returns a copy of
   * the listener array, so that application cannot trash the listener list.
   *
   * If a security manager is installed, it is asked first if an
   * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
   * This may result in a <code>SecurityException</code> beeing thrown.
   *
   * It is not recommended to use this kind of notification for normal
   * applications. It is intended solely for the purpose of debugging and to
   * support special facilities.
   *
   * @param mask the event mask
   *
   * @throws SecurityException if there is a <code>SecurityManager</code> that
   *         doesn't grant
   *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
   *
   *
   * @since 1.4
   *
   * @see #addAWTEventListener(AWTEventListener, long)
   * @see #removeAWTEventListener(AWTEventListener)
   * @see #getAWTEventListeners()
   */
  public AWTEventListener[] getAWTEventListeners(long mask)
  {
    // First we must check the security permissions.
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkPermission(new AWTPermission("listenToAllAWTEvents"));

    // Create a copy of the array with only the requested listeners in it.
    ArrayList l = new ArrayList(awtEventListeners.length);
    for (int i = 0; i < awtEventListeners.length; ++i)
      {
        if ((awtEventListeners[i].getEventMask() & mask) != 0)
          l.add(awtEventListeners[i]);
      }

    return (AWTEventListener[] ) l.toArray(new AWTEventListener[l.size()]);
  }


  /**
   * Dispatches events to listeners registered to this Toolkit. This is called
   * by {@link Component#dispatchEventImpl(AWTEvent)} in order to dispatch
   * events globally.
   *
   * @param ev the event to dispatch
   */
  void globalDispatchEvent(AWTEvent ev)
  {
    // We do not use the accessor methods here because they create new
    // arrays each time. We must be very efficient, so we access this directly.
    for (int i = 0; i < awtEventListeners.length; ++i)
      {
        AWTEventListenerProxy proxy = awtEventListeners[i];
        if ((proxy.getEventMask() & AWTEvent.eventIdToMask(ev.getID())) != 0)
          proxy.eventDispatched(ev);
      }
  }

  /**
   * @since 1.3
   */
  public abstract Map mapInputMethodHighlight(InputMethodHighlight highlight);

  /**
   * Initializes the accessibility framework. In particular, this loads the
   * properties javax.accessibility.screen_magnifier_present and
   * javax.accessibility.screen_reader_present and loads
   * the classes specified in javax.accessibility.assistive_technologies.
   */
  private static void initAccessibility()
  {
    AccessController.doPrivileged
    (new PrivilegedAction()
     {
       public Object run()
       {
         Properties props = new Properties();
         String sep = File.separator;

         // Try the user configuration.
         try
           {
             File propsFile = new File(System.getProperty("user.home") + sep
                                       + ".accessibility.properties");
             FileInputStream in = new FileInputStream(propsFile);
             props.load(in);
             in.close();
           }
         catch (Exception ex)
           {
             // User configuration not present, ignore.
           }

         // Try the system configuration if there was no user configuration.
         if (props.size() == 0)
           {
             try
               {
                 File propsFile =
                   new File(System.getProperty("gnu.classpath.home.url")
                            + sep + "accessibility.properties");
                 FileInputStream in = new FileInputStream(propsFile);
                 props.load(in);
                 in.close();
               }
             catch (Exception ex)
               {
                 // System configuration not present, ignore.
               }
           }

       // Fetch the screen_magnifier_present property. Check systen properties
       // first, then fallback to the configuration file.
       String magPresent = SystemProperties.getProperty
                              ("javax.accessibility.screen_magnifier_present");
       if (magPresent == null)
         {
           magPresent = props.getProperty("screen_magnifier_present");
           if (magPresent != null)
             {
               SystemProperties.setProperty
                 ("javax.accessibility.screen_magnifier_present", magPresent);
             }
         }

       // Fetch the screen_reader_present property. Check systen properties
       // first, then fallback to the configuration file.
       String readerPresent = SystemProperties.getProperty
                                ("javax.accessibility.screen_reader_present");
       if (readerPresent == null)
         {
           readerPresent = props.getProperty("screen_reader_present");
           if (readerPresent != null)
             {
               SystemProperties.setProperty
                 ("javax.accessibility.screen_reader_present", readerPresent);
             }
         }

       // Fetch the list of classes to be loaded.
       String classes = SystemProperties.getProperty
         ("javax.accessibility.assistive_technologies");
       if (classes == null)
         {
           classes = props.getProperty("assistive_technologies");
           if (classes != null)
             {
               SystemProperties.setProperty
               ("javax.accessibility.assistive_technologies", classes);
             }
         }

       // Try to load the assisitive_technologies classes.
       if (classes != null)
         {
           ClassLoader cl = ClassLoader.getSystemClassLoader();
           StringTokenizer tokenizer = new StringTokenizer(classes, ",");
           while (tokenizer.hasMoreTokens())
             {
               String className = tokenizer.nextToken();
               try
                 {
                   Class atClass = cl.loadClass(className);
                   atClass.newInstance();
                 }
               catch (ClassNotFoundException ex)
                 {
                   AWTError err = new AWTError("Assistive Technology class not"
                                               + " found: " + className);
                   err.initCause(ex);
                   throw err;
                 }
               catch (InstantiationException ex)
                 {
                   AWTError err =
                     new AWTError("Assistive Technology class cannot be "
                                  + "instantiated: " + className);
                   err.initCause(ex);
                   throw err;
                 }
               catch (IllegalAccessException ex)
                 {
                   AWTError err =
                     new AWTError("Assistive Technology class cannot be "
                                  + "accessed: " + className);
                   err.initCause(err);
                   throw err;
                 }
             }
         }
       return null;
       }
     });

  }

} // class Toolkit
