/* InputContext.java -- provides the context for text input
   Copyright (C) 2002, 2003, 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 java.awt.im;

import gnu.java.util.EmptyEnumeration;

import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.im.spi.InputMethod;
import java.awt.im.spi.InputMethodDescriptor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;

/**
 * Provides a context for controlling input methods and keyboard layouts.
 * This class provides the communication layer between the client component,
 * and the various locale-dependent text entry input methods that can be used
 * for the client. By default, there is one instance per Window, shared among
 * all components, but this limits text entry to one component at a time.
 * Thus, text components can create their own instance to allow text entry
 * in multiple components at a time.
 *
 * <p>By using the interfaces of {@link java.awt.im.spi}, you can install
 * extensions which allow additional input methods. Some of these may use
 * platform native input methods, or keyboard layouts provided by the platform.
 * Input methods are unavailable if none have been installed and the platform
 * has no underlying native input methods. Extensions are installed as jar
 * files, usually accessed in the default extension location or specified by
 * the -extdir VM flag. The jar must contain a file named
 * "META_INF/services/java.awt.im.spi.InputMethodDescriptor" which lists,
 * one entry per line in UTF-8 encoding, each class in the jar that implements
 * java.awt.im.spi.InputMethodDescriptor.
 *
 * @author Eric Blake (ebb9@email.byu.edu)
 * @see Component#getInputContext()
 * @see Component#enableInputMethods(boolean)
 * @since 1.2
 * @status updated to 1.4, but unverified
 */
public class InputContext
{
  /**
   * The list of installed input method descriptors.
   */
  private static final ArrayList descriptors = new ArrayList();
  static
  {
    Enumeration e;
    try
      {
        e = ClassLoader.getSystemResources
          ("META_INF/services/java.awt.im.spi.InputMethodDescriptor");
      }
    catch (IOException ex)
      {
        // XXX Should we do something else?
        e = EmptyEnumeration.getInstance();
      }
    while (e.hasMoreElements())
      {
        URL url = (URL) e.nextElement();
        BufferedReader in;
        String line;
        try
          {
            in = new BufferedReader
              (new InputStreamReader(url.openConnection().getInputStream(),
                                     "UTF-8"));
            line = in.readLine().trim();
          }
        catch (IOException ignored)
          {
            continue;
          }
      outer:
        while (line != null)
          {
            try
              {
                if (line.charAt(0) != '#')
                  {
                    Class c = Class.forName(line);
                    descriptors.add((InputMethodDescriptor) c.newInstance());
                  }
                line = in.readLine().trim();
              }
            catch (IOException ex)
              {
                continue outer;
              }
            catch (Exception ignored)
              {
              }
          }
      }
  }

  /** The current input method; null if no input methods are installed. */
  private InputMethod im;

  /** Map of locales to the most recently selected input method. */
  private final HashMap recent = new HashMap();

  /** The list of acceptable character subsets. */
  private Character.Subset[] subsets;

  /**
   * Construct an InputContext. This is protected, so clients must use
   * {@link #getInstance()} instead.
   */
  protected InputContext()
  {
  }

  /**
   * Returns a new InputContext.
   *
   * @return a new instance, initialized to the default locale if available
   */
  public static InputContext getInstance()
  {
    InputContext ic = new InputContext();
    ic.selectInputMethod(Locale.getDefault());
    return ic;
  }

  /**
   * Attempts to select an input method or keyboard layout which supports the
   * given locale. This returns true if a locale is available and was selected.
   * The following steps are taken in choosing an input method:<ul>
   * <li>If the currently selected input method or keyboard layout supports
   * the requested locale, it remains selected.</li>
   * <li>If there is no input method or keyboard layout available that
   * supports the requested locale, the current input method or keyboard
   * layout remains selected.</li>
   * <li>If the user has previously selected an input method or keyboard
   * layout for the requested locale from the user interface, then the most
   * recently selected such input method or keyboard layout is reselected.</li>
   * <li>Otherwise, an input method or keyboard layout that supports the
   * requested locale is selected in an implementation dependent way. This
   * implementation chooses the first input method which supports the requested
   * locale based on the InputMethodDescriptors loaded from the extensions
   * installed on the CLASSPATH.</li>
   * </ul>
   *
   * <p>Before switching away from an input method, any currently uncommitted
   * text is committed. Not all host operating systems provide API to
   * determine the locale of the currently selected native input method or
   * keyboard layout, and to select a native input method or keyboard layout
   * by locale. For host operating systems that don't provide such API,
   * selectInputMethod assumes that native input methods or keyboard layouts
   * provided by the host operating system support only the system's default
   * locale.
   *
   * <p>An example of where this may be called is in a multi-language document,
   * when moving the insertion point between sections of different locale, so
   * that the user may use the input method appropriate to that section of the
   * document.
   *
   * @param locale the desired new locale
   * @return true if the new locale is active
   * @throws NullPointerException if locale is null
   */
  public boolean selectInputMethod(Locale locale)
  {
    if (im != null && im.setLocale(locale))
      {
        recent.put(locale, im);
        return true;
      }
    InputMethod next = (InputMethod) recent.get(locale);
  outer:
    if (next != null)
      for (int i = 0, limit = descriptors.size(); i < limit; i++)
        {
          InputMethodDescriptor d = (InputMethodDescriptor) descriptors.get(i);
          Locale[] list;
          try
            {
              list = d.getAvailableLocales();
            }
          catch (AWTException ignored)
            {
              continue;
            }
          for (int j = list.length; --j >= 0; )
            if (locale.equals(list[j]))
              {
                try
                  {
                    next = d.createInputMethod();
                    recent.put(locale, next);
                  }
                catch (Exception ignored)
                  {
                    continue;
                  }
              }
        }
    if (next == null)
      return false;
    // XXX I'm not sure if this does all the necessary steps in the switch.
    if (im != null)
      {
        try
          {
            next.setCompositionEnabled(im.isCompositionEnabled());
          }
        catch (UnsupportedOperationException ignored)
          {
          }
        im.endComposition();
        im.deactivate(false);
        im.hideWindows();
      }
    im = next;
    im.setLocale(locale);
    im.setCharacterSubsets(subsets);
    return true;
  }

