jdk/src/share/classes/com/sun/inputmethods/internal/indicim/IndicInputMethodImpl.java
changeset 6061 30da66e3cac8
parent 6060 f93277335d21
parent 6036 88db80c8e49c
child 6066 3046588b1ba8
child 6069 7c7d1bb51db4
--- a/jdk/src/share/classes/com/sun/inputmethods/internal/indicim/IndicInputMethodImpl.java	Tue Jul 20 16:09:44 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,475 +0,0 @@
-/*
- * Copyright (c) 2002, 2004, 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.
- */
-
-/*
- * (C) Copyright IBM Corp. 2000 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- *
- */
-
-package com.sun.inputmethods.internal.indicim;
-
-import java.awt.im.spi.InputMethodContext;
-
-import java.awt.event.KeyEvent;
-import java.awt.event.InputMethodEvent;
-import java.awt.font.TextAttribute;
-import java.awt.font.TextHitInfo;
-
-import java.text.AttributedCharacterIterator;
-
-import java.util.Hashtable;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-class IndicInputMethodImpl {
-
-    protected char[] KBD_MAP;
-
-    private static final char SUBSTITUTION_BASE = '\uff00';
-
-    // Indexed by map value - SUBSTITUTION_BASE
-    protected char[][] SUBSTITUTION_TABLE;
-
-    // Invalid character.
-    private static final char INVALID_CHAR              = '\uffff';
-
-    // Unmapped versions of some interesting characters.
-    private static final char KEY_SIGN_VIRAMA           = '\u0064'; // or just 'd'??
-    private static final char KEY_SIGN_NUKTA            = '\u005d';  // or just ']'??
-
-    // Two succeeding viramas are replaced by one virama and one ZWNJ.
-    // Viram followed by Nukta is replaced by one VIRAMA and one ZWJ
-    private static final char ZWJ                       = '\u200d';
-    private static final char ZWNJ                      = '\u200c';
-
-    // Backspace
-    private static final char BACKSPACE                 = '\u0008';
-
-    // Sorted list of characters which can be followed by Nukta
-    protected char[] JOIN_WITH_NUKTA;
-
-    // Nukta form of the above characters
-    protected char[] NUKTA_FORM;
-
-    private int log2;
-    private int power;
-    private int extra;
-
-    // cached TextHitInfo. Only one type of TextHitInfo is required.
-    private static final TextHitInfo ZERO_TRAILING_HIT_INFO = TextHitInfo.trailing(0);
-
-    /**
-     * Returns the index of the given character in the JOIN_WITH_NUKTA array.
-     * If character is not found, -1 is returned.
-     */
-    private int nuktaIndex(char ch) {
-
-        if (JOIN_WITH_NUKTA == null) {
-            return -1;
-        }
-
-        int probe = power;
-        int index = 0;
-
-        if (JOIN_WITH_NUKTA[extra] <= ch) {
-            index = extra;
-        }
-
-        while (probe > (1 << 0)) {
-            probe >>= 1;
-
-            if (JOIN_WITH_NUKTA[index + probe] <= ch) {
-                index += probe;
-            }
-        }
-
-        if (JOIN_WITH_NUKTA[index] != ch) {
-            index = -1;
-        }
-
-        return index;
-    }
-
-    /**
-     * Returns the equivalent character for hindi locale.
-     * @param originalChar The original character.
-     */
-    private char getMappedChar( char originalChar )
-    {
-        if (originalChar <= KBD_MAP.length) {
-            return KBD_MAP[originalChar];
-        }
-
-        return originalChar;
-    }//getMappedChar()
-
-    // Array used to hold the text to be sent.
-    // If the last character was not committed it is stored in text[0].
-    // The variable totalChars give an indication of whether the last
-    // character was committed or not. If at any time ( but not within a
-    // a call to dispatchEvent ) totalChars is not equal to 0 ( it can
-    // only be 1 otherwise ) the last character was not committed.
-    private char [] text = new char[4];
-
-    // this is always 0 before and after call to dispatchEvent. This character assumes
-    // significance only within a call to dispatchEvent.
-    private int committedChars = 0;// number of committed characters
-
-    // the total valid characters in variable text currently.
-    private int totalChars = 0;//number of total characters ( committed + composed )
-
-    private boolean lastCharWasVirama = false;
-
-    private InputMethodContext context;
-
-    //
-    // Finds the high bit by binary searching
-    // through the bits in n.
-    //
-    private static byte highBit(int n)
-    {
-        if (n <= 0) {
-            return -32;
-        }
-
-        byte bit = 0;
-
-        if (n >= 1 << 16) {
-            n >>= 16;
-            bit += 16;
-        }
-
-        if (n >= 1 << 8) {
-            n >>= 8;
-            bit += 8;
-        }
-
-        if (n >= 1 << 4) {
-            n >>= 4;
-            bit += 4;
-        }
-
-        if (n >= 1 << 2) {
-            n >>= 2;
-            bit += 2;
-        }
-
-        if (n >= 1 << 1) {
-            n >>= 1;
-            bit += 1;
-        }
-
-        return bit;
-    }
-
-    IndicInputMethodImpl(char[] keyboardMap, char[] joinWithNukta, char[] nuktaForm,
-                         char[][] substitutionTable) {
-        KBD_MAP = keyboardMap;
-        JOIN_WITH_NUKTA = joinWithNukta;
-        NUKTA_FORM = nuktaForm;
-        SUBSTITUTION_TABLE = substitutionTable;
-
-        if (JOIN_WITH_NUKTA != null) {
-            int log2 = highBit(JOIN_WITH_NUKTA.length);
-
-            power = 1 << log2;
-            extra = JOIN_WITH_NUKTA.length - power;
-        } else {
-            power = extra = 0;
-        }
-
-    }
-
-    void setInputMethodContext(InputMethodContext context) {
-
-        this.context = context;
-    }
-
-    void handleKeyTyped(KeyEvent kevent) {
-
-        char keyChar = kevent.getKeyChar();
-        char currentChar = getMappedChar(keyChar);
-
-        // The Explicit and Soft Halanta case.
-        if ( lastCharWasVirama ) {
-            switch (keyChar) {
-            case KEY_SIGN_NUKTA:
-                currentChar = ZWJ;
-                break;
-            case KEY_SIGN_VIRAMA:
-                currentChar = ZWNJ;
-                break;
-            default:
-            }//endSwitch
-        }//endif
-
-        if (currentChar == INVALID_CHAR) {
-            kevent.consume();
-            return;
-        }
-
-        if (currentChar == BACKSPACE) {
-            lastCharWasVirama = false;
-
-            if (totalChars > 0) {
-                totalChars = committedChars = 0;
-            } else {
-                return;
-            }
-        }
-        else if (keyChar == KEY_SIGN_NUKTA) {
-            int nuktaIndex = nuktaIndex(text[0]);
-
-            if (nuktaIndex != -1) {
-                text[0] = NUKTA_FORM[nuktaIndex];
-            } else {
-                // the last character was committed, commit just Nukta.
-                // Note : the lastChar must have been committed if it is not one of
-                // the characters which combine with nukta.
-                // the state must be totalChars = committedChars = 0;
-                text[totalChars++] = currentChar;
-            }
-
-            committedChars += 1;
-        }
-        else {
-            int nuktaIndex = nuktaIndex(currentChar);
-
-            if (nuktaIndex != -1) {
-                // Commit everything but currentChar
-                text[totalChars++] = currentChar;
-                committedChars = totalChars-1;
-            } else {
-                if (currentChar >= SUBSTITUTION_BASE) {
-                    char[] sub = SUBSTITUTION_TABLE[currentChar - SUBSTITUTION_BASE];
-
-                    System.arraycopy(sub, 0, text, totalChars, sub.length);
-                    totalChars += sub.length;
-                } else {
-                    text[totalChars++] = currentChar;
-                }
-
-                committedChars = totalChars;
-            }
-        }
-
-        ACIText aText = new ACIText( text, 0, totalChars, committedChars );
-        int composedCharLength = totalChars - committedChars;
-        TextHitInfo caret=null,visiblePosition=null;
-        switch( composedCharLength ) {
-            case 0:
-                break;
-            case 1:
-                visiblePosition = caret = ZERO_TRAILING_HIT_INFO;
-                break;
-            default:
-                assert false : "The code should not reach here. There is no case where there can be more than one character pending.";
-        }
-
-        context.dispatchInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
-                                         aText,
-                                         committedChars,
-                                         caret,
-                                         visiblePosition);
-
-        if (totalChars == 0) {
-            text[0] = INVALID_CHAR;
-        } else {
-            text[0] = text[totalChars - 1];// make text[0] hold the last character
-        }
-
-        lastCharWasVirama =  keyChar == KEY_SIGN_VIRAMA && !lastCharWasVirama;
-
-        totalChars -= committedChars;
-        committedChars = 0;
-        // state now text[0] = last character
-        // totalChars = ( last character committed )? 0 : 1;
-        // committedChars = 0;
-
-        kevent.consume();// prevent client from getting this event.
-    }//dispatchEvent()
-
-    void endComposition() {
-        if( totalChars != 0 ) {// if some character is not committed.
-            ACIText aText = new ACIText( text, 0, totalChars, totalChars );
-            context.dispatchInputMethodEvent( InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
-                                aText, totalChars, null, null );
-            totalChars = committedChars = 0;
-            text[0] = INVALID_CHAR;
-            lastCharWasVirama = false;
-        }//end if
-    }//endComposition()
-
-    // custom AttributedCharacterIterator -- much lightweight since currently there is no
-    // attribute defined on the text being generated by the input method.
-    private class ACIText implements AttributedCharacterIterator {
-        private char [] text = null;
-        private int committed = 0;
-        private int index = 0;
-
-        ACIText( char [] chArray, int offset, int length, int committed ) {
-            this.text = new char[length];
-            this.committed = committed;
-            System.arraycopy( chArray, offset, text, 0, length );
-        }//c'tor
-
-        // CharacterIterator methods.
-        public char first() {
-            return _setIndex( 0 );
-        }
-
-        public char last() {
-            if( text.length == 0 ) {
-                return _setIndex( text.length );
-            }
-            return _setIndex( text.length - 1 );
-        }
-
-        public char current() {
-            if( index == text.length )
-                return DONE;
-            return text[index];
-        }
-
-        public char next() {
-            if( index == text.length ) {
-                return DONE;
-            }
-            return _setIndex( index + 1 );
-        }
-
-        public char previous() {
-            if( index == 0 )
-                return DONE;
-            return _setIndex( index - 1 );
-        }
-
-        public char setIndex(int position) {
-            if( position < 0 || position > text.length ) {
-                throw new IllegalArgumentException();
-            }
-            return _setIndex( position );
-        }
-
-        public int getBeginIndex() {
-            return 0;
-        }
-
-        public int getEndIndex() {
-            return text.length;
-        }
-
-        public int getIndex() {
-            return index;
-        }
-
-        public Object clone() {
-            try {
-                ACIText clone = (ACIText) super.clone();
-                return clone;
-            } catch (CloneNotSupportedException e) {
-                throw new InternalError();
-            }
-        }
-
-
-        // AttributedCharacterIterator methods.
-        public int getRunStart() {
-            return index >= committed ? committed : 0;
-        }
-
-        public int getRunStart(AttributedCharacterIterator.Attribute attribute) {
-            return (index >= committed &&
-                attribute == TextAttribute.INPUT_METHOD_UNDERLINE) ? committed : 0;
-        }
-
-        public int getRunStart(Set<? extends Attribute> attributes) {
-            return (index >= committed &&
-                    attributes.contains(TextAttribute.INPUT_METHOD_UNDERLINE)) ? committed : 0;
-        }
-
-        public int getRunLimit() {
-            return index < committed ? committed : text.length;
-        }
-
-        public int getRunLimit(AttributedCharacterIterator.Attribute attribute) {
-            return (index < committed &&
-                    attribute == TextAttribute.INPUT_METHOD_UNDERLINE) ? committed : text.length;
-        }
-
-        public int getRunLimit(Set<? extends Attribute> attributes) {
-            return (index < committed &&
-                    attributes.contains(TextAttribute.INPUT_METHOD_UNDERLINE)) ? committed : text.length;
-        }
-
-        public Map getAttributes() {
-            Hashtable result = new Hashtable();
-            if (index >= committed && committed < text.length) {
-                result.put(TextAttribute.INPUT_METHOD_UNDERLINE,
-                           TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
-            }
-            return result;
-        }
-
-        public Object getAttribute(AttributedCharacterIterator.Attribute attribute) {
-            if (index >= committed &&
-                committed < text.length &&
-                attribute == TextAttribute.INPUT_METHOD_UNDERLINE) {
-
-                return TextAttribute.UNDERLINE_LOW_ONE_PIXEL;
-            }
-            return null;
-        }
-
-        public Set getAllAttributeKeys() {
-            HashSet result = new HashSet();
-            if (committed < text.length) {
-                result.add(TextAttribute.INPUT_METHOD_UNDERLINE);
-            }
-            return result;
-        }
-
-        // private methods
-
-        /**
-         * This is always called with valid i ( 0 < i <= text.length )
-         */
-        private char _setIndex( int i ) {
-            index = i;
-            if( i == text.length ) {
-                return DONE;
-            }
-            return text[i];
-        }//_setIndex()
-
-    }//end of inner class
-}