sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // template\template_variant\specific\keymap.cpp sl@0: // This file is part of the Template Base port sl@0: // The keyboard lookup tables giving the function to be carried out sl@0: // and the new state of the keyboard sl@0: // sl@0: // sl@0: sl@0: sl@0: #include sl@0: sl@0: #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) sl@0: sl@0: sl@0: // sl@0: // Scancode conversion tables sl@0: // -------------------------- sl@0: // The scancode conversion is arranged as a tree of tables which are used to sl@0: // convert a scancode to a keycode, taking into account the modifier state sl@0: // (shift, control, fn) sl@0: // sl@0: // How the tables work: sl@0: // -------------------- sl@0: // Firstly, there is a distinction between the "scancodes" used in scanning sl@0: // the keyboard, and the "scancodes" used in this files. sl@0: // sl@0: // Typically the keyboard driver already contains a table to convert hardware sl@0: // key location codes produced during keyboard scanning into EPOC "scancodes". sl@0: // EPOC scancodes are defined for "standard" keys like shift, backspace, sl@0: // escape, in the TStdScanCode enum (see E32KEYS.H), and should be ASCII codes sl@0: // for normal characters. The keyboard driver should add these EPOC scancodes sl@0: // to the event queue, not hardware-dependant key locations. sl@0: // sl@0: // For now on "scancode" refers to EPOC scancodes: sl@0: // sl@0: // The keyboard is divided into a number of "blocks" of contiguous scancodes sl@0: // sl@0: // Blocks map to keycodes in a keycode table, and several blocks can be sl@0: // grouped and map to a single keycode table. Blocks map into the keycode sl@0: // table in the order they are declared. For example, if two scancode blocks sl@0: // with a range of 5 scancodes map to a single 10-entry keycode table, scancodes sl@0: // which fall in the first block will map to the first 5 entries in the keycode sl@0: // table, scancodes falling in the second block map the the next 5 entries in sl@0: // the keycode table. sl@0: // sl@0: // In theory it is possible to have multiple [keycode,scancode blocks] groups sl@0: // but there is little point doing this - grouping all the scancode blocks sl@0: // with a single keycode table holding all possible keycode values is usually sl@0: // sufficient (and simpler). However, there are some special cases where this sl@0: // is useful - the most obvious example is handling of shift and caps lock. sl@0: // The shift key implies everything that the caps-lock key does (upper case sl@0: // letters) plus some shifted characters for other keys. This is done by sl@0: // defining two tables - the first handles only caps-lock (upper case), the sl@0: // second handles all other keys that are affected only by shift. If caps- sl@0: // lock is active, only the caps-lock table is used. If shift is pressed both sl@0: // the caps-lock and shift tables are scanned for the conversion. This allows sl@0: // a base table to be extended with "extras", much like deriving a class from sl@0: // base class and extending it. sl@0: // sl@0: // sl@0: // There is one or more [keycode table, scancode blocks] group for each sl@0: // modifier state - e.g. a lower-case table, upper-case, ctrl, ctrl-shift. sl@0: // This is the root of the table. sl@0: // sl@0: // When converting a scancode the key translator first obtains the correct sl@0: // conversion tables for the modifier state. It then traverses all the scancode sl@0: // blocks looking for one which contains the scancode being converted. Once sl@0: // a matching scancode range is located, the key translator maps this into sl@0: // its position in the associated keycode table to obtain the converted keycode. sl@0: // sl@0: // The key tables below appear more complicated than they really are because of sl@0: // the intermediate structures that hold pointers to other structures. The sl@0: // important structures are: sl@0: // SScanCodeBlock - contains a "start" and "end" for a scancode range sl@0: // SConvSubTable - groups a number of scanode blocks with a keycode table sl@0: // SConvTableNode - points to SConvSubTables for each modifier state sl@0: // SConvTable - the root of the translation table - points to 1..n SConvTableNode sl@0: // sl@0: // The keycode tables are just an array of TUint16. sl@0: // sl@0: sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // Keys which are not affected by modifier state sl@0: // sl@0: sl@0: // sl@0: // This is a simple example of scancode to keycode mapping. The first block sl@0: // in scanCodeBlock_unmodifiable is a range of several scancodes, so maps to sl@0: // several entries in the keycode table convKeyCodes_unmodifiable. sl@0: // EStdKeyLeftShift -> maps to -> EKeyLeftShift sl@0: // EStdKeyRightShift -> maps to -> EKeyRightShift sl@0: // ... sl@0: // EStdKeyScrollLock -> maps to -> EKeyScrollLock sl@0: // sl@0: LOCAL_D const SScanCodeBlock scanCodeBlock_unmodifiable[]= sl@0: { sl@0: {EStdKeyLeftShift, EStdKeyScrollLock}, // range 1: left shift to scroll lock sl@0: }; sl@0: sl@0: LOCAL_D const TUint16 convKeyCodes_unmodifiable[]= sl@0: { sl@0: EKeyLeftShift, sl@0: EKeyRightShift, sl@0: EKeyLeftAlt, sl@0: EKeyRightAlt, sl@0: EKeyLeftCtrl, sl@0: EKeyRightCtrl, sl@0: EKeyLeftFunc, sl@0: EKeyRightFunc, sl@0: EKeyCapsLock, sl@0: EKeyNumLock, sl@0: EKeyScrollLock sl@0: }; sl@0: sl@0: sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // Base conversion table sl@0: // this table traps all of the keyboard's scanCodes except those in sl@0: // convKeyCodes_unmodifiable. It appears last in the top-level table and sl@0: // is used to convert any scancode that is not converted by any of the sl@0: // other tables sl@0: // sl@0: LOCAL_D const SScanCodeBlock scanCodeBlock_base[]= sl@0: { sl@0: {EStdKeyNull, EStdKeyDownArrow}, // scancode range 1 sl@0: {'0', '9'}, // scancode range 2 sl@0: {'A', 'Z'}, // scancode range 3 sl@0: {EStdKeyF1, EStdKeyDictaphoneRecord}, // scancode range 4 sl@0: }; sl@0: sl@0: LOCAL_D const TUint16 convKeyCodes_base[]= sl@0: { sl@0: EKeyNull, // scancode range 1 mapping starts here sl@0: EKeyBackspace, sl@0: EKeyTab, sl@0: EKeyEnter, sl@0: EKeyEscape, sl@0: ' ', sl@0: EKeyPrintScreen, sl@0: EKeyPause, sl@0: EKeyHome, sl@0: EKeyEnd, sl@0: EKeyPageUp, sl@0: EKeyPageDown, sl@0: EKeyInsert, sl@0: EKeyDelete, sl@0: EKeyLeftArrow, sl@0: EKeyRightArrow, sl@0: EKeyUpArrow, sl@0: EKeyDownArrow, sl@0: '0', // scancode range 2 mapping starts here sl@0: '1', sl@0: '2', sl@0: '3', sl@0: '4', sl@0: '5', sl@0: '6', sl@0: '7', sl@0: '8', sl@0: '9', sl@0: 'a', // scancode range 3 mapping starts here sl@0: 'b', sl@0: 'c', sl@0: 'd', sl@0: 'e', sl@0: 'f', sl@0: 'g', sl@0: 'h', sl@0: 'i', sl@0: 'j', sl@0: 'k', sl@0: 'l', sl@0: 'm', sl@0: 'n', sl@0: 'o', sl@0: 'p', sl@0: 'q', sl@0: 'r', sl@0: 's', sl@0: 't', sl@0: 'u', sl@0: 'v', sl@0: 'w', sl@0: 'x', sl@0: 'y', sl@0: 'z', sl@0: EKeyF1, // scancode range 4 mapping starts here sl@0: EKeyF2, sl@0: EKeyF3, sl@0: EKeyF4, sl@0: EKeyF5, sl@0: EKeyF6, sl@0: EKeyF7, sl@0: EKeyF8, sl@0: EKeyF9, sl@0: EKeyF10, sl@0: EKeyF11, sl@0: EKeyF12, sl@0: EKeyF13, sl@0: EKeyF14, sl@0: EKeyF15, sl@0: EKeyF16, sl@0: EKeyF17, sl@0: EKeyF18, sl@0: EKeyF19, sl@0: EKeyF20, sl@0: EKeyF21, sl@0: EKeyF22, sl@0: EKeyF23, sl@0: EKeyF24, sl@0: '`', sl@0: ',', sl@0: '.', sl@0: '/', sl@0: '\\', sl@0: ';', sl@0: '\'', sl@0: '#', sl@0: '[', sl@0: ']', sl@0: '-', sl@0: '=', sl@0: '/', sl@0: '*', sl@0: '-', sl@0: '+', sl@0: EKeyEnter, sl@0: EKeyEnd, sl@0: EKeyDownArrow, sl@0: EKeyPageDown, sl@0: EKeyLeftArrow, sl@0: EKeyNull, // numeric keypad '5' sl@0: EKeyRightArrow, sl@0: EKeyHome, sl@0: EKeyUpArrow, sl@0: EKeyPageUp, sl@0: EKeyInsert, sl@0: EKeyDelete, sl@0: EKeyMenu, sl@0: EKeyBacklightOn, sl@0: EKeyBacklightOff, sl@0: EKeyBacklightToggle, sl@0: EKeyIncContrast, sl@0: EKeyDecContrast, sl@0: EKeySliderDown, sl@0: EKeySliderUp, sl@0: EKeyDictaphonePlay, sl@0: EKeyDictaphoneStop, sl@0: EKeyDictaphoneRecord sl@0: }; sl@0: sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // caps-lock: this table traps those scanCodes which are affected by caps-lock sl@0: // sl@0: LOCAL_D const SScanCodeBlock scanCodeBlock_capsLock[]= sl@0: { sl@0: {'A', 'Z'} // only alpha keys are affected by caps-lock sl@0: }; sl@0: sl@0: LOCAL_D const TUint16 convKeyCodes_capsLock[]= sl@0: { sl@0: 'A', sl@0: 'B', sl@0: 'C', sl@0: 'D', sl@0: 'E', sl@0: 'F', sl@0: 'G', sl@0: 'H', sl@0: 'I', sl@0: 'J', sl@0: 'K', sl@0: 'L', sl@0: 'M', sl@0: 'N', sl@0: 'O', sl@0: 'P', sl@0: 'Q', sl@0: 'R', sl@0: 'S', sl@0: 'T', sl@0: 'U', sl@0: 'V', sl@0: 'W', sl@0: 'X', sl@0: 'Y', sl@0: 'Z' sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // shift: this table traps those scanCodes which are affected sl@0: // by normal shift key EXCEPT for those scanCodes affected by caps-lock sl@0: // sl@0: sl@0: LOCAL_D const SScanCodeBlock scanCodeBlock_shift[]= sl@0: { sl@0: {'0', '9'}, sl@0: {EStdKeyXXX, EStdKeyEquals}, sl@0: }; sl@0: sl@0: LOCAL_D const TUint16 convKeyCodes_shift[]= sl@0: { sl@0: ')', sl@0: '!', sl@0: '@',/*'"',*/ sl@0: '#', /*ELatin1Pound,*/ sl@0: '$', sl@0: '%', sl@0: '^', sl@0: '&', sl@0: '*', sl@0: '(', sl@0: '~', /*ELatin1LogicNot,*/ sl@0: '<', sl@0: '>', sl@0: '?', sl@0: '|', sl@0: ':', sl@0: '"', sl@0: '|', /*'~',*/ sl@0: '{', sl@0: '}', sl@0: '_', sl@0: '+' sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // func: this table traps those scanCodes which are affected sl@0: // by the func key but not shift sl@0: // sl@0: LOCAL_D const SScanCodeBlock scanCodeBlock_func[]= sl@0: { sl@0: {EStdKeyEscape, EStdKeyEscape}, sl@0: {'M', 'M'}, sl@0: {EStdKeyComma, EStdKeyComma}, sl@0: {EStdKeyLeftArrow, EStdKeyDownArrow}, sl@0: }; sl@0: sl@0: LOCAL_D const TUint16 convKeyCodes_func[]= sl@0: { sl@0: EKeyOff, sl@0: EKeyDecContrast, sl@0: EKeyIncContrast, sl@0: EKeyHome, sl@0: EKeyEnd, sl@0: EKeyPageUp, sl@0: EKeyPageDown, sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // func: this table traps those scanCodes which are affected sl@0: // by func and shift - this is for func pressed, shift not pressed sl@0: // sl@0: //LOCAL_D const SScanCodeBlock scanCodeBlock_funcUnshifted[]= sl@0: // { sl@0: // {'E', 'E'}, sl@0: // }; sl@0: sl@0: //LOCAL_D const TUint16 convKeyCodes_funcUnshifted[]= sl@0: // { sl@0: // ELatin1LcEacute, sl@0: // }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // func: this table traps those scanCodes which are affected sl@0: // by func and shift - this is for func and shift both pressed sl@0: // sl@0: //LOCAL_D const SScanCodeBlock scanCodeBlock_funcShifted[]= sl@0: // { sl@0: // {'E', 'E'}, sl@0: // }; sl@0: sl@0: //LOCAL_D const TUint16 convKeyCodes_funcShifted[]= sl@0: // { sl@0: // ELatin1UcEacute, sl@0: // }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // ctrl: this table traps those scanCodes which are affected by ctrl sl@0: // sl@0: LOCAL_D const SScanCodeBlock scanCodeBlock_ctrl[]= sl@0: { sl@0: // sl@0: // NOTE: The space key gets handled elsewhere, otherwise it gets sl@0: // thrown away as a NULL key sl@0: // {EStdKeySpace, EStdKeySpace}, sl@0: sl@0: {'A', 'Z'}, sl@0: {EStdKeyComma, EStdKeyComma}, sl@0: }; sl@0: sl@0: LOCAL_D const TUint16 convKeyCodes_ctrl[]= sl@0: { sl@0: // 0, sl@0: 1, sl@0: 2, sl@0: 3, sl@0: 4, sl@0: 5, sl@0: 6, sl@0: 7, sl@0: 8, sl@0: 9, sl@0: 10, sl@0: 11, sl@0: 12, sl@0: 13, sl@0: 14, sl@0: 15, sl@0: 16, sl@0: 17, sl@0: 18, sl@0: 19, sl@0: 20, sl@0: 21, sl@0: 22, sl@0: 23, sl@0: 24, sl@0: 25, sl@0: 26, sl@0: ',', sl@0: }; sl@0: sl@0: sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // Each set of scancode+keycode tables must be grouped into a SConvSubTable. sl@0: // The lines below define a number of SConvSubTables for each of the groups sl@0: // above. sl@0: // sl@0: LOCAL_D const SConvSubTable sl@0: convSubTable_unmodifiable= // table for unmodifiable keys sl@0: { sl@0: &convKeyCodes_unmodifiable[0], // the keycode table sl@0: { sl@0: ARRAY_LENGTH(scanCodeBlock_unmodifiable), // number of scancode blocks sl@0: &scanCodeBlock_unmodifiable[0] // pointer to scancode blocks sl@0: } sl@0: }, sl@0: convSubTable_base= // table for base keys sl@0: { sl@0: &convKeyCodes_base[0], // keycode table sl@0: { sl@0: ARRAY_LENGTH(scanCodeBlock_base), // number of scancode blocks sl@0: &scanCodeBlock_base[0] // pointer to scancode blocks sl@0: } sl@0: }, sl@0: convSubTable_capsLock= sl@0: { sl@0: &convKeyCodes_capsLock[0], sl@0: { sl@0: ARRAY_LENGTH(scanCodeBlock_capsLock), sl@0: &scanCodeBlock_capsLock[0] sl@0: } sl@0: }, sl@0: convSubTable_shift= sl@0: { sl@0: &convKeyCodes_shift[0], sl@0: { sl@0: ARRAY_LENGTH(scanCodeBlock_shift), sl@0: &scanCodeBlock_shift[0] sl@0: } sl@0: }, sl@0: convSubTable_func= sl@0: { sl@0: &convKeyCodes_func[0], sl@0: { sl@0: ARRAY_LENGTH(scanCodeBlock_func), sl@0: &scanCodeBlock_func[0] sl@0: } sl@0: }, sl@0: // convSubTable_funcUnshifted= sl@0: // { sl@0: // &convKeyCodes_funcUnshifted[0], sl@0: // { sl@0: // ARRAY_LENGTH(scanCodeBlock_funcUnshifted), sl@0: // &scanCodeBlock_funcUnshifted[0] sl@0: // } sl@0: // }, sl@0: // convSubTable_funcShifted= sl@0: // { sl@0: // &convKeyCodes_funcShifted[0], sl@0: // { sl@0: // ARRAY_LENGTH(scanCodeBlock_funcShifted), sl@0: // &scanCodeBlock_funcShifted[0] sl@0: // } sl@0: // }, sl@0: convSubTable_ctrl= sl@0: { sl@0: &convKeyCodes_ctrl[0], sl@0: { sl@0: ARRAY_LENGTH(scanCodeBlock_ctrl), sl@0: &scanCodeBlock_ctrl[0] sl@0: } sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // We need to declare arrays of SConvSubTable for each modifier state we sl@0: // are going to handle. As mentioned above, it is possible to have several sl@0: // [keycode table, scancode blocks] groups scanned for each keyboard state. sl@0: // sl@0: // Some modifier states use more than one conversion group. The simple example sl@0: // is handling of caps-lock and shift. sl@0: // sl@0: // Caps-lock means all letters are upper-case sl@0: // shift means all letters are upper case AND some other keys return control characters sl@0: // sl@0: // Obviously the shift key means everything cpas-lock means PLUS a bit more. So sl@0: // we define two tables, the caps-lock table defines only the uppercase conversion, sl@0: // and the shift table defines all OTHER shifted keys not already handled by sl@0: // caps-lock. The caps-lock modifier state then only scans the caps-lock table, and sl@0: // the shift state scans both tables. sl@0: // sl@0: LOCAL_D const SConvSubTable sl@0: * const convSubTableArray_unmodifiable[]={&convSubTable_unmodifiable}, sl@0: * const convSubTableArray_base[]={&convSubTable_base}, sl@0: sl@0: // sl@0: // The caps-lock state scans only the caps-lock table, to handle sl@0: // conversion to upper case sl@0: // sl@0: * const convSubTableArray_capsLock[]={&convSubTable_capsLock}, sl@0: // sl@0: // The shift table scans the caps-lock table to handle upper case, sl@0: // and also the shift table which handles some keys that are not affected sl@0: // by caps lock (such as 0-9). sl@0: // sl@0: * const convSubTableArray_shift[]={&convSubTable_capsLock, &convSubTable_shift}, sl@0: // sl@0: // Pressing shift with caps-lock active reverts to lower-case letters, sl@0: // but other keys remain shifted. This time we only scan the shift table sl@0: // so only the non-alpha keys will be shifted sl@0: // sl@0: * const convSubTableArray_capsLockShift[]={&convSubTable_shift}, sl@0: sl@0: // sl@0: // Like the shift/caps-lock situation, the function key has two states, sl@0: // shifted and unshifted. Also, some keys may be independant of whether sl@0: // the shift key is pressed. So there are three tables defined. One declares sl@0: // all keys that are independant of shift state, the other two tables handle sl@0: // shifted and unshifted func. sl@0: // sl@0: // Unshifted func uses the independant set + funcUnshifted sl@0: // sl@0: // * const convSubTableArray_func[]={&convSubTable_func, &convSubTable_funcUnshifted}, sl@0: * const convSubTableArray_func[]={&convSubTable_func}, sl@0: // sl@0: // Shifted func uses the independant set + funcShifted sl@0: // sl@0: // * const convSubTableArray_funcShift[]={&convSubTable_func,&convSubTable_funcShifted}, sl@0: // sl@0: // This keyboard table makes control independant of func and shift sl@0: // sl@0: * const convSubTableArray_ctrl[]={&convSubTable_ctrl}; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // This is the top of the scancode conversion tree. It is a set of pointers sl@0: // to the SConvSubTable arrays declared above. sl@0: // sl@0: // The order of these nodes is VITAL, as the scanCode/modifiers are sl@0: // searched for a match in this order sl@0: // sl@0: // The modifier state is matched by using a mask and a compare value. This is sl@0: // used as follows: sl@0: // sl@0: // match is true if ( (modifierState & mask) == compareValue sl@0: // sl@0: // For example, if the mask is (EModifierFunc|EModifierShift) and the sl@0: // compare value is EModifierFunc, this will match ANY combination of sl@0: // modifiers that has func pressed and shift not pressed sl@0: // sl@0: LOCAL_D const SConvTableNode convTableNodes[]= sl@0: { sl@0: { sl@0: { sl@0: 0, // modifier mask = no modifiers sl@0: 0 // modifier compare = no modifiers sl@0: }, sl@0: ARRAY_LENGTH(convSubTableArray_unmodifiable), // number of SConvSubTables sl@0: &convSubTableArray_unmodifiable[0] // pointer to SConvSubTable array sl@0: }, sl@0: { sl@0: { sl@0: EModifierCtrl, // modifier mask = check for ctrl sl@0: EModifierCtrl // modifier compare = anything with ctrl pressed sl@0: }, sl@0: ARRAY_LENGTH(convSubTableArray_ctrl), sl@0: &convSubTableArray_ctrl[0] sl@0: }, sl@0: { sl@0: { sl@0: // sl@0: // Check for Func pressed sl@0: // sl@0: EModifierFunc, sl@0: EModifierFunc sl@0: }, sl@0: ARRAY_LENGTH(convSubTableArray_func), sl@0: &convSubTableArray_func[0] sl@0: }, sl@0: { sl@0: { sl@0: // sl@0: // Check for caps-lock pressed, shift not pressed sl@0: // sl@0: EModifierCapsLock|EModifierShift, sl@0: EModifierCapsLock sl@0: }, sl@0: ARRAY_LENGTH(convSubTableArray_capsLock), sl@0: &convSubTableArray_capsLock[0] sl@0: }, sl@0: { sl@0: { sl@0: // sl@0: // Check for caps-lock not pressed, shift pressed sl@0: // sl@0: EModifierShift|EModifierCapsLock, sl@0: EModifierShift sl@0: }, sl@0: ARRAY_LENGTH(convSubTableArray_shift), sl@0: &convSubTableArray_shift[0] sl@0: }, sl@0: { sl@0: { sl@0: // sl@0: // Check for caps-lock pressed, shift pressed sl@0: // sl@0: EModifierCapsLock|EModifierShift, sl@0: EModifierCapsLock|EModifierShift sl@0: }, sl@0: ARRAY_LENGTH(convSubTableArray_capsLockShift), sl@0: &convSubTableArray_capsLockShift[0] sl@0: }, sl@0: { sl@0: // sl@0: // This is the base table. It must appear last so that it can sl@0: // provide a default conversion for any scancodes that are not sl@0: // handled by any of the tables above sl@0: // sl@0: { sl@0: 0, sl@0: 0 sl@0: }, sl@0: ARRAY_LENGTH(convSubTableArray_base), sl@0: &convSubTableArray_base[0] sl@0: } sl@0: }; sl@0: sl@0: // sl@0: // The top-level exported data structure of all the conversion tables sl@0: // This just points to the SConvTableNodes above sl@0: // sl@0: LOCAL_D const SConvTable ConvTable= sl@0: { sl@0: ARRAY_LENGTH(convTableNodes), sl@0: &convTableNodes[0] sl@0: }; sl@0: sl@0: // The list of scan-codes on the numeric keypad sl@0: LOCAL_D const SScanCodeBlock keypadScanCodeBlockArray[]= sl@0: { sl@0: {EStdKeyNumLock, EStdKeyNumLock}, sl@0: {EStdKeyNkpForwardSlash, EStdKeyNkpFullStop} sl@0: }; sl@0: sl@0: LOCAL_D const SScanCodeBlockList ConvTableKeypadScanCodes= sl@0: { sl@0: ARRAY_LENGTH(keypadScanCodeBlockArray), sl@0: &keypadScanCodeBlockArray[0] sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // List of keycodes that do not autorepeat sl@0: // sl@0: // These are usually control keys like shift, ctrl, escape sl@0: // sl@0: LOCAL_D const TUint16 nonAutorepKeyCodeArray[]= sl@0: { sl@0: EKeyEscape, sl@0: EKeyPrintScreen, sl@0: EKeyPause, sl@0: EKeyInsert, sl@0: EKeyLeftShift, sl@0: EKeyRightShift, sl@0: EKeyLeftAlt, sl@0: EKeyRightAlt, sl@0: EKeyLeftCtrl, sl@0: EKeyRightCtrl, sl@0: EKeyLeftFunc, sl@0: EKeyRightFunc, sl@0: EKeyCapsLock, sl@0: EKeyNumLock, sl@0: EKeyScrollLock, sl@0: EKeyMenu, sl@0: EKeyDictaphonePlay, sl@0: EKeyDictaphoneStop, sl@0: EKeyDictaphoneRecord sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // Declare blocks of non-autorepeating keycodes sl@0: // sl@0: LOCAL_D const SKeyCodeList ConvTableNonAutorepKeyCodes= sl@0: { sl@0: ARRAY_LENGTH(nonAutorepKeyCodeArray), // number of keycode arrays sl@0: &nonAutorepKeyCodeArray[0] // pointer to arrays sl@0: }; sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: ///////////////////////////////////////////////////////////////////// sl@0: // Keyboard state tables sl@0: // sl@0: sl@0: // What these tables do sl@0: // -------------------- sl@0: // sl@0: // These tables control the way "special" keystrokes modify the behaviour sl@0: // of the keyboard. There are two major uses for this: sl@0: // sl@0: // - handling modifier keys e.g. caps-lock, shift, alt, fn and defining sl@0: // what modifier flags are affected by these keypresses sl@0: // sl@0: // - switching the keyboard into special states (see below) sl@0: // sl@0: // Keyboard states sl@0: // --------------- sl@0: // sl@0: // Keyboard states are used to switch the keyboard into a special mode where it sl@0: // can be used to enter unusual characters. There are two uses for this: sl@0: // sl@0: // - entering numeric codes, by pressing ctrl and typing the decimal code sl@0: // - entering accented characters by pressing a key combination which sl@0: // enters "accented mode" then pressing a key. There can be multiple sl@0: // accented modes. sl@0: // sl@0: // You can see an example of accented modes on a Psion Series 5 by sl@0: // pressing Fn+Z, followed by A - this will produce an a with an umlaut (ä) sl@0: // sl@0: // These tables are also used to select simpler states such as caps-lock sl@0: // and num-lock. sl@0: // sl@0: // sl@0: // The main data structure is a SFuncTableEntry. Each of these contains sl@0: // three fields: sl@0: // sl@0: // 1. modifier match - this works the same way as the scancode conversion sl@0: // tables above, there is a mask and a compare value sl@0: // sl@0: // 2. a keycode patters - this is used to match with the keycode or keycodes sl@0: // that the state should respond to. This is a TKeyCodePattern structure sl@0: // which defines what sort of match should be performed. sl@0: // sl@0: // 3. a function and state change structure, SFuncAndState. This defines the sl@0: // state to change to, the function to perform, and a parameter for the sl@0: // function if required. sl@0: // sl@0: // TKeyCodePattern structures have two fields. The first is a keycode value sl@0: // and is only used for some match types. The second field select the type sl@0: // of match to perform: sl@0: // sl@0: // EAnyKey - match any key sl@0: // EAnyAlphaNumeric - match any alpha or numeric key sl@0: // EAnyAlpha - match any alpha key sl@0: // EAnyAlphaLowerCase - match any lower-case key sl@0: // EAnyAlphaUpperCase - match any upper-case key sl@0: // EAnyDecimalDigit - match any decimal digit sl@0: // EAnyModifierKey - match any modifier key (e.g. alt, fn, ctrl) sl@0: // EMatchKey - match if equal to keycode value in first field sl@0: // EMatchLeftOrRight - match if equal to keycode value or (keycode value + 1) sl@0: // EMatchKeyCaseInsens - like EMatchKey but perform case-insensitive comparison sl@0: // sl@0: // sl@0: sl@0: // the "array" parameter must be a true array and not a pointer sl@0: #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) sl@0: sl@0: #define TABLE_ENTRY_ANOTHER_CTRL_DIGIT \ sl@0: { \ sl@0: { \ sl@0: EModifierKeyUp|EModifierFunc, \ sl@0: 0 \ sl@0: }, \ sl@0: { \ sl@0: EKeyNull, \ sl@0: EAnyDigitGivenRadix \ sl@0: }, \ sl@0: { \ sl@0: EStateCtrlDigits, \ sl@0: EAddOnCtrlDigit, \ sl@0: 0 \ sl@0: } \ sl@0: } sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // This table is searched for a match if a match has not been sl@0: // found in the current state's table sl@0: // sl@0: sl@0: LOCAL_D const SFuncTableEntry defaultTable[]= sl@0: { sl@0: { sl@0: // sl@0: // prevent key up events generating keycodes sl@0: // sl@0: { sl@0: EModifierKeyUp, // mask = key up sl@0: EModifierKeyUp // match = key up - i.e. accept any key up event sl@0: }, sl@0: { sl@0: EKeyNull, // dummy value, not used sl@0: EAnyKey // accept any key sl@0: }, sl@0: { sl@0: EStateUnchanged, // state will not change sl@0: EDoNothing, // no action to perform sl@0: 0 sl@0: } sl@0: }, sl@0: { sl@0: // sl@0: // prevent any modifier key (e.g. shift, ctrl) from changing state sl@0: // sl@0: { sl@0: 0, // match any modifier state sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyNull, // dummy value sl@0: EAnyModifierKey // match any modifier key sl@0: }, sl@0: { sl@0: EStateUnchanged, // don't change state sl@0: EDoNothing, // nothing to do sl@0: 0 sl@0: } sl@0: }, sl@0: { sl@0: // sl@0: // filter out any unprocessed codes sl@0: // sl@0: { sl@0: 0, // match any modifier state sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyNull, // dummy value sl@0: EAnyKey // match any key sl@0: }, sl@0: { sl@0: EStateNormal, // switch back to normal keyboard state sl@0: EDoNothing, // nothing to do sl@0: 0 sl@0: } sl@0: } sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // This table controls which keys change which modifiers; sl@0: // NOTE: the state field in this table is ignored sl@0: // sl@0: sl@0: LOCAL_D const SFuncTableEntry modifierTable[]= sl@0: { sl@0: { sl@0: { sl@0: EModifierKeyUp, // check key-up modifier flag sl@0: 0 // make sure it's zero (i.e. ignore key-up events) sl@0: }, sl@0: { sl@0: // sl@0: // Here we want to match only the caps-lock key. We specify the sl@0: // keycode we are looking for in the first field, and EMatchKey sl@0: // in the second field sl@0: // sl@0: EKeyCapsLock, // we want to respond to caps-lock key sl@0: EMatchKey // match caps-lock only sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: EToggleModifier, // function = toggle modifier state sl@0: EModifierCapsLock // this is the modifier to toggle sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyNumLock, // this one matched num-lock sl@0: EMatchKey // match only num-lock sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: EToggleModifier, // function = toggle modifier state sl@0: EModifierNumLock // this is the modifier to toggle sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyScrollLock, // match scroll-lock key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, sl@0: EToggleModifier, // function = toggle modifier sl@0: EModifierScrollLock // modifier to toggle sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyLeftAlt, // match left alt key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on a modifier sl@0: EModifierAlt|EModifierLeftAlt // alt turns on this modifier combination sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with previous table, this handles the alt sl@0: EModifierKeyUp // key being released sl@0: }, sl@0: { sl@0: EKeyLeftAlt, // match left alt key again sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, sl@0: ETurnOffModifier, // function = turn off the modifier sl@0: EModifierLeftAlt // modifier to turn off sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // key down event (key-up flag == 0) sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyLeftFunc, // match left fn key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on modifier sl@0: EModifierFunc|EModifierLeftFunc // modifier combination to turn on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with above table, this matched the sl@0: EModifierKeyUp // left-fn key up event sl@0: }, sl@0: { sl@0: EKeyLeftFunc, // match left fn key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOffModifier, // function = turn off modifier sl@0: EModifierLeftFunc // modifier to turn off sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // key down event (key-up flag == 0) sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyLeftShift, // match left shift key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on modifier sl@0: EModifierShift|EModifierLeftShift // modifier combination to turn on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with above table, matches left shift sl@0: EModifierKeyUp // key up event sl@0: }, sl@0: { sl@0: EKeyLeftShift, // match left shift key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOffModifier, // turn off modifier sl@0: EModifierLeftShift // modifier to turn off sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // key down event (key-up flag == 0) sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyLeftCtrl, // match left ctrl key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on modifier sl@0: EModifierCtrl|EModifierLeftCtrl // modifier combination to turn on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with above table, matches left ctrl sl@0: EModifierKeyUp // key up event sl@0: }, sl@0: { sl@0: EKeyLeftCtrl, // match left ctrl key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOffModifier, // function = turn off modifier sl@0: EModifierLeftCtrl // modifier to turn off sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // key down event (key-up flag == 0) sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyRightAlt, // match right alt key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on modifier sl@0: EModifierAlt|EModifierRightAlt // modifier combination to turn on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with above table, matches right alt sl@0: EModifierKeyUp // key up event sl@0: }, sl@0: { sl@0: EKeyRightAlt, // match right alt key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOffModifier, // function = turn off modifier sl@0: EModifierRightAlt // modifier to turn off sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // key down event (key-up flag == 0) sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyRightFunc, // match right fn key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on modifier sl@0: EModifierFunc|EModifierRightFunc // modifier combination to turn on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with above table, matches right fn sl@0: EModifierKeyUp // key up event sl@0: }, sl@0: { sl@0: EKeyRightFunc, // match right fn key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOffModifier, // function = turn off modifier sl@0: EModifierRightFunc // modifier to turn off sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // key down event (key-up flag == 0) sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyRightShift, // match right shift key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on modifier sl@0: EModifierShift|EModifierRightShift // modifier combinatoin to turn on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with above table, handles right shift sl@0: EModifierKeyUp // key up event sl@0: }, sl@0: { sl@0: EKeyRightShift, // match right shift key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOffModifier, // function = turn off modifier sl@0: EModifierRightShift // modifier to turn off sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // key down event (key-up flag == 0) sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyRightCtrl, // match right ctrl key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOnModifier, // function = turn on modifier sl@0: EModifierCtrl|EModifierRightCtrl // modifier combination to turn on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierKeyUp, // goes with above table, matched right ctrl sl@0: EModifierKeyUp // key up event sl@0: }, sl@0: { sl@0: EKeyRightCtrl, // match right ctrl key sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateUnchanged, // ignored sl@0: ETurnOffModifier, // function = turn off modifier sl@0: EModifierRightCtrl // modifier to turn off sl@0: } sl@0: } sl@0: }; sl@0: sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // Tables corresponding to keyboard states. sl@0: // sl@0: // There are 13 keyboard states. States 0 to 9 can be used to create alternative sl@0: // keyboard layouts for entering accented or unusual characters. Switching into sl@0: // these states is done by a keypress. Implementation of the states is optional sl@0: // depending on how many special state you want - you may implement 10 states, sl@0: // you might decide not to implement any. sl@0: // sl@0: // State 10 is the normal state. The table for state 10 defines which keypresses sl@0: // change to other states. sl@0: // sl@0: // States 11 and 12 are used when entering the numeric code of a character. State sl@0: // 11 is for entering a specific number of digits. State 12 is for accepting sl@0: // digits until Ctrl is released. sl@0: // sl@0: // sl@0: // As before, each SFuncTableEntry entry defines: sl@0: // - modifier conditions that must be matched sl@0: // - a keycode match pattern (typically an exact key match) sl@0: // - the function to perform and new state sl@0: // sl@0: // Switching into states 0..9,11,12 is done by entries in table10 sl@0: // sl@0: sl@0: //LOCAL_D const SFuncTableEntry table0[]= sl@0: // { sl@0: // TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: // }; sl@0: sl@0: LOCAL_D const SFuncTableEntry table1[]= sl@0: { sl@0: // sl@0: // Table for special keyboard state 1 sl@0: // This state is entered by pressing Fn+q (see table10) sl@0: // sl@0: // The table makes certain keys return accented characters sl@0: // sl@0: { sl@0: { sl@0: // sl@0: // Function must be release, and this must be a key down event sl@0: // sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: // sl@0: // match an 'e' keypress, convert to an ae ligature (æ) sl@0: // sl@0: 'e', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, // switch back to state normal (table10) sl@0: EPassSpecialKeyThru, // turn keypress into a special character sl@0: ELatin1LcAe // this is the character to pass on sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'c', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcCcedilla sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 's', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1EsTset sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'o', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcOslash sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'd', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcThorn sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 't', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcSoftTh sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'l', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LeftChevron sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'r', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1RightChevron sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'x', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1InvExclam sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'q', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1InvQuest sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'a', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcAo sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'p', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1Pound sl@0: } sl@0: }, sl@0: TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: }; sl@0: sl@0: LOCAL_D const SFuncTableEntry table2[]= sl@0: { sl@0: // sl@0: // Table for special keyboard state 2 sl@0: // This state is entered by pressing Fn+z (see table10) sl@0: // sl@0: // The table makes certain keys return accented characters sl@0: // See table1 for an explanation of the contents sl@0: // sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'a', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcAumlaut sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'e', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcEumlaut sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'i', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcIumlaut sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'o', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcOumlaut sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'u', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcUumlaut sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'y', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcYumlaut sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: ' ', sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1SpaceUmlaut sl@0: } sl@0: }, sl@0: TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: }; sl@0: sl@0: LOCAL_D const SFuncTableEntry table3[]= sl@0: { sl@0: // sl@0: // Table for special keyboard state 3 sl@0: // This state is entered by pressing Fn+x (see table10) sl@0: // sl@0: // The table makes certain keys return accented characters sl@0: // sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'a', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcAgrave sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'e', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcEgrave sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'i', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcIgrave sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'o', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcOgrave sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'u', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcUgrave sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: ' ', sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1SpaceGrave sl@0: } sl@0: }, sl@0: TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: }; sl@0: sl@0: LOCAL_D const SFuncTableEntry table4[]= sl@0: { sl@0: // sl@0: // Table for special keyboard state 4 sl@0: // This state is entered by pressing Fn+c (see table10) sl@0: // sl@0: // The table makes certain keys return accented characters sl@0: // sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'a', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcAacute sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'e', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcEacute sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'i', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcIacute sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'o', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcOacute sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'u', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcUacute sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'y', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcYacute sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: ' ', sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcSpaceAcute sl@0: } sl@0: }, sl@0: TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: }; sl@0: sl@0: LOCAL_D const SFuncTableEntry table5[]= sl@0: { sl@0: // sl@0: // Table for special keyboard state 5 sl@0: // This state is entered by pressing Fn+v (see table10) sl@0: // sl@0: // The table makes certain keys return accented characters sl@0: // sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'a', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcAtilde sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'n', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcNtilde sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'o', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcOtilde sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: ' ', sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcSpaceTilde sl@0: } sl@0: }, sl@0: TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: }; sl@0: sl@0: LOCAL_D const SFuncTableEntry table6[]= sl@0: { sl@0: // sl@0: // Table for special keyboard state 6 sl@0: // This state is entered by pressing Fn+b (see table6) sl@0: // sl@0: // The table makes certain keys return accented characters sl@0: // sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'a', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcAcirc sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'e', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcEcirc sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'i', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcIcirc sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'o', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcOcirc sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: 'u', sl@0: EMatchKeyCaseInsens sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcUcirc sl@0: } sl@0: }, sl@0: { sl@0: { sl@0: EModifierFunc|EModifierKeyUp, sl@0: 0 sl@0: }, sl@0: { sl@0: ' ', sl@0: EMatchKey sl@0: }, sl@0: { sl@0: EStateNormal, sl@0: EPassSpecialKeyThru, sl@0: ELatin1LcSpaceCirc sl@0: } sl@0: }, sl@0: TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: }; sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // State 7,8,9 aren't used in this example. sl@0: // You can implement them if you want more special states sl@0: // sl@0: sl@0: //LOCAL_D const SFuncTableEntry table7[]= sl@0: // { sl@0: // TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: // }; sl@0: sl@0: //LOCAL_D const SFuncTableEntry table8[]= sl@0: // { sl@0: // TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: // }; sl@0: sl@0: //LOCAL_D const SFuncTableEntry table9[]= sl@0: // { sl@0: // TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: // }; sl@0: sl@0: sl@0: LOCAL_D const SFuncTableEntry table10[]= sl@0: { sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // Table keyboard state 10 - the normal state sl@0: // sl@0: // This table controls which keys switch into the special states sl@0: // 0-9, 11 and 12. sl@0: // sl@0: sl@0: { sl@0: // sl@0: // Make sure key-up events are ignored by handling them first and sl@0: // doing nothing sl@0: // sl@0: { sl@0: EModifierKeyUp, sl@0: EModifierKeyUp sl@0: }, sl@0: { sl@0: EKeyNull, sl@0: EAnyKey sl@0: }, sl@0: { sl@0: EStateUnchanged, sl@0: EDoNothing, sl@0: 0 sl@0: } sl@0: }, sl@0: { sl@0: // sl@0: // Check for ctrl-number presses sl@0: // This will enter state EStateCtrlDigits (state 12) which allows sl@0: // entry of a numeric keycode sl@0: // sl@0: { sl@0: EModifierCtrl|EModifierFunc|EModifierKeyUp, sl@0: EModifierCtrl sl@0: }, sl@0: { sl@0: EKeyNull, sl@0: EAnyDecimalDigit sl@0: }, sl@0: { sl@0: EStateDerivedFromDigitEntered, sl@0: EAddOnCtrlDigit, sl@0: 0 sl@0: } sl@0: }, sl@0: { sl@0: // sl@0: // Any other key events that have not been trapped are just sl@0: // passed through unchanged sl@0: // sl@0: { sl@0: 0, sl@0: 0 sl@0: }, sl@0: { sl@0: EKeyNull, sl@0: EAnyKey sl@0: }, sl@0: { sl@0: EStateUnchanged, sl@0: EPassKeyThru, sl@0: 0 sl@0: } sl@0: } sl@0: }; sl@0: sl@0: //LOCAL_D const SFuncTableEntry table11[]= sl@0: // { sl@0: // TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: // }; sl@0: sl@0: LOCAL_D const SFuncTableEntry table12[]= sl@0: { sl@0: // sl@0: // Table 12 handles entring digit codes. The keyboard will remain in this sl@0: // state until the Ctrl key is released sl@0: // sl@0: { sl@0: { sl@0: // sl@0: // Look for a key up event sl@0: // sl@0: EModifierKeyUp, sl@0: EModifierKeyUp sl@0: }, sl@0: { sl@0: // sl@0: // Match either left or right Ctrl key (i.e. this matches a Ctrl key release) sl@0: // sl@0: EKeyLeftCtrl, sl@0: EMatchLeftOrRight sl@0: }, sl@0: { sl@0: EStateNormal, // return to normal state (table10) sl@0: EPassCtrlDigitsThru, // and pass through the numeric code we have accumulated sl@0: 0 sl@0: } sl@0: }, sl@0: TABLE_ENTRY_ANOTHER_CTRL_DIGIT sl@0: }; sl@0: sl@0: sl@0: // sl@0: // TO DO: (optional) sl@0: // sl@0: // Array of state control tables above. If a state is not used set the array sl@0: // size to zero and the pointer to NULL sl@0: // sl@0: // The tables must be declared here in order from table 0 to table 12 sl@0: // sl@0: LOCAL_D const SFuncTable genFuncTables[]= sl@0: { sl@0: { sl@0: // sl@0: // state 0 sl@0: // sl@0: 0, // state 0 not used, size = 0 sl@0: NULL // state 0 not used, pointer = NULL sl@0: }, sl@0: { sl@0: // sl@0: // state 1 sl@0: // sl@0: ARRAY_LENGTH(table1), // size of table 1 sl@0: &table1[0] // pointer to table 1 sl@0: }, sl@0: { sl@0: // sl@0: // state 2 sl@0: // sl@0: ARRAY_LENGTH(table2), sl@0: &table2[0] sl@0: }, sl@0: { sl@0: // sl@0: // state 3 sl@0: // sl@0: ARRAY_LENGTH(table3), sl@0: &table3[0] sl@0: }, sl@0: { sl@0: // sl@0: // state 4 sl@0: // sl@0: ARRAY_LENGTH(table4), sl@0: &table4[0] sl@0: }, sl@0: { sl@0: // sl@0: // state 5 sl@0: // sl@0: ARRAY_LENGTH(table5), sl@0: &table5[0] sl@0: }, sl@0: { sl@0: // sl@0: // state 6 sl@0: // sl@0: ARRAY_LENGTH(table6), sl@0: &table6[0] sl@0: }, sl@0: { sl@0: // sl@0: // state 7 sl@0: // sl@0: 0, sl@0: NULL sl@0: }, sl@0: { sl@0: // sl@0: // state 8 sl@0: // sl@0: 0, sl@0: NULL sl@0: }, sl@0: { sl@0: // sl@0: // state 9 sl@0: // sl@0: 0, sl@0: NULL sl@0: }, sl@0: { sl@0: // sl@0: // state 10 sl@0: // sl@0: ARRAY_LENGTH(table10), sl@0: &table10[0] sl@0: }, sl@0: { sl@0: // sl@0: // state 11 sl@0: // sl@0: 0, sl@0: NULL sl@0: }, sl@0: { sl@0: // sl@0: // state 12 sl@0: // sl@0: ARRAY_LENGTH(table12), sl@0: &table12[0] sl@0: } sl@0: }; sl@0: sl@0: sl@0: // sl@0: // Root of the state modifier tables sl@0: // sl@0: LOCAL_D const SFuncTables FuncTables= sl@0: { sl@0: { sl@0: // sl@0: // The default processing table sl@0: // sl@0: ARRAY_LENGTH(defaultTable), sl@0: &defaultTable[0] sl@0: }, sl@0: { sl@0: // sl@0: // The modifier control table sl@0: // sl@0: ARRAY_LENGTH(modifierTable), sl@0: &modifierTable[0] sl@0: }, sl@0: // sl@0: // The state control tables sl@0: // sl@0: ARRAY_LENGTH(genFuncTables), sl@0: &genFuncTables[0] sl@0: }; sl@0: sl@0: sl@0: // sl@0: // The following exported functions give the key translator access to sl@0: // the control tables above sl@0: // sl@0: EXPORT_C void KeyDataSettings(TRadix &aRadix,TCtrlDigitsTermination &aCtrlDigitsTermination,TInt &aDefaultCtrlDigitsMaxCount, sl@0: TInt &aMaximumCtrlDigitsMaxCount) sl@0: { sl@0: aRadix=EDecimal; sl@0: aCtrlDigitsTermination=ETerminationByCtrlUp; sl@0: aDefaultCtrlDigitsMaxCount=3; sl@0: aMaximumCtrlDigitsMaxCount=10; sl@0: } sl@0: sl@0: EXPORT_C void KeyDataFuncTable(SFuncTables &aFuncTables) sl@0: { sl@0: aFuncTables=FuncTables; sl@0: } sl@0: sl@0: EXPORT_C void KeyDataConvTable(SConvTable &aConvTable, TUint &aConvTableFirstScanCode,TUint &aConvTableLastScanCode, sl@0: SScanCodeBlockList &aKeypadScanCode,SKeyCodeList &aNonAutorepKeyCodes) sl@0: { sl@0: aConvTable=ConvTable; sl@0: aConvTableFirstScanCode=scanCodeBlock_base[0].firstScanCode; sl@0: aConvTableLastScanCode=scanCodeBlock_base[ARRAY_LENGTH(scanCodeBlock_base)-1].lastScanCode; sl@0: aKeypadScanCode=ConvTableKeypadScanCodes; sl@0: aNonAutorepKeyCodes=ConvTableNonAutorepKeyCodes; sl@0: }