--- 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
-}