FileDocCategorySizeDatePackage
DefaultInputMethodHandler.javaAPI DocJ2ME MIDP 2.036377Thu Nov 07 12:02:22 GMT 2002com.sun.midp.lcdui

DefaultInputMethodHandler

public class DefaultInputMethodHandler extends InputMethodHandler
A Default implementation of the InputMethodHandler interface.

Fields Summary
protected InputMethodClient
imc
the client that receives callbacks
protected static final int
IM_NONE
The 'none' input mode.
protected static final int
IM_ROMAN_CAPS
The 'roman caps' input mode.
protected static final int
IM_ROMAN_SMALL
The 'lowercase roman' input mode.
protected static final int
IM_NUMERIC
The 'numeric' input mode.
protected static final int
IM_SYMBOL
The 'symbol' input mode.
protected static int
NUM_INPUT_MODES
Number of supported input modes.
protected int
currentConstraints
the constraints in use
protected int
currentModifiers
the modifiers in use
protected int
defaultMode
Default input mode.
protected int
allowedModesNum
The number of allowed input modes.
protected int[]
allowedModes
The set of allowed input modes.
protected int
inputMode
Current input mode.
protected int
oldInputMode
Old input mode.
protected boolean
quickSymbolAccess
boolean to determine if the user had accessed the symbol table via the quick access method of holding SHIFT
protected boolean
canUseSymbolTable
Constraints allow a symbol table to be used
protected int
lastInputMode
This is the "last" input mode before jumping into the SYM mode (by holding down the mode shift key for 1 sec). This last mode tells the input method to switch back to this mode after handling an character from the symbol table.
protected String[]
supportedCharSubset
Character Subset values for supported input modes.
protected int[]
supportedInputModes
values for supported input modes.
protected Object[]
inputModeConvTable
Conversion table between character subsets and input modes.
protected boolean
capWord
cap word mode variable
protected boolean
capSentence
cap sentence mode variable
protected static final int
KEY_UNKNOWN
Unknown key.
protected static final int
KEY_NUM0
The '0' key.
protected static final int
KEY_NUM1
The '1' key.
protected static final int
KEY_NUM2
The '2' key.
protected static final int
KEY_NUM3
The '3' key.
protected static final int
KEY_NUM4
The '4' key.
protected static final int
KEY_NUM5
The '5' key.
protected static final int
KEY_NUM6
The '6' key.
protected static final int
KEY_NUM7
The '7' key.
protected static final int
KEY_NUM8
The '8' key.
protected static final int
KEY_NUM9
The '9' key.
protected static final int
KEY_STAR
The '*' key.
protected static final int
KEY_POUND
The '#' key.
protected static final int
KEY_CLEAR
The 'CLR' key.
protected char[]
upperRomanKeyMap
The uppercase roman key map.
protected char[]
lowerRomanKeyMap
The lowercase roman key map.
protected char[]
numericKeyMap
The numeric key map. Includes 0-9, *, and space.
protected char[]
decimalKeyMap
The decimal key map. Includes 0-9, and period.
protected char[]
phoneNumericKeyMap
The phone numeric key map. Includes 0-9, *, #, +.
protected char[]
symbolTableChars
The number of symbol_table is designed to be 25 for 5x5 matrix, starting the selection at 12. But if you have more, the total must be under 36 for 6x6 matrix.
protected SymbolTable
st
Symbol table.
protected char[]
keyMap
Current input table that can be one of the previous maps.
protected static final int
TM_NONE
The '0' Timer.
protected static final int
TM_INPUT_MODE
The input mode timer.
protected static final int
TM_IN_COMPOSING
The 'in composition' timer.
protected static final int
TM_CLEAR_BUFFER
The 'clear buffer' timer.
protected int
timerType
The type of timer to set.
protected Timer
timerService
The Timer to service TimerTasks.
protected TimerTask
timerClient
A TimerTask.
protected int
lastKey
The last key and last position of the input.
protected int
lastKeyIndex
lastKey index into the key map
protected int
charIndex
last character index into the key map at the
protected boolean
ignoreNextKeyRelease
ignore the next keyRelease event
Constructors Summary
Methods Summary
protected booleanbuildInputModes(int constraints, int modifiers, java.lang.String dMode, java.lang.String[] aMode)
Set the input mode.