  /**
   * Returns the current locale of the current input method or keyboard
   * layout. Returns null if the input context does not have a current input
   * method or keyboard layout or if the current input method's
   * {@link InputMethod#getLocale()} method returns null. Not all host
   * operating systems provide API to determine the locale of the currently
   * selected native input method or keyboard layout. For host operating
   * systems that don't provide such API, getLocale assumes that the current
   * locale of all native input methods or keyboard layouts provided by the
   * host operating system is the system's default locale.
   *
   * @return the locale of the current input method, or null
   * @since 1.3
   */
  public Locale getLocale()
  {
    return im == null ? null : im.getLocale();
  }

  /**
   * Sets the subsets of Unicode characters allowed to be input by the current
   * input method, as well as subsequent input methods. The value of null
   * implies all characters are legal. Applications should not rely on this
   * behavior, since native host input methods may not allow restrictions.
   * If no current input method is available, this has no immediate effect.
   *
   * @param subsets the set of Unicode subsets to accept, or null
   */
  public void setCharacterSubsets(Character.Subset[] subsets)
  {
    this.subsets = subsets;
    if (im != null)
      im.setCharacterSubsets(subsets);
  }

  /**
   * Changes the enabled status of the current input method. An input method
   * that is enabled for composition interprets incoming events for both
   * composition and control purposes, while a disabled input method only
   * interprets control commands (including commands to enable itself).
   *
   * @param enable whether to enable the input method
   * @throws UnsupportedOperationException if there is no current input method,
   *         or the input method does not support enabling
   * @see #isCompositionEnabled()
   * @since 1.3
   */
  public void setCompositionEnabled(boolean enable)
  {
    if (im == null)
      throw new UnsupportedOperationException();
    im.setCompositionEnabled(enable);
  }

  /**
   * Find out if the current input method is enabled.
   *
   * @return true if the current input method is enabled
   * @throws UnsupportedOperationException if there is no current input method,
   *         or the input method does not support enabling
   * @see #setCompositionEnabled(boolean)
   * @since 1.3
   */
  public boolean isCompositionEnabled()
  {
    if (im == null)
      throw new UnsupportedOperationException();
    return im.isCompositionEnabled();
  }

  /**
   * Starts a reconversion operation in the current input method. The input
   * method gets the text to reconvert from the client component, using
   * {@link InputMethodRequests#getSelectedText(Attribute[])}. Then the
   * composed and committed text produced by the operation is sent back to
   * the client using a sequence of InputMethodRequests.
   *
   * @throws UnsupportedOperationException if there is no current input method,
   *         or the input method does not support reconversion
   * @since 1.3
   */
  public void reconvert()
  {
    if (im == null)
      throw new UnsupportedOperationException();
    im.reconvert();
  }

  /**
   * Dispatches an event to the current input method. This is called
   * automatically by AWT. If no input method is available, then the event
   * will never be consumed.
   *
   * @param event the event to dispatch
   * @throws NullPointerException if event is null
   */
  public void dispatchEvent(AWTEvent event)
  {
    if (im != null)
      im.dispatchEvent(event);
  }

  /**
   * Notifies the input context that a client component has been removed from
   * its containment hierarchy, or that input method support has been disabled
   * for the component. This method is usually called from the client
   * component's {@link Component#removeNotify()} method. Potentially pending
   * input from input methods for this component is discarded. If no input
   * methods are available, then this method has no effect.
   *
   * @param client the client component
   * @throws NullPointerException if client is null
   */
  public void removeNotify(Component client)
  {
    // XXX What to do with client information?
    if (im != null)
      {
        im.deactivate(false);
        im.removeNotify();
      }
  }

  /**
   * Ends any input composition that may currently be going on in this
   * context. Depending on the platform and possibly user preferences, this
   * may commit or delete uncommitted text. Any changes to the text are
   * communicated to the active component using an input method event. If no
   * input methods are available, then this method has no effect. This may
   * be called for a variety of reasons, such as when the user moves the
   * insertion point in the client text outside the range of the composed text,
   * or when text is saved to file.
   */
  public void endComposition()
  {
    if (im != null)
      im.endComposition();
  }

  /**
   * Disposes of the input context and release the resources used by it.
   * Called automatically by AWT for the default input context of each
   * Window. If no input methods are available, then this method has no
   * effect.
   */
  public void dispose()
  {
    if (im != null)
      {
        im.deactivate(false);
        im.dispose();
      }
  }

  /**
   * Returns a control object from the current input method, or null. A
   * control object provides implementation-dependent methods that control
   * the behavior of the input method or obtain information from the input
   * method. Clients have to compare the result against known input method
   * control object types. If no input methods are available or the current
   * input method does not provide an input method control object, then null
   * is returned. 
   *
   * @return the control object, or null
   */
  public Object getInputMethodControlObject()
  {
    return im == null ? null : im.getControlObject();
  }
} // class InputContext
