/*
 * Copyright (c) 2011, 2013, 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.lwawt.macosx;

import java.awt.im.spi.*;
import java.util.*;
import java.awt.*;
import java.awt.peer.*;
import java.awt.event.*;
import java.awt.im.*;
import java.awt.font.*;
import java.lang.Character.Subset;
import java.lang.reflect.InvocationTargetException;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.*;
import javax.swing.text.JTextComponent;

import sun.awt.im.InputMethodAdapter;
import sun.lwawt.*;

public class CInputMethod extends InputMethodAdapter {
    private InputMethodContext fIMContext;
    private Component fAwtFocussedComponent;
    private LWComponentPeer fAwtFocussedComponentPeer;
    private boolean isActive;

    private static Map<TextAttribute, Integer>[] sHighlightStyles;

    // Intitalize highlight mapping table and its mapper.
    static {
        Map<TextAttribute, Integer> styles[] = new Map[4];
        HashMap<TextAttribute, Integer> map;

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

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

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

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

        sHighlightStyles = styles;

        nativeInit();

    }

    public CInputMethod() {
    }


    /**
        * Sets the input method context, which is used to dispatch input method
     * events to the client component and to request information from
     * the client component.
     * <p>
     * This method is called once immediately after instantiating this input
     * method.
     *
     * @param context the input method context for this input method
     * @exception NullPointerException if <code>context</code> is null
     */
    public void setInputMethodContext(InputMethodContext context) {
        fIMContext = context;
    }

    /**
        * Attempts to set the input locale. If the input method supports the
     * desired locale, it changes its behavior to support input for the locale
     * and returns true.
     * Otherwise, it returns false and does not change its behavior.
     * <p>
     * This method is called
     * <ul>
     * <li>by {@link java.awt.im.InputContext#selectInputMethod InputContext.selectInputMethod},
     * <li>when switching to this input method through the user interface if the user
     *     specified a locale or if the previously selected input method's
     *     {@link java.awt.im.spi.InputMethod#getLocale getLocale} method
     *     returns a non-null value.
     * </ul>
     *
     * @param lang locale to input
     * @return whether the specified locale is supported
     * @exception NullPointerException if <code>locale</code> is null
     */
    public boolean setLocale(Locale lang) {
        return setLocale(lang, false);
    }

    private boolean setLocale(Locale lang, boolean onActivate) {
        Object[] available = CInputMethodDescriptor.getAvailableLocalesInternal();
        for (int i = 0; i < available.length; i++) {
            Locale locale = (Locale)available[i];
            if (lang.equals(locale) ||
                // special compatibility rule for Japanese and Korean
                locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) ||
                locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) {
                if (isActive) {
                    setNativeLocale(locale.toString(), onActivate);
                }
                return true;
            }
        }
        return false;
    }

    /**
        * Returns the current input locale. Might return null in exceptional cases.
     * <p>
     * This method is called
     * <ul>
     * <li>by {@link java.awt.im.InputContext#getLocale InputContext.getLocale} and
     * <li>when switching from this input method to a different one through the
     *     user interface.
     * </ul>
     *
     * @return the current input locale, or null
     */
    public Locale getLocale() {
        // On Mac OS X we'll ask the currently active input method what its locale is.
        Locale returnValue = getNativeLocale();
        if (returnValue == null) {
            returnValue = Locale.getDefault();
        }

        return returnValue;
    }

    /**
        * Sets the subsets of the Unicode character set that this input method
     * is allowed to input. Null may be passed in to indicate that all
     * characters are allowed.
     * <p>
     * This method is called
     * <ul>
     * <li>immediately after instantiating this input method,
     * <li>when switching to this input method from a different one, and
     * <li>by {@link java.awt.im.InputContext#setCharacterSubsets InputContext.setCharacterSubsets}.
     * </ul>
     *
     * @param subsets the subsets of the Unicode character set from which
     * characters may be input
     */
    public void setCharacterSubsets(Subset[] subsets) {
        // -- SAK: Does mac OS X support this?
    }

    /**
        * Composition cannot be set on Mac OS X -- the input method remembers this
     */
    public void setCompositionEnabled(boolean enable) {
        throw new UnsupportedOperationException("Can't adjust composition mode on Mac OS X.");
    }

    public boolean isCompositionEnabled() {
        throw new UnsupportedOperationException("Can't adjust composition mode on Mac OS X.");
    }

    /**
     * Dispatches the event to the input method. If input method support is
     * enabled for the focussed component, incoming events of certain types
     * are dispatched to the current input method for this component before
     * they are dispatched to the component's methods or event listeners.
     * The input method decides whether it needs to handle the event. If it
     * does, it also calls the event's <code>consume</code> method; this
     * causes the event to not get dispatched to the component's event
     * processing methods or event listeners.
     * <p>
     * Events are dispatched if they are instances of InputEvent or its
     * subclasses.
     * This includes instances of the AWT classes KeyEvent and MouseEvent.
     * <p>
     * This method is called by {@link java.awt.im.InputContext#dispatchEvent InputContext.dispatchEvent}.
     *
     * @param event the event being dispatched to the input method
     * @exception NullPointerException if <code>event</code> is null
     */
    public void dispatchEvent(final AWTEvent event) {
        // No-op for Mac OS X.
    }


    /**
     * Activate and deactivate are no-ops on Mac OS X.
     * A non-US keyboard layout is an 'input method' in that it generates events the same way as
     * a CJK input method. A component that doesn't want input method events still wants the dead-key
     * events.
     *
     *
     */
    public void activate() {
        isActive = true;
    }

    public void deactivate(boolean isTemporary) {
        isActive = false;
    }

    /**
     * Closes or hides all windows opened by this input method instance or
     * its class.  Deactivate hides windows for us on Mac OS X.
     */
    public void hideWindows() {
    }

    long getNativeViewPtr(LWComponentPeer peer) {
        if (peer.getPlatformWindow() instanceof CPlatformWindow) {
            CPlatformWindow platformWindow = (CPlatformWindow) peer.getPlatformWindow();
            CPlatformView platformView = platformWindow.getContentView();
            return platformView.getAWTView();
        } else {
            return 0;
        }
    }

    /**
        * Notifies the input method that a client component has been
     * removed from its containment hierarchy, or that input method
     * support has been disabled for the component.
     */
    public void removeNotify() {
        if (fAwtFocussedComponentPeer != null) {
            nativeEndComposition(getNativeViewPtr(fAwtFocussedComponentPeer));
        }

        fAwtFocussedComponentPeer = null;
    }

    /**
     * Informs the input method adapter about the component that has the AWT
     * focus if it's using the input context owning this adapter instance.
     * We also take the opportunity to tell the native side that we are the input method
     * to talk to when responding to key events.
     */
    protected void setAWTFocussedComponent(Component component) {
        LWComponentPeer peer = null;
        long modelPtr = 0;
        CInputMethod imInstance = this;

        // component will be null when we are told there's no focused component.
        // When that happens we need to notify the native architecture to stop generating IMEs
        if (component == null) {
            peer = fAwtFocussedComponentPeer;
            imInstance = null;
        } else {
            peer = getNearestNativePeer(component);

            // If we have a passive client, don't pass input method events to it.
            if (component.getInputMethodRequests() == null) {
                imInstance = null;
            }

            LWWindowPeer windowPeer = peer.getPlatformWindow().getPeer();
            if (windowPeer.isSimpleWindow()) {
                // A simple window gains focus. Cocoa won't dispatch IME events into the simple window, but into its owner.
                // This IM represents the focused component in the simple window. We will use the owner as IME proxy.
                // For that, this IM is set for the owner and is dropped for the simple window.
                Window owner = windowPeer.getTarget().getOwner();
                assert owner != null && owner.isActive();
                long ownerPtr = getNativeViewPtr((LWComponentPeer)owner.getPeer());
                nativeNotifyPeer(ownerPtr, this);
                imInstance = null;
            }
        }

        if (peer != null) {
            modelPtr = getNativeViewPtr(peer);

            // modelPtr refers to the ControlModel that either got or lost focus.
            nativeNotifyPeer(modelPtr, imInstance);
        }

        // Track the focused component and its nearest peer.
        fAwtFocussedComponent = component;
        fAwtFocussedComponentPeer = getNearestNativePeer(component);
    }

    /**
        * @see java.awt.Toolkit#mapInputMethodHighlight
     */
    public static Map 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 sHighlightStyles[index];
    }

    /**
        * 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.
     * <p>
     * This method is called
     * <ul>
     * <li>by {@link java.awt.im.InputContext#endComposition InputContext.endComposition},
     * <li>by {@link java.awt.im.InputContext#dispatchEvent InputContext.dispatchEvent}
     *     when switching to a different client component
     * <li>when switching from this input method to a different one using the
     *     user interface or
     *     {@link java.awt.im.InputContext#selectInputMethod InputContext.selectInputMethod}.
     * </ul>
     */
    public void endComposition() {
        if (fAwtFocussedComponentPeer != null)
            nativeEndComposition(getNativeViewPtr(fAwtFocussedComponentPeer));
    }

    /**
        * Disposes of the input method and releases the resources used by it.
     * In particular, the input method should dispose windows and close files that are no
     * longer needed.
     * <p>
     * This method is called by {@link java.awt.im.InputContext#dispose InputContext.dispose}.
     * <p>
     * The method is only called when the input method is inactive.
     * No method of this interface is called on this instance after dispose.
     */
    public void dispose() {
        fIMContext = null;
        fAwtFocussedComponent = null;
        fAwtFocussedComponentPeer = null;
    }

    /**
        * Returns a control object from this input method, or null. A
     * control object provides methods that control the behavior of the
     * input method or obtain information from the input method. The type
     * of the object is an input method specific class. Clients have to
     * compare the result against known input method control object
     * classes and cast to the appropriate class to invoke the methods
     * provided.
     * <p>
     * This method is called by
     * {@link java.awt.im.InputContext#getInputMethodControlObject InputContext.getInputMethodControlObject}.
     *
     * @return a control object from this input method, or null
     */
    public Object getControlObject() {
        return null;
    }

    // java.awt.Toolkit#getNativeContainer() is not available
    //    from this package
    private LWComponentPeer getNearestNativePeer(Component comp) {
        if (comp==null)
            return null;

        ComponentPeer peer = comp.getPeer();
        if (peer==null)
            return null;

        while (peer instanceof java.awt.peer.LightweightPeer) {
            comp = comp.getParent();
            if (comp==null)
                return null;
            peer = comp.getPeer();
            if (peer==null)
                return null;
        }

        if (peer instanceof LWComponentPeer)
            return (LWComponentPeer)peer;

        return null;
    }

    // =========================== NSTextInput callbacks ===========================
    // The 'marked text' that we get from Cocoa.  We need to track this separately, since
    // Java doesn't let us ask the IM context for it.
    private AttributedString fCurrentText = null;
    private String fCurrentTextAsString = null;
    private int fCurrentTextLength = 0;

    /**
     * Tell the component to commit all of the characters in the string to the current
     * text view. This effectively wipes out any text in progress.
     */
    synchronized private void insertText(String aString) {
        AttributedString attribString = new AttributedString(aString);

        // Set locale information on the new string.
        attribString.addAttribute(Attribute.LANGUAGE, getLocale(), 0, aString.length());

        TextHitInfo theCaret = TextHitInfo.afterOffset(aString.length() - 1);
        InputMethodEvent event = new InputMethodEvent(fAwtFocussedComponent,
                                                      InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                                      attribString.getIterator(),
                                                      aString.length(),
                                                      theCaret,
                                                      theCaret);
        LWCToolkit.postEvent(LWCToolkit.targetToAppContext(fAwtFocussedComponent), event);
        fCurrentText = null;
        fCurrentTextAsString = null;
        fCurrentTextLength = 0;
    }

    private void startIMUpdate (String rawText) {
        fCurrentTextAsString = new String(rawText);
        fCurrentText = new AttributedString(fCurrentTextAsString);
        fCurrentTextLength = rawText.length();
    }

    static private final int kCaretPosition = 0;
    static private final int kRawText = 1;
    static private final int kSelectedRawText = 2;
    static private final int kConvertedText = 3;
    static private final int kSelectedConvertedText = 4;

    /**
     * Convert Cocoa text highlight attributes into Java input method highlighting.
     */
    private void addAttribute (boolean isThickUnderline, boolean isGray, int start, int length) {
        int begin = start;
        int end = start + length;
        int markupType = kRawText;

        if (isThickUnderline && isGray) {
            markupType = kRawText;
        } else if (!isThickUnderline && isGray) {
            markupType = kRawText;
        } else if (isThickUnderline && !isGray) {
            markupType = kSelectedConvertedText;
        } else if (!isThickUnderline && !isGray) {
            markupType = kConvertedText;
        }

        InputMethodHighlight theHighlight;

        switch (markupType) {
            case kSelectedRawText:
                theHighlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT;
                break;
            case kConvertedText:
                theHighlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT;
                break;
            case kSelectedConvertedText:
                theHighlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT;
                break;
            case kRawText:
            default:
                theHighlight = InputMethodHighlight.UNSELECTED_RAW_TEXT_HIGHLIGHT;
                break;
        }

        fCurrentText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, theHighlight, begin, end);
    }

   /* Called from JNI to select the previously typed glyph during press and hold */
    private void selectPreviousGlyph() {
        if (fIMContext == null) return; // ???
        try {
            LWCToolkit.invokeLater(new Runnable() {
                public void run() {
                    final int offset = fIMContext.getInsertPositionOffset();
                    if (offset < 1) return; // ???

                    if (fAwtFocussedComponent instanceof JTextComponent) {
                        ((JTextComponent) fAwtFocussedComponent).select(offset - 1, offset);
                        return;
                    }

                    if (fAwtFocussedComponent instanceof TextComponent) {
                        ((TextComponent) fAwtFocussedComponent).select(offset - 1, offset);
                        return;
                    }
                    // TODO: Ideally we want to disable press-and-hold in this case
                }
            }, fAwtFocussedComponent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void selectNextGlyph() {
        if (fIMContext == null || !(fAwtFocussedComponent instanceof JTextComponent)) return;
        try {
            LWCToolkit.invokeLater(new Runnable() {
                public void run() {
                    final int offset = fIMContext.getInsertPositionOffset();
                    if (offset < 0) return;
                    ((JTextComponent) fAwtFocussedComponent).select(offset, offset + 1);
                    return;
                }
            }, fAwtFocussedComponent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void dispatchText(int selectStart, int selectLength, boolean pressAndHold) {
        // Nothing to do if we have no text.
        if (fCurrentText == null)
            return;

        TextHitInfo theCaret = (selectLength == 0 ? TextHitInfo.beforeOffset(selectStart) : null);
        TextHitInfo visiblePosition = TextHitInfo.beforeOffset(0);

        InputMethodEvent event = new InputMethodEvent(fAwtFocussedComponent,
                                                      InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                                      fCurrentText.getIterator(),
                                                      0,
                                                      theCaret,
                                                      visiblePosition);
        LWCToolkit.postEvent(LWCToolkit.targetToAppContext(fAwtFocussedComponent), event);

        if (pressAndHold) selectNextGlyph();
    }

    /**
     * Frequent callbacks from NSTextInput.  I think we're supposed to commit it here?
     */
    synchronized private void unmarkText() {
        if (fCurrentText == null)
            return;

        TextHitInfo theCaret = TextHitInfo.afterOffset(fCurrentTextLength);
        TextHitInfo visiblePosition = theCaret;
        InputMethodEvent event = new InputMethodEvent(fAwtFocussedComponent,
                                                      InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                                      fCurrentText.getIterator(),
                                                      fCurrentTextLength,
                                                      theCaret,
                                                      visiblePosition);
        LWCToolkit.postEvent(LWCToolkit.targetToAppContext(fAwtFocussedComponent), event);
        fCurrentText = null;
        fCurrentTextAsString = null;
        fCurrentTextLength = 0;
    }

    synchronized private boolean hasMarkedText() {
        return fCurrentText != null;
    }

    /**
        * Cocoa assumes the marked text and committed text is all stored in the same storage, but
     * Java does not.  So, we have to see where the request is and based on that return the right
     * substring.
     */
    synchronized private String attributedSubstringFromRange(final int locationIn, final int lengthIn) {
        final String[] retString = new String[] {""};

        try {
            if (fIMContext != null)
            LWCToolkit.invokeAndWait(new Runnable() {
                public void run() { synchronized(retString) {
                    int location = locationIn;
                    int length = lengthIn;

                    if ((location + length) > (fIMContext.getCommittedTextLength() + fCurrentTextLength)) {
                        length = fIMContext.getCommittedTextLength() - location;
                    }

                    AttributedCharacterIterator theIterator = null;

                    if (fCurrentText == null) {
                        theIterator = fIMContext.getCommittedText(location, location + length, null);
                    } else {
                        int insertSpot = fIMContext.getInsertPositionOffset();

                        if (location < insertSpot) {
                            theIterator = fIMContext.getCommittedText(location, location + length, null);
                        } else if (location >= insertSpot && location < insertSpot + fCurrentTextLength) {
                            theIterator = fCurrentText.getIterator(null, location - insertSpot, location - insertSpot +length);
                        } else  {
                            theIterator = fIMContext.getCommittedText(location - fCurrentTextLength, location - fCurrentTextLength + length, null);
                        }
                    }

                    // Get the characters from the iterator
                    char selectedText[] = new char[theIterator.getEndIndex() - theIterator.getBeginIndex()];
                    char current = theIterator.first();
                    int index = 0;
                    while (current != CharacterIterator.DONE) {
                        selectedText[index++] = current;
                        current = theIterator.next();
                    }

                    retString[0] = new String(selectedText);
                }}
            }, fAwtFocussedComponent);
        } catch (InvocationTargetException ite) { ite.printStackTrace(); }

        synchronized(retString) { return retString[0]; }
    }

    /**
     * Cocoa wants the range of characters that are currently selected.  We have to synthesize this
     * by getting the insert location and the length of the selected text. NB:  This does NOT allow
     * for the fact that the insert point in Swing can come AFTER the selected text, making this
     * potentially incorrect.
     */
    synchronized private int[] selectedRange() {
        final int[] returnValue = new int[2];

        try {
            if (fIMContext != null)
            LWCToolkit.invokeAndWait(new Runnable() {
                public void run() { synchronized(returnValue) {
                    AttributedCharacterIterator theIterator = fIMContext.getSelectedText(null);
                    if (theIterator == null) {
                        returnValue[0] = fIMContext.getInsertPositionOffset();
                        returnValue[1] = 0;
                        return;
                    }

                    int startLocation;

                    if (fAwtFocussedComponent instanceof JTextComponent) {
                        JTextComponent theComponent = (JTextComponent)fAwtFocussedComponent;
                        startLocation = theComponent.getSelectionStart();
                    } else if (fAwtFocussedComponent instanceof TextComponent) {
                        TextComponent theComponent = (TextComponent)fAwtFocussedComponent;
                        startLocation = theComponent.getSelectionStart();
                    } else {
                        // If we don't have a Swing or AWT component, we have to guess whether the selection is before or after the input spot.
                        startLocation = fIMContext.getInsertPositionOffset() - (theIterator.getEndIndex() - theIterator.getBeginIndex());

                        // If the calculated spot is negative the insert spot must be at the beginning of
                        // the selection.
                        if (startLocation <  0) {
                            startLocation = fIMContext.getInsertPositionOffset() + (theIterator.getEndIndex() - theIterator.getBeginIndex());
                        }
                    }

                    returnValue[0] = startLocation;
                    returnValue[1] = theIterator.getEndIndex() - theIterator.getBeginIndex();

                }}
            }, fAwtFocussedComponent);
        } catch (InvocationTargetException ite) { ite.printStackTrace(); }

        synchronized(returnValue) { return returnValue; }
    }

    /**
     * Cocoa wants the range of characters that are currently marked.  Since Java doesn't store committed and
     * text in progress (composed text) together, we have to synthesize it.  We know where the text will be
     * inserted, so we can return that position, and the length of the text in progress.  If there is no marked text
     * return null.
     */
    synchronized private int[] markedRange() {
        if (fCurrentText == null)
            return null;

        final int[] returnValue = new int[2];

        try {
            LWCToolkit.invokeAndWait(new Runnable() {
                public void run() { synchronized(returnValue) {
                    // The insert position is always after the composed text, so the range start is the
                    // insert spot less the length of the composed text.
                    returnValue[0] = fIMContext.getInsertPositionOffset();
                }}
            }, fAwtFocussedComponent);
        } catch (InvocationTargetException ite) { ite.printStackTrace(); }

        returnValue[1] = fCurrentTextLength;
        synchronized(returnValue) { return returnValue; }
    }

    /**
     * Cocoa wants a rectangle that describes where a particular range is on screen, but only cares about the
     * location of that rectangle.  We are given the index of the character for which we want the location on
     * screen, which will be a character in the in-progress text.  By subtracting the current insert position,
     * which is always in front of the in-progress text, we get the offset into the composed text, and we get
     * that location from the input method context.
     */
    synchronized private int[] firstRectForCharacterRange(final int absoluteTextOffset) {
        final int[] rect = new int[4];

        try {
            if (fIMContext != null)
            LWCToolkit.invokeAndWait(new Runnable() {
                public void run() { synchronized(rect) {
                    int insertOffset = fIMContext.getInsertPositionOffset();
                    int composedTextOffset = absoluteTextOffset - insertOffset;
                    if (composedTextOffset < 0) composedTextOffset = 0;
                    Rectangle r = fIMContext.getTextLocation(TextHitInfo.beforeOffset(composedTextOffset));
                    rect[0] = r.x;
                    rect[1] = r.y;
                    rect[2] = r.width;
                    rect[3] = r.height;

                    // This next if-block is a hack to work around a bug in JTextComponent. getTextLocation ignores
                    // the TextHitInfo passed to it and always returns the location of the insertion point, which is
                    // at the start of the composed text.  We'll do some calculation so the candidate window for Kotoeri
                    // follows the requested offset into the composed text.
                    if (composedTextOffset > 0 && (fAwtFocussedComponent instanceof JTextComponent)) {
                        Rectangle r2 = fIMContext.getTextLocation(TextHitInfo.beforeOffset(0));

                        if (r.equals(r2) && fCurrentTextAsString != null) {
                            // FIXME: (SAK) If the candidate text wraps over two lines, this calculation pushes the candidate
                            // window off the right edge of the component.
                            String inProgressSubstring = fCurrentTextAsString.substring(0, composedTextOffset);
                            Graphics g = fAwtFocussedComponent.getGraphics();
                            int xOffset = g.getFontMetrics().stringWidth(inProgressSubstring);
                            rect[0] += xOffset;
                            g.dispose();
                        }
                    }
                }}
            }, fAwtFocussedComponent);
        } catch (InvocationTargetException ite) { ite.printStackTrace(); }

        synchronized(rect) { return rect; }
    }

    /* This method returns the index for the character that is nearest to the point described by screenX and screenY.
     * The coordinates are in Java screen coordinates.  If no character in the composed text was hit, we return -1, indicating
     * not found.
     */
    synchronized private int characterIndexForPoint(final int screenX, final int screenY) {
        final TextHitInfo[] offsetInfo = new TextHitInfo[1];
        final int[] insertPositionOffset = new int[1];

        try {
            if (fIMContext != null)
            LWCToolkit.invokeAndWait(new Runnable() {
                public void run() { synchronized(offsetInfo) {
                    offsetInfo[0] = fIMContext.getLocationOffset(screenX, screenY);
                    insertPositionOffset[0] = fIMContext.getInsertPositionOffset();
                }}
            }, fAwtFocussedComponent);
        } catch (InvocationTargetException ite) { ite.printStackTrace(); }

        // This bit of gymnastics ensures that the returned location is within the composed text.
        // If it falls outside that region, the input method will commit the text, which is inconsistent with native
        // Cocoa apps (see TextEdit, for example.)  Clicking to the left of or above the selected text moves the
        // cursor to the start of the composed text, and to the right or below moves it to one character before the end.
        if (offsetInfo[0] == null) {
            return insertPositionOffset[0];
        }

        int returnValue = offsetInfo[0].getCharIndex() + insertPositionOffset[0];

        if (offsetInfo[0].getCharIndex() == fCurrentTextLength)
            returnValue --;

        return returnValue;
    }

    // On Mac OS X we effectively disabled the input method when focus was lost, so
    // this call can be ignored.
    public void disableInputMethod()
    {
        // Deliberately ignored. See setAWTFocussedComponent above.
    }

    public String getNativeInputMethodInfo()
    {
        return nativeGetCurrentInputMethodInfo();
    }


    // =========================== Native methods ===========================
    // Note that if nativePeer isn't something that normally accepts keystrokes (i.e., a CPanel)
    // these calls will be ignored.
    private native void nativeNotifyPeer(long nativePeer, CInputMethod imInstance);
    private native void nativeEndComposition(long nativePeer);
    private native void nativeHandleEvent(LWComponentPeer peer, AWTEvent event);

    // Returns the locale of the active input method.
    static native Locale getNativeLocale();

    // Switches to the input method with language indicated in localeName
    static native boolean setNativeLocale(String localeName, boolean onActivate);

    // Returns information about the currently selected input method.
    static native String nativeGetCurrentInputMethodInfo();

    // Initialize toolbox routines
    static native void nativeInit();
}