param
constraints The constraints
param
modifiers The modifiers
param
dMode the default mode, null to choose one
param
aMode array of allowed modes, or null to use all
return
boolean True, if the mode was valid


        boolean ret = true;

        capWord = capSentence = false;

        if (constraints == TextField.NUMERIC ||
            constraints == TextField.DECIMAL ||
            constraints == TextField.PHONENUMBER) {

            defaultMode = IM_NUMERIC;
            allowedModesNum = 1;
            allowedModes[0] = IM_NUMERIC;
        } 
        else if (constraints == TextField.EMAILADDR ||
                 constraints == TextField.URL) {

            defaultMode = IM_ROMAN_SMALL;
            allowedModesNum = 4;
            allowedModes[0] = IM_ROMAN_SMALL;
            allowedModes[1] = IM_ROMAN_CAPS;
            allowedModes[2] = IM_NUMERIC;
            allowedModes[3] = IM_SYMBOL;
        } 
        else {
            if (constraints != TextField.ANY) {
                dMode = null;
                aMode = null;
            }

            /* 
             * The mappings from character subsets to input modes are not
             * unique. So, we use this vector to make sure we do not end up
             * with the same input mode multiple times.
             */
            Vector uniqueModes = new Vector(NUM_INPUT_MODES);

            if (dMode == null && aMode == null) {
                allowedModesNum = supportedInputModes.length;
                System.arraycopy(supportedInputModes, 0, 
                                 allowedModes, 0, allowedModesNum);
                defaultMode = allowedModes[0];
            } else {
                if (dMode == null && aMode != null) {
                    dMode = aMode[0];
                }
                if (dMode != null && aMode == null) {
                    aMode = new String[supportedCharSubset.length];
                    System.arraycopy(supportedCharSubset, 0, 
                                     aMode, 0, supportedCharSubset.length);
                }

                /* get the default initial mode based on the character subset */
                for (int i = 0; i < inputModeConvTable.length; i++) {
                    if (((String)inputModeConvTable[i][0]).
                        equals(dMode)) {
                        defaultMode = 
                            ((Integer)inputModeConvTable[i][1]).intValue();
                        break;
                    }
                }

                /* 
                 * get all the allowed input modes based on the character 
                 * subset 
                 */
                for (int j = 0; j < inputModeConvTable.length; j++) {
                    for (int i = 0; i < aMode.length; i++) {
                        Integer imode = (Integer)inputModeConvTable[i][1];
                        if (((String)inputModeConvTable[j][0]).equals(aMode[i]) 
                            && uniqueModes.indexOf(imode) == -1) {
                            uniqueModes.addElement(imode);
                        }
                    }
                }

                allowedModesNum = uniqueModes.size();
                for (int i = 0; i < allowedModesNum; i++) {
                   allowedModes[i] = 
                       ((Integer)uniqueModes.elementAt(i)).intValue();
                }

                if (defaultMode == IM_NONE) {
                    defaultMode = allowedModes[0];
                }
                /*
                  temp comment out this code. Not sure the purpose of this
                  code. We do not want to swap the input mode sequence.
                  -tylee 060302

                } else {
                    if (defaultMode != allowedModes[0]) {
                        for (i = 0; i < allowedModesNum; i++) {
                            if (defaultMode == allowedModes[i]) {
                                break;
                            }
                        }
                        int t = allowedModes[0];
                        allowedModes[i] = t;
                        allowedModes[0] = defaultMode;
                    }
                }
               */

            }

            capWord     = 
                (modifiers & TextField.INITIAL_CAPS_WORD) == 
                TextField.INITIAL_CAPS_WORD;

            capSentence = 
                (modifiers & TextField.INITIAL_CAPS_SENTENCE) == 
                TextField.INITIAL_CAPS_SENTENCE;

            if (capWord || capSentence) {
                defaultMode = IM_ROMAN_CAPS;
            }
        }

        oldInputMode = defaultMode;
        inputMode = defaultMode;

        return ret;
    
