javauis/lcdui_akn/lcdui/src/CMIDKeyDecoder.cpp
branchRCL_3
changeset 19 04becd199f91
child 29 0561add730c4
child 71 d5e927d5853b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdui/src/CMIDKeyDecoder.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,715 @@
+/*
+* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  ?Description
+*
+*/
+
+// CEikonEnv API used for retrieving resource (resId) in GetKeyName function
+#include <eikenv.h>
+// macros for resources
+#include <lcdui.rsg>
+// FeatureManager
+#include <featmgr.h>
+#include <bldvariant.hrh>
+
+#include <j2me/jdebug.h>
+/**
+@page Key Mapping.
+*/
+
+// used for retrieving CR repository codes
+#include <centralrepository.h>
+// S60 LCDUI Plugin internal keys
+#include "S60LCDUIInternalCRKeys.h"
+
+#include "CMIDKeyDecoder.h"
+// used for getting instance of ourselves from TlsStruct
+#include "CMIDMenuHandler.h"
+// using API for iRemConObserver initialization
+#include "CMIDRemConObserver.h"
+// using constants from enumeration TMediaKey (in InitSpecialKeysL)
+#include "MMIDMediaKeysListener.h"
+#include "CMIDDisplayable.h"
+#include "CMIDUIManager.h"
+
+/**
+ * MIDP key codes for keys that have no corresponding
+ * Unicode character, as from MIDP specs negative values
+ * must be used.
+ *
+ * ALL characters with code >= ENonCharacterKeyBase
+ * should be mapped to -ve numbers (see e32keys.h)
+ */
+const TInt KMIDKeyUpArrow                       = -1;
+const TInt KMIDKeyDownArrow                     = -2;
+const TInt KMIDKeyLeftArrow                     = -3;
+const TInt KMIDKeyRightArrow                    = -4;
+const TInt KMIDKeyClear                         = -8;  // Clear key
+const TInt KMIDKeySelect                        = -5;  // Selection key
+const TInt KMIDKeyEdit                          = -50; // Edit Key
+const TInt KMIDKeySend                          = -10; // Send Key
+const TInt KMIDKeyCBA1                          = -6;  // Left CBA
+const TInt KMIDKeyCBA2                          = -7;  // Right CBA
+const TInt KMIDKeyEnd                           = -11; // End key
+const TInt KMIDKeyApplications                  = -12; // Applications key
+const TInt KMIDKeyVoiceKey                      = -13; // Voice key
+//const TInt KMIDKeyClockWiseRotate               = -16; // not used at the moment
+//const TInt KMIDKeyCounterClockWiseRotate        = -17; // not used at the moment
+//const TInt KMIDKeyClockWiseFastRotate           = -18; // not used at the moment
+//const TInt KMIDKeyCounterClockWiseFastRotate    = -19; // not used at the moment
+const TInt KMIDKeyZoomIn                        = -EKeyZoomIn;  // Negative value (-63582)
+const TInt KMIDKeyZoomOut                       = -EKeyZoomOut; // Negative value (-63583)
+
+/** The number of game actions */
+const TInt KNumGameActions = 9;
+
+/** The max number of scan codes per game action */
+const TInt KMaxScanCodesPerAction = 16;
+
+/** The MIDP game action codes, this array must have the same index as
+    KDefaultActionScanCodes and KActionKeys.*/
+const TInt KActionCodes[KNumGameActions] =
+{
+    MMIDUtils::EActionUp,
+    MMIDUtils::EActionDown,
+    MMIDUtils::EActionLeft,
+    MMIDUtils::EActionRight,
+    MMIDUtils::EActionFire,
+
+    MMIDUtils::EActionGameA,
+    MMIDUtils::EActionGameB,
+    MMIDUtils::EActionGameC,
+    MMIDUtils::EActionGameD
+};
+
+
+/** The MIDP game action keys in the central repository.
+These are used to override the default scan codes.
+This array must have the same index as KActionCodes.
+*/
+const TUint32 KActionKeys[KNumGameActions] =
+{
+    KScanCodeUp,
+    KScanCodeDown,
+    KScanCodeLeft,
+    KScanCodeRight,
+    KScanCodeFire,
+    KScanCodeGameA,
+    KScanCodeGameB,
+    KScanCodeGameC,
+    KScanCodeGameD
+};
+
+
+/** Default scan codes for game actions. These are only used when
+    the scan codes in the central repository have not been set.
+
+    Because for each action there can be one or more code, use a zero
+    to indicate that there are no more codes.
+
+    This array must have the same index as KActionCodes.
+
+    @see CR keys, ConstructL()
+ */
+
+// ITU-T keypad with standard grid layout.
+const TInt KDefaultActionScanCodes[] =
+{
+    EStdKeyUpArrow, '2', 0,              // EActionUp
+    EStdKeyDownArrow, '8', 0,            // EActionDown
+    EStdKeyLeftArrow, '4', 0,            // EActionLeft
+    EStdKeyRightArrow, '6', 0,           // EActionRight
+    EStdKeyDevice3, EStdKeyYes, '5', 0,  // EActionFire
+
+    '7', 0,                             // EActionGameA
+    '9', 0,                             // EActionGameB
+    EStdKeyNkpAsterisk, '*', 0,         // EActionGameC
+    EStdKeyHash, 0                      // EActionGameD
+};
+
+// Full QWERTY keyboard with screen in the middle (Table 14 in internal specs)
+const TInt KDefaultQwertyActionScanCodes[] =
+{
+    EStdKeyUpArrow, 'R', 'P', 0,                   // EActionUp
+    EStdKeyDownArrow, 'V', EStdKeyForwardSlash, 0, // EActionDown
+    EStdKeyLeftArrow, 'D', 'L', 0,                 // EActionLeft
+    EStdKeyRightArrow, 'G', EStdKeySingleQuote, 0, // EActionRight
+    'A', 'J', EStdKeyDevice3, 0,                   // EActionFire
+
+    EStdKeyHash, 'H', 0,                     // EActionGameA
+    'S', 'K', 0,                             // EActionGameB
+    'Q', 'U', 0,                             // EActionGameC
+    'Z', 'M', 0                              // EActionGameD
+};
+
+
+
+/** Usual symbian two phase construction. @see ConstructL() */
+CMIDKeyDecoder* CMIDKeyDecoder::NewL(MMIDEnv& aEnv)
+{
+    CMIDKeyDecoder* self = new(ELeave) CMIDKeyDecoder(aEnv);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+}
+
+/** */
+CMIDKeyDecoder::~CMIDKeyDecoder()
+{
+    DEBUG("< CMIDKeyDecoder::~CMIDKeyDecoder");
+    iSpecialKeys.Close();
+    iGameActions.ResetAndDestroy();
+
+    delete iCaptureKeys;
+    delete iKeyTranslator;
+
+    delete iQwertyWatch;
+
+    if (iUseCRScanCodes)
+    {
+        delete iActionScanCodes;
+    }
+
+    FeatureManager::UnInitializeLib();
+
+    delete iRemConObserver;
+
+    DEBUG("> CMIDKeyDecoder::~CMIDKeyDecoder");
+}
+
+/** */
+CMIDKeyDecoder::CMIDKeyDecoder(MMIDEnv& aEnv)
+        : iEnv(aEnv)
+        ,iMediaKeysEnabled(EFalse)
+{
+    DEBUG("< CMIDKeyDecoder::CMIDKeyDecoder");
+    DEBUG("> CMIDKeyDecoder::CMIDKeyDecoder");
+}
+
+/**
+Creates the key translator and another accessory, the capture keys
+(needed by the key translator). The key translator can convert scan codes
+into key codes. Calls CreateGameActionsL(), which will fill iGameActions:
+for each action a set of key codes will be stored. These are MIDP key codes.
+*/
+void CMIDKeyDecoder::ConstructL()
+{
+    DEBUG("< CMIDKeyDecoder::ConstructL");
+
+    iCaptureKeys = new(ELeave) CCaptureKeys;
+    iCaptureKeys->Construct();
+
+    iKeyTranslator = CKeyTranslator::New();
+
+    // If Select key mapping is defined in central repository an extra MIDP
+    // keycode will be used for Select key.
+    // Not all the devices have rocker in their keyboard,
+    // so other key can be defined instead.
+    CRepository* repository = NULL;
+    TInt err = KErrNone;
+    TRAP(err, repository = CRepository::NewL(KCRUidMidpLcdui));
+    // 2 bytes in scan code
+    TBuf8<2> scanCodeBuffer;
+    CleanupStack::PushL(repository);
+    err = repository->Get(KAdditionalSelectKeyMapping,scanCodeBuffer);
+    CleanupStack::PopAndDestroy(repository);
+    if (err == KErrNone)
+    {
+        TUint8 scanCodeLeft = scanCodeBuffer[0];
+        TUint8 scanCodeRight = scanCodeBuffer[1];
+        TUint scanCode = (scanCodeLeft << 8) + scanCodeRight;
+        if (scanCode != 0)
+        {
+            iAdditionalSelectkeyMapping = scanCode;
+        }
+    }
+
+    CreateQwertyWatchL();
+    CreateGameActionsL();
+
+    FeatureManager::InitializeLibL();
+
+    if (iEnv.MidletAttributeContainsVal(
+                LcduiMidletAttributes::KAttribUIEnhancement,
+                LcduiMidletAttributeValues::KUIEnhMediaKeys))
+    {
+        InitRemConObserverL();
+        iMediaKeysEnabled = ETrue;
+    }
+
+    DEBUG("> CMIDKeyDecoder::ConstructL");
+}
+
+/**
+Special keys that require separate handling: these are
+either non unicode keys or non standard unicode keys.
+For standard unicode keys, the MIDP key code is the
+unicode charactler. */
+
+void CMIDKeyDecoder::InitSpecialKeysL()
+{
+    iSpecialKeys.Reset();
+
+    // Keys shared by ITU-T and QWERTY modes
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftArrow,   KMIDKeyLeftArrow,  R_MIDP_KEY_LEFT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightArrow,  KMIDKeyRightArrow, R_MIDP_KEY_RIGHT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyUpArrow,     KMIDKeyUpArrow,    R_MIDP_KEY_UP)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDownArrow,   KMIDKeyDownArrow,  R_MIDP_KEY_DOWN)));
+    // If Select key mapping is defined in central repository an extra MIDP keycode will be used for Select key.
+    if (iAdditionalSelectkeyMapping != 0)
+    {
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(iAdditionalSelectkeyMapping, KMIDKeySelect, R_MIDP_KEY_SELECT)));
+    }
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice3,     KMIDKeySelect,       R_MIDP_KEY_SELECT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightShift,  KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftShift,   KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyF21,         KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftFunc,    KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightFunc,   KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
+
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyYes,         KMIDKeySend,         R_MIDP_KEY_SEND)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice0,     KMIDKeyCBA1,         R_MIDP_KEY_LSK)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice1,     KMIDKeyCBA2,         R_MIDP_KEY_RSK)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNo,          KMIDKeyEnd,          R_MIDP_KEY_END)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyApplication0,KMIDKeyApplications, R_MIDP_KEY_APPS)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice6,     KMIDKeyVoiceKey,     R_MIDP_KEY_VOICE)));
+    // QWERTY keys for qwerty  and ITU-T mode with qwerty wireless keyboard.
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeySpace,EKeySpace, R_MIDP_KEY_SPACE)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyEscape,EKeyEscape, R_MIDP_KEY_ESC)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyTab,EKeyTab, R_MIDP_KEY_TAB)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyEnter, EKeyLineFeed, R_MIDP_KEY_ENTER)));
+    // Diagonal keys for 9-way Navigation Support
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice10, EKeyLeftUpArrow, R_MIDP_KEY_LEFT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice11,EKeyRightUpArrow, R_MIDP_KEY_RIGHT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice12,EKeyRightDownArrow, R_MIDP_KEY_RIGHT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice13,EKeyLeftDownArrow, R_MIDP_KEY_LEFT)));
+    User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDelete,EKeyDelete, R_MIDP_KEY_DELETE)));
+    if (!iQwertyModeActive)
+    { // ITU-T keys with different behaviour
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyBackspace, KMIDKeyClear, R_MIDP_KEY_CLEAR)));
+    }
+    else
+    { // QWERTY  keys with different behaviour
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyBackspace, EKeyBackspace, R_MIDP_KEY_BACKSPACE)));
+    }
+
+    /*
+        // Keys defined in specs but not yet present in Series 60
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyFormFeed, R_MIDP_KEY_FORM_FEED)));
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyLineFeed, R_MIDP_KEY_LINE_FEED)));
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyBell, R_MIDP_KEY_BELL)));
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyVerticalTab, R_MIDP_KEY_VERTICAL_TAB)));
+
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyClockWiseRotate, R_MIDP_KEY_CLOCKWISE_ROTATE)));
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyCounterClockWiseRotate, R_MIDP_KEY_COUNTER_CLOCKWISE_ROTATE)));
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyClockWiseFastRotate, R_MIDP_KEY_CLOCKWISE_FAST_ROTATE)));
+        User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyCounterClockWiseFastRotate, R_MIDP_KEY_COUNTER_CLOCKWISE_FAST_ROTATE)));
+    */
+
+    // Add media keys. These are used only in GetKeyName method.
+    // EStdKeyNull used as a scancode as media keys don't have a real scancode.
+    User::LeaveIfError(iSpecialKeys.Append(
+                           TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyPlay,     R_MIDP_KEY_PLAY)));
+    User::LeaveIfError(iSpecialKeys.Append(
+                           TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyPrevious, R_MIDP_KEY_PREVIOUS)));
+    User::LeaveIfError(iSpecialKeys.Append(
+                           TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyNext,     R_MIDP_KEY_NEXT)));
+    User::LeaveIfError(iSpecialKeys.Append(
+                           TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyStop,     R_MIDP_KEY_STOP)));
+
+    // Zoom in and zoom out keys events support
+    User::LeaveIfError(iSpecialKeys.Append(
+                           TMIDKey(EStdKeyApplicationC, KMIDKeyZoomIn, R_MIDP_KEY_ZOOM_IN)));
+    User::LeaveIfError(iSpecialKeys.Append(
+                           TMIDKey(EStdKeyApplicationD, KMIDKeyZoomOut, R_MIDP_KEY_ZOOM_OUT)));
+};
+
+
+
+/**  */
+void CMIDKeyDecoder::CreateQwertyWatchL()
+{
+    iQwertyWatch = CMIDQwertyWatch::NewL(this);
+}
+
+
+void CMIDKeyDecoder::InitRemConObserverL()
+{
+    if (!iRemConObserver)
+    {
+        iRemConObserver = CMIDRemConObserver::NewL();
+    }
+}
+
+/** */
+void CMIDKeyDecoder::NewQwertyValueL(TInt aNewValue)
+{
+    TBool oldQwertyMode = iQwertyModeActive;
+
+    if (aNewValue == 1)
+    {
+        iQwertyModeActive = ETrue;
+    }
+    else
+    {
+        iQwertyModeActive = EFalse;
+    }
+
+    if (iQwertyModeActive != oldQwertyMode)
+    {
+        CreateGameActionsL();
+    }
+}
+
+/**
+ * Gets a key code that corresponds to the specified game action on the device.
+ * The implementation is required to provide a mapping for every game action,
+ * so this method will always return a valid key code for every game action.
+ *
+ * Note that a key code is associated with at most one game action, whereas a
+ * game action may be associated with several key codes.
+ *
+ * Returns zero if aGameAction is not a valid game action
+ */
+TInt CMIDKeyDecoder::GetKeyCode(TInt aGameAction)
+{
+    DEBUG_INT("< CMIDKeyDecoder::GetKeyCode - game action is %D", aGameAction);
+    for (TInt i = 0; i < KNumGameActions; ++i)
+    {
+        if (iGameActions[i]->iActionCode == aGameAction)
+        {
+            DEBUG_INT("> CMIDKeyDecoder::GetKeyCode - return code %D", iGameActions[i]->iCodes[0]);
+            return iGameActions[i]->iCodes[0]; //just return the first code
+        }
+    }
+
+    DEBUG_INT("> CMIDKeyDecoder::GetKeyCode - return code %D", 0);
+    return 0;
+}
+
+/**
+ * Maps EPOC scan code to negative key code required by MIDP spec.
+ * For keys that have no corresponding Unicode character,
+ * the implementation must use negative values.
+ */
+TInt CMIDKeyDecoder::MapNonUnicodeKey(TUint aScanCode)
+{
+    DEBUG_INT("< CMIDKeyDecoder::MapNonUnicodeKey - scan code is %D", aScanCode);
+    TInt numSpecialKeys = iSpecialKeys.Count();
+    for (TInt i = 0; i < numSpecialKeys; i++)
+    {
+        if (iSpecialKeys[i].iScanCode == aScanCode)
+        {
+            DEBUG_INT("> CMIDKeyDecoder::MapNonUnicodeKey - return code is %D", iSpecialKeys[i].iMIDPCode);
+            return iSpecialKeys[i].iMIDPCode;
+        }
+    }
+
+    DEBUG_INT("> CMIDKeyDecoder::MapNonUnicodeKey - return code is %D", 0);
+    return 0;
+}
+
+/**
+ * Gets an informative key string for a key. The string returned will resemble the text
+ * physically printed on the key. This string is suitable for displaying to the user.
+ * For example, on a device with function keys F1 through F4, calling this method on
+ * the keyCode for the F1 key will return the string "F1". A typical use for this string
+ * will be to compose help text such as "Press F1 to proceed."
+ *
+ * This method will return a non-empty string for every valid key code.
+ *
+ */
+void CMIDKeyDecoder::GetKeyName(TDes& aText,TInt aKeyCode)
+{
+    DEBUG_INT("< CMIDKeyDecoder::GetKeyName - key code is %D", aKeyCode);
+    aText.Zero();
+
+    TInt resId = R_MIDP_KEY_NON_CHARACTER;
+    TInt numSpecialKeys = iSpecialKeys.Count();
+    for (TInt i = 0; i < numSpecialKeys; i++)
+    {
+        if (iSpecialKeys[i].iMIDPCode == aKeyCode)
+        {
+            resId = iSpecialKeys[i].iNameResId;
+            break;
+        }
+    }
+
+    if ((resId == R_MIDP_KEY_NON_CHARACTER) && (IsUnicode(aKeyCode)))
+    {
+        aText.Append(TChar(aKeyCode));
+    }
+    else
+    {
+        CEikonEnv::Static()->ReadResource(aText,resId);
+    }
+
+    DEBUG_STR("> CMIDKeyDecoder::GetKeyName - key name is %S", aText);
+}
+
+
+TInt CMIDKeyDecoder::GameAction(TInt aKeyCode)
+{
+    DEBUG_INT("< CMIDKeyDecoder::GameAction - key code is %D", aKeyCode);
+
+    for (TInt i = 0; i < KNumGameActions; ++i)
+    {
+        TInt numCodes = iGameActions[i]->iCodes.Count();
+        for (TInt j = 0; j < numCodes; ++j)
+        {
+            if (iGameActions[i]->iCodes[j] == aKeyCode)
+            {
+                DEBUG_INT("> CMIDKeyDecoder::GameAction -game action is %D", iGameActions[i]->iActionCode);
+                return iGameActions[i]->iActionCode;
+            }
+        }
+    }
+
+    DEBUG_INT("> CMIDKeyDecoder::GameAction -game action is %D", 0);
+    return 0; //invalid action
+}
+
+/**
+ * Determines if a key code should be sent to MIDP applications.
+ */
+TBool CMIDKeyDecoder::IsJavaKey(TInt aScanCode)
+{
+    TBool ret = (ScanToMidpCode(aScanCode) != 0);
+
+    DEBUG_INT2("<> CMIDKeyDecoder::IsJavaKey - return %D for scan code %D", ret, aScanCode);
+    return ret;
+}
+
+TBool CMIDKeyDecoder::MediaKeysEnabled() const
+{
+    return iMediaKeysEnabled;
+}
+
+CMIDRemConObserver* CMIDKeyDecoder::GetRemConObserver()
+{
+    return iRemConObserver;
+}
+
+/** Create the game actions. This method is called at startup and
+each time the qwerty availability changes. Because special keys
+also depend on qwerty availability, call InitSpecialKeysL() -
+which will reset special keys. The reset the actions and call
+LoadGameActionCodesL() - which loads the correct codes. Then
+for each action appens the codes stored in iActionScanCodes.
+Action codes in this array are separated by a null byte. */
+void CMIDKeyDecoder::CreateGameActionsL()
+{
+    DEBUG("< CMIDKeyDecoder::CreateGameActionsL");
+
+    InitSpecialKeysL();
+    iGameActions.ResetAndDestroy();
+
+    LoadGameActionCodesL();
+    ASSERT(iActionScanCodes != NULL);
+
+    TInt index = 0;
+    for (TInt i = 0; i < KNumGameActions; ++i)
+    {
+        TMIDGameAction* action = new(ELeave) TMIDGameAction(KActionCodes[i]);
+        CleanupStack::PushL(action);
+
+        while (iActionScanCodes[index] != 0)
+        {
+            AddCodeToActionL(action, iActionScanCodes[index]);
+            index++;
+        }
+        index++;    // skip null byte separating actions
+
+        User::LeaveIfError(iGameActions.Append(action));
+        CleanupStack::Pop(action);
+    }
+
+    DEBUG("> CMIDKeyDecoder::CreateGameActionsL");
+}
+
+/** Load the game action codes: either the default ITU-T codes
+    if no qwerty input is available or load the codes
+    from Central Repository (if available and if
+    flag in CR indicates to do so) or load some default QWERTY codes.
+*/
+void CMIDKeyDecoder::LoadGameActionCodesL()
+{
+    DEBUG("< CMIDKeyDecoder::LoadGameActionCodesL");
+
+    if (iUseCRScanCodes)
+    {
+        delete iActionScanCodes;
+        iUseCRScanCodes = EFalse;
+    }
+
+    iActionScanCodes = NULL;
+
+    if (!QwertyInputAvailable())
+    { // if no qwerty always use default ITU-T codes
+        DEBUG("  CMIDKeyDecoder::LoadGameActionCodesL - use default ITU-T scan codes");
+        iActionScanCodes = (TInt*)&KDefaultActionScanCodes[0];
+    }
+    else
+    { // if there is qwerty either use CR repository codes or default qwerty codes
+        CRepository* repository = NULL;
+        TRAPD(crExists, repository = CRepository::NewL(KCRUidMidpLcdui));
+
+        if (crExists == KErrNone)
+        {
+            CleanupStack::PushL(repository);
+            repository->Get(KUseCustomGameActionScanCodes, iUseCRScanCodes);
+        }
+
+        if (iUseCRScanCodes)
+        { // use CR QWERTY codes
+            DEBUG("  CMIDKeyDecoder::LoadGameActionCodesL - use central repository scan codes");
+            LoadCentralRepositoryCodesL(repository);
+        }
+        else
+        { //  use default QWERTY codes
+            DEBUG("  CMIDKeyDecoder::LoadGameActionCodesL - add default qwerty scan codes");
+            iActionScanCodes = (TInt*)&KDefaultQwertyActionScanCodes[0];
+        }
+
+        if (crExists == KErrNone)
+        {
+            CleanupStack::PopAndDestroy(repository);
+        }
+    }
+
+    DEBUG("> CMIDKeyDecoder::LoadGameActionCodesL");
+}
+
+/** Load the game action scan codes stored in the central repository
+    database. Two bytes are available per scan code, LSB is left. Max
+    number of codes per action is KMaxScanCodesPerAction. Allocate
+    some memory for iActionScanCodes.
+    */
+void CMIDKeyDecoder::LoadCentralRepositoryCodesL(CRepository* aRepository)
+{
+    DEBUG("< CMIDKeyDecoder::LoadCentralRepositoryCodesL");
+
+    ASSERT(aRepository != NULL);
+    ASSERT(iActionScanCodes == NULL);
+
+    iActionScanCodes = new(ELeave) TInt[KNumGameActions*KMaxScanCodesPerAction];
+
+    TInt index = 0;
+    for (TInt i = 0; i < KNumGameActions; ++i)
+    {
+        //2 bytes per scan code
+        TBuf8<KMaxScanCodesPerAction*2> scanCodeBuffer;
+        aRepository->Get(KActionKeys[i],scanCodeBuffer);
+
+        for (TInt j = 0; j < (scanCodeBuffer.Length() - 1); j++)
+        {
+            TUint8 scanCodeLeft = scanCodeBuffer[j++];
+            TUint8 scanCodeRight = scanCodeBuffer[j];
+
+            TUint scanCode = (scanCodeLeft << 8) + scanCodeRight;
+
+            if (scanCode != 0)
+            {
+                iActionScanCodes[index++] = scanCode;
+            }
+        }
+
+        iActionScanCodes[index++] = 0;   //indicates end of scan codes
+    }
+
+    DEBUG("> CMIDKeyDecoder::LoadCentralRepositoryCodesL");
+}
+
+/** Return true if this device supports qwerty and the qwerty keyboard
+    is available */
+TBool CMIDKeyDecoder::QwertyInputAvailable() const
+{
+    return iQwertyModeActive;
+}
+
+/**
+    Convert the scan code into a MIDP key code taking into account possible
+    modifiers. Add the resulting MIDP key codes to the action specified as long
+    as they are all different.
+  */
+void CMIDKeyDecoder::AddCodeToActionL(TMIDGameAction* aGameAction, TInt aScanCode)
+{
+    DEBUG_INT("< CMIDKeyDecoder::AddCodeToActionL - scan code is %D", aScanCode);
+    TInt midpCode = ScanToMidpCode(aScanCode);
+
+    if (aGameAction->iCodes.Find(midpCode) == KErrNotFound && midpCode != 0)
+    {
+        DEBUG_INT("  CMIDKeyDecoder::AddCodeToActionL - adding midp code %D", midpCode);
+        User::LeaveIfError(aGameAction->iCodes.Append(midpCode));
+    }
+
+    if (IsUnicode(midpCode))
+    {
+        midpCode = ScanToMidpCode(aScanCode | EModifierShift);
+
+        if (aGameAction->iCodes.Find(midpCode) == KErrNotFound)
+        {
+            DEBUG_INT("  CMIDKeyDecoder::AddCodeToActionL - adding midp code %D", midpCode);
+            User::LeaveIfError(aGameAction->iCodes.Append(midpCode));
+        }
+    }
+
+    DEBUG("> CMIDKeyDecoder::AddCodeToActionL");
+}
+
+/** Take a scan code and convert it into a MIDP code. First see if it
+is one of the special keys, otherwise ask the window server to convert it. */
+TInt CMIDKeyDecoder::ScanToMidpCode(TInt aScanCode)
+{
+    DEBUG_INT("< CMIDKeyDecoder::ScanToMidpCode - scan Code is %D", aScanCode);
+    TInt keyCode = MapNonUnicodeKey(aScanCode);
+
+    if (keyCode == 0)
+    {
+        // fake a key down to convert scan code into key code
+        // Note: on WINS (and WINSCW) this conversion works only for QWERTY layout
+        // unless you specify the char code in the HI part of the scan code - which
+        // we cannot do - hence on the emulator only QWERTY layout works.
+        TKeyData keyData;
+        TBool translated = iKeyTranslator->TranslateKey(aScanCode,EFalse,*iCaptureKeys,keyData);
+
+        if (translated)
+        {
+            DEBUG_INT("  CMIDKeyDecoder::ScanToMidpCode - ws translated code is %D", keyData.iKeyCode);
+            keyCode = IsUnicode(keyData.iKeyCode) ? keyData.iKeyCode : 0;
+        }
+
+        // fake a key up to restore modifiers
+        iKeyTranslator->TranslateKey(aScanCode,ETrue,*iCaptureKeys,keyData);
+    }
+
+    DEBUG_INT("> CMIDKeyDecoder::ScanToMidpCode - return key code %D", keyCode);
+    return keyCode;
+}
+
+/** Return true if the key code corresponds to a unicode character */
+TBool CMIDKeyDecoder::IsUnicode(TInt aKeyCode) const
+{
+    TBool ret = (aKeyCode > 0) && (aKeyCode < ENonCharacterKeyBase ||
+                                   aKeyCode >= (ENonCharacterKeyBase + ENonCharacterKeyCount));
+
+    DEBUG_INT2("<> CMIDKeyDecoder::IsUnicode - return %D for key code %D", ret, aKeyCode);
+    return ret;
+}
+
+TInt CMIDKeyDecoder::AdditionalSelectionKeyMappingCode()
+{
+    return iAdditionalSelectkeyMapping;
+}