/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.awt.im;

import java.awt.AWTEvent;
import java.awt.AWTKeyStroke;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.im.InputMethodRequests;
import java.awt.im.spi.InputMethod;
import java.lang.Character.Subset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.logging.*;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import sun.awt.SunToolkit;

/**
 * This InputContext class contains parts of the implementation of
 * java.text.im.InputContext. These parts have been moved
 * here to avoid exposing protected members that are needed by the
 * subclass InputMethodContext.
 *
 * @see java.awt.im.InputContext
 * @author JavaSoft Asia/Pacific
 */

public class InputContext extends java.awt.im.InputContext
                          implements ComponentListener, WindowListener {
    private static final Logger log = Logger.getLogger("sun.awt.im.InputContext");
    // The current input method is represented by two objects:
    // a locator is used to keep information about the selected
    // input method and locale until we actually need a real input
    // method; only then the input method itself is created.
    // Once there is an input method, the input method's locale
    // takes precedence over locale information in the locator.
    private InputMethodLocator inputMethodLocator;
    private InputMethod inputMethod;
    private boolean inputMethodCreationFailed;

    // holding bin for previously used input method instances, but not the current one
    private HashMap usedInputMethods;

    // the current client component is kept until the user focusses on a different
    // client component served by the same input context. When that happens, we call
    // endComposition so that text doesn't jump from one component to another.
    private Component currentClientComponent;
    private Component awtFocussedComponent;
    private boolean   isInputMethodActive;
    private Subset[]  characterSubsets = null;

    // true if composition area has been set to invisible when focus was lost
    private boolean compositionAreaHidden = false;

    // The input context for whose input method we may have to call hideWindows
    private static InputContext inputMethodWindowContext;

    // Previously active input method to decide whether we need to call
    // InputMethodAdapter.stopListening() on activateInputMethod()
    private static InputMethod previousInputMethod = null;

    // true if the current input method requires client window change notification
    private boolean clientWindowNotificationEnabled = false;
    // client window to which this input context is listening
    private Window clientWindowListened;
    // cache location notification
    private Rectangle clientWindowLocation = null;
    // holding the state of clientWindowNotificationEnabled of only non-current input methods
    private HashMap perInputMethodState;

    // Input Method selection hot key stuff
    private static AWTKeyStroke inputMethodSelectionKey;
    private static boolean inputMethodSelectionKeyInitialized = false;
    private static final String inputMethodSelectionKeyPath = "/java/awt/im/selectionKey";
    private static final String inputMethodSelectionKeyCodeName = "keyCode";
    private static final String inputMethodSelectionKeyModifiersName = "modifiers";

    /**
     * Constructs an InputContext.
     */
    protected InputContext() {
        InputMethodManager imm = InputMethodManager.getInstance();
        synchronized (InputContext.class) {
            if (!inputMethodSelectionKeyInitialized) {
                inputMethodSelectionKeyInitialized = true;
                if (imm.hasMultipleInputMethods()) {
                    initializeInputMethodSelectionKey();
                }
            }
        }
        selectInputMethod(imm.getDefaultKeyboardLocale());
    }

    /**
     * @see java.awt.im.InputContext#selectInputMethod
     * @exception NullPointerException when the locale is null.
     */
    public synchronized boolean selectInputMethod(Locale locale) {
        if (locale == null) {
            throw new NullPointerException();
        }

        // see whether the current input method supports the locale
        if (inputMethod != null) {
            if (inputMethod.setLocale(locale)) {
                return true;
            }
        } else if (inputMethodLocator != null) {
            // This is not 100% correct, since the input method
            // may support the locale without advertising it.
            // But before we try instantiations and setLocale,
            // we look for an input method that's more confident.
            if (inputMethodLocator.isLocaleAvailable(locale)) {
                inputMethodLocator = inputMethodLocator.deriveLocator(locale);
                return true;
            }
        }

        // see whether there's some other input method that supports the locale
        InputMethodLocator newLocator = InputMethodManager.getInstance().findInputMethod(locale);
        if (newLocator != null) {
            changeInputMethod(newLocator);
            return true;
        }

        // make one last desperate effort with the current input method
        // ??? is this good? This is pretty high cost for something that's likely to fail.
        if (inputMethod == null && inputMethodLocator != null) {
            inputMethod = getInputMethod();
            if (inputMethod != null) {
                return inputMethod.setLocale(locale);
            }
        }
        return false;
    }

    /**
     * @see java.awt.im.InputContext#getLocale
     */
    public Locale getLocale() {
        if (inputMethod != null) {
            return inputMethod.getLocale();
        } else if (inputMethodLocator != null) {
            return inputMethodLocator.getLocale();
        } else {
            return null;
        }
    }

    /**
     * @see java.awt.im.InputContext#setCharacterSubsets
     */
    public void setCharacterSubsets(Subset[] subsets) {
        if (subsets == null) {
            characterSubsets = null;
        } else {
            characterSubsets = new Subset[subsets.length];
            System.arraycopy(subsets, 0,
                             characterSubsets, 0, characterSubsets.length);
        }
        if (inputMethod != null) {
            inputMethod.setCharacterSubsets(subsets);
        }
    }

    /**
     * @see java.awt.im.InputContext#reconvert
     * @since 1.3
     * @exception UnsupportedOperationException when input method is null
     */
    public synchronized void reconvert() {
        InputMethod inputMethod = getInputMethod();
        if (inputMethod == null) {
            throw new UnsupportedOperationException();
        }
        inputMethod.reconvert();
    }

    /**
     * @see java.awt.im.InputContext#dispatchEvent
     */
    public void dispatchEvent(AWTEvent event) {

        if (event instanceof InputMethodEvent) {
            return;
        }

        // Ignore focus events that relate to the InputMethodWindow of this context.
        // This is a workaround.  Should be removed after 4452384 is fixed.
        if (event instanceof FocusEvent) {
            Component opposite = ((FocusEvent)event).getOppositeComponent();
            if ((opposite != null) &&
                (getComponentWindow(opposite) instanceof InputMethodWindow) &&
                (opposite.getInputContext() == this)) {
                return;
            }
        }

        InputMethod inputMethod = getInputMethod();
        int id = event.getID();

        switch (id) {
        case FocusEvent.FOCUS_GAINED:
            focusGained((Component) event.getSource());
            break;

        case FocusEvent.FOCUS_LOST:
            focusLost((Component) event.getSource(), ((FocusEvent) event).isTemporary());
            break;

        case KeyEvent.KEY_PRESSED:
            if (checkInputMethodSelectionKey((KeyEvent)event)) {
                // pop up the input method selection menu
                InputMethodManager.getInstance().notifyChangeRequestByHotKey((Component)event.getSource());
                break;
            }

            // fall through

        default:
            if ((inputMethod != null) && (event instanceof InputEvent)) {
                inputMethod.dispatchEvent(event);
            }
        }
    }

    /**
     * Handles focus gained events for any component that's using
     * this input context.
     * These events are generated by AWT when the keyboard focus
     * moves to a component.
     * Besides actual client components, the source components
     * may also be the composition area or any component in an
     * input method window.
     * <p>
     * When handling the focus event for a client component, this
     * method checks whether the input context was previously
     * active for a different client component, and if so, calls
     * endComposition for the previous client component.
     *
     * @param source the component gaining the focus
     */
    private void focusGained(Component source) {

        /*
         * NOTE: When a Container is removing its Component which
         * invokes this.removeNotify(), the Container has the global
         * Component lock. It is possible to happen that an
         * application thread is calling this.removeNotify() while an
         * AWT event queue thread is dispatching a focus event via
         * this.dispatchEvent(). If an input method uses AWT
         * components (e.g., IIIMP status window), it causes deadlock,
         * for example, Component.show()/hide() in this situation
         * because hide/show tried to obtain the lock.  Therefore,
         * it's necessary to obtain the global Component lock before
         * activating or deactivating an input method.
         */
        synchronized (source.getTreeLock()) {
            synchronized (this) {
                if (source instanceof CompositionArea) {
                    // no special handling for this one
                } else if (getComponentWindow(source) instanceof InputMethodWindow) {
                    // no special handling for this one either
                } else {
                    if (!source.isDisplayable()) {
                        // Component is being disposed
                        return;
                    }

                    // Focus went to a real client component.
                    // Check whether we're switching between client components
                    // that share an input context. We can't do that earlier
                    // than here because we don't want to end composition
                    // until we really know we're switching to a different component
                    if (inputMethod != null) {
                        if (currentClientComponent != null && currentClientComponent != source) {
                            if (!isInputMethodActive) {
                                activateInputMethod(false);
                            }
                            endComposition();
                            deactivateInputMethod(false);
                        }
                    }

                    currentClientComponent = source;
                }

                awtFocussedComponent = source;
                if (inputMethod instanceof InputMethodAdapter) {
                    ((InputMethodAdapter) inputMethod).setAWTFocussedComponent(source);
                }

                // it's possible that the input method is still active because
                // we suppressed a deactivate cause by an input method window
                // coming up
                if (!isInputMethodActive) {
                    activateInputMethod(true);
                }


                // If the client component is an active client with the below-the-spot
                // input style, then make the composition window undecorated without a title bar.
                InputMethodContext inputContext = ((InputMethodContext)this);
                if (!inputContext.isCompositionAreaVisible()) {
                      InputMethodRequests req = source.getInputMethodRequests();
                      if (req != null && inputContext.useBelowTheSpotInput()) {
                          inputContext.setCompositionAreaUndecorated(true);
                      } else {
                          inputContext.setCompositionAreaUndecorated(false);
                      }
                }
                // restores the composition area if it was set to invisible
                // when focus got lost
                if (compositionAreaHidden == true) {
                    ((InputMethodContext)this).setCompositionAreaVisible(true);
                    compositionAreaHidden = false;
                }
            }
        }
    }

    /**
     * Activates the current input method of this input context, and grabs
     * the composition area for use by this input context.
     * If updateCompositionArea is true, the text in the composition area
     * is updated (set to false if the text is going to change immediately
     * to avoid screen flicker).
     */
    private void activateInputMethod(boolean updateCompositionArea) {
        // call hideWindows() if this input context uses a different
        // input method than the previously activated one
        if (inputMethodWindowContext != null && inputMethodWindowContext != this &&
                inputMethodWindowContext.inputMethodLocator != null &&
                !inputMethodWindowContext.inputMethodLocator.sameInputMethod(inputMethodLocator) &&
                inputMethodWindowContext.inputMethod != null) {
            inputMethodWindowContext.inputMethod.hideWindows();
        }
        inputMethodWindowContext = this;

        if (inputMethod != null) {
            if (previousInputMethod != inputMethod &&
                    previousInputMethod instanceof InputMethodAdapter) {
                // let the host adapter pass through the input events for the
                // new input method
                ((InputMethodAdapter) previousInputMethod).stopListening();
            }
            previousInputMethod = null;

            if (log.isLoggable(Level.FINE)) log.fine("Current client component " + currentClientComponent);
            if (inputMethod instanceof InputMethodAdapter) {
                ((InputMethodAdapter) inputMethod).setClientComponent(currentClientComponent);
            }
            inputMethod.activate();
            isInputMethodActive = true;

            if (perInputMethodState != null) {
                Boolean state = (Boolean) perInputMethodState.remove(inputMethod);
                if (state != null) {
                    clientWindowNotificationEnabled = state.booleanValue();
                }
            }
            if (clientWindowNotificationEnabled) {
                if (!addedClientWindowListeners()) {
                    addClientWindowListeners();
                }
                synchronized(this) {
                    if (clientWindowListened != null) {
                        notifyClientWindowChange(clientWindowListened);
                    }
                }
            } else {
                if (addedClientWindowListeners()) {
                    removeClientWindowListeners();
                }
            }
        }
        InputMethodManager.getInstance().setInputContext(this);

        ((InputMethodContext) this).grabCompositionArea(updateCompositionArea);
    }

    static Window getComponentWindow(Component component) {
        while (true) {
            if (component == null) {
                return null;
            } else if (component instanceof Window) {
                return (Window) component;
            } else {
                component = component.getParent();
            }
        }
    }

    /**
     * Handles focus lost events for any component that's using
     * this input context.
     * These events are generated by AWT when the keyboard focus
     * moves away from a component.
     * Besides actual client components, the source components
     * may also be the composition area or any component in an
     * input method window.
     *
     * @param source the component losing the focus
     * @isTemporary whether the focus change is temporary
     */
    private void focusLost(Component source, boolean isTemporary) {

        // see the note on synchronization in focusGained
        synchronized (source.getTreeLock()) {
            synchronized (this) {

                // We need to suppress deactivation if removeNotify has been called earlier.
                // This is indicated by isInputMethodActive == false.
                if (isInputMethodActive) {
                    deactivateInputMethod(isTemporary);
                }

                awtFocussedComponent = null;
                if (inputMethod instanceof InputMethodAdapter) {
                    ((InputMethodAdapter) inputMethod).setAWTFocussedComponent(null);
                }

                // hides the composition area if currently it is visible
                InputMethodContext inputContext = ((InputMethodContext)this);
                if (inputContext.isCompositionAreaVisible()) {
                    inputContext.setCompositionAreaVisible(false);
                    compositionAreaHidden = true;
                }
            }
        }
    }

    /**
     * Checks the key event is the input method selection key or not.
     */
    private boolean checkInputMethodSelectionKey(KeyEvent event) {
        if (inputMethodSelectionKey != null) {
            AWTKeyStroke aKeyStroke = AWTKeyStroke.getAWTKeyStrokeForEvent(event);
            return inputMethodSelectionKey.equals(aKeyStroke);
        } else {
            return false;
        }
    }

    private void deactivateInputMethod(boolean isTemporary) {
        InputMethodManager.getInstance().setInputContext(null);
        if (inputMethod != null) {
            isInputMethodActive = false;
            inputMethod.deactivate(isTemporary);
            previousInputMethod = inputMethod;
        }
    }

    /**
     * Switches from the current input method to the one described by newLocator.
     * The current input method, if any, is asked to end composition, deactivated,
     * and saved for future use. The newLocator is made the current locator. If
     * the input context is active, an input method instance for the new locator
     * is obtained; otherwise this is deferred until required.
     */
    synchronized void changeInputMethod(InputMethodLocator newLocator) {
        // If we don't have a locator yet, this must be a new input context.
        // If we created a new input method here, we might get into an
        // infinite loop: create input method -> create some input method window ->
        // create new input context -> add input context to input method manager's context list ->
        // call changeInputMethod on it.
        // So, just record the locator. dispatchEvent will create the input method when needed.
        if (inputMethodLocator == null) {
            inputMethodLocator = newLocator;
            inputMethodCreationFailed = false;
            return;
        }

        // If the same input method is specified, just keep it.
        // Adjust the locale if necessary.
        if (inputMethodLocator.sameInputMethod(newLocator)) {
            Locale newLocale = newLocator.getLocale();
            if (newLocale != null && inputMethodLocator.getLocale() != newLocale) {
                if (inputMethod != null) {
                    inputMethod.setLocale(newLocale);
                }
                inputMethodLocator = newLocator;
            }
            return;
        }

        // Switch out the old input method
        Locale savedLocale = inputMethodLocator.getLocale();
        boolean wasInputMethodActive = isInputMethodActive;
        boolean wasCompositionEnabledSupported = false;
        boolean wasCompositionEnabled = false;
        if (inputMethod != null) {
            try {
                wasCompositionEnabled = inputMethod.isCompositionEnabled();
                wasCompositionEnabledSupported = true;
            } catch (UnsupportedOperationException e) { }

            if (currentClientComponent != null) {
                if (!isInputMethodActive) {
                    activateInputMethod(false);
                }
                endComposition();
                deactivateInputMethod(false);
                if (inputMethod instanceof InputMethodAdapter) {
                    ((InputMethodAdapter) inputMethod).setClientComponent(null);
                }
            }
            savedLocale = inputMethod.getLocale();

            // keep the input method instance around for future use
            if (usedInputMethods == null) {
                usedInputMethods = new HashMap(5);
            }
            if (perInputMethodState == null) {
                perInputMethodState = new HashMap(5);
            }
            usedInputMethods.put(inputMethodLocator.deriveLocator(null), inputMethod);
            perInputMethodState.put(inputMethod,
                                    new Boolean(clientWindowNotificationEnabled));
            enableClientWindowNotification(inputMethod, false);
            if (this == inputMethodWindowContext) {
                inputMethod.hideWindows();
                inputMethodWindowContext = null;
            }
            inputMethodLocator = null;
            inputMethod = null;
            inputMethodCreationFailed = false;
        }

        // Switch in the new input method
        if (newLocator.getLocale() == null && savedLocale != null &&
                newLocator.isLocaleAvailable(savedLocale)) {
            newLocator = newLocator.deriveLocator(savedLocale);
        }
        inputMethodLocator = newLocator;
        inputMethodCreationFailed = false;

        // activate the new input method if the old one was active
        if (wasInputMethodActive) {
            inputMethod = getInputMethodInstance();
            if (inputMethod instanceof InputMethodAdapter) {
                ((InputMethodAdapter) inputMethod).setAWTFocussedComponent(awtFocussedComponent);
            }
            activateInputMethod(true);
        }

        // enable/disable composition if the old one supports querying enable/disable
        if (wasCompositionEnabledSupported) {
            inputMethod = getInputMethod();
            if (inputMethod != null) {
                try {
                    inputMethod.setCompositionEnabled(wasCompositionEnabled);
                } catch (UnsupportedOperationException e) { }
            }
        }
    }

    /**
     * Returns the client component.
     */
    Component getClientComponent() {
        return currentClientComponent;
    }

    /**
     * @see java.awt.im.InputContext#removeNotify
     * @exception NullPointerException when the component is null.
     */
    public synchronized void removeNotify(Component component) {
        if (component == null) {
            throw new NullPointerException();
        }

        if (inputMethod == null) {
            if (component == currentClientComponent) {
                currentClientComponent = null;
            }
            return;
        }

        // We may or may not get a FOCUS_LOST event for this component,
        // so do the deactivation stuff here too.
        if (component == awtFocussedComponent) {
            focusLost(component, false);
        }

        if (component == currentClientComponent) {
            if (isInputMethodActive) {
                // component wasn't the one that had the focus
                deactivateInputMethod(false);
            }
            inputMethod.removeNotify();
            if (clientWindowNotificationEnabled && addedClientWindowListeners()) {
                removeClientWindowListeners();
            }
            currentClientComponent = null;
            if (inputMethod instanceof InputMethodAdapter) {
                ((InputMethodAdapter) inputMethod).setClientComponent(null);
            }

            // removeNotify() can be issued from a thread other than the event dispatch
            // thread.  In that case, avoid possible deadlock between Component.AWTTreeLock
            // and InputMethodContext.compositionAreaHandlerLock by releasing the composition
            // area on the event dispatch thread.
            if (EventQueue.isDispatchThread()) {
                ((InputMethodContext)this).releaseCompositionArea();
            } else {
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        ((InputMethodContext)InputContext.this).releaseCompositionArea();
                    }
                });
            }
        }
    }

    /**
     * @see java.awt.im.InputContext#dispose
     * @exception IllegalStateException when the currentClientComponent is not null
     */
    public synchronized void dispose() {
        if (currentClientComponent != null) {
            throw new IllegalStateException("Can't dispose InputContext while it's active");
        }
        if (inputMethod != null) {
            if (this == inputMethodWindowContext) {
                inputMethod.hideWindows();
                inputMethodWindowContext = null;
            }
            if (inputMethod == previousInputMethod) {
                previousInputMethod = null;
            }
            if (clientWindowNotificationEnabled) {
                if (addedClientWindowListeners()) {
                    removeClientWindowListeners();
                }
                clientWindowNotificationEnabled = false;
            }
            inputMethod.dispose();

            // in case the input method enabled the client window
            // notification in dispose(), which shouldn't happen, it
            // needs to be cleaned up again.
            if (clientWindowNotificationEnabled) {
                enableClientWindowNotification(inputMethod, false);
            }

            inputMethod = null;
        }
        inputMethodLocator = null;
        if (usedInputMethods != null && !usedInputMethods.isEmpty()) {
            Iterator iterator = usedInputMethods.values().iterator();
            usedInputMethods = null;
            while (iterator.hasNext()) {
                ((InputMethod) iterator.next()).dispose();
            }
        }

        // cleanup client window notification variables
        clientWindowNotificationEnabled = false;
        clientWindowListened = null;
        perInputMethodState = null;
    }

    /**
     * @see java.awt.im.InputContext#getInputMethodControlObject
     */
    public synchronized Object getInputMethodControlObject() {
        InputMethod inputMethod = getInputMethod();

        if (inputMethod != null) {
            return inputMethod.getControlObject();
        } else {
            return null;
        }
    }

    /**
     * @see java.awt.im.InputContext#setCompositionEnabled(boolean)
     * @exception UnsupportedOperationException when input method is null
     */
    public void setCompositionEnabled(boolean enable) {
        InputMethod inputMethod = getInputMethod();

        if (inputMethod == null) {
            throw new UnsupportedOperationException();
        }
        inputMethod.setCompositionEnabled(enable);
    }

    /**
     * @see java.awt.im.InputContext#isCompositionEnabled
     * @exception UnsupportedOperationException when input method is null
     */
    public boolean isCompositionEnabled() {
        InputMethod inputMethod = getInputMethod();

        if (inputMethod == null) {
            throw new UnsupportedOperationException();
        }
        return inputMethod.isCompositionEnabled();
    }

    /**
     * @return a string with information about the current input method.
     * @exception UnsupportedOperationException when input method is null
     */
    public String getInputMethodInfo() {
        InputMethod inputMethod = getInputMethod();

        if (inputMethod == null) {
            throw new UnsupportedOperationException("Null input method");
        }

        String inputMethodInfo = null;
        if (inputMethod instanceof InputMethodAdapter) {
            // returns the information about the host native input method.
            inputMethodInfo = ((InputMethodAdapter)inputMethod).
                getNativeInputMethodInfo();
        }

        // extracts the information from the InputMethodDescriptor
        // associated with the current java input method.
        if (inputMethodInfo == null && inputMethodLocator != null) {
            inputMethodInfo = inputMethodLocator.getDescriptor().
                getInputMethodDisplayName(getLocale(), SunToolkit.
                                          getStartupLocale());
        }

        if (inputMethodInfo != null && !inputMethodInfo.equals("")) {
            return inputMethodInfo;
        }

        // do our best to return something useful.
        return inputMethod.toString() + "-" + inputMethod.getLocale().toString();
    }

    /**
     * Turns off the native IM. The native IM is diabled when
     * the deactive method of InputMethod is called. It is
     * delayed until the active method is called on a different
     * peer component. This method is provided to explicitly disable
     * the native IM.
     */
    public void disableNativeIM() {
        InputMethod inputMethod = getInputMethod();
        if (inputMethod != null && inputMethod instanceof InputMethodAdapter) {
            ((InputMethodAdapter)inputMethod).disableInputMethod();
        }
    }


    private synchronized InputMethod getInputMethod() {
        if (inputMethod != null) {
            return inputMethod;
        }

        if (inputMethodCreationFailed) {
            return null;
        }

        inputMethod = getInputMethodInstance();
        return inputMethod;
    }

    /**
     * Returns an instance of the input method described by
     * the current input method locator. This may be an input
     * method that was previously used and switched out of,
     * or a new instance. The locale, character subsets, and
     * input method context of the input method are set.
     *
     * The inputMethodCreationFailed field is set to true if the
     * instantiation failed.
     *
     * @return an InputMethod instance
     * @see java.awt.im.spi.InputMethod#setInputMethodContext
     * @see java.awt.im.spi.InputMethod#setLocale
     * @see java.awt.im.spi.InputMethod#setCharacterSubsets
     */
    private InputMethod getInputMethodInstance() {
        InputMethodLocator locator = inputMethodLocator;
        if (locator == null) {
            inputMethodCreationFailed = true;
            return null;
        }

        Locale locale = locator.getLocale();
        InputMethod inputMethodInstance = null;

        // see whether we have a previously used input method
        if (usedInputMethods != null) {
            inputMethodInstance = (InputMethod) usedInputMethods.remove(locator.deriveLocator(null));
            if (inputMethodInstance != null) {
                if (locale != null) {
                    inputMethodInstance.setLocale(locale);
                }
                inputMethodInstance.setCharacterSubsets(characterSubsets);
                Boolean state = (Boolean) perInputMethodState.remove(inputMethodInstance);
                if (state != null) {
                    enableClientWindowNotification(inputMethodInstance, state.booleanValue());
                }
                ((InputMethodContext) this).setInputMethodSupportsBelowTheSpot(
                        (!(inputMethodInstance instanceof InputMethodAdapter)) ||
                        ((InputMethodAdapter) inputMethodInstance).supportsBelowTheSpot());
                return inputMethodInstance;
            }
        }

        // need to create new instance
        try {
            inputMethodInstance = locator.getDescriptor().createInputMethod();

            if (locale != null) {
                inputMethodInstance.setLocale(locale);
            }
            inputMethodInstance.setInputMethodContext((InputMethodContext) this);
            inputMethodInstance.setCharacterSubsets(characterSubsets);

        } catch (Exception e) {
            logCreationFailed(e);

            // there are a number of bad things that can happen while creating
            // the input method. In any case, we just continue without an
            // input method.
            inputMethodCreationFailed = true;

            // if the instance has been created, then it means either
            // setLocale() or setInputMethodContext() failed.
            if (inputMethodInstance != null) {
                inputMethodInstance = null;
            }
        } catch (LinkageError e) {
            logCreationFailed(e);

            // same as above
            inputMethodCreationFailed = true;
        }
        ((InputMethodContext) this).setInputMethodSupportsBelowTheSpot(
                (!(inputMethodInstance instanceof InputMethodAdapter)) ||
                ((InputMethodAdapter) inputMethodInstance).supportsBelowTheSpot());
        return inputMethodInstance;
    }

    private void logCreationFailed(Throwable throwable) {
        String errorTextFormat = Toolkit.getProperty("AWT.InputMethodCreationFailed",
                                                     "Could not create {0}. Reason: {1}");
        Object[] args =
            {inputMethodLocator.getDescriptor().getInputMethodDisplayName(null, Locale.getDefault()),
             throwable.getLocalizedMessage()};
        MessageFormat mf = new MessageFormat(errorTextFormat);
        Logger logger = Logger.getLogger("sun.awt.im");
        logger.config(mf.format(args));
    }

    InputMethodLocator getInputMethodLocator() {
        if (inputMethod != null) {
            return inputMethodLocator.deriveLocator(inputMethod.getLocale());
        }
        return inputMethodLocator;
    }

    /**
     * @see java.awt.im.InputContext#endComposition
     */
    public synchronized void endComposition() {
        if (inputMethod != null) {
            inputMethod.endComposition();
        }
    }

    /**
     * @see java.awt.im.spi.InputMethodContext#enableClientWindowNotification
     */
    synchronized void enableClientWindowNotification(InputMethod requester,
                                                     boolean enable) {
        // in case this request is not from the current input method,
        // store the request and handle it when this requesting input
        // method becomes the current one.
        if (requester != inputMethod) {
            if (perInputMethodState == null) {
                perInputMethodState = new HashMap(5);
            }
            perInputMethodState.put(requester, new Boolean(enable));
            return;
        }

        if (clientWindowNotificationEnabled != enable) {
            clientWindowLocation = null;
            clientWindowNotificationEnabled = enable;
        }
        if (clientWindowNotificationEnabled) {
            if (!addedClientWindowListeners()) {
                addClientWindowListeners();
            }
            if (clientWindowListened != null) {
                clientWindowLocation = null;
                notifyClientWindowChange(clientWindowListened);
            }
        } else {
            if (addedClientWindowListeners()) {
                removeClientWindowListeners();
            }
        }
    }

    private synchronized void notifyClientWindowChange(Window window) {
        if (inputMethod == null) {
            return;
        }

        // if the window is invisible or iconified, send null to the input method.
        if (!window.isVisible() ||
            ((window instanceof Frame) && ((Frame)window).getState() == Frame.ICONIFIED)) {
            clientWindowLocation = null;
            inputMethod.notifyClientWindowChange(null);
            return;
        }
        Rectangle location = window.getBounds();
        if (clientWindowLocation == null || !clientWindowLocation.equals(location)) {
            clientWindowLocation = location;
            inputMethod.notifyClientWindowChange(clientWindowLocation);
        }
    }

    private synchronized void addClientWindowListeners() {
        Component client = getClientComponent();
        if (client == null) {
            return;
        }
        Window window = getComponentWindow(client);
        if (window == null) {
            return;
        }
        window.addComponentListener(this);
        window.addWindowListener(this);
        clientWindowListened = window;
    }

    private synchronized void removeClientWindowListeners() {
        clientWindowListened.removeComponentListener(this);
        clientWindowListened.removeWindowListener(this);
        clientWindowListened = null;
    }

    /**
     * Returns true if listeners have been set up for client window
     * change notification.
     */
    private boolean addedClientWindowListeners() {
        return clientWindowListened != null;
    }

    /*
     * ComponentListener and WindowListener implementation
     */
    public void componentResized(ComponentEvent e) {
        notifyClientWindowChange((Window)e.getComponent());
    }

    public void componentMoved(ComponentEvent e) {
        notifyClientWindowChange((Window)e.getComponent());
    }

    public void componentShown(ComponentEvent e) {
        notifyClientWindowChange((Window)e.getComponent());
    }

    public void componentHidden(ComponentEvent e) {
        notifyClientWindowChange((Window)e.getComponent());
    }

    public void windowOpened(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

    public void windowIconified(WindowEvent e) {
        notifyClientWindowChange(e.getWindow());
    }

    public void windowDeiconified(WindowEvent e) {
        notifyClientWindowChange(e.getWindow());
    }

    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}

    /**
     * Initializes the input method selection key definition in preference trees
     */
    private void initializeInputMethodSelectionKey() {
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                // Look in user's tree
                Preferences root = Preferences.userRoot();
                inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root);

                if (inputMethodSelectionKey == null) {
                    // Look in system's tree
                    root = Preferences.systemRoot();
                    inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root);
                }
                return null;
            }
        });
    }

    private AWTKeyStroke getInputMethodSelectionKeyStroke(Preferences root) {
        try {
            if (root.nodeExists(inputMethodSelectionKeyPath)) {
                Preferences node = root.node(inputMethodSelectionKeyPath);
                int keyCode = node.getInt(inputMethodSelectionKeyCodeName, KeyEvent.VK_UNDEFINED);
                if (keyCode != KeyEvent.VK_UNDEFINED) {
                    int modifiers = node.getInt(inputMethodSelectionKeyModifiersName, 0);
                    return AWTKeyStroke.getAWTKeyStroke(keyCode, modifiers);
                }
            }
        } catch (BackingStoreException bse) {
        }

        return null;
    }
}