protected synchronized voidcancelTimer()
Cancel any running Timer.

        if (timerType != TM_NONE && timerClient != null) {
            timerClient.cancel();
            timerClient = null;
            timerType = TM_NONE;
        }
    
public synchronized booleanclearInputMethodClient(InputMethodClient imc)
Clears the current input handler if it matches the specified one.

param
imc the client that was set to receive callbacks
return
true if the current client was cleared, false otherwise

        if (this.imc == imc) {
            //
            // send any pending keys to the client before we clear it
            //
            endComposition(false);
            setKeyMap(IM_NONE, currentConstraints);
            this.imc = null;
            return true;
        }
        return false;
    
public synchronized voidendComposition(boolean discard)
End the on-going composition. Any keys that are pending are conditionally sent to the client.

param
discard true to discard any pending keys


        if (lastKey == KEYCODE_NONE) {
            return;
        }

        cancelTimer();

        if (!discard && imc != null) {
            imc.keyEntered(lastKey);

            if (imc.isNewInputEntry()) {

                capWord     =
                    (currentModifiers & TextField.INITIAL_CAPS_WORD) ==
                    TextField.INITIAL_CAPS_WORD;

                capSentence =
                    (currentModifiers & TextField.INITIAL_CAPS_SENTENCE) ==
                    TextField.INITIAL_CAPS_SENTENCE;

            }
        }

        lastKey = KEYCODE_NONE;
        lastKeyIndex = KEY_UNKNOWN;
        charIndex = 0;
    
public voidflush()
Removes any pending key presses

        cancelTimer(); 
        ignoreNextKeyRelease = true;
        lastKey = KEYCODE_NONE;
        lastKeyIndex = KEY_UNKNOWN;
        charIndex = 0;
    
protected intgetKeyMapIndex(int keyCode)
Translate the given key code to its index in the key map.

param
keyCode The key code of the key pressed
return
int The index of the given key code in the key map

        switch (keyCode) {
            case Canvas.KEY_NUM0:
                return KEY_NUM0;
            case Canvas.KEY_NUM1:
                return KEY_NUM1;
            case Canvas.KEY_NUM2:
                return KEY_NUM2;
            case Canvas.KEY_NUM3:
                return KEY_NUM3;
            case Canvas.KEY_NUM4:
                return KEY_NUM4;
            case Canvas.KEY_NUM5:
                return KEY_NUM5;
            case Canvas.KEY_NUM6:
                return KEY_NUM6;
            case Canvas.KEY_NUM7:
                return KEY_NUM7;
            case Canvas.KEY_NUM8:
                return KEY_NUM8;
            case Canvas.KEY_NUM9:
                return KEY_NUM9;
            case Canvas.KEY_STAR:
                return KEY_STAR;
            case Canvas.KEY_POUND:
                return KEY_POUND;
            case -8:
                return KEY_CLEAR;
            default:
                return KEY_UNKNOWN;
            }
    
public booleanisSymbol(char c)
Determine if the given character is considered a symbol

param
c character to check
return
true if the character is a symbol, false otherwise

        for (int i = 0; i < symbolTableChars.length; i++) {
            if (symbolTableChars[i] == c) {
                return true;
            }
        }
        return false;
    
public synchronized intkeyPressed(int keyCode)
Handle a key pressed event. Overrides InputMethodHandler.keyPressed.

param
keyCode The code of the key that was pressed
return
int Returns the character that was entered according to to the current InputMode and constraints, or -1 if the keyCode was not recognized or will be handled with a call back


        cancelTimer();

        //
        // a new key press means a fresh start so we'll initialize some
        // variables before we begin
        //
        ignoreNextKeyRelease = false;
        quickSymbolAccess = false;


        int idx = getKeyMapIndex(keyCode);

        //
        // the user has pressed another key so commit the previous one
        //
        if (idx != lastKeyIndex) {
            endComposition(false);
        }

        //
        // remember this key index for next time
        //
        lastKeyIndex = idx;


        if (idx == KEY_UNKNOWN) {
            lastKey = KEYCODE_NONE;
            return KEYCODE_NONE;
        }


        //
        // if the user holds the CLEAR key we need to tell the
        // input client
        //
        if (idx == KEY_CLEAR) {
            lastKey = KEYCODE_CLEAR;
            setTimer(TM_CLEAR_BUFFER, 1500);
            return KEYCODE_NONE;
        }


        //
        // these flags will only be set if the user has not tried to 
        // change modes on their own
        //
        if (capWord || capSentence) {
            if (imc.isNewWord() || imc.isNewSentence()) {
                oldInputMode = IM_ROMAN_CAPS;
                inputMode = IM_ROMAN_CAPS;
            } else {
                oldInputMode = IM_ROMAN_SMALL;
                inputMode = IM_ROMAN_SMALL;
            }
            setKeyMap(inputMode, currentConstraints);
   
        } 
      
        lastKey = keyMap[idx][charIndex];
        charIndex = (charIndex + 1) % keyMap[idx].length;

        // System.err.println("keyPressed: lastKey=" + lastKey);

        //
        // if the user holds the star key in these constraints then
        // we need to tell the input client
        //
        if (idx == KEY_STAR && canUseSymbolTable) {
            setTimer(TM_INPUT_MODE, 1000);
            lastKey = KEYCODE_SHIFT;
            return KEYCODE_NONE;
        }

        if (idx == KEY_POUND &&
             (currentConstraints == TextField.NUMERIC   ||
              currentConstraints == TextField.DECIMAL)) {

            lastKey = KEYCODE_SIGNCHANGE;
            endComposition(false);
            return KEYCODE_NONE;
        }

        //
        // if a key has more than one choice we need to cycle through them
        //
        if (keyMap[idx].length > 1) {
            setTimer(TM_IN_COMPOSING, 1600);
        } else {
            endComposition(false);
        }

        return lastKey;
    
public synchronized intkeyReleased(int keyCode)
Handle a key released event. Overrides InputMethodHandler.keyReleased.

param
keyCode The code of the key that was released
return
boolean If True, this handler has handled the key release


        if (ignoreNextKeyRelease) {
            ignoreNextKeyRelease = false;
            lastKey = KEYCODE_NONE;
            lastKeyIndex = KEY_UNKNOWN;
            return lastKey;
        }

        int idx = getKeyMapIndex(keyCode);

        switch (idx) {
            case KEY_UNKNOWN:
                return KEYCODE_NONE;
   
            case KEY_STAR:
                if (timerType == TM_INPUT_MODE) {
                    cancelTimer();
                    if (canUseSymbolTable) {
                        lastKey = KEYCODE_NONE;
                        lastKeyIndex = KEY_UNKNOWN;
                        switchToNextInputMode(false);
                    } else {
                        endComposition(false);
                    }
                }
                break;
            case KEY_CLEAR:
                if (timerType == TM_CLEAR_BUFFER) {
                    cancelTimer();
                    endComposition(false);
                }
                break;
        }

        return lastKey;
    
public synchronized intkeyRepeated(int keyCode)
Handle a key repeated event. Overrides InputMethodHandler.keyRepeated.

param
keyCode The code of the key that was repeated
return
boolean If True, this handler has handled the key repeat

        return keyPressed(keyCode);
    
public synchronized intkeyTyped(char c)
Handle a typed key

param
c character that was typed
return
int Returns the character that was entered according to to the current InputMode and constraints, or -1 if the keyCode was not recognized or will be handled with a call back


        cancelTimer();


        ignoreNextKeyRelease = false;
        quickSymbolAccess = false;

        endComposition(false);

        if ((c == 8) || (c == 127)) {
            lastKey = KEYCODE_CLEAR;
        } else {
            lastKey = (int)c;
        }

        endComposition(false);

        return KEYCODE_NONE;
    
public synchronized booleansetConstraints(int constraints)
Set the internal constraint and modifier variables. Determine the best inputMode and keyMap to use for the given constraints

