javauis/lcdui_akn/lcdui/src/CMIDKeyDecoder.cpp
branchRCL_3
changeset 19 04becd199f91
child 29 0561add730c4
child 71 d5e927d5853b
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 // CEikonEnv API used for retrieving resource (resId) in GetKeyName function
       
    19 #include <eikenv.h>
       
    20 // macros for resources
       
    21 #include <lcdui.rsg>
       
    22 // FeatureManager
       
    23 #include <featmgr.h>
       
    24 #include <bldvariant.hrh>
       
    25 
       
    26 #include <j2me/jdebug.h>
       
    27 /**
       
    28 @page Key Mapping.
       
    29 */
       
    30 
       
    31 // used for retrieving CR repository codes
       
    32 #include <centralrepository.h>
       
    33 // S60 LCDUI Plugin internal keys
       
    34 #include "S60LCDUIInternalCRKeys.h"
       
    35 
       
    36 #include "CMIDKeyDecoder.h"
       
    37 // used for getting instance of ourselves from TlsStruct
       
    38 #include "CMIDMenuHandler.h"
       
    39 // using API for iRemConObserver initialization
       
    40 #include "CMIDRemConObserver.h"
       
    41 // using constants from enumeration TMediaKey (in InitSpecialKeysL)
       
    42 #include "MMIDMediaKeysListener.h"
       
    43 #include "CMIDDisplayable.h"
       
    44 #include "CMIDUIManager.h"
       
    45 
       
    46 /**
       
    47  * MIDP key codes for keys that have no corresponding
       
    48  * Unicode character, as from MIDP specs negative values
       
    49  * must be used.
       
    50  *
       
    51  * ALL characters with code >= ENonCharacterKeyBase
       
    52  * should be mapped to -ve numbers (see e32keys.h)
       
    53  */
       
    54 const TInt KMIDKeyUpArrow                       = -1;
       
    55 const TInt KMIDKeyDownArrow                     = -2;
       
    56 const TInt KMIDKeyLeftArrow                     = -3;
       
    57 const TInt KMIDKeyRightArrow                    = -4;
       
    58 const TInt KMIDKeyClear                         = -8;  // Clear key
       
    59 const TInt KMIDKeySelect                        = -5;  // Selection key
       
    60 const TInt KMIDKeyEdit                          = -50; // Edit Key
       
    61 const TInt KMIDKeySend                          = -10; // Send Key
       
    62 const TInt KMIDKeyCBA1                          = -6;  // Left CBA
       
    63 const TInt KMIDKeyCBA2                          = -7;  // Right CBA
       
    64 const TInt KMIDKeyEnd                           = -11; // End key
       
    65 const TInt KMIDKeyApplications                  = -12; // Applications key
       
    66 const TInt KMIDKeyVoiceKey                      = -13; // Voice key
       
    67 //const TInt KMIDKeyClockWiseRotate               = -16; // not used at the moment
       
    68 //const TInt KMIDKeyCounterClockWiseRotate        = -17; // not used at the moment
       
    69 //const TInt KMIDKeyClockWiseFastRotate           = -18; // not used at the moment
       
    70 //const TInt KMIDKeyCounterClockWiseFastRotate    = -19; // not used at the moment
       
    71 const TInt KMIDKeyZoomIn                        = -EKeyZoomIn;  // Negative value (-63582)
       
    72 const TInt KMIDKeyZoomOut                       = -EKeyZoomOut; // Negative value (-63583)
       
    73 
       
    74 /** The number of game actions */
       
    75 const TInt KNumGameActions = 9;
       
    76 
       
    77 /** The max number of scan codes per game action */
       
    78 const TInt KMaxScanCodesPerAction = 16;
       
    79 
       
    80 /** The MIDP game action codes, this array must have the same index as
       
    81     KDefaultActionScanCodes and KActionKeys.*/
       
    82 const TInt KActionCodes[KNumGameActions] =
       
    83 {
       
    84     MMIDUtils::EActionUp,
       
    85     MMIDUtils::EActionDown,
       
    86     MMIDUtils::EActionLeft,
       
    87     MMIDUtils::EActionRight,
       
    88     MMIDUtils::EActionFire,
       
    89 
       
    90     MMIDUtils::EActionGameA,
       
    91     MMIDUtils::EActionGameB,
       
    92     MMIDUtils::EActionGameC,
       
    93     MMIDUtils::EActionGameD
       
    94 };
       
    95 
       
    96 
       
    97 /** The MIDP game action keys in the central repository.
       
    98 These are used to override the default scan codes.
       
    99 This array must have the same index as KActionCodes.
       
   100 */
       
   101 const TUint32 KActionKeys[KNumGameActions] =
       
   102 {
       
   103     KScanCodeUp,
       
   104     KScanCodeDown,
       
   105     KScanCodeLeft,
       
   106     KScanCodeRight,
       
   107     KScanCodeFire,
       
   108     KScanCodeGameA,
       
   109     KScanCodeGameB,
       
   110     KScanCodeGameC,
       
   111     KScanCodeGameD
       
   112 };
       
   113 
       
   114 
       
   115 /** Default scan codes for game actions. These are only used when
       
   116     the scan codes in the central repository have not been set.
       
   117 
       
   118     Because for each action there can be one or more code, use a zero
       
   119     to indicate that there are no more codes.
       
   120 
       
   121     This array must have the same index as KActionCodes.
       
   122 
       
   123     @see CR keys, ConstructL()
       
   124  */
       
   125 
       
   126 // ITU-T keypad with standard grid layout.
       
   127 const TInt KDefaultActionScanCodes[] =
       
   128 {
       
   129     EStdKeyUpArrow, '2', 0,              // EActionUp
       
   130     EStdKeyDownArrow, '8', 0,            // EActionDown
       
   131     EStdKeyLeftArrow, '4', 0,            // EActionLeft
       
   132     EStdKeyRightArrow, '6', 0,           // EActionRight
       
   133     EStdKeyDevice3, EStdKeyYes, '5', 0,  // EActionFire
       
   134 
       
   135     '7', 0,                             // EActionGameA
       
   136     '9', 0,                             // EActionGameB
       
   137     EStdKeyNkpAsterisk, '*', 0,         // EActionGameC
       
   138     EStdKeyHash, 0                      // EActionGameD
       
   139 };
       
   140 
       
   141 // Full QWERTY keyboard with screen in the middle (Table 14 in internal specs)
       
   142 const TInt KDefaultQwertyActionScanCodes[] =
       
   143 {
       
   144     EStdKeyUpArrow, 'R', 'P', 0,                   // EActionUp
       
   145     EStdKeyDownArrow, 'V', EStdKeyForwardSlash, 0, // EActionDown
       
   146     EStdKeyLeftArrow, 'D', 'L', 0,                 // EActionLeft
       
   147     EStdKeyRightArrow, 'G', EStdKeySingleQuote, 0, // EActionRight
       
   148     'A', 'J', EStdKeyDevice3, 0,                   // EActionFire
       
   149 
       
   150     EStdKeyHash, 'H', 0,                     // EActionGameA
       
   151     'S', 'K', 0,                             // EActionGameB
       
   152     'Q', 'U', 0,                             // EActionGameC
       
   153     'Z', 'M', 0                              // EActionGameD
       
   154 };
       
   155 
       
   156 
       
   157 
       
   158 /** Usual symbian two phase construction. @see ConstructL() */
       
   159 CMIDKeyDecoder* CMIDKeyDecoder::NewL(MMIDEnv& aEnv)
       
   160 {
       
   161     CMIDKeyDecoder* self = new(ELeave) CMIDKeyDecoder(aEnv);
       
   162     CleanupStack::PushL(self);
       
   163     self->ConstructL();
       
   164     CleanupStack::Pop(self);
       
   165     return self;
       
   166 }
       
   167 
       
   168 /** */
       
   169 CMIDKeyDecoder::~CMIDKeyDecoder()
       
   170 {
       
   171     DEBUG("< CMIDKeyDecoder::~CMIDKeyDecoder");
       
   172     iSpecialKeys.Close();
       
   173     iGameActions.ResetAndDestroy();
       
   174 
       
   175     delete iCaptureKeys;
       
   176     delete iKeyTranslator;
       
   177 
       
   178     delete iQwertyWatch;
       
   179 
       
   180     if (iUseCRScanCodes)
       
   181     {
       
   182         delete iActionScanCodes;
       
   183     }
       
   184 
       
   185     FeatureManager::UnInitializeLib();
       
   186 
       
   187     delete iRemConObserver;
       
   188 
       
   189     DEBUG("> CMIDKeyDecoder::~CMIDKeyDecoder");
       
   190 }
       
   191 
       
   192 /** */
       
   193 CMIDKeyDecoder::CMIDKeyDecoder(MMIDEnv& aEnv)
       
   194         : iEnv(aEnv)
       
   195         ,iMediaKeysEnabled(EFalse)
       
   196 {
       
   197     DEBUG("< CMIDKeyDecoder::CMIDKeyDecoder");
       
   198     DEBUG("> CMIDKeyDecoder::CMIDKeyDecoder");
       
   199 }
       
   200 
       
   201 /**
       
   202 Creates the key translator and another accessory, the capture keys
       
   203 (needed by the key translator). The key translator can convert scan codes
       
   204 into key codes. Calls CreateGameActionsL(), which will fill iGameActions:
       
   205 for each action a set of key codes will be stored. These are MIDP key codes.
       
   206 */
       
   207 void CMIDKeyDecoder::ConstructL()
       
   208 {
       
   209     DEBUG("< CMIDKeyDecoder::ConstructL");
       
   210 
       
   211     iCaptureKeys = new(ELeave) CCaptureKeys;
       
   212     iCaptureKeys->Construct();
       
   213 
       
   214     iKeyTranslator = CKeyTranslator::New();
       
   215 
       
   216     // If Select key mapping is defined in central repository an extra MIDP
       
   217     // keycode will be used for Select key.
       
   218     // Not all the devices have rocker in their keyboard,
       
   219     // so other key can be defined instead.
       
   220     CRepository* repository = NULL;
       
   221     TInt err = KErrNone;
       
   222     TRAP(err, repository = CRepository::NewL(KCRUidMidpLcdui));
       
   223     // 2 bytes in scan code
       
   224     TBuf8<2> scanCodeBuffer;
       
   225     CleanupStack::PushL(repository);
       
   226     err = repository->Get(KAdditionalSelectKeyMapping,scanCodeBuffer);
       
   227     CleanupStack::PopAndDestroy(repository);
       
   228     if (err == KErrNone)
       
   229     {
       
   230         TUint8 scanCodeLeft = scanCodeBuffer[0];
       
   231         TUint8 scanCodeRight = scanCodeBuffer[1];
       
   232         TUint scanCode = (scanCodeLeft << 8) + scanCodeRight;
       
   233         if (scanCode != 0)
       
   234         {
       
   235             iAdditionalSelectkeyMapping = scanCode;
       
   236         }
       
   237     }
       
   238 
       
   239     CreateQwertyWatchL();
       
   240     CreateGameActionsL();
       
   241 
       
   242     FeatureManager::InitializeLibL();
       
   243 
       
   244     if (iEnv.MidletAttributeContainsVal(
       
   245                 LcduiMidletAttributes::KAttribUIEnhancement,
       
   246                 LcduiMidletAttributeValues::KUIEnhMediaKeys))
       
   247     {
       
   248         InitRemConObserverL();
       
   249         iMediaKeysEnabled = ETrue;
       
   250     }
       
   251 
       
   252     DEBUG("> CMIDKeyDecoder::ConstructL");
       
   253 }
       
   254 
       
   255 /**
       
   256 Special keys that require separate handling: these are
       
   257 either non unicode keys or non standard unicode keys.
       
   258 For standard unicode keys, the MIDP key code is the
       
   259 unicode charactler. */
       
   260 
       
   261 void CMIDKeyDecoder::InitSpecialKeysL()
       
   262 {
       
   263     iSpecialKeys.Reset();
       
   264 
       
   265     // Keys shared by ITU-T and QWERTY modes
       
   266     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftArrow,   KMIDKeyLeftArrow,  R_MIDP_KEY_LEFT)));
       
   267     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightArrow,  KMIDKeyRightArrow, R_MIDP_KEY_RIGHT)));
       
   268     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyUpArrow,     KMIDKeyUpArrow,    R_MIDP_KEY_UP)));
       
   269     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDownArrow,   KMIDKeyDownArrow,  R_MIDP_KEY_DOWN)));
       
   270     // If Select key mapping is defined in central repository an extra MIDP keycode will be used for Select key.
       
   271     if (iAdditionalSelectkeyMapping != 0)
       
   272     {
       
   273         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(iAdditionalSelectkeyMapping, KMIDKeySelect, R_MIDP_KEY_SELECT)));
       
   274     }
       
   275     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice3,     KMIDKeySelect,       R_MIDP_KEY_SELECT)));
       
   276     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightShift,  KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
       
   277     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftShift,   KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
       
   278     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyF21,         KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
       
   279     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftFunc,    KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
       
   280     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightFunc,   KMIDKeyEdit,         R_MIDP_KEY_EDIT)));
       
   281 
       
   282     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyYes,         KMIDKeySend,         R_MIDP_KEY_SEND)));
       
   283     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice0,     KMIDKeyCBA1,         R_MIDP_KEY_LSK)));
       
   284     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice1,     KMIDKeyCBA2,         R_MIDP_KEY_RSK)));
       
   285     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNo,          KMIDKeyEnd,          R_MIDP_KEY_END)));
       
   286     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyApplication0,KMIDKeyApplications, R_MIDP_KEY_APPS)));
       
   287     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice6,     KMIDKeyVoiceKey,     R_MIDP_KEY_VOICE)));
       
   288     // QWERTY keys for qwerty  and ITU-T mode with qwerty wireless keyboard.
       
   289     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeySpace,EKeySpace, R_MIDP_KEY_SPACE)));
       
   290     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyEscape,EKeyEscape, R_MIDP_KEY_ESC)));
       
   291     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyTab,EKeyTab, R_MIDP_KEY_TAB)));
       
   292     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyEnter, EKeyLineFeed, R_MIDP_KEY_ENTER)));
       
   293     // Diagonal keys for 9-way Navigation Support
       
   294     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice10, EKeyLeftUpArrow, R_MIDP_KEY_LEFT)));
       
   295     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice11,EKeyRightUpArrow, R_MIDP_KEY_RIGHT)));
       
   296     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice12,EKeyRightDownArrow, R_MIDP_KEY_RIGHT)));
       
   297     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice13,EKeyLeftDownArrow, R_MIDP_KEY_LEFT)));
       
   298     User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDelete,EKeyDelete, R_MIDP_KEY_DELETE)));
       
   299     if (!iQwertyModeActive)
       
   300     { // ITU-T keys with different behaviour
       
   301         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyBackspace, KMIDKeyClear, R_MIDP_KEY_CLEAR)));
       
   302     }
       
   303     else
       
   304     { // QWERTY  keys with different behaviour
       
   305         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyBackspace, EKeyBackspace, R_MIDP_KEY_BACKSPACE)));
       
   306     }
       
   307 
       
   308     /*
       
   309         // Keys defined in specs but not yet present in Series 60
       
   310         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyFormFeed, R_MIDP_KEY_FORM_FEED)));
       
   311         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyLineFeed, R_MIDP_KEY_LINE_FEED)));
       
   312         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyBell, R_MIDP_KEY_BELL)));
       
   313         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyVerticalTab, R_MIDP_KEY_VERTICAL_TAB)));
       
   314 
       
   315         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyClockWiseRotate, R_MIDP_KEY_CLOCKWISE_ROTATE)));
       
   316         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyCounterClockWiseRotate, R_MIDP_KEY_COUNTER_CLOCKWISE_ROTATE)));
       
   317         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyClockWiseFastRotate, R_MIDP_KEY_CLOCKWISE_FAST_ROTATE)));
       
   318         User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyCounterClockWiseFastRotate, R_MIDP_KEY_COUNTER_CLOCKWISE_FAST_ROTATE)));
       
   319     */
       
   320 
       
   321     // Add media keys. These are used only in GetKeyName method.
       
   322     // EStdKeyNull used as a scancode as media keys don't have a real scancode.
       
   323     User::LeaveIfError(iSpecialKeys.Append(
       
   324                            TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyPlay,     R_MIDP_KEY_PLAY)));
       
   325     User::LeaveIfError(iSpecialKeys.Append(
       
   326                            TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyPrevious, R_MIDP_KEY_PREVIOUS)));
       
   327     User::LeaveIfError(iSpecialKeys.Append(
       
   328                            TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyNext,     R_MIDP_KEY_NEXT)));
       
   329     User::LeaveIfError(iSpecialKeys.Append(
       
   330                            TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyStop,     R_MIDP_KEY_STOP)));
       
   331 
       
   332     // Zoom in and zoom out keys events support
       
   333     User::LeaveIfError(iSpecialKeys.Append(
       
   334                            TMIDKey(EStdKeyApplicationC, KMIDKeyZoomIn, R_MIDP_KEY_ZOOM_IN)));
       
   335     User::LeaveIfError(iSpecialKeys.Append(
       
   336                            TMIDKey(EStdKeyApplicationD, KMIDKeyZoomOut, R_MIDP_KEY_ZOOM_OUT)));
       
   337 };
       
   338 
       
   339 
       
   340 
       
   341 /**  */
       
   342 void CMIDKeyDecoder::CreateQwertyWatchL()
       
   343 {
       
   344     iQwertyWatch = CMIDQwertyWatch::NewL(this);
       
   345 }
       
   346 
       
   347 
       
   348 void CMIDKeyDecoder::InitRemConObserverL()
       
   349 {
       
   350     if (!iRemConObserver)
       
   351     {
       
   352         iRemConObserver = CMIDRemConObserver::NewL();
       
   353     }
       
   354 }
       
   355 
       
   356 /** */
       
   357 void CMIDKeyDecoder::NewQwertyValueL(TInt aNewValue)
       
   358 {
       
   359     TBool oldQwertyMode = iQwertyModeActive;
       
   360 
       
   361     if (aNewValue == 1)
       
   362     {
       
   363         iQwertyModeActive = ETrue;
       
   364     }
       
   365     else
       
   366     {
       
   367         iQwertyModeActive = EFalse;
       
   368     }
       
   369 
       
   370     if (iQwertyModeActive != oldQwertyMode)
       
   371     {
       
   372         CreateGameActionsL();
       
   373     }
       
   374 }
       
   375 
       
   376 /**
       
   377  * Gets a key code that corresponds to the specified game action on the device.
       
   378  * The implementation is required to provide a mapping for every game action,
       
   379  * so this method will always return a valid key code for every game action.
       
   380  *
       
   381  * Note that a key code is associated with at most one game action, whereas a
       
   382  * game action may be associated with several key codes.
       
   383  *
       
   384  * Returns zero if aGameAction is not a valid game action
       
   385  */
       
   386 TInt CMIDKeyDecoder::GetKeyCode(TInt aGameAction)
       
   387 {
       
   388     DEBUG_INT("< CMIDKeyDecoder::GetKeyCode - game action is %D", aGameAction);
       
   389     for (TInt i = 0; i < KNumGameActions; ++i)
       
   390     {
       
   391         if (iGameActions[i]->iActionCode == aGameAction)
       
   392         {
       
   393             DEBUG_INT("> CMIDKeyDecoder::GetKeyCode - return code %D", iGameActions[i]->iCodes[0]);
       
   394             return iGameActions[i]->iCodes[0]; //just return the first code
       
   395         }
       
   396     }
       
   397 
       
   398     DEBUG_INT("> CMIDKeyDecoder::GetKeyCode - return code %D", 0);
       
   399     return 0;
       
   400 }
       
   401 
       
   402 /**
       
   403  * Maps EPOC scan code to negative key code required by MIDP spec.
       
   404  * For keys that have no corresponding Unicode character,
       
   405  * the implementation must use negative values.
       
   406  */
       
   407 TInt CMIDKeyDecoder::MapNonUnicodeKey(TUint aScanCode)
       
   408 {
       
   409     DEBUG_INT("< CMIDKeyDecoder::MapNonUnicodeKey - scan code is %D", aScanCode);
       
   410     TInt numSpecialKeys = iSpecialKeys.Count();
       
   411     for (TInt i = 0; i < numSpecialKeys; i++)
       
   412     {
       
   413         if (iSpecialKeys[i].iScanCode == aScanCode)
       
   414         {
       
   415             DEBUG_INT("> CMIDKeyDecoder::MapNonUnicodeKey - return code is %D", iSpecialKeys[i].iMIDPCode);
       
   416             return iSpecialKeys[i].iMIDPCode;
       
   417         }
       
   418     }
       
   419 
       
   420     DEBUG_INT("> CMIDKeyDecoder::MapNonUnicodeKey - return code is %D", 0);
       
   421     return 0;
       
   422 }
       
   423 
       
   424 /**
       
   425  * Gets an informative key string for a key. The string returned will resemble the text
       
   426  * physically printed on the key. This string is suitable for displaying to the user.
       
   427  * For example, on a device with function keys F1 through F4, calling this method on
       
   428  * the keyCode for the F1 key will return the string "F1". A typical use for this string
       
   429  * will be to compose help text such as "Press F1 to proceed."
       
   430  *
       
   431  * This method will return a non-empty string for every valid key code.
       
   432  *
       
   433  */
       
   434 void CMIDKeyDecoder::GetKeyName(TDes& aText,TInt aKeyCode)
       
   435 {
       
   436     DEBUG_INT("< CMIDKeyDecoder::GetKeyName - key code is %D", aKeyCode);
       
   437     aText.Zero();
       
   438 
       
   439     TInt resId = R_MIDP_KEY_NON_CHARACTER;
       
   440     TInt numSpecialKeys = iSpecialKeys.Count();
       
   441     for (TInt i = 0; i < numSpecialKeys; i++)
       
   442     {
       
   443         if (iSpecialKeys[i].iMIDPCode == aKeyCode)
       
   444         {
       
   445             resId = iSpecialKeys[i].iNameResId;
       
   446             break;
       
   447         }
       
   448     }
       
   449 
       
   450     if ((resId == R_MIDP_KEY_NON_CHARACTER) && (IsUnicode(aKeyCode)))
       
   451     {
       
   452         aText.Append(TChar(aKeyCode));
       
   453     }
       
   454     else
       
   455     {
       
   456         CEikonEnv::Static()->ReadResource(aText,resId);
       
   457     }
       
   458 
       
   459     DEBUG_STR("> CMIDKeyDecoder::GetKeyName - key name is %S", aText);
       
   460 }
       
   461 
       
   462 
       
   463 TInt CMIDKeyDecoder::GameAction(TInt aKeyCode)
       
   464 {
       
   465     DEBUG_INT("< CMIDKeyDecoder::GameAction - key code is %D", aKeyCode);
       
   466 
       
   467     for (TInt i = 0; i < KNumGameActions; ++i)
       
   468     {
       
   469         TInt numCodes = iGameActions[i]->iCodes.Count();
       
   470         for (TInt j = 0; j < numCodes; ++j)
       
   471         {
       
   472             if (iGameActions[i]->iCodes[j] == aKeyCode)
       
   473             {
       
   474                 DEBUG_INT("> CMIDKeyDecoder::GameAction -game action is %D", iGameActions[i]->iActionCode);
       
   475                 return iGameActions[i]->iActionCode;
       
   476             }
       
   477         }
       
   478     }
       
   479 
       
   480     DEBUG_INT("> CMIDKeyDecoder::GameAction -game action is %D", 0);
       
   481     return 0; //invalid action
       
   482 }
       
   483 
       
   484 /**
       
   485  * Determines if a key code should be sent to MIDP applications.
       
   486  */
       
   487 TBool CMIDKeyDecoder::IsJavaKey(TInt aScanCode)
       
   488 {
       
   489     TBool ret = (ScanToMidpCode(aScanCode) != 0);
       
   490 
       
   491     DEBUG_INT2("<> CMIDKeyDecoder::IsJavaKey - return %D for scan code %D", ret, aScanCode);
       
   492     return ret;
       
   493 }
       
   494 
       
   495 TBool CMIDKeyDecoder::MediaKeysEnabled() const
       
   496 {
       
   497     return iMediaKeysEnabled;
       
   498 }
       
   499 
       
   500 CMIDRemConObserver* CMIDKeyDecoder::GetRemConObserver()
       
   501 {
       
   502     return iRemConObserver;
       
   503 }
       
   504 
       
   505 /** Create the game actions. This method is called at startup and
       
   506 each time the qwerty availability changes. Because special keys
       
   507 also depend on qwerty availability, call InitSpecialKeysL() -
       
   508 which will reset special keys. The reset the actions and call
       
   509 LoadGameActionCodesL() - which loads the correct codes. Then
       
   510 for each action appens the codes stored in iActionScanCodes.
       
   511 Action codes in this array are separated by a null byte. */
       
   512 void CMIDKeyDecoder::CreateGameActionsL()
       
   513 {
       
   514     DEBUG("< CMIDKeyDecoder::CreateGameActionsL");
       
   515 
       
   516     InitSpecialKeysL();
       
   517     iGameActions.ResetAndDestroy();
       
   518 
       
   519     LoadGameActionCodesL();
       
   520     ASSERT(iActionScanCodes != NULL);
       
   521 
       
   522     TInt index = 0;
       
   523     for (TInt i = 0; i < KNumGameActions; ++i)
       
   524     {
       
   525         TMIDGameAction* action = new(ELeave) TMIDGameAction(KActionCodes[i]);
       
   526         CleanupStack::PushL(action);
       
   527 
       
   528         while (iActionScanCodes[index] != 0)
       
   529         {
       
   530             AddCodeToActionL(action, iActionScanCodes[index]);
       
   531             index++;
       
   532         }
       
   533         index++;    // skip null byte separating actions
       
   534 
       
   535         User::LeaveIfError(iGameActions.Append(action));
       
   536         CleanupStack::Pop(action);
       
   537     }
       
   538 
       
   539     DEBUG("> CMIDKeyDecoder::CreateGameActionsL");
       
   540 }
       
   541 
       
   542 /** Load the game action codes: either the default ITU-T codes
       
   543     if no qwerty input is available or load the codes
       
   544     from Central Repository (if available and if
       
   545     flag in CR indicates to do so) or load some default QWERTY codes.
       
   546 */
       
   547 void CMIDKeyDecoder::LoadGameActionCodesL()
       
   548 {
       
   549     DEBUG("< CMIDKeyDecoder::LoadGameActionCodesL");
       
   550 
       
   551     if (iUseCRScanCodes)
       
   552     {
       
   553         delete iActionScanCodes;
       
   554         iUseCRScanCodes = EFalse;
       
   555     }
       
   556 
       
   557     iActionScanCodes = NULL;
       
   558 
       
   559     if (!QwertyInputAvailable())
       
   560     { // if no qwerty always use default ITU-T codes
       
   561         DEBUG("  CMIDKeyDecoder::LoadGameActionCodesL - use default ITU-T scan codes");
       
   562         iActionScanCodes = (TInt*)&KDefaultActionScanCodes[0];
       
   563     }
       
   564     else
       
   565     { // if there is qwerty either use CR repository codes or default qwerty codes
       
   566         CRepository* repository = NULL;
       
   567         TRAPD(crExists, repository = CRepository::NewL(KCRUidMidpLcdui));
       
   568 
       
   569         if (crExists == KErrNone)
       
   570         {
       
   571             CleanupStack::PushL(repository);
       
   572             repository->Get(KUseCustomGameActionScanCodes, iUseCRScanCodes);
       
   573         }
       
   574 
       
   575         if (iUseCRScanCodes)
       
   576         { // use CR QWERTY codes
       
   577             DEBUG("  CMIDKeyDecoder::LoadGameActionCodesL - use central repository scan codes");
       
   578             LoadCentralRepositoryCodesL(repository);
       
   579         }
       
   580         else
       
   581         { //  use default QWERTY codes
       
   582             DEBUG("  CMIDKeyDecoder::LoadGameActionCodesL - add default qwerty scan codes");
       
   583             iActionScanCodes = (TInt*)&KDefaultQwertyActionScanCodes[0];
       
   584         }
       
   585 
       
   586         if (crExists == KErrNone)
       
   587         {
       
   588             CleanupStack::PopAndDestroy(repository);
       
   589         }
       
   590     }
       
   591 
       
   592     DEBUG("> CMIDKeyDecoder::LoadGameActionCodesL");
       
   593 }
       
   594 
       
   595 /** Load the game action scan codes stored in the central repository
       
   596     database. Two bytes are available per scan code, LSB is left. Max
       
   597     number of codes per action is KMaxScanCodesPerAction. Allocate
       
   598     some memory for iActionScanCodes.
       
   599     */
       
   600 void CMIDKeyDecoder::LoadCentralRepositoryCodesL(CRepository* aRepository)
       
   601 {
       
   602     DEBUG("< CMIDKeyDecoder::LoadCentralRepositoryCodesL");
       
   603 
       
   604     ASSERT(aRepository != NULL);
       
   605     ASSERT(iActionScanCodes == NULL);
       
   606 
       
   607     iActionScanCodes = new(ELeave) TInt[KNumGameActions*KMaxScanCodesPerAction];
       
   608 
       
   609     TInt index = 0;
       
   610     for (TInt i = 0; i < KNumGameActions; ++i)
       
   611     {
       
   612         //2 bytes per scan code
       
   613         TBuf8<KMaxScanCodesPerAction*2> scanCodeBuffer;
       
   614         aRepository->Get(KActionKeys[i],scanCodeBuffer);
       
   615 
       
   616         for (TInt j = 0; j < (scanCodeBuffer.Length() - 1); j++)
       
   617         {
       
   618             TUint8 scanCodeLeft = scanCodeBuffer[j++];
       
   619             TUint8 scanCodeRight = scanCodeBuffer[j];
       
   620 
       
   621             TUint scanCode = (scanCodeLeft << 8) + scanCodeRight;
       
   622 
       
   623             if (scanCode != 0)
       
   624             {
       
   625                 iActionScanCodes[index++] = scanCode;
       
   626             }
       
   627         }
       
   628 
       
   629         iActionScanCodes[index++] = 0;   //indicates end of scan codes
       
   630     }
       
   631 
       
   632     DEBUG("> CMIDKeyDecoder::LoadCentralRepositoryCodesL");
       
   633 }
       
   634 
       
   635 /** Return true if this device supports qwerty and the qwerty keyboard
       
   636     is available */
       
   637 TBool CMIDKeyDecoder::QwertyInputAvailable() const
       
   638 {
       
   639     return iQwertyModeActive;
       
   640 }
       
   641 
       
   642 /**
       
   643     Convert the scan code into a MIDP key code taking into account possible
       
   644     modifiers. Add the resulting MIDP key codes to the action specified as long
       
   645     as they are all different.
       
   646   */
       
   647 void CMIDKeyDecoder::AddCodeToActionL(TMIDGameAction* aGameAction, TInt aScanCode)
       
   648 {
       
   649     DEBUG_INT("< CMIDKeyDecoder::AddCodeToActionL - scan code is %D", aScanCode);
       
   650     TInt midpCode = ScanToMidpCode(aScanCode);
       
   651 
       
   652     if (aGameAction->iCodes.Find(midpCode) == KErrNotFound && midpCode != 0)
       
   653     {
       
   654         DEBUG_INT("  CMIDKeyDecoder::AddCodeToActionL - adding midp code %D", midpCode);
       
   655         User::LeaveIfError(aGameAction->iCodes.Append(midpCode));
       
   656     }
       
   657 
       
   658     if (IsUnicode(midpCode))
       
   659     {
       
   660         midpCode = ScanToMidpCode(aScanCode | EModifierShift);
       
   661 
       
   662         if (aGameAction->iCodes.Find(midpCode) == KErrNotFound)
       
   663         {
       
   664             DEBUG_INT("  CMIDKeyDecoder::AddCodeToActionL - adding midp code %D", midpCode);
       
   665             User::LeaveIfError(aGameAction->iCodes.Append(midpCode));
       
   666         }
       
   667     }
       
   668 
       
   669     DEBUG("> CMIDKeyDecoder::AddCodeToActionL");
       
   670 }
       
   671 
       
   672 /** Take a scan code and convert it into a MIDP code. First see if it
       
   673 is one of the special keys, otherwise ask the window server to convert it. */
       
   674 TInt CMIDKeyDecoder::ScanToMidpCode(TInt aScanCode)
       
   675 {
       
   676     DEBUG_INT("< CMIDKeyDecoder::ScanToMidpCode - scan Code is %D", aScanCode);
       
   677     TInt keyCode = MapNonUnicodeKey(aScanCode);
       
   678 
       
   679     if (keyCode == 0)
       
   680     {
       
   681         // fake a key down to convert scan code into key code
       
   682         // Note: on WINS (and WINSCW) this conversion works only for QWERTY layout
       
   683         // unless you specify the char code in the HI part of the scan code - which
       
   684         // we cannot do - hence on the emulator only QWERTY layout works.
       
   685         TKeyData keyData;
       
   686         TBool translated = iKeyTranslator->TranslateKey(aScanCode,EFalse,*iCaptureKeys,keyData);
       
   687 
       
   688         if (translated)
       
   689         {
       
   690             DEBUG_INT("  CMIDKeyDecoder::ScanToMidpCode - ws translated code is %D", keyData.iKeyCode);
       
   691             keyCode = IsUnicode(keyData.iKeyCode) ? keyData.iKeyCode : 0;
       
   692         }
       
   693 
       
   694         // fake a key up to restore modifiers
       
   695         iKeyTranslator->TranslateKey(aScanCode,ETrue,*iCaptureKeys,keyData);
       
   696     }
       
   697 
       
   698     DEBUG_INT("> CMIDKeyDecoder::ScanToMidpCode - return key code %D", keyCode);
       
   699     return keyCode;
       
   700 }
       
   701 
       
   702 /** Return true if the key code corresponds to a unicode character */
       
   703 TBool CMIDKeyDecoder::IsUnicode(TInt aKeyCode) const
       
   704 {
       
   705     TBool ret = (aKeyCode > 0) && (aKeyCode < ENonCharacterKeyBase ||
       
   706                                    aKeyCode >= (ENonCharacterKeyBase + ENonCharacterKeyCount));
       
   707 
       
   708     DEBUG_INT2("<> CMIDKeyDecoder::IsUnicode - return %D for key code %D", ret, aKeyCode);
       
   709     return ret;
       
   710 }
       
   711 
       
   712 TInt CMIDKeyDecoder::AdditionalSelectionKeyMappingCode()
       
   713 {
       
   714     return iAdditionalSelectkeyMapping;
       
   715 }