/*
 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt;

import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Window;
import java.awt.im.InputMethodHighlight;
import java.awt.im.spi.InputMethodContext;
import sun.awt.im.InputMethodAdapter;
import java.awt.event.InputMethodEvent;
import java.awt.font.TextAttribute;
import java.awt.font.TextHitInfo;
import java.awt.peer.ComponentPeer;
import java.lang.Character.Subset;
import java.text.AttributedString;
import java.text.AttributedCharacterIterator;

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.ref.WeakReference;
import sun.util.logging.PlatformLogger;
import java.util.StringTokenizer;
import java.util.regex.Pattern;


/**
 * Input Method Adapter for XIM
 *
 * @author JavaSoft International
 */
public abstract class X11InputMethod extends InputMethodAdapter {
    private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11InputMethod");
    /*
     * The following XIM* values must be the same as those defined in
     * Xlib.h
     */
    private static final int XIMReverse = (1<<0);
    private static final int XIMUnderline = (1<<1);
    private static final int XIMHighlight = (1<<2);
    private static final int XIMPrimary = (1<<5);
    private static final int XIMSecondary = (1<<6);
    private static final int XIMTertiary = (1<<7);

    /*
     * visible position values
     */
    private static final int XIMVisibleToForward = (1<<8);
    private static final int XIMVisibleToBackward = (1<<9);
    private static final int XIMVisibleCenter = (1<<10);
    private static final int XIMVisibleMask = (XIMVisibleToForward|
                                               XIMVisibleToBackward|
                                               XIMVisibleCenter);

    private Locale locale;
    private static boolean isXIMOpened = false;
    protected Container clientComponentWindow = null;
    private Component awtFocussedComponent = null;
    private Component lastXICFocussedComponent = null;
    private boolean   isLastXICActive = false;
    private boolean   isLastTemporary = false;
    private boolean   isActive = false;
    private boolean   isActiveClient = false;
    private static Map<TextAttribute, ?>[] highlightStyles;
    private boolean disposed = false;

    //reset the XIC if necessary
    private boolean   needResetXIC = false;
    private WeakReference<Component> needResetXICClient = new WeakReference<>(null);

    // The use of compositionEnableSupported is to reduce unnecessary
    // native calls if set/isCompositionEnabled
    // throws UnsupportedOperationException.
    // It is set to false if that exception is thrown first time
    // either of the two methods are called.
    private boolean compositionEnableSupported = true;
    // The savedCompositionState indicates the composition mode when
    // endComposition or setCompositionEnabled is called. It doesn't always
    // reflect the actual composition state because it doesn't get updated
    // when the user changes the composition state through direct interaction
    // with the input method. It is used to save the composition mode when
    // focus is traversed across different client components sharing the
    // same java input context. Also if set/isCompositionEnabled are not
    // supported, it remains false.
    private boolean savedCompositionState = false;

    // variables to keep track of preedit context.
    // these variables need to be accessed within AWT_LOCK/UNLOCK
    private String committedText = null;
    private StringBuffer composedText = null;
    private IntBuffer rawFeedbacks;

    // private data (X11InputMethodData structure defined in
    // awt_InputMethod.c) for native methods
    // this structure needs to be accessed within AWT_LOCK/UNLOCK
    private transient long pData = 0; // accessed by native

    // Initialize highlight mapping table
    static {
        @SuppressWarnings({"unchecked", "rawtypes"})
        Map<TextAttribute, ?> styles[] = new Map[4];
        HashMap<TextAttribute, Object> map;

        // UNSELECTED_RAW_TEXT_HIGHLIGHT
        map = new HashMap<>(1);
        map.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
        styles[0] = Collections.unmodifiableMap(map);

        // SELECTED_RAW_TEXT_HIGHLIGHT
        map = new HashMap<>(1);
        map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON);
        styles[1] = Collections.unmodifiableMap(map);

        // UNSELECTED_CONVERTED_TEXT_HIGHLIGHT
        map = new HashMap<>(1);
        map.put(TextAttribute.INPUT_METHOD_UNDERLINE,
                TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
        styles[2] = Collections.unmodifiableMap(map);

        // SELECTED_CONVERTED_TEXT_HIGHLIGHT
        map = new HashMap<>(1);
        map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON);
        styles[3] = Collections.unmodifiableMap(map);

        highlightStyles = styles;
    }

    static {
        initIDs();
    }

    /**
     * Initialize JNI field and method IDs for fields that may be
       accessed from C.
     */
    private static native void initIDs();

    /**
     * Constructs an X11InputMethod instance. It initializes the XIM
     * environment if it's not done yet.
     *
     * @exception AWTException if XOpenIM() failed.
     */
    public X11InputMethod() throws AWTException {
        // supports only the locale in which the VM is started
        locale = X11InputMethodDescriptor.getSupportedLocale();
        if (initXIM() == false) {
            throw new AWTException("Cannot open X Input Method");
        }
    }

    protected void finalize() throws Throwable {
        dispose();
        super.finalize();
    }

    /**
     * Invokes openIM() that invokes XOpenIM() if it's not opened yet.
     * @return  true if openXIM() is successful or it's already been opened.
     */
    private synchronized boolean initXIM() {
        if (isXIMOpened == false)
            isXIMOpened = openXIM();
        return isXIMOpened;
    }

    protected abstract boolean openXIM();

    protected boolean isDisposed() {
        return disposed;
    }

    protected abstract void setXICFocus(ComponentPeer peer,
                                    boolean value, boolean active);

    /**
     * Does nothing - this adapter doesn't use the input method context.
     *
     * @see java.awt.im.spi.InputMethod#setInputMethodContext
     */
    public void setInputMethodContext(InputMethodContext context) {
    }

    /**
     * Set locale to input. If input method doesn't support specified locale,
     * false will be returned and its behavior is not changed.
     *
     * @param lang locale to input
     * @return the true is returned when specified locale is supported.
     */
    public boolean setLocale(Locale lang) {
        if (lang.equals(locale)) {
            return true;
        }
        // special compatibility rule for Japanese and Korean
        if (locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) ||
                locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) {
            return true;
        }
        return false;
    }

    /**
     * Returns current input locale.
     */
    public Locale getLocale() {
        return locale;
    }

    /**
     * Does nothing - XIM doesn't let you specify which characters you expect.
     *
     * @see java.awt.im.spi.InputMethod#setCharacterSubsets
     */
    public void setCharacterSubsets(Subset[] subsets) {
    }

    /**
     * Dispatch event to input method. InputContext dispatch event with this
     * method. Input method set consume flag if event is consumed in
     * input method.
     *
     * @param e event
     */
    public void dispatchEvent(AWTEvent e) {
    }


    protected final void resetXICifneeded(){
        /* needResetXIC is used to indicate whether to call
           resetXIC on the active client. resetXIC will always be
           called on the passive client when endComposition is called.
        */
        if (needResetXIC && haveActiveClient() &&
            getClientComponent() != needResetXICClient.get()){
            resetXIC();

            // needs to reset the last xic focussed component.
            lastXICFocussedComponent = null;
            isLastXICActive = false;

            needResetXICClient.clear();
            needResetXIC = false;
        }
    }

    /**
     * Reset the composition state to the current composition state.
     */
    private void resetCompositionState() {
        if (compositionEnableSupported) {
            try {
                /* Restore the composition mode to the last saved composition
                   mode. */
                setCompositionEnabled(savedCompositionState);
            } catch (UnsupportedOperationException e) {
                compositionEnableSupported = false;
            }
        }
    }

    /**
     * Query and then return the current composition state.
     * @return the composition state if isCompositionEnabled call
     * is successful. Otherwise, it returns false.
     */
    private boolean getCompositionState() {
        boolean compositionState = false;
        if (compositionEnableSupported) {
            try {
                compositionState = isCompositionEnabled();
            } catch (UnsupportedOperationException e) {
                compositionEnableSupported = false;
            }
        }
        return compositionState;
    }

    /**
     * Activate input method.
     */
    public synchronized void activate() {
        clientComponentWindow = getClientComponentWindow();
        if (clientComponentWindow == null)
            return;

        if (lastXICFocussedComponent != null){
            if (log.isLoggable(PlatformLogger.Level.FINE)) {
                log.fine("XICFocused {0}, AWTFocused {1}",
                         lastXICFocussedComponent, awtFocussedComponent);
            }
        }

        if (pData == 0) {
            if (!createXIC()) {
                return;
            }
            disposed = false;
        }

        /*  reset input context if necessary and set the XIC focus
        */
        resetXICifneeded();
        ComponentPeer lastXICFocussedComponentPeer = null;
        ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent);

        if (lastXICFocussedComponent != null) {
           lastXICFocussedComponentPeer = getPeer(lastXICFocussedComponent);
        }

        /* If the last XIC focussed component has a different peer as the
           current focussed component, change the XIC focus to the newly
           focussed component.
        */
        if (isLastTemporary || lastXICFocussedComponentPeer != awtFocussedComponentPeer ||
            isLastXICActive != haveActiveClient()) {
            if (lastXICFocussedComponentPeer != null) {
                setXICFocus(lastXICFocussedComponentPeer, false, isLastXICActive);
            }
            if (awtFocussedComponentPeer != null) {
                setXICFocus(awtFocussedComponentPeer, true, haveActiveClient());
            }
            lastXICFocussedComponent = awtFocussedComponent;
            isLastXICActive = haveActiveClient();
        }
        resetCompositionState();
        isActive = true;
    }

    protected abstract boolean createXIC();

    /**
     * Deactivate input method.
     */
    public synchronized void deactivate(boolean isTemporary) {
        boolean   isAc =  haveActiveClient();
        /* Usually as the client component, let's call it component A,
           loses the focus, this method is called. Then when another client
           component, let's call it component B,  gets the focus, activate is first called on
           the previous focused compoent which is A, then endComposition is called on A,
           deactivate is called on A again. And finally activate is called on the newly
           focused component B. Here is the call sequence.

           A loses focus               B gains focus
           -------------> deactivate A -------------> activate A -> endComposition A ->
           deactivate A -> activate B ----....

           So in order to carry the composition mode across the components sharing the same
           input context, we save it when deactivate is called so that when activate is
           called, it can be restored correctly till activate is called on the newly focused
           component. (See also sun/awt/im/InputContext and bug 6184471).
           Last note, getCompositionState should be called before setXICFocus since
           setXICFocus here sets the XIC to 0.
        */
        savedCompositionState = getCompositionState();

        if (isTemporary){
            //turn the status window off...
            turnoffStatusWindow();
        }

        /* Delay resetting the XIC focus until activate is called and the newly
           focussed component has a different peer as the last focussed component.
        */
        lastXICFocussedComponent = awtFocussedComponent;
        isLastXICActive = isAc;
        isLastTemporary = isTemporary;
        isActive = false;
    }

    /**
     * Explicitly disable the native IME. Native IME is not disabled when
     * deactivate is called.
     */
    public void disableInputMethod() {
        if (lastXICFocussedComponent != null) {
            setXICFocus(getPeer(lastXICFocussedComponent), false, isLastXICActive);
            lastXICFocussedComponent = null;
            isLastXICActive = false;

            resetXIC();
            needResetXICClient.clear();
            needResetXIC = false;
        }
    }

    // implements java.awt.im.spi.InputMethod.hideWindows
    public void hideWindows() {
        // ??? need real implementation
    }

    /**
     * @see java.awt.Toolkit#mapInputMethodHighlight
     */
    public static Map<TextAttribute, ?> mapInputMethodHighlight(InputMethodHighlight highlight) {
        int index;
        int state = highlight.getState();
        if (state == InputMethodHighlight.RAW_TEXT) {
            index = 0;
        } else if (state == InputMethodHighlight.CONVERTED_TEXT) {
            index = 2;
        } else {
            return null;
        }
        if (highlight.isSelected()) {
            index += 1;
        }
        return highlightStyles[index];
    }

    /**
     * @see sun.awt.im.InputMethodAdapter#setAWTFocussedComponent
     */
    protected void setAWTFocussedComponent(Component component) {
        if (component == null) {
            return;
        }
        if (isActive) {
            // deactivate/activate are being suppressed during a focus change -
            // this may happen when an input method window is made visible
            boolean ac = haveActiveClient();
            setXICFocus(getPeer(awtFocussedComponent), false, ac);
            setXICFocus(getPeer(component), true, ac);
        }
        awtFocussedComponent = component;
    }

    /**
     * @see sun.awt.im.InputMethodAdapter#stopListening
     */
    protected void stopListening() {
        // It is desirable to disable XIM by calling XSetICValues with
        // XNPreeditState == XIMPreeditDisable.  But Solaris 2.6 and
        // Solaris 7 do not implement this correctly without a patch,
        // so just call resetXIC here.  Prior endComposition call commits
        // the existing composed text.
        endComposition();
        // disable the native input method so that the other input
        // method could get the input focus.
        disableInputMethod();
        if (needResetXIC) {
            resetXIC();
            needResetXICClient.clear();
            needResetXIC = false;
        }
    }

    /**
     * Returns the Window instance in which the client component is
     * contained. If not found, null is returned. (IS THIS POSSIBLE?)
     */
    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    private Window getClientComponentWindow() {
        Component client = getClientComponent();
        Container container;

        if (client instanceof Container) {
            container = (Container) client;
        } else {
            container = getParent(client);
        }

        while (container != null && !(container instanceof java.awt.Window)) {
            container = getParent(container);
        }
        return (Window) container;
    }

    protected abstract Container getParent(Component client);

    /**
     * Returns peer of the given client component. If the given client component
     * doesn't have peer, peer of the native container of the client is returned.
     */
    protected abstract ComponentPeer getPeer(Component client);

    /**
     * Used to protect preedit data
     */
    protected abstract void awtLock();
    protected abstract void awtUnlock();

    /**
     * Creates an input method event from the arguments given
     * and posts it on the AWT event queue. For arguments,
     * see InputMethodEvent. Called by input method.
     *
     * @see java.awt.event.InputMethodEvent#InputMethodEvent
     */
    private void postInputMethodEvent(int id,
                                      AttributedCharacterIterator text,
                                      int committedCharacterCount,
                                      TextHitInfo caret,
                                      TextHitInfo visiblePosition,
                                      long when) {
        Component source = getClientComponent();
        if (source != null) {
            InputMethodEvent event = new InputMethodEvent(source,
                id, when, text, committedCharacterCount, caret, visiblePosition);
            SunToolkit.postEvent(SunToolkit.targetToAppContext(source), (AWTEvent)event);
        }
    }

    private void postInputMethodEvent(int id,
                                      AttributedCharacterIterator text,
                                      int committedCharacterCount,
                                      TextHitInfo caret,
                                      TextHitInfo visiblePosition) {
        postInputMethodEvent(id, text, committedCharacterCount,
                             caret, visiblePosition, EventQueue.getMostRecentEventTime());
    }

    /**
     * Dispatches committed text from XIM to the awt event queue. This
     * method is invoked from the event handler in canvas.c in the
     * AWT Toolkit thread context and thus inside the AWT Lock.
     * @param   str     committed text
     * @param   when    when
     */
    // NOTE: This method may be called by privileged threads.
    //       This functionality is implemented in a package-private method
    //       to insure that it cannot be overridden by client subclasses.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    void dispatchCommittedText(String str, long when) {
        if (str == null)
            return;

        if (composedText == null) {
            AttributedString attrstr = new AttributedString(str);
            postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                 attrstr.getIterator(),
                                 str.length(),
                                 null,
                                 null,
                                 when);
        } else {
            // if there is composed text, wait until the preedit
            // callback is invoked.
            committedText = str;
        }
    }

    private void dispatchCommittedText(String str) {
        dispatchCommittedText(str, EventQueue.getMostRecentEventTime());
    }

    /**
     * Updates composed text with XIM preedit information and
     * posts composed text to the awt event queue. The args of
     * this method correspond to the XIM preedit callback
     * information. The XIM highlight attributes are translated via
     * fixed mapping (i.e., independent from any underlying input
     * method engine). This method is invoked in the AWT Toolkit
     * (X event loop) thread context and thus inside the AWT Lock.
     */
    // NOTE: This method may be called by privileged threads.
    //       This functionality is implemented in a package-private method
    //       to insure that it cannot be overridden by client subclasses.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    void dispatchComposedText(String chgText,
                                           int chgStyles[],
                                           int chgOffset,
                                           int chgLength,
                                           int caretPosition,
                                           long when) {
        if (disposed) {
            return;
        }

        //Workaround for deadlock bug on solaris2.6_zh bug#4170760
        if (chgText == null
            && chgStyles == null
            && chgOffset == 0
            && chgLength == 0
            && caretPosition == 0
            && composedText == null
            && committedText == null)
            return;

        if (composedText == null) {
            // TODO: avoid reallocation of those buffers
            composedText = new StringBuffer(INITIAL_SIZE);
            rawFeedbacks = new IntBuffer(INITIAL_SIZE);
        }
        if (chgLength > 0) {
            if (chgText == null && chgStyles != null) {
                rawFeedbacks.replace(chgOffset, chgStyles);
            } else {
                if (chgLength == composedText.length()) {
                    // optimization for the special case to replace the
                    // entire previous text
                    composedText = new StringBuffer(INITIAL_SIZE);
                    rawFeedbacks = new IntBuffer(INITIAL_SIZE);
                } else {
                    if (composedText.length() > 0) {
                        if (chgOffset+chgLength < composedText.length()) {
                            String text;
                            text = composedText.toString().substring(chgOffset+chgLength,
                                                                     composedText.length());
                            composedText.setLength(chgOffset);
                            composedText.append(text);
                        } else {
                            // in case to remove substring from chgOffset
                            // to the end
                            composedText.setLength(chgOffset);
                        }
                        rawFeedbacks.remove(chgOffset, chgLength);
                    }
                }
            }
        }
        if (chgText != null) {
            composedText.insert(chgOffset, chgText);
            if (chgStyles != null)
                rawFeedbacks.insert(chgOffset, chgStyles);
        }

        if (composedText.length() == 0) {
            composedText = null;
            rawFeedbacks = null;

            // if there is any outstanding committed text stored by
            // dispatchCommittedText(), it has to be sent to the
            // client component.
            if (committedText != null) {
                dispatchCommittedText(committedText, when);
                committedText = null;
                return;
            }

            // otherwise, send null text to delete client's composed
            // text.
            postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                 null,
                                 0,
                                 null,
                                 null,
                                 when);

            return;
        }

        // Now sending the composed text to the client
        int composedOffset;
        AttributedString inputText;

        // if there is any partially committed text, concatenate it to
        // the composed text.
        if (committedText != null) {
            composedOffset = committedText.length();
            inputText = new AttributedString(committedText + composedText);
            committedText = null;
        } else {
            composedOffset = 0;
            inputText = new AttributedString(composedText.toString());
        }

        int currentFeedback;
        int nextFeedback;
        int startOffset = 0;
        int currentOffset;
        int visiblePosition = 0;
        TextHitInfo visiblePositionInfo = null;

        rawFeedbacks.rewind();
        currentFeedback = rawFeedbacks.getNext();
        rawFeedbacks.unget();
        while ((nextFeedback = rawFeedbacks.getNext()) != -1) {
            if (visiblePosition == 0) {
                visiblePosition = nextFeedback & XIMVisibleMask;
                if (visiblePosition != 0) {
                    int index = rawFeedbacks.getOffset() - 1;

                    if (visiblePosition == XIMVisibleToBackward)
                        visiblePositionInfo = TextHitInfo.leading(index);
                    else
                        visiblePositionInfo = TextHitInfo.trailing(index);
                }
            }
            nextFeedback &= ~XIMVisibleMask;
            if (currentFeedback != nextFeedback) {
                rawFeedbacks.unget();
                currentOffset = rawFeedbacks.getOffset();
                inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
                                       convertVisualFeedbackToHighlight(currentFeedback),
                                       composedOffset + startOffset,
                                       composedOffset + currentOffset);
                startOffset = currentOffset;
                currentFeedback = nextFeedback;
            }
        }
        currentOffset = rawFeedbacks.getOffset();
        if (currentOffset >= 0) {
            inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
                                   convertVisualFeedbackToHighlight(currentFeedback),
                                   composedOffset + startOffset,
                                   composedOffset + currentOffset);
        }

        postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                             inputText.getIterator(),
                             composedOffset,
                             TextHitInfo.leading(caretPosition),
                             visiblePositionInfo,
                             when);
    }

    /**
     * Flushes composed and committed text held in this context.
     * This method is invoked in the AWT Toolkit (X event loop) thread context
     * and thus inside the AWT Lock.
     */
    // NOTE: This method may be called by privileged threads.
    //       This functionality is implemented in a package-private method
    //       to insure that it cannot be overridden by client subclasses.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    void flushText() {
        String flush = (committedText != null ? committedText : "");
        if (composedText != null) {
            flush += composedText.toString();
        }

        if (!flush.equals("")) {
            AttributedString attrstr = new AttributedString(flush);
            postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                 attrstr.getIterator(),
                                 flush.length(),
                                 null,
                                 null,
                                 EventQueue.getMostRecentEventTime());
            composedText = null;
            committedText = null;
        }
    }

    /*
     * Subclasses should override disposeImpl() instead of dispose(). Client
     * code should always invoke dispose(), never disposeImpl().
     */
    protected synchronized void disposeImpl() {
        disposeXIC();
        awtLock();
        composedText = null;
        committedText = null;
        rawFeedbacks = null;
        awtUnlock();
        awtFocussedComponent = null;
        lastXICFocussedComponent = null;
    }

    /**
     * Frees all X Window resources associated with this object.
     *
     * @see java.awt.im.spi.InputMethod#dispose
     */
    public final void dispose() {
        boolean call_disposeImpl = false;

        if (!disposed) {
            synchronized (this) {
                if (!disposed) {
                    disposed = call_disposeImpl = true;
                }
            }
        }

        if (call_disposeImpl) {
            disposeImpl();
        }
    }

    /**
     * Returns null.
     *
     * @see java.awt.im.spi.InputMethod#getControlObject
     */
    public Object getControlObject() {
        return null;
    }

    /**
     * @see java.awt.im.spi.InputMethod#removeNotify
     */
    public synchronized void removeNotify() {
        dispose();
    }

    /**
     * @see java.awt.im.spi.InputMethod#setCompositionEnabled(boolean)
     */
    public void setCompositionEnabled(boolean enable) {
        /* If the composition state is successfully changed, set
           the savedCompositionState to 'enable'. Otherwise, simply
           return.
           setCompositionEnabledNative may throw UnsupportedOperationException.
           Don't try to catch it since the method may be called by clients.
           Use package private mthod 'resetCompositionState' if you want the
           exception to be caught.
        */
        if (setCompositionEnabledNative(enable)) {
            savedCompositionState = enable;
        }
    }

    /**
     * @see java.awt.im.spi.InputMethod#isCompositionEnabled
     */
    public boolean isCompositionEnabled() {
        /* isCompositionEnabledNative may throw UnsupportedOperationException.
           Don't try to catch it since this method may be called by clients.
           Use package private method 'getCompositionState' if you want the
           exception to be caught.
        */
        return isCompositionEnabledNative();
    }

    /**
     * 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.
     *
     * <p>
     * A text editing component may call this in a variety of situations,
     * for example, when the user moves the insertion point within the text
     * (but outside the composed text), or when the component's text is
     * saved to a file or copied to the clipboard.
     *
     */
    public void endComposition() {
        if (disposed) {
            return;
        }

        /* Before calling resetXIC, record the current composition mode
           so that it can be restored later. */
        savedCompositionState = getCompositionState();
        boolean active = haveActiveClient();
        if (active && composedText == null && committedText == null){
            needResetXIC = true;
            needResetXICClient = new WeakReference<>(getClientComponent());
            return;
        }

        String text = resetXIC();
        /* needResetXIC is only set to true for active client. So passive
           client should not reset the flag to false. */
        if (active) {
            needResetXIC = false;
        }

        // Remove any existing composed text by posting an InputMethodEvent
        // with null composed text.  It would be desirable to wait for a
        // dispatchComposedText call from X input method engine, but some
        // input method does not conform to the XIM specification and does
        // not call the preedit callback to erase preedit text on calling
        // XmbResetIC.  To work around this problem, do it here by ourselves.
        awtLock();
        composedText = null;
        postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                             null,
                             0,
                             null,
                             null);

        if (text != null && text.length() > 0) {
            dispatchCommittedText(text);
        }
        awtUnlock();

        // Restore the preedit state if it was enabled
        if (savedCompositionState) {
            resetCompositionState();
        }
    }

    /**
     * Returns a string with information about the current input method server, or null.
     * On both Linux & SunOS, the value of environment variable XMODIFIERS is
     * returned if set. Otherwise, on SunOS, $HOME/.dtprofile will be parsed
     * to find out the language service engine (atok or wnn) since there is
     * no API in Xlib which returns the information of native
     * IM server or language service and we want to try our best to return as much
     * information as possible.
     *
     * Note: This method could return null on Linux if XMODIFIERS is not set properly or
     * if any IOException is thrown.
     * See man page of XSetLocaleModifiers(3X11) for the usgae of XMODIFIERS,
     * atok12setup(1) and wnn6setup(1) for the information written to
     * $HOME/.dtprofile when you run these two commands.
     *
     */
    public String getNativeInputMethodInfo() {
        String xmodifiers = System.getenv("XMODIFIERS");
        String imInfo = null;

        // If XMODIFIERS is set, return the value
        if (xmodifiers != null) {
            int imIndex = xmodifiers.indexOf("@im=");
            if (imIndex != -1) {
                imInfo = xmodifiers.substring(imIndex + 4);
            }
        } else if (System.getProperty("os.name").startsWith("SunOS")) {
            File dtprofile = new File(System.getProperty("user.home") +
                                      "/.dtprofile");
            String languageEngineInfo = null;
            try {
                BufferedReader br = new BufferedReader(new FileReader(dtprofile));
                String line = null;

                while ( languageEngineInfo == null && (line = br.readLine()) != null) {
                    if (line.contains("atok") || line.contains("wnn")) {
                        StringTokenizer tokens =  new StringTokenizer(line);
                        while (tokens.hasMoreTokens()) {
                            String token = tokens.nextToken();
                            if (Pattern.matches("atok.*setup", token) ||
                                Pattern.matches("wnn.*setup", token)){
                                languageEngineInfo = token.substring(0, token.indexOf("setup"));
                                break;
                            }
                        }
                    }
                }

                br.close();
            } catch(IOException ioex) {
                // Since this method is provided for internal testing only,
                // we dump the stack trace for the ease of debugging.
                ioex.printStackTrace();
            }

            imInfo = "htt " + languageEngineInfo;
        }

        return imInfo;
    }


    /**
     * Performs mapping from an XIM visible feedback value to Java IM highlight.
     * @return Java input method highlight
     */
    private InputMethodHighlight convertVisualFeedbackToHighlight(int feedback) {
        InputMethodHighlight highlight;

        switch (feedback) {
        case XIMUnderline:
            highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT;
            break;
        case XIMReverse:
            highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT;
            break;
        case XIMHighlight:
            highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT;
            break;
        case XIMPrimary:
            highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT;
            break;
        case XIMSecondary:
            highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT;
            break;
        case XIMTertiary:
            highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT;
            break;
        default:
            highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT;
            break;
        }
        return highlight;
    }

    // initial capacity size for string buffer, etc.
    private static final int INITIAL_SIZE = 64;

    /**
     * IntBuffer is an inner class that manipulates an int array and
     * provides UNIX file io stream-like programming interfaces to
     * access it. (An alternative would be to use ArrayList which may
     * be too expensive for the work.)
     */
    private final class IntBuffer {
        private int[] intArray;
        private int size;
        private int index;

        IntBuffer(int initialCapacity) {
            intArray = new int[initialCapacity];
            size = 0;
            index = 0;
        }

        void insert(int offset, int[] values) {
            int newSize = size + values.length;
            if (intArray.length < newSize) {
                int[] newIntArray = new int[newSize * 2];
                System.arraycopy(intArray, 0, newIntArray, 0, size);
                intArray = newIntArray;
            }
            System.arraycopy(intArray, offset, intArray, offset+values.length,
                             size - offset);
            System.arraycopy(values, 0, intArray, offset, values.length);
            size += values.length;
            if (index > offset)
                index = offset;
        }

        void remove(int offset, int length) {
            if (offset + length != size)
                System.arraycopy(intArray, offset+length, intArray, offset,
                                 size - offset - length);
            size -= length;
            if (index > offset)
                index = offset;
        }

        void replace(int offset, int[] values) {
            System.arraycopy(values, 0, intArray, offset, values.length);
        }

        void removeAll() {
            size = 0;
            index = 0;
        }

        void rewind() {
            index = 0;
        }

        int getNext() {
            if (index == size)
                return -1;
            return intArray[index++];
        }

        void unget() {
            if (index != 0)
                index--;
        }

        int getOffset() {
            return index;
        }

        public String toString() {
            StringBuffer s = new StringBuffer();
            for (int i = 0; i < size;) {
                s.append(intArray[i++]);
                if (i < size)
                    s.append(",");
            }
            return s.toString();
        }
    }

    /*
     * Native methods
     */
    private native String resetXIC();
    private native void disposeXIC();
    private native boolean setCompositionEnabledNative(boolean enable);
    private native boolean isCompositionEnabledNative();
    private native void turnoffStatusWindow();
}