param
constraints Constraints to use
return
true if the constraints were set correctly


        boolean ret = false;

        currentConstraints = constraints & TextField.CONSTRAINT_MASK;
        currentModifiers   = constraints & ~TextField.CONSTRAINT_MASK;

        canUseSymbolTable = (currentConstraints == TextField.URL) ||
                            (currentConstraints == TextField.EMAILADDR) ||
                            (currentConstraints == TextField.ANY);

        // if (constraints != currentConstraints) 
        {
            ret = buildInputModes(currentConstraints, currentModifiers,
                                  imc.getInputMode(), 
                                  imc.getAllowedModes());

        }

        // currentConstraints = constraints;
        setKeyMap(inputMode, currentConstraints);

        return ret;
    
public synchronized voidsetInputMethodClient(InputMethodClient imc)
Sets the client that will receive callbacks

param
imc the client to receive callbacks


                        
         
        //
        // we don't want keys to hang over onto someone else's turf
        //

        cancelTimer(); 

        ignoreNextKeyRelease = true;
        this.imc = imc;

        lastKey = KEYCODE_NONE;
        lastKeyIndex = KEY_UNKNOWN;
        charIndex = 0;

        if (imc != null) {
            setConstraints(imc.getConstraints());
        }
    
protected booleansetKeyMap(int mode, int constraints)
Set the appropriate keypad mapping according to the input mode

param
mode The new input mode to use
param
constraints the constraints to use
return
true if keyMap is set.

        switch (mode) {
            case IM_ROMAN_CAPS:
                keyMap = upperRomanKeyMap;
                break;
            case IM_ROMAN_SMALL:
                keyMap = lowerRomanKeyMap;
                break;
            case IM_NUMERIC:
                keyMap = (constraints == TextField.PHONENUMBER) 
                       ? phoneNumericKeyMap
                       : (constraints == TextField.DECIMAL 
                           ? decimalKeyMap 
                           : numericKeyMap);

                break;
            case IM_SYMBOL:
                st.invokeSYM();
                break;
            case IM_NONE:
                break;
            default:
                return false;
        }
   
        imc.showInputMode(mode);

        return true;
    
protected voidsetTimer(int type, long delay)
Set a new timer.

param
type The type of Timer to set
param
delay The length of delay for the Timer


                              
          
        if (type != timerType) {
            if (type == TM_IN_COMPOSING) {
            }
            timerType = type;
        }
        cancelTimer();
        try {
            timerClient = new TimerClient();
            timerService.schedule(timerClient, delay);
        } catch (IllegalStateException e) {
            e.printStackTrace();
            cancelTimer();
        }
    
public java.lang.String[]supportedInputModes()
Get the list of supported input modes of this handler. Overrides InputMethodHandler.supportedInputModes.

return
String[] The array of supported input modes

        return supportedCharSubset;
    
protected voidswitchToNextInputMode(boolean fromSymTable)
Switch to the next available input mode. Sets capWord and capSentence to false

param
fromSymTable true if this is being called from the symbol table class. false otherwise


                                                           
        

        if (fromSymTable && quickSymbolAccess) {
            inputMode = oldInputMode;
        } else if (fromSymTable) {
            oldInputMode = defaultMode;
            inputMode = defaultMode;
        } else {
            int n = 0;

            // get the current input mode
            while (n < allowedModesNum) {
                if (allowedModes[n] == inputMode) {
                    break;
                }
                n++;
            }
            n = (n + 1) % allowedModesNum;
            oldInputMode = inputMode;
            inputMode = allowedModes[n];

            capWord = capSentence = false;

        }

        setKeyMap(inputMode, currentConstraints);
        
    
protected synchronized voidtimerWentOff()
Called by the TimerTask when a Timer executes.


        switch (timerType) {
            case TM_INPUT_MODE:
                quickSymbolAccess = true;

                ignoreNextKeyRelease = true;
                endComposition(true);

                oldInputMode = inputMode;
                st.invokeSYM();

                break;
            case TM_CLEAR_BUFFER:
                lastKey = KEYCODE_CLEARALL;
                // fall through
            case TM_IN_COMPOSING:
                endComposition(false);
                ignoreNextKeyRelease = true;
                break;
        }