Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4543 lines
113 KiB

  1. /**************************************************************************\
  2. * Module Name: softkbdc.cpp
  3. *
  4. * Copyright (c) 1985 - 2000, Microsoft Corporation
  5. *
  6. * Implementation of interface ISoftKbd
  7. *
  8. * History:
  9. * 28-March-2000 weibz Created
  10. \**************************************************************************/
  11. #include "private.h"
  12. #include "globals.h"
  13. #include "SoftKbdc.h"
  14. #include "softkbdui.h"
  15. #define MAX_LABEL_LEN 20
  16. /*******************************************************************************
  17. *
  18. * WstrToInt( )
  19. *
  20. * A utility function to convert a string to integer.
  21. *
  22. /********************************************************************************/
  23. WORD WstrToInt(WCHAR *wszStr)
  24. {
  25. int ret, i;
  26. if ( wszStr == NULL )
  27. return 0;
  28. ret = 0;
  29. i = 0;
  30. while ( wszStr[i] != L'\0' )
  31. {
  32. if ( (wszStr[i] < L'0') || (wszStr[i] > L'9') )
  33. {
  34. // this is not a legal string.
  35. // just return back 0.
  36. return 0;
  37. }
  38. ret = ret * 10 + (wszStr[i] - L'0');
  39. i++;
  40. }
  41. return (WORD)ret;
  42. }
  43. /*******************************************************************************
  44. *
  45. * Constructor function:
  46. *
  47. * Initialize necessary data fields.
  48. *
  49. /********************************************************************************/
  50. CSoftKbd::CSoftKbd( )
  51. {
  52. _lpCurKbdLayout = NULL;
  53. _lpKbdLayoutDesList = NULL;
  54. _wCurKbdLayoutID = NON_KEYBOARD;
  55. _pSoftkbdUIWnd = NULL;
  56. _hOwner = NULL;
  57. _xReal = _yReal = _widthReal = _heightReal = 0;
  58. _pDoc = NULL;
  59. _pskbdwndes = NULL;
  60. _TitleBar_Type = TITLEBAR_NONE;
  61. _plfTextFont = NULL;
  62. }
  63. /*******************************************************************************
  64. *
  65. * Destructor
  66. *
  67. * Free all allocated memories.
  68. *
  69. /********************************************************************************/
  70. CSoftKbd::~CSoftKbd( )
  71. {
  72. KBDLAYOUTDES *lpKbdLayoutDes;
  73. KBDLAYOUTDES *lpLayoutDesTmp;
  74. KEYMAP *lpKeyMapList;
  75. int i, iState;
  76. SafeRelease(_pDoc);
  77. //
  78. //
  79. // Free Memory for soft keyboard layouts , and Label Text Mapping List
  80. //
  81. //
  82. lpKbdLayoutDes = _lpKbdLayoutDesList;
  83. while ( lpKbdLayoutDes != NULL )
  84. {
  85. KEYMAP *lpKeyMapListTmp;
  86. lpKeyMapList = lpKbdLayoutDes->lpKeyMapList;
  87. while ( lpKeyMapList != NULL )
  88. {
  89. for ( i=0; i<(int)(lpKeyMapList->wNumOfKeys); i++)
  90. {
  91. // free lppLabelText string for each state.
  92. for ( iState=0; iState < lpKeyMapList->lpKeyLabels[i].wNumModComb; iState++)
  93. {
  94. if (lpKeyMapList->lpKeyLabels[i].lppLabelText[iState])
  95. SysFreeString(lpKeyMapList->lpKeyLabels[i].lppLabelText[iState]);
  96. }
  97. SafeFreePointer(lpKeyMapList->lpKeyLabels[i].lppLabelText);
  98. SafeFreePointer(lpKeyMapList->lpKeyLabels[i].lpLabelType);
  99. SafeFreePointer(lpKeyMapList->lpKeyLabels[i].lpLabelDisp);
  100. }
  101. lpKeyMapListTmp = lpKeyMapList;
  102. lpKeyMapList = lpKeyMapList->pNext;
  103. SafeFreePointer(lpKeyMapListTmp);
  104. }
  105. lpLayoutDesTmp = lpKbdLayoutDes;
  106. lpKbdLayoutDes = lpKbdLayoutDes->pNext;
  107. SafeFreePointer(lpLayoutDesTmp);
  108. }
  109. if ( _plfTextFont )
  110. SafeFreePointer(_plfTextFont);
  111. // Destroy the window if the window is still active.
  112. if ( _pSoftkbdUIWnd != NULL )
  113. {
  114. DestroySoftKeyboardWindow( );
  115. _pSoftkbdUIWnd = NULL;
  116. }
  117. }
  118. /*******************************************************************************
  119. *
  120. * Method function: _LoadDocumentSync( )
  121. *
  122. * Load an XML Document from the specified file or URL synchronously.
  123. *
  124. *
  125. * fFileName is TRUE, means pBURL contains XML file path.
  126. * fFilename is FALSE, means pBURL contains real XML content
  127. *
  128. /********************************************************************************/
  129. HRESULT CSoftKbd::_LoadDocumentSync(BSTR pBURL, BOOL fFileName)
  130. {
  131. IXMLDOMParseError *pXMLError = NULL;
  132. LONG errorCode = E_FAIL;
  133. VARIANT vURL;
  134. VARIANT_BOOL vb;
  135. HRESULT hr;
  136. if ( _pDoc == NULL ) {
  137. return E_FAIL;
  138. }
  139. CHECKHR(_pDoc->put_async(VARIANT_FALSE));
  140. // Load xml document from the given URL or file path
  141. vURL.vt = VT_BSTR;
  142. V_BSTR(&vURL) = pBURL;
  143. if ( fFileName == TRUE )
  144. {
  145. CHECKHR(_pDoc->load(vURL, &vb));
  146. }
  147. else
  148. {
  149. CHECKHR(_pDoc->loadXML(pBURL, &vb) );
  150. }
  151. CHECKHR(_pDoc->get_parseError(&pXMLError));
  152. CHECKHR(pXMLError->get_errorCode(&errorCode));
  153. if (errorCode != 0)
  154. {
  155. hr = E_FAIL;
  156. }
  157. CleanUp:
  158. SafeReleaseClear(pXMLError);
  159. return hr;
  160. }
  161. /*******************************************************************************
  162. *
  163. * Method function: Initialize( )
  164. *
  165. * Initialize all necessary field for this class object.
  166. * Generate Standard soft keyboard layouts.
  167. *
  168. /********************************************************************************/
  169. STDMETHODIMP CSoftKbd::Initialize()
  170. {
  171. // initialize standard layouts
  172. HRESULT hr = S_OK;
  173. COLORTYPE crType;
  174. // Initialize the different types of colors.
  175. // Following types of colors are supported.
  176. // bkcolor = 0 , for the window's back ground color
  177. // UnSelForeColor = 1,
  178. // UnSelTextColor = 2,
  179. // SelForeColor = 3,
  180. // SelTextColor = 4
  181. crType = bkcolor;
  182. _color[crType] = GetSysColor(COLOR_MENU);
  183. crType = UnSelForeColor;
  184. _color[crType] = GetSysColor(COLOR_MENU);
  185. crType = UnSelTextColor;
  186. _color[crType] = GetSysColor(COLOR_WINDOWTEXT);
  187. crType = SelForeColor;
  188. _color[crType] = GetSysColor(COLOR_MENU);
  189. crType = SelTextColor;
  190. _color[crType] = GetSysColor(COLOR_WINDOWTEXT);
  191. CHECKHR(_CreateStandardSoftKbdLayout(SOFTKBD_US_STANDARD, L"IDSKD_STDUS101"));
  192. CHECKHR(_CreateStandardSoftKbdLayout(SOFTKBD_EURO_STANDARD, L"IDSKD_STDEURO102"));
  193. CHECKHR(_CreateStandardSoftKbdLayout(SOFTKBD_JPN_STANDARD, L"IDSKD_STDJPN106"));
  194. CleanUp:
  195. return hr;
  196. }
  197. /*******************************************************************************
  198. *
  199. * Method function: _CreateStandardSoftKbdLayout( )
  200. *
  201. * Create standard soft keyboard layout.
  202. *
  203. * dwStdSoftKbdID, predefined Standard soft keyboard layout ID.
  204. *
  205. * wszStdResStr : Resource ID string for the created standard soft keyboard.
  206. *
  207. /********************************************************************************/
  208. HRESULT CSoftKbd::_CreateStandardSoftKbdLayout(DWORD dwStdSoftKbdID, WCHAR *wszStdResStr )
  209. {
  210. KBDLAYOUTDES *pKbdLayout;
  211. BYTE *lpszKeyboardDes;
  212. WCHAR wszModuleFile[MAX_PATH];
  213. CHAR szModuleFile[MAX_PATH];
  214. CHAR szStdResStr[MAX_PATH]; // Ansi name of the Res Str ID
  215. WCHAR wszInternalDesFileName[MAX_PATH];
  216. HRESULT hr = S_OK;
  217. HGLOBAL hResData = NULL;
  218. HRSRC hRsRc = NULL;
  219. DWORD dwFileLen;
  220. DWORD dwResLen;
  221. dwFileLen = GetModuleFileNameA(g_hInst, szModuleFile, MAX_PATH);
  222. if ( dwFileLen == 0 )
  223. {
  224. hr = E_FAIL;
  225. return hr;
  226. }
  227. MultiByteToWideChar(CP_ACP, 0, szModuleFile, -1,
  228. wszModuleFile, MAX_PATH);
  229. WideCharToMultiByte(CP_ACP, 0, wszStdResStr, -1,
  230. szStdResStr, MAX_PATH, NULL, NULL );
  231. hRsRc = FindResourceA(g_hInst,szStdResStr, "SKDFILE" );
  232. if ( hRsRc == NULL ) return E_FAIL;
  233. dwResLen = SizeofResource(g_hInst, hRsRc);
  234. hResData = LoadResource(g_hInst, hRsRc);
  235. if ( hResData == NULL ) return E_FAIL;
  236. lpszKeyboardDes = (BYTE *)LockResource(hResData);
  237. if ( lpszKeyboardDes == NULL ) return E_FAIL;
  238. CHECKHR(_GenerateKeyboardLayoutFromSKD(lpszKeyboardDes, dwStdSoftKbdID, &pKbdLayout));
  239. // Change the internal DesFile name as following format:
  240. //
  241. // SKDFILE: ResFileName : KBDResString to identify this layout's des file.
  242. //
  243. StringCchCopyW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), L"SKDFILE:");
  244. StringCchCatW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), wszModuleFile);
  245. StringCchCatW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), L":");
  246. StringCchCatW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), wszStdResStr );
  247. StringCchCopyW(pKbdLayout->KbdLayoutDesFile, ARRAYSIZE(pKbdLayout->KbdLayoutDesFile), wszInternalDesFileName);
  248. // link this new layout to the list.
  249. if ( _lpKbdLayoutDesList == NULL ) {
  250. _lpKbdLayoutDesList = pKbdLayout;
  251. pKbdLayout->pNext = NULL;
  252. }
  253. else
  254. {
  255. pKbdLayout->pNext = _lpKbdLayoutDesList;
  256. _lpKbdLayoutDesList = pKbdLayout;
  257. }
  258. CleanUp:
  259. return hr;
  260. }
  261. /*******************************************************************************
  262. *
  263. * Method function: EnumSoftKeyBoard( )
  264. *
  265. * Enumerate all possible soft keybaord layouts.
  266. *
  267. /********************************************************************************/
  268. STDMETHODIMP CSoftKbd::EnumSoftKeyBoard(LANGID langid, DWORD *lpdwKeyboard)
  269. {
  270. /* The return value could be one of following:
  271. SOFTKBD_US_STANDARD
  272. SOFTKBD_US_ENHANCE
  273. SOFTKBD_EURO_STANDARD
  274. SOFTKBD_EURO_ENHANCE
  275. SOFTKBD_JPN_STANDARD
  276. SOFTKBD_JPN_ENHANCE
  277. Any customized soft keyboard layout
  278. SOFTKBD_NO_MORE.
  279. */
  280. return S_OK;
  281. }
  282. /*******************************************************************************
  283. *
  284. * Method function: _GetXMLNodeValueWORD( )
  285. *
  286. * Get the WORD value for the specified Node.
  287. *
  288. *
  289. /********************************************************************************/
  290. HRESULT CSoftKbd::_GetXMLNodeValueWORD(IXMLDOMNode *pNode, WORD *lpWord)
  291. {
  292. HRESULT hr = S_OK;
  293. IXMLDOMNode *pValueChild = NULL;
  294. VARIANT value;
  295. if ( (pNode == NULL) || (lpWord == NULL) )
  296. {
  297. hr = E_FAIL;
  298. return hr;
  299. }
  300. CHECKHR(pNode->get_firstChild(&pValueChild));
  301. CHECKHR(pValueChild->get_nodeValue(&value));
  302. *lpWord = (WORD)WstrToInt(V_BSTR(&value));
  303. VariantClear(&value);
  304. CleanUp:
  305. SafeRelease(pValueChild);
  306. return hr;
  307. }
  308. /*******************************************************************************
  309. *
  310. * Method function: _ParseOneKeyInLayout( )
  311. *
  312. * Parse One Key in Layout Description, fill the data structure for
  313. * the specified key.
  314. *
  315. *
  316. /********************************************************************************/
  317. HRESULT CSoftKbd::_ParseOneKeyInLayout(IXMLDOMNode *pNode, KEYDES *lpKeyDes)
  318. {
  319. HRESULT hr;
  320. IXMLDOMNode *pAttrChild = NULL, *pKey = NULL, *pKeyNext = NULL;
  321. BSTR nodeName=NULL;
  322. IXMLDOMNamedNodeMap *pattrs=NULL;
  323. BSTR name=NULL;
  324. VARIANT value;
  325. IXMLDOMNode *pValueChild=NULL;
  326. hr = S_OK;
  327. if ( (lpKeyDes == NULL) || (pNode == NULL) )
  328. {
  329. hr = E_FAIL;
  330. return hr;
  331. }
  332. if (SUCCEEDED(pNode->get_attributes(&pattrs)) && pattrs != NULL)
  333. {
  334. CHECKHR(pattrs->nextNode(&pAttrChild));
  335. while (pAttrChild)
  336. {
  337. CHECKHR(pAttrChild->get_nodeName(&name));
  338. if ( wcscmp(name, xMODIFIER ) == 0 )
  339. {
  340. CHECKHR(pAttrChild->get_nodeValue(&value));
  341. if (value.vt == VT_BSTR)
  342. {
  343. if ( wcscmp(V_BSTR(&value), xNONE) == 0 )
  344. lpKeyDes->tModifier = none;
  345. else if ( wcscmp(V_BSTR(&value), xCAPSLOCK) == 0 )
  346. lpKeyDes->tModifier = CapsLock;
  347. else if ( wcscmp(V_BSTR(&value), xSHIFT) == 0 )
  348. lpKeyDes->tModifier = Shift;
  349. else if ( wcscmp(V_BSTR(&value),xCTRL ) == 0 )
  350. lpKeyDes->tModifier = Ctrl;
  351. else if ( wcscmp(V_BSTR(&value), xATL) == 0 )
  352. lpKeyDes->tModifier = Alt;
  353. else if ( wcscmp(V_BSTR(&value), xALTGR) == 0 )
  354. lpKeyDes->tModifier = AltGr;
  355. else if ( wcscmp(V_BSTR(&value), xKANA) == 0 )
  356. lpKeyDes->tModifier = Kana;
  357. else if ( wcscmp(V_BSTR(&value), xNUMLOCK) == 0 )
  358. lpKeyDes->tModifier = NumLock;
  359. else
  360. lpKeyDes->tModifier = none;
  361. }
  362. VariantClear(&value);
  363. }
  364. if ( name != NULL)
  365. SysFreeString(name);
  366. SafeReleaseClear(pAttrChild);
  367. CHECKHR(pattrs->nextNode(&pAttrChild));
  368. }
  369. SafeReleaseClear(pattrs);
  370. }
  371. CHECKHR(pNode->get_firstChild(&pKey));
  372. while ( pKey )
  373. {
  374. CHECKHR(pKey->get_nodeName(&nodeName));
  375. CHECKHR(pKey->get_firstChild(&pValueChild));
  376. CHECKHR(pValueChild->get_nodeValue(&value));
  377. if ( wcscmp(nodeName, xKEYID ) == 0 )
  378. {
  379. lpKeyDes->keyId = WstrToInt(V_BSTR(&value));
  380. }
  381. else if ( wcscmp(nodeName,xLEFT ) == 0 )
  382. {
  383. lpKeyDes->wLeft = (WORD)WstrToInt(V_BSTR(&value));
  384. }
  385. else if ( wcscmp(nodeName, xTOP) == 0 )
  386. {
  387. lpKeyDes->wTop = WstrToInt(V_BSTR(&value));
  388. }
  389. else if ( wcscmp(nodeName, xWIDTH) == 0 )
  390. {
  391. lpKeyDes->wWidth = WstrToInt(V_BSTR(&value));
  392. }
  393. else if ( wcscmp(nodeName, xHEIGHT) == 0 )
  394. {
  395. lpKeyDes->wHeight = WstrToInt(V_BSTR(&value));
  396. }
  397. VariantClear(&value);
  398. SafeReleaseClear(pValueChild);
  399. if ( nodeName != NULL )
  400. {
  401. SysFreeString(nodeName);
  402. nodeName = NULL;
  403. }
  404. CHECKHR(pKey->get_nextSibling(&pKeyNext));
  405. SafeReleaseClear(pKey);
  406. pKey = pKeyNext;
  407. }
  408. CleanUp:
  409. if ( FAILED(hr) )
  410. {
  411. if ( nodeName != NULL )
  412. {
  413. SysFreeString(nodeName);
  414. nodeName = NULL;
  415. }
  416. if ( pValueChild )
  417. SafeReleaseClear(pValueChild);
  418. if ( pKey )
  419. SafeReleaseClear(pKey);
  420. }
  421. return hr;
  422. }
  423. /*******************************************************************************
  424. *
  425. * Method function: _ParseLayoutDescription( )
  426. *
  427. * Parse Layout description part in the XML file, and fill the internal
  428. * Layout data structure.
  429. *
  430. /********************************************************************************/
  431. HRESULT CSoftKbd::_ParseLayoutDescription(IXMLDOMNode *pLayoutChild, KBDLAYOUT *pLayout)
  432. {
  433. HRESULT hr = S_OK;
  434. IXMLDOMNode *pNode = NULL;
  435. IXMLDOMNode *pChild = NULL, *pNext = NULL, *pAttrChild=NULL;
  436. BSTR nodeName=NULL;
  437. IXMLDOMNamedNodeMap *pattrs=NULL;
  438. BSTR name=NULL;
  439. VARIANT value;
  440. int iKey;
  441. BSTR pBURL = NULL;
  442. if ( (pLayoutChild == NULL) || (pLayout == NULL ) )
  443. {
  444. hr = E_FAIL;
  445. return hr;
  446. }
  447. iKey = 0;
  448. // Parse layout part.
  449. if (SUCCEEDED(pLayoutChild->get_attributes(&pattrs)) && pattrs != NULL)
  450. {
  451. //
  452. // Get the softkbe type attribute
  453. //
  454. CHECKHR(pattrs->nextNode(&pAttrChild));
  455. while (pAttrChild)
  456. {
  457. CHECKHR(pAttrChild->get_nodeName(&name));
  458. if ( wcscmp(name, xSOFTKBDTYPE) )
  459. {
  460. // this is not the right attribute.
  461. if ( name != NULL)
  462. {
  463. SysFreeString(name);
  464. name = NULL;
  465. }
  466. SafeReleaseClear(pAttrChild);
  467. CHECKHR(pattrs->nextNode(&pAttrChild));
  468. continue;
  469. }
  470. if ( name != NULL)
  471. {
  472. SysFreeString(name);
  473. name = NULL;
  474. }
  475. CHECKHR(pAttrChild->get_nodeValue(&value));
  476. if (value.vt == VT_BSTR)
  477. {
  478. if ( wcscmp(V_BSTR(&value), xTCUSTOMIZED) == 0 )
  479. pLayout->fStandard = FALSE;
  480. else
  481. pLayout->fStandard = TRUE;
  482. }
  483. VariantClear(&value);
  484. break;
  485. }
  486. SafeReleaseClear(pattrs);
  487. }
  488. CHECKHR(pLayoutChild->get_firstChild(&pChild));
  489. pLayout->wLeft = 0;
  490. pLayout->wTop = 0;
  491. while ( pChild )
  492. {
  493. CHECKHR(pChild->get_nodeName(&nodeName));
  494. if ( wcscmp(nodeName, xWIDTH) == 0 )
  495. {
  496. CHECKHR(_GetXMLNodeValueWORD(pChild, &(pLayout->wWidth) ));
  497. }
  498. else if ( wcscmp(nodeName, xHEIGHT) == 0 )
  499. {
  500. CHECKHR(_GetXMLNodeValueWORD(pChild, &(pLayout->wHeight) ));
  501. }
  502. else if ( wcscmp(nodeName, xMARGIN_WIDTH) == 0 )
  503. {
  504. CHECKHR(_GetXMLNodeValueWORD(pChild, &(pLayout->wMarginWidth )));
  505. }
  506. else if ( wcscmp(nodeName, xMARGIN_HEIGHT) == 0 )
  507. {
  508. CHECKHR(_GetXMLNodeValueWORD(pChild, &(pLayout->wMarginHeight) ));
  509. }
  510. else if ( wcscmp(nodeName, xKEYNUMBER) == 0 )
  511. {
  512. CHECKHR(_GetXMLNodeValueWORD(pChild, &(pLayout->wNumberOfKeys) ));
  513. }
  514. else if ( wcscmp(nodeName, xKEY) == 0 )
  515. {
  516. KEYDES *pKeyDes;
  517. pKeyDes = &(pLayout->lpKeyDes[iKey]);
  518. CHECKHR(_ParseOneKeyInLayout(pChild, pKeyDes) );
  519. iKey++;
  520. }
  521. if (nodeName != NULL)
  522. {
  523. SysFreeString(nodeName);
  524. nodeName = NULL;
  525. }
  526. CHECKHR(pChild->get_nextSibling(&pNext));
  527. SafeReleaseClear(pChild);
  528. pChild = pNext;
  529. }
  530. CleanUp:
  531. if ( FAILED(hr) )
  532. {
  533. if (nodeName != NULL )
  534. {
  535. SysFreeString(nodeName);
  536. nodeName = NULL;
  537. }
  538. if ( pChild )
  539. SafeReleaseClear(pChild);
  540. }
  541. return hr;
  542. }
  543. /*******************************************************************************
  544. *
  545. * Method function: _ParseOneKeyInLabel( )
  546. *
  547. * Parse One Key in Label Description, fill the data structure for
  548. * the specified key
  549. *
  550. *
  551. /********************************************************************************/
  552. HRESULT CSoftKbd::_ParseOneKeyInLabel(IXMLDOMNode *pNode, KEYLABELS *lpKeyLabels)
  553. {
  554. IXMLDOMNode *pValueChild = NULL;
  555. HRESULT hr = S_OK;
  556. IXMLDOMNode *pAttrChild = NULL, *pKey=NULL, *pKeyNext=NULL;
  557. BSTR nodeName=NULL;
  558. IXMLDOMNamedNodeMap *pattrs=NULL;
  559. BSTR name=NULL;
  560. VARIANT value;
  561. int iState;
  562. iState = 0;
  563. if ( (pNode == NULL) || (lpKeyLabels == NULL) )
  564. {
  565. hr = E_FAIL;
  566. return hr;
  567. }
  568. CHECKHR(pNode->get_firstChild(&pKey));
  569. while ( pKey )
  570. {
  571. CHECKHR(pKey->get_nodeName(&nodeName));
  572. CHECKHR(pKey->get_firstChild(&pValueChild));
  573. CHECKHR(pValueChild->get_nodeValue(&value));
  574. if ( wcscmp(nodeName, xKEYID) == 0 )
  575. {
  576. lpKeyLabels->keyId = WstrToInt(V_BSTR(&value));
  577. }
  578. else if ( wcscmp(nodeName, xVALIDSTATES) == 0 )
  579. {
  580. lpKeyLabels->wNumModComb = WstrToInt(V_BSTR(&value));
  581. lpKeyLabels->lppLabelText = (BSTR *)cicMemAllocClear(
  582. lpKeyLabels->wNumModComb * sizeof(BSTR) );
  583. if ( lpKeyLabels->lppLabelText == NULL )
  584. {
  585. // Not enough memory.
  586. // release all allocated memory.
  587. hr = E_OUTOFMEMORY;
  588. goto CleanUp;
  589. }
  590. lpKeyLabels->lpLabelType = (WORD *)cicMemAllocClear(
  591. lpKeyLabels->wNumModComb * sizeof(WORD) );
  592. if ( lpKeyLabels->lpLabelType == NULL )
  593. {
  594. // Not enough memory.
  595. // release all allocated memory.
  596. hr = E_OUTOFMEMORY;
  597. goto CleanUp;
  598. }
  599. lpKeyLabels->lpLabelDisp = (WORD *)cicMemAllocClear(
  600. lpKeyLabels->wNumModComb * sizeof(WORD) );
  601. if ( lpKeyLabels->lpLabelDisp == NULL )
  602. {
  603. // Not enough memory.
  604. // release all allocated memory.
  605. hr = E_OUTOFMEMORY;
  606. goto CleanUp;
  607. }
  608. }
  609. else if ( wcscmp(nodeName, xLABELTEXT) == 0 )
  610. {
  611. if ( iState < lpKeyLabels->wNumModComb )
  612. {
  613. lpKeyLabels->lppLabelText[iState]=SysAllocString(V_BSTR(&value));
  614. // set the default value for label type and label disp attribute.
  615. lpKeyLabels->lpLabelType[iState] = LABEL_TEXT;
  616. lpKeyLabels->lpLabelDisp[iState] = LABEL_DISP_ACTIVE;
  617. // Get the label type: Text or Picture.
  618. // if it is picture, the above string stands for path of bitmap file.
  619. if (SUCCEEDED(pKey->get_attributes(&pattrs)) && pattrs != NULL)
  620. {
  621. CHECKHR(pattrs->nextNode(&pAttrChild));
  622. while (pAttrChild)
  623. {
  624. CHECKHR(pAttrChild->get_nodeName(&name));
  625. if ( wcscmp(name, xLABELTYPE) == 0 )
  626. {
  627. CHECKHR(pAttrChild->get_nodeValue(&value));
  628. if (value.vt == VT_BSTR)
  629. {
  630. if ( wcscmp(V_BSTR(&value),xTEXT ) == 0 )
  631. lpKeyLabels->lpLabelType[iState] = LABEL_TEXT;
  632. else
  633. lpKeyLabels->lpLabelType[iState] = LABEL_PICTURE;
  634. }
  635. VariantClear(&value);
  636. }
  637. else if ( wcscmp(name, xLABELDISP) == 0 )
  638. {
  639. CHECKHR(pAttrChild->get_nodeValue(&value));
  640. if (value.vt == VT_BSTR)
  641. {
  642. if ( wcscmp(V_BSTR(&value),xGRAY ) == 0 )
  643. lpKeyLabels->lpLabelDisp[iState] = LABEL_DISP_GRAY;
  644. else
  645. lpKeyLabels->lpLabelDisp[iState] = LABEL_DISP_ACTIVE;
  646. }
  647. VariantClear(&value);
  648. }
  649. if ( name != NULL)
  650. {
  651. SysFreeString(name);
  652. name = NULL;
  653. }
  654. SafeReleaseClear(pAttrChild);
  655. CHECKHR(pattrs->nextNode(&pAttrChild));
  656. }
  657. SafeReleaseClear(pattrs);
  658. }
  659. }
  660. iState++;
  661. }
  662. VariantClear(&value);
  663. SafeReleaseClear(pValueChild);
  664. if ( nodeName != NULL)
  665. {
  666. SysFreeString(nodeName);
  667. nodeName = NULL;
  668. }
  669. CHECKHR(pKey->get_nextSibling(&pKeyNext));
  670. SafeRelease(pKey);
  671. pKey = pKeyNext;
  672. }
  673. CleanUp:
  674. if ( FAILED(hr) )
  675. {
  676. if ( pKey )
  677. SafeReleaseClear(pKey);
  678. if ( name != NULL)
  679. {
  680. SysFreeString(name);
  681. name = NULL;
  682. }
  683. if ( pAttrChild )
  684. SafeReleaseClear(pAttrChild);
  685. if ( pValueChild )
  686. SafeReleaseClear(pValueChild);
  687. if ( lpKeyLabels->lppLabelText != NULL )
  688. {
  689. while ( iState >= 0 )
  690. {
  691. if ( lpKeyLabels->lppLabelText[iState] )
  692. {
  693. SysFreeString(lpKeyLabels->lppLabelText[iState]);
  694. lpKeyLabels->lppLabelText[iState] = NULL;
  695. }
  696. iState --;
  697. }
  698. SafeFreePointer(lpKeyLabels->lppLabelText);
  699. }
  700. if ( lpKeyLabels->lpLabelType != NULL )
  701. {
  702. SafeFreePointer(lpKeyLabels->lpLabelType);
  703. }
  704. if ( lpKeyLabels->lpLabelDisp != NULL )
  705. {
  706. SafeFreePointer(lpKeyLabels->lpLabelDisp);
  707. }
  708. }
  709. return hr;
  710. }
  711. /*******************************************************************************
  712. *
  713. * Method function: _ParseMappingDescription( )
  714. *
  715. * Parse Mapping description part in the XML file, and fill the internal
  716. * Mapping Table structure.
  717. *
  718. /********************************************************************************/
  719. HRESULT CSoftKbd::_ParseMappingDescription( IXMLDOMNode *pLabelChild, KEYMAP *lpKeyMapList )
  720. {
  721. HRESULT hr = S_OK;
  722. IXMLDOMNode *pChild=NULL, *pNext=NULL;
  723. BSTR nodeName=NULL;
  724. int iKey;
  725. BSTR pBURL = NULL;
  726. // Parse for customized layout
  727. if ( (pLabelChild == NULL) || (lpKeyMapList == NULL) )
  728. {
  729. hr = E_FAIL;
  730. return hr;
  731. }
  732. iKey = 0;
  733. CHECKHR(pLabelChild->get_firstChild(&pChild));
  734. while ( pChild )
  735. {
  736. CHECKHR(pChild->get_nodeName(&nodeName));
  737. if ( wcscmp(nodeName, xVALIDSTATES) == 0 )
  738. {
  739. CHECKHR(_GetXMLNodeValueWORD(pChild, &(lpKeyMapList->wNumModComb) ));
  740. }
  741. else if ( wcscmp(nodeName, xKEYNUMBER) == 0 )
  742. {
  743. CHECKHR(_GetXMLNodeValueWORD(pChild, &(lpKeyMapList->wNumOfKeys) ));
  744. }
  745. else if ( wcscmp(nodeName, xRESOURCEFILE) == 0 )
  746. {
  747. IXMLDOMNode *pValueChild;
  748. VARIANT value;
  749. CHECKHR(pChild->get_firstChild(&pValueChild));
  750. if ( FAILED((pValueChild->get_nodeValue(&value))))
  751. {
  752. SafeRelease(pValueChild);
  753. goto CleanUp;
  754. }
  755. StringCchCopyW(lpKeyMapList->wszResource, ARRAYSIZE(lpKeyMapList->wszResource), V_BSTR(&value) );
  756. VariantClear(&value);
  757. SafeRelease(pValueChild);
  758. }
  759. else if ( wcscmp(nodeName, xKEYLABEL) == 0 )
  760. {
  761. KEYLABELS *lpKeyLabels;
  762. lpKeyLabels = &(lpKeyMapList->lpKeyLabels[iKey]);
  763. CHECKHR(_ParseOneKeyInLabel(pChild, lpKeyLabels));
  764. iKey++;
  765. }
  766. if ( nodeName != NULL)
  767. {
  768. SysFreeString(nodeName);
  769. nodeName = NULL;
  770. }
  771. pChild->get_nextSibling(&pNext);
  772. SafeReleaseClear(pChild);
  773. pChild = pNext;
  774. }
  775. CleanUp:
  776. if ( FAILED(hr) )
  777. {
  778. if ( nodeName != NULL)
  779. {
  780. SysFreeString(nodeName);
  781. nodeName = NULL;
  782. }
  783. if ( pChild != NULL )
  784. SafeReleaseClear(pChild);
  785. if ( lpKeyMapList ) {
  786. int i, iState;
  787. for ( i=0; i<(int)(lpKeyMapList->wNumOfKeys); i++)
  788. {
  789. // free lppLabelText string for each state.
  790. for ( iState=0; iState < lpKeyMapList->lpKeyLabels[i].wNumModComb; iState++)
  791. {
  792. if (lpKeyMapList->lpKeyLabels[i].lppLabelText[iState])
  793. SysFreeString(lpKeyMapList->lpKeyLabels[i].lppLabelText[iState]);
  794. }
  795. SafeFreePointer(lpKeyMapList->lpKeyLabels[i].lppLabelText);
  796. SafeFreePointer(lpKeyMapList->lpKeyLabels[i].lpLabelType);
  797. SafeFreePointer(lpKeyMapList->lpKeyLabels[i].lpLabelDisp);
  798. }
  799. }
  800. }
  801. return hr;
  802. }
  803. /*******************************************************************************
  804. *
  805. * Method function: _GenerateMapDesFromSKD( )
  806. *
  807. * Generate Mapping description part in the KBD file, and fill the internal
  808. * Mapping Table structure.
  809. *
  810. /********************************************************************************/
  811. HRESULT CSoftKbd::_GenerateMapDesFromSKD(BYTE *pMapTable, KEYMAP *lpKeyMapList)
  812. {
  813. HRESULT hr = S_OK;
  814. int iKey;
  815. WORD wNumModComb;
  816. WORD wNumOfKeys;
  817. WORD *pMapPtr;
  818. // Parse for customized layout
  819. // Customized layout doesn't care about HKL, so there will be only one KeyMapList per layout.
  820. if ( (pMapTable == NULL) || (lpKeyMapList == NULL) ) return E_FAIL;
  821. pMapPtr = (WORD *)pMapTable;
  822. wNumModComb = pMapPtr[0];
  823. wNumOfKeys = pMapPtr[1];
  824. pMapPtr += 2;
  825. lpKeyMapList->wNumModComb = wNumModComb;
  826. lpKeyMapList->wNumOfKeys = wNumOfKeys;
  827. StringCchCopyW(lpKeyMapList->wszResource, ARRAYSIZE(lpKeyMapList->wszResource), (WCHAR *)pMapPtr);
  828. pMapPtr += wcslen((WCHAR *)pMapPtr) + 1; // Plus NULL terminator
  829. // Now strat to fill every Keylabel.
  830. for ( iKey=0; iKey<wNumOfKeys; iKey++)
  831. {
  832. KEYLABELS *lpKeyLabel;
  833. WORD wNumModInKey;
  834. int jMod;
  835. lpKeyLabel = &(lpKeyMapList->lpKeyLabels[iKey]);
  836. lpKeyLabel->keyId = *pMapPtr;
  837. pMapPtr += sizeof(KEYID)/sizeof(WORD);
  838. wNumModInKey = *pMapPtr;
  839. pMapPtr++;
  840. lpKeyLabel->wNumModComb = wNumModInKey;
  841. lpKeyLabel->lppLabelText=(BSTR *)cicMemAllocClear(lpKeyLabel->wNumModComb * sizeof(BSTR) );
  842. if ( lpKeyLabel->lppLabelText == NULL )
  843. {
  844. // Not enough memory.
  845. // release all allocated memory.
  846. hr = E_OUTOFMEMORY;
  847. goto CleanUp;
  848. }
  849. lpKeyLabel->lpLabelType = (WORD *)cicMemAllocClear(lpKeyLabel->wNumModComb * sizeof(WORD) );
  850. if ( lpKeyLabel->lpLabelType == NULL )
  851. {
  852. // Not enough memory.
  853. // release all allocated memory.
  854. hr = E_OUTOFMEMORY;
  855. goto CleanUp;
  856. }
  857. lpKeyLabel->lpLabelDisp = (WORD *)cicMemAllocClear(lpKeyLabel->wNumModComb * sizeof(WORD));
  858. if ( lpKeyLabel->lpLabelDisp == NULL )
  859. {
  860. // Not enough memory.
  861. // release all allocated memory.
  862. hr = E_OUTOFMEMORY;
  863. goto CleanUp;
  864. }
  865. for ( jMod=0; jMod < wNumModInKey; jMod++)
  866. {
  867. lpKeyLabel->lppLabelText[jMod] = SysAllocString( pMapPtr );
  868. pMapPtr += wcslen(pMapPtr) + 1;
  869. }
  870. CopyMemory(lpKeyLabel->lpLabelType, pMapPtr, wNumModInKey * sizeof(WORD) );
  871. pMapPtr += wNumModInKey;
  872. CopyMemory(lpKeyLabel->lpLabelDisp, pMapPtr, wNumModInKey * sizeof(WORD) );
  873. pMapPtr += wNumModInKey;
  874. }
  875. CleanUp:
  876. if ( FAILED(hr) )
  877. {
  878. // Release all allocated memory in this function.
  879. int i;
  880. for (i=0; i<=iKey; i++)
  881. {
  882. KEYLABELS *lpKeyLabel;
  883. int jMod;
  884. if (lpKeyLabel = &(lpKeyMapList->lpKeyLabels[i]))
  885. {
  886. // free lppLabelText string for each state.
  887. for ( jMod=0; jMod<lpKeyLabel->wNumModComb; jMod++)
  888. {
  889. if (lpKeyLabel->lppLabelText && lpKeyLabel->lppLabelText[jMod])
  890. SysFreeString(lpKeyLabel->lppLabelText[jMod]);
  891. }
  892. SafeFreePointer(lpKeyLabel->lppLabelText);
  893. SafeFreePointer(lpKeyLabel->lpLabelType);
  894. SafeFreePointer(lpKeyLabel->lpLabelDisp);
  895. }
  896. }
  897. }
  898. return hr;
  899. }
  900. /*******************************************************************************
  901. *
  902. * Method function: ParseKeyboardLayout( )
  903. *
  904. * Parse Keyboard Layout description XML file, and fill the internal
  905. * Layout and Mapping Table structure.
  906. *
  907. * if fFileName is TRUE, means lpszKeyboardDesFile stands for a file name
  908. * if it is FALSE, lpszKeyboardDesFile points to the real memory block which
  909. * contains XML content.
  910. /********************************************************************************/
  911. HRESULT CSoftKbd::_ParseKeyboardLayout(BOOL fFileName, WCHAR *lpszKeyboardDesFile, DWORD dwKbdLayoutID, KBDLAYOUTDES **lppKbdLayout )
  912. {
  913. KBDLAYOUTDES *pKbdLayout = NULL;
  914. KBDLAYOUT *pLayout = NULL;
  915. IXMLDOMNode *pNode = NULL;
  916. IXMLDOMNode *pLayoutChild =NULL, *pLabelChild = NULL, *pNext = NULL, *pRoot=NULL ;
  917. BSTR nodeName=NULL;
  918. KEYMAP *lpKeyMapList = NULL;
  919. BSTR pBURL = NULL;
  920. HRESULT hr = S_OK;
  921. if ( (lpszKeyboardDesFile == NULL) || ( lppKbdLayout == NULL) )
  922. {
  923. //
  924. // this is not appropriate parameter.
  925. //
  926. hr = E_FAIL;
  927. return hr;
  928. }
  929. if ( _pDoc == NULL )
  930. {
  931. // the first time this method is called.
  932. hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  933. IID_IXMLDOMDocument, (void**)&_pDoc);
  934. if ( FAILED(hr) )
  935. return hr;
  936. }
  937. pKbdLayout = (KBDLAYOUTDES *)cicMemAllocClear(sizeof(KBDLAYOUTDES) );
  938. if ( pKbdLayout == NULL )
  939. {
  940. hr = E_OUTOFMEMORY;
  941. return hr;
  942. }
  943. pKbdLayout->wKbdLayoutID = dwKbdLayoutID;
  944. pKbdLayout->ModifierStatus = 0;
  945. pKbdLayout->CurModiState = 0;
  946. pKbdLayout->lpKeyMapList = NULL;
  947. if ( fFileName == TRUE )
  948. StringCchCopyW(pKbdLayout->KbdLayoutDesFile, ARRAYSIZE(pKbdLayout->KbdLayoutDesFile), lpszKeyboardDesFile );
  949. else
  950. {
  951. //
  952. // we just set "_string" at this moment,
  953. // after this function returns, the caller needs to set the real
  954. // file path + resource ID as its new desfilepath.
  955. //
  956. wcscpy(pKbdLayout->KbdLayoutDesFile, L"_String");
  957. }
  958. pLayout = &(pKbdLayout->kbdLayout);
  959. if ( fFileName == TRUE )
  960. pBURL = SysAllocString(lpszKeyboardDesFile);
  961. else
  962. pBURL = lpszKeyboardDesFile;
  963. CHECKHR(_LoadDocumentSync(pBURL, fFileName));
  964. CHECKHR(_pDoc->QueryInterface(IID_IXMLDOMNode,(void**)&pNode));
  965. CHECKHR(pNode->get_firstChild(&pRoot));
  966. CHECKHR(pRoot->get_nodeName(&nodeName));
  967. // Get the Root node
  968. while ( wcscmp(nodeName, xSOFTKBDDES) ) {
  969. pRoot->get_nextSibling(&pNext);
  970. pRoot->Release();
  971. pRoot = pNext;
  972. if ( nodeName != NULL )
  973. SysFreeString(nodeName);
  974. pRoot->get_nodeName(&nodeName);
  975. }
  976. if ( nodeName != NULL )
  977. SysFreeString(nodeName);
  978. // Get the layout child and label child,
  979. pLayoutChild = pLabelChild = NULL;
  980. pRoot->get_firstChild(&pLayoutChild);
  981. if ( pLayoutChild != NULL )
  982. pLayoutChild->get_nextSibling(&pLabelChild);
  983. CHECKHR(_ParseLayoutDescription(pLayoutChild, pLayout) );
  984. // Handle Label part.
  985. if ( pLayout->fStandard == TRUE )
  986. {
  987. //
  988. // Generate mapping table for standard layout
  989. //
  990. // Mapping table is generated by SetKeyboardLabelText( ) method.
  991. goto CleanUp;
  992. }
  993. if ( pLabelChild == NULL )
  994. {
  995. // the XML file is not complete.
  996. hr = E_FAIL;
  997. goto CleanUp;
  998. }
  999. lpKeyMapList = (KEYMAP *)cicMemAllocClear(sizeof(KEYMAP) );
  1000. if ( lpKeyMapList == NULL )
  1001. {
  1002. SafeFreePointer(pKbdLayout);
  1003. hr = E_OUTOFMEMORY;
  1004. goto CleanUp;
  1005. }
  1006. CHECKHR(_ParseMappingDescription(pLabelChild, lpKeyMapList));
  1007. pKbdLayout->lpKeyMapList = lpKeyMapList;
  1008. CleanUp:
  1009. SafeReleaseClear(pLayoutChild);
  1010. if ( pLabelChild != NULL )
  1011. pLabelChild->Release( );
  1012. SafeReleaseClear(pRoot);
  1013. SafeReleaseClear(pNode);
  1014. if ( fFileName == TRUE )
  1015. SysFreeString(pBURL);
  1016. if ( FAILED(hr) )
  1017. {
  1018. if ( pKbdLayout != NULL )
  1019. SafeFreePointer(pKbdLayout);
  1020. if ( lpKeyMapList != NULL )
  1021. SafeFreePointer( lpKeyMapList );
  1022. }
  1023. else
  1024. {
  1025. if ( lppKbdLayout != NULL )
  1026. *lppKbdLayout = pKbdLayout;
  1027. }
  1028. return hr;
  1029. }
  1030. /*******************************************************************************
  1031. *
  1032. * Method function: _GenerateKeyboardLayoutFromSKD( )
  1033. *
  1034. * KBD file is a precompiled xml file, it is binary format, This KBD has been put
  1035. * into the resource section of DLL, the resource type is SKDFILE.
  1036. *
  1037. * This method function will read the resource content and try to fill the internal
  1038. * Layout and Mapping Table structure.
  1039. *
  1040. ********************************************************************************/
  1041. HRESULT CSoftKbd::_GenerateKeyboardLayoutFromSKD(BYTE *lpszKeyboardDes, DWORD dwKbdLayoutID, KBDLAYOUTDES **lppKbdLayout)
  1042. {
  1043. KBDLAYOUTDES *pKbdLayout = NULL;
  1044. KBDLAYOUT *pLayout = NULL;
  1045. BYTE *pMapTable = NULL;
  1046. KEYMAP *lpKeyMapList = NULL;
  1047. WORD wNumberOfKeys, wLenLayout;
  1048. HRESULT hr = S_OK;
  1049. if ( (lpszKeyboardDes == NULL) || ( lppKbdLayout == NULL) )
  1050. {
  1051. //
  1052. // this is not appropriate parameter.
  1053. //
  1054. return E_FAIL;
  1055. }
  1056. pKbdLayout = (KBDLAYOUTDES *)cicMemAllocClear(sizeof(KBDLAYOUTDES) );
  1057. if ( pKbdLayout == NULL )
  1058. {
  1059. hr = E_OUTOFMEMORY;
  1060. return hr;
  1061. }
  1062. pKbdLayout->wKbdLayoutID = dwKbdLayoutID;
  1063. pKbdLayout->ModifierStatus = 0;
  1064. pKbdLayout->CurModiState = 0;
  1065. pKbdLayout->lpKeyMapList = NULL;
  1066. //
  1067. // we just set "_string" at this moment,
  1068. // after this function returns, the caller needs to set the real
  1069. // file path + resource ID as its new desfilepath.
  1070. //
  1071. wcscpy(pKbdLayout->KbdLayoutDesFile, L"_String");
  1072. pLayout = &(pKbdLayout->kbdLayout);
  1073. // Fill the layout internal structure from lpszKeyboardDes.
  1074. wNumberOfKeys = *(lpszKeyboardDes + sizeof(WORD) * 6 + sizeof(BOOL));
  1075. wLenLayout = sizeof(WORD) * 7 + sizeof(BOOL) + wNumberOfKeys * sizeof(KEYDES);
  1076. CopyMemory(pLayout, lpszKeyboardDes, wLenLayout);
  1077. // Handle Label part.
  1078. if ( pLayout->fStandard == TRUE )
  1079. {
  1080. // Mapping table is generated later by SetKeyboardLabelText( ) method.
  1081. goto CleanUp;
  1082. }
  1083. lpKeyMapList=(KEYMAP *)cicMemAllocClear(sizeof(KEYMAP));
  1084. if ( lpKeyMapList == NULL )
  1085. {
  1086. SafeFreePointer(pKbdLayout);
  1087. hr = E_OUTOFMEMORY;
  1088. goto CleanUp;
  1089. }
  1090. //Get the start position of Mapping Table content.
  1091. pMapTable = lpszKeyboardDes + wLenLayout;
  1092. CHECKHR(_GenerateMapDesFromSKD(pMapTable, lpKeyMapList));
  1093. pKbdLayout->lpKeyMapList = lpKeyMapList;
  1094. CleanUp:
  1095. if ( FAILED(hr) )
  1096. {
  1097. if ( pKbdLayout != NULL )
  1098. SafeFreePointer(pKbdLayout);
  1099. if ( lpKeyMapList != NULL )
  1100. SafeFreePointer( lpKeyMapList );
  1101. }
  1102. else
  1103. {
  1104. if ( lppKbdLayout != NULL )
  1105. *lppKbdLayout = pKbdLayout;
  1106. }
  1107. return hr;
  1108. }
  1109. /*******************************************************************************
  1110. *
  1111. * Method function: CreateSoftKeyboardLayoutFromXMLFile( )
  1112. *
  1113. * Create the real Soft Keyboard layout based on specified description XML file.
  1114. *
  1115. /********************************************************************************/
  1116. STDMETHODIMP CSoftKbd::CreateSoftKeyboardLayoutFromXMLFile(WCHAR *lpszKeyboardDesFile,INT szFileStrLen, DWORD *pdwLayoutCookie)
  1117. {
  1118. DWORD dwCurKbdLayoutID;
  1119. KBDLAYOUTDES *pKbdLayout=NULL;
  1120. HRESULT hr = S_OK;
  1121. dwCurKbdLayoutID = SOFTKBD_CUSTOMIZE_BEGIN;
  1122. if ( _lpKbdLayoutDesList != NULL )
  1123. {
  1124. // check if this des file is alreay parsed.
  1125. pKbdLayout = _lpKbdLayoutDesList;
  1126. while ( pKbdLayout != NULL ) {
  1127. if ( pKbdLayout->wKbdLayoutID > dwCurKbdLayoutID )
  1128. dwCurKbdLayoutID = pKbdLayout->wKbdLayoutID;
  1129. if ( wcscmp(pKbdLayout->KbdLayoutDesFile, lpszKeyboardDesFile) == 0 )
  1130. {
  1131. // find it.
  1132. *pdwLayoutCookie = pKbdLayout->wKbdLayoutID;
  1133. hr = S_OK;
  1134. return hr;
  1135. }
  1136. pKbdLayout = pKbdLayout->pNext;
  1137. }
  1138. }
  1139. // this is a new des file
  1140. dwCurKbdLayoutID ++;
  1141. CHECKHR(_ParseKeyboardLayout(TRUE, lpszKeyboardDesFile, dwCurKbdLayoutID, &pKbdLayout));
  1142. // link this new layout to the list.
  1143. pKbdLayout->CurModiState = 0; // use state 0 as initialization
  1144. if ( _lpKbdLayoutDesList == NULL ) {
  1145. _lpKbdLayoutDesList = pKbdLayout;
  1146. pKbdLayout->pNext = NULL;
  1147. }
  1148. else
  1149. {
  1150. pKbdLayout->pNext = _lpKbdLayoutDesList;
  1151. _lpKbdLayoutDesList = pKbdLayout;
  1152. }
  1153. *pdwLayoutCookie = pKbdLayout->wKbdLayoutID;
  1154. CleanUp:
  1155. return hr;
  1156. }
  1157. /*******************************************************************************
  1158. *
  1159. * Method function: CreateSoftKeyboardLayoutFromResource( )
  1160. *
  1161. * Create the real Soft Keyboard layout based on XML content in resource section
  1162. * There will be two kinds of resouces, XMLFILE, and SKDFILE, SKDFILE is a
  1163. * Precomipled XML binary file.
  1164. *
  1165. * lpszResFile : path of file which contains XML content in its resource.
  1166. * lpszResString : resource string identifier for the XML or KBD resource.
  1167. *
  1168. * the resource Type could be either "XMLFILE" or "SKDFILE"
  1169. *
  1170. * lpdwLayoutCookie: receive the returned layout id.
  1171. *
  1172. /********************************************************************************/
  1173. HRESULT CSoftKbd::CreateSoftKeyboardLayoutFromResource(WCHAR *lpszResFile, WCHAR *lpszResType, WCHAR *lpszResString, DWORD *lpdwLayoutCookie)
  1174. {
  1175. DWORD dwCurKbdLayoutID;
  1176. KBDLAYOUTDES *pKbdLayout=NULL;
  1177. WCHAR *lpszKeyboardDesFile=NULL;
  1178. WCHAR wszInternalDesFileName[MAX_PATH];
  1179. CHAR lpszAnsiResString[MAX_PATH];
  1180. CHAR lpszAnsiResFile[MAX_PATH];
  1181. CHAR lpszAnsiResType[MAX_PATH];
  1182. HMODULE hResFile = NULL;
  1183. HRSRC hRsRc = NULL;
  1184. HGLOBAL hResData = NULL;
  1185. HRESULT hr = S_OK;
  1186. BOOL fXMLUnicode=TRUE;
  1187. DWORD dwResLen;
  1188. if ( (lpszResFile == NULL) || (lpszResString == NULL) || (lpszResType == NULL) || ( lpdwLayoutCookie == NULL) )
  1189. {
  1190. hr = E_FAIL;
  1191. return hr;
  1192. }
  1193. //
  1194. // Generate internal DesFile Name
  1195. //
  1196. StringCchCopyW(wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), lpszResType);
  1197. StringCchCatW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), L":");
  1198. StringCchCatW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), lpszResFile );
  1199. StringCchCatW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), L":");
  1200. StringCchCatW( wszInternalDesFileName, ARRAYSIZE(wszInternalDesFileName), lpszResString );
  1201. dwCurKbdLayoutID = SOFTKBD_CUSTOMIZE_BEGIN;
  1202. if ( _lpKbdLayoutDesList != NULL )
  1203. {
  1204. // check if this des file is alreay parsed.
  1205. pKbdLayout = _lpKbdLayoutDesList;
  1206. while ( pKbdLayout != NULL ) {
  1207. if ( pKbdLayout->wKbdLayoutID > dwCurKbdLayoutID )
  1208. dwCurKbdLayoutID = pKbdLayout->wKbdLayoutID;
  1209. if ( wcscmp(pKbdLayout->KbdLayoutDesFile, wszInternalDesFileName) == 0 )
  1210. {
  1211. // find it.
  1212. *lpdwLayoutCookie = pKbdLayout->wKbdLayoutID;
  1213. hr = S_OK;
  1214. return hr;
  1215. }
  1216. pKbdLayout = pKbdLayout->pNext;
  1217. }
  1218. }
  1219. // this is a new des file
  1220. dwCurKbdLayoutID ++;
  1221. WideCharToMultiByte(CP_ACP, 0, lpszResFile, -1,
  1222. lpszAnsiResFile, MAX_PATH, NULL, NULL );
  1223. hResFile = LoadLibraryA(lpszAnsiResFile);
  1224. if ( hResFile == NULL )
  1225. {
  1226. hr = E_FAIL;
  1227. goto CleanUp;
  1228. }
  1229. WideCharToMultiByte(CP_ACP, 0, lpszResString, -1,
  1230. lpszAnsiResString, MAX_PATH, NULL, NULL );
  1231. WideCharToMultiByte(CP_ACP, 0, lpszResType, -1,
  1232. lpszAnsiResType, MAX_PATH, NULL, NULL );
  1233. hRsRc = FindResourceA(hResFile, lpszAnsiResString, lpszAnsiResType );
  1234. if ( hRsRc == NULL )
  1235. {
  1236. hr = E_FAIL;
  1237. goto CleanUp;
  1238. }
  1239. dwResLen = SizeofResource(hResFile, hRsRc);
  1240. hResData = LoadResource(hResFile, hRsRc );
  1241. if ( hResData == NULL )
  1242. {
  1243. hr = E_FAIL;
  1244. goto CleanUp;
  1245. }
  1246. lpszKeyboardDesFile = (WCHAR *)LockResource(hResData);
  1247. if ( lpszKeyboardDesFile == NULL )
  1248. {
  1249. hr = E_FAIL;
  1250. goto CleanUp;
  1251. }
  1252. if ( wcscmp(lpszResType, L"SKDFILE") == 0 )
  1253. {
  1254. CHECKHR(_GenerateKeyboardLayoutFromSKD((BYTE *)lpszKeyboardDesFile, dwCurKbdLayoutID, &pKbdLayout));
  1255. }
  1256. else if ( wcscmp(lpszResType, L"XMLFILE") == 0 )
  1257. {
  1258. // This is XMLFILE resource
  1259. //
  1260. // we assume the XML content in resource is in Unicode format.
  1261. //
  1262. if ( lpszKeyboardDesFile[0] == 0xFEFF )
  1263. {
  1264. fXMLUnicode = TRUE;
  1265. lpszKeyboardDesFile = lpszKeyboardDesFile + 1;
  1266. }
  1267. else
  1268. {
  1269. // if the content is UTF-8, we need to translate the string to Unicode
  1270. //
  1271. char *lpszXMLContentUtf8;
  1272. int iSize;
  1273. lpszXMLContentUtf8 = (char *)lpszKeyboardDesFile;
  1274. lpszKeyboardDesFile = NULL;
  1275. iSize = _Utf8ToUnicode(lpszXMLContentUtf8, dwResLen ,NULL, 0 );
  1276. if ( iSize == 0 )
  1277. {
  1278. hr = E_FAIL;
  1279. goto CleanUp;
  1280. }
  1281. fXMLUnicode = FALSE;
  1282. lpszKeyboardDesFile = (WCHAR *) cicMemAllocClear( (iSize+1) * sizeof(WCHAR) );
  1283. if ( lpszKeyboardDesFile == NULL )
  1284. {
  1285. hr = E_FAIL;
  1286. goto CleanUp;
  1287. }
  1288. iSize = _Utf8ToUnicode(lpszXMLContentUtf8, dwResLen,lpszKeyboardDesFile, iSize+1 );
  1289. if ( iSize == 0 )
  1290. {
  1291. hr = E_FAIL;
  1292. goto CleanUp;
  1293. }
  1294. lpszKeyboardDesFile[iSize] = L'\0';
  1295. }
  1296. CHECKHR(_ParseKeyboardLayout(FALSE, lpszKeyboardDesFile, dwCurKbdLayoutID, &pKbdLayout));
  1297. }
  1298. else
  1299. {
  1300. // This resource type is not supported.
  1301. hr = E_FAIL;
  1302. goto CleanUp;
  1303. }
  1304. // Change the internal DesFile name as following format:
  1305. //
  1306. // XMLRES: ResFileName : XMLResString to identify this layout's des file.
  1307. // Or
  1308. // KBDRES: ResFileName : KBDResString
  1309. //
  1310. wcscpy(pKbdLayout->KbdLayoutDesFile, wszInternalDesFileName);
  1311. // link this new layout to the list.
  1312. pKbdLayout->CurModiState = 0; // use state 0 as initialization
  1313. if ( _lpKbdLayoutDesList == NULL ) {
  1314. _lpKbdLayoutDesList = pKbdLayout;
  1315. pKbdLayout->pNext = NULL;
  1316. }
  1317. else
  1318. {
  1319. pKbdLayout->pNext = _lpKbdLayoutDesList;
  1320. _lpKbdLayoutDesList = pKbdLayout;
  1321. }
  1322. *lpdwLayoutCookie = pKbdLayout->wKbdLayoutID;
  1323. CleanUp:
  1324. if ( hResFile != NULL )
  1325. FreeLibrary(hResFile);
  1326. if ( (fXMLUnicode == FALSE) && ( lpszKeyboardDesFile != NULL ) )
  1327. SafeFreePointer(lpszKeyboardDesFile);
  1328. return hr;
  1329. }
  1330. HRESULT CSoftKbd::_GenerateRealKbdLayout( )
  1331. {
  1332. float fWidRat, fHigRat;
  1333. INT i;
  1334. KBDLAYOUT *realKbdLayout;
  1335. HRESULT hr;
  1336. WORD skbd_x, skbd_y, skbd_width, skbd_height;
  1337. BOOL fNewTitleSize = FALSE;
  1338. hr = S_OK;
  1339. if ( (_xReal == 0) &&
  1340. (_yReal == 0 ) &&
  1341. (_widthReal == 0) &&
  1342. (_heightReal == 0) )
  1343. {
  1344. //
  1345. // means CreateSoftKeyboardWindow( ) has not been called yet
  1346. // we don't do more things.
  1347. //
  1348. return hr;
  1349. }
  1350. //
  1351. // The soft keyboard window has already been created, and the window size is set,
  1352. // generate realKbdLayout by extending or shrinking the key size from the size
  1353. // specified in the des file.
  1354. //
  1355. // check if there is SoftKeyboard Layout is set.
  1356. //
  1357. if ( _wCurKbdLayoutID == NON_KEYBOARD || _lpCurKbdLayout == NULL )
  1358. {
  1359. //
  1360. // No layout is selected.
  1361. //
  1362. return hr;
  1363. }
  1364. // Generate the titlebar rect size, and button panel rectangle size.
  1365. // Keep the relative postion. ( window client coordinate )
  1366. switch ( _TitleBar_Type )
  1367. {
  1368. case TITLEBAR_NONE :
  1369. _TitleBarRect.left = 0;
  1370. _TitleBarRect.top = 0;
  1371. _TitleBarRect.right = 0;
  1372. _TitleBarRect.bottom = 0;
  1373. break;
  1374. case TITLEBAR_GRIPPER_HORIZ_ONLY :
  1375. _TitleBarRect.left = 0;
  1376. _TitleBarRect.top = 0;
  1377. _TitleBarRect.right = _TitleBarRect.left + _widthReal - 1;
  1378. _TitleBarRect.bottom = _TitleBarRect.top + 6;
  1379. break;
  1380. case TITLEBAR_GRIPPER_VERTI_ONLY :
  1381. _TitleBarRect.left = 0;
  1382. _TitleBarRect.top = 0;
  1383. _TitleBarRect.right = _TitleBarRect.left + 6;
  1384. _TitleBarRect.bottom = _TitleBarRect.top + _heightReal - 1;
  1385. break;
  1386. case TITLEBAR_GRIPPER_BUTTON :
  1387. // assume to use horizontal title bar.
  1388. _TitleBarRect.left = 0;
  1389. _TitleBarRect.top = 0;
  1390. _TitleBarRect.right = _TitleBarRect.left + _widthReal - 1;
  1391. _TitleBarRect.bottom = _TitleBarRect.top + 16;
  1392. fNewTitleSize = TRUE;
  1393. break;
  1394. }
  1395. if ( (_TitleBarRect.right - _TitleBarRect.left + 1) == _widthReal )
  1396. {
  1397. // This is a horizontal titlebar
  1398. skbd_x = 0;
  1399. skbd_y = (WORD)_TitleBarRect.bottom + 1;
  1400. skbd_width = (WORD)_widthReal;
  1401. skbd_height = (WORD)_heightReal - (WORD)(_TitleBarRect.bottom - _TitleBarRect.top + 1 );
  1402. }
  1403. else if ((_TitleBarRect.bottom - _TitleBarRect.top + 1) == _heightReal )
  1404. {
  1405. // This is a vertical titlebar.
  1406. skbd_y = 0;
  1407. skbd_x = (WORD)_TitleBarRect.right + 1;
  1408. skbd_height = (WORD)_heightReal;
  1409. skbd_width = (WORD)_widthReal - (WORD)(_TitleBarRect.right - _TitleBarRect.left + 1 );
  1410. }
  1411. else
  1412. {
  1413. // there is no titlebar
  1414. skbd_x = 0;
  1415. skbd_y = 0;
  1416. skbd_height = (WORD)_heightReal;
  1417. skbd_width = (WORD) _widthReal;
  1418. }
  1419. realKbdLayout = &( _lpCurKbdLayout->kbdLayout );
  1420. if ( (realKbdLayout->wWidth == skbd_width) && (realKbdLayout->wHeight == skbd_height) )
  1421. {
  1422. // this keyboard layout has been already adjusted.
  1423. //
  1424. hr = S_OK;
  1425. return hr;
  1426. }
  1427. if ( (realKbdLayout->wWidth == 0) || ( realKbdLayout->wHeight==0) )
  1428. {
  1429. Assert(0);
  1430. hr = E_FAIL;
  1431. return hr;
  1432. }
  1433. fWidRat = (float)skbd_width / (float)realKbdLayout->wWidth;
  1434. fHigRat = (float)(skbd_height) / (float) realKbdLayout->wHeight;
  1435. // Adjust every key's size
  1436. realKbdLayout->wMarginWidth = (WORD)((float)realKbdLayout->wMarginWidth * fWidRat);
  1437. realKbdLayout->wMarginHeight = (WORD)((float)realKbdLayout->wMarginHeight * fHigRat);
  1438. for ( i=0; i< realKbdLayout->wNumberOfKeys; i++ )
  1439. {
  1440. WORD wLeft;
  1441. WORD wTop;
  1442. WORD wWidth;
  1443. WORD wHeight;
  1444. wLeft = (WORD)((float)(realKbdLayout->lpKeyDes[i].wLeft - realKbdLayout->wLeft ) * fWidRat);
  1445. wTop = (WORD)((float)(realKbdLayout->lpKeyDes[i].wTop - realKbdLayout->wTop) * fHigRat);
  1446. wWidth = (WORD)((float)realKbdLayout->lpKeyDes[i].wWidth * fWidRat);
  1447. wHeight = (WORD)((float)realKbdLayout->lpKeyDes[i].wHeight * fHigRat);
  1448. realKbdLayout->lpKeyDes[i].wLeft = wLeft + skbd_x;
  1449. realKbdLayout->lpKeyDes[i].wTop = wTop + skbd_y;
  1450. realKbdLayout->lpKeyDes[i].wWidth = wWidth;
  1451. realKbdLayout->lpKeyDes[i].wHeight = wHeight;
  1452. }
  1453. realKbdLayout->wLeft = (WORD)skbd_x;
  1454. realKbdLayout->wTop = (WORD)skbd_y;
  1455. realKbdLayout->wWidth = (WORD)skbd_width;
  1456. realKbdLayout->wHeight = (WORD)skbd_height;
  1457. if ( fNewTitleSize )
  1458. {
  1459. _TitleBarRect.left = realKbdLayout->lpKeyDes[0].wLeft;
  1460. _TitleBarRect.right = realKbdLayout->lpKeyDes[realKbdLayout->wNumberOfKeys-1].wLeft +
  1461. realKbdLayout->lpKeyDes[realKbdLayout->wNumberOfKeys-1].wWidth - 1;
  1462. }
  1463. return hr;
  1464. }
  1465. /*******************************************************************************
  1466. *
  1467. * Method function: SelectSoftKeyboard( )
  1468. *
  1469. * Select current Active soft keyboard layout.
  1470. *
  1471. /********************************************************************************/
  1472. STDMETHODIMP CSoftKbd::SelectSoftKeyboard(DWORD dwKeyboardId)
  1473. {
  1474. HRESULT hr;
  1475. KBDLAYOUTDES *pKbdLayout;
  1476. hr = S_OK;
  1477. if ( _wCurKbdLayoutID == dwKeyboardId )
  1478. return hr;
  1479. pKbdLayout = _lpKbdLayoutDesList;
  1480. while ( pKbdLayout != NULL ) {
  1481. if ( pKbdLayout->wKbdLayoutID == dwKeyboardId )
  1482. break;
  1483. pKbdLayout = pKbdLayout->pNext;
  1484. }
  1485. if ( pKbdLayout == NULL )
  1486. {
  1487. //
  1488. // Cannot find this keyboard layout
  1489. //
  1490. hr = E_FAIL;
  1491. return hr;
  1492. }
  1493. _lpCurKbdLayout = pKbdLayout;
  1494. _wCurKbdLayoutID = dwKeyboardId;
  1495. // initialize realKbdLayout
  1496. hr = _GenerateRealKbdLayout( );
  1497. if ( _pSoftkbdUIWnd )
  1498. {
  1499. hr=_pSoftkbdUIWnd->_GenerateWindowLayout( );
  1500. }
  1501. return hr;
  1502. }
  1503. /*******************************************************************************
  1504. *
  1505. * Method function: _SetStandardLabelText( )
  1506. *
  1507. * Generate mapping table in a certain modifier status for a standard soft
  1508. * keyboard.
  1509. *
  1510. /********************************************************************************/
  1511. HRESULT CSoftKbd::_SetStandardLabelText(LPBYTE pKeyState, KBDLAYOUT *realKbdLayout,
  1512. KEYMAP *lpKeyMapList, int iState)
  1513. {
  1514. UINT i, j, nKeyNum;
  1515. UINT uVirtkey, uScanCode;
  1516. HRESULT hr;
  1517. hr = S_OK;
  1518. nKeyNum = (UINT)(realKbdLayout->wNumberOfKeys);
  1519. // fill _CurLabel
  1520. for ( i=0; i<nKeyNum; i++) {
  1521. // Assume the KEYID is scancode.
  1522. WCHAR szLabel[MAX_LABEL_LEN];
  1523. int iRet, jIndex;
  1524. KEYID keyId;
  1525. BOOL fPitcureKey;
  1526. PICTUREKEY *pPictureKeys;
  1527. switch ( _wCurKbdLayoutID ) {
  1528. case SOFTKBD_JPN_STANDARD :
  1529. case SOFTKBD_JPN_ENHANCE :
  1530. pPictureKeys = gJpnPictureKeys;
  1531. break;
  1532. case SOFTKBD_US_STANDARD :
  1533. case SOFTKBD_US_ENHANCE :
  1534. case SOFTKBD_EURO_STANDARD :
  1535. case SOFTKBD_EURO_ENHANCE :
  1536. pPictureKeys = gPictureKeys;
  1537. break;
  1538. }
  1539. keyId = lpKeyMapList->lpKeyLabels[i].keyId = realKbdLayout->lpKeyDes[i].keyId;
  1540. fPitcureKey = FALSE;
  1541. for ( j=0; j<NUM_PICTURE_KEYS; j++)
  1542. {
  1543. if ( pPictureKeys[j].uScanCode == keyId )
  1544. {
  1545. // this is a picture key.
  1546. fPitcureKey = TRUE;
  1547. jIndex = j;
  1548. break;
  1549. }
  1550. if ( pPictureKeys[j].uScanCode == 0 )
  1551. {
  1552. // This is the last item in pPictureKeys.
  1553. break;
  1554. }
  1555. }
  1556. if ( fPitcureKey )
  1557. {
  1558. lpKeyMapList->lpKeyLabels[i].lpLabelType[iState] = LABEL_PICTURE;
  1559. lpKeyMapList->lpKeyLabels[i].lpLabelDisp[iState] = LABEL_DISP_ACTIVE;
  1560. lpKeyMapList->lpKeyLabels[i].lppLabelText[iState] = SysAllocString(pPictureKeys[jIndex].PictBitmap);
  1561. }
  1562. else
  1563. {
  1564. // All others are text labels. and have different strings for
  1565. // different modifier combination statets.
  1566. //
  1567. UINT uScanSpace = 0x39;
  1568. int iLabelSize;
  1569. BOOL fFunctKey;
  1570. uScanCode = realKbdLayout->lpKeyDes[i].keyId;
  1571. uVirtkey = MapVirtualKeyEx(uScanCode, 1, _lpCurKbdLayout->CurhKl);
  1572. fFunctKey = FALSE;
  1573. // For the Function keys, we just use the hard code string to set
  1574. // them as F1, F2, F3, ..... F12.
  1575. WCHAR wszFuncKey[MAX_LABEL_LEN];
  1576. wszFuncKey[0] = L'F';
  1577. switch (uScanCode) {
  1578. case KID_F1 :
  1579. case KID_F2 :
  1580. case KID_F3 :
  1581. case KID_F4 :
  1582. case KID_F5 :
  1583. case KID_F6 :
  1584. case KID_F7 :
  1585. case KID_F8 :
  1586. case KID_F9 :
  1587. wszFuncKey[1] = L'0' + uScanCode - KID_F1 + 1;
  1588. wszFuncKey[2] = L'\0';
  1589. wcscpy(szLabel, wszFuncKey);
  1590. fFunctKey = TRUE;
  1591. break;
  1592. case KID_F10 :
  1593. wcscpy(szLabel, L"F10");
  1594. fFunctKey = TRUE;
  1595. break;
  1596. case KID_F11 :
  1597. wcscpy(szLabel, L"F11");
  1598. fFunctKey = TRUE;
  1599. break;
  1600. case KID_F12 :
  1601. wcscpy(szLabel, L"F12");
  1602. fFunctKey = TRUE;
  1603. break;
  1604. default :
  1605. break;
  1606. }
  1607. if ( fFunctKey == TRUE )
  1608. {
  1609. lpKeyMapList->lpKeyLabels[i].lppLabelText[iState] = SysAllocString(szLabel);
  1610. lpKeyMapList->lpKeyLabels[i].lpLabelType[iState] = LABEL_TEXT;
  1611. lpKeyMapList->lpKeyLabels[i].lpLabelDisp[iState] = LABEL_DISP_ACTIVE;
  1612. continue;
  1613. }
  1614. if ( IsOnNT( ) )
  1615. {
  1616. iRet = ToUnicodeEx(uVirtkey, uScanCode | 0x80, pKeyState, szLabel, (int)(sizeof(szLabel)/sizeof(WCHAR)), 0, _lpCurKbdLayout->CurhKl);
  1617. if ( iRet == 2 )
  1618. {
  1619. // it is possible to have previous dead key, flush again.
  1620. iRet = ToUnicodeEx(uVirtkey, uScanCode | 0x80, pKeyState, szLabel, (int)(sizeof(szLabel)/sizeof(WCHAR)), 0, _lpCurKbdLayout->CurhKl);
  1621. }
  1622. iLabelSize = iRet;
  1623. }
  1624. else
  1625. {
  1626. // Win9x doesn't support ToUnicodeEx, we just use alternative ToAsciiEx.
  1627. char szLabelAnsi[MAX_LABEL_LEN];
  1628. iRet = ToAsciiEx(uVirtkey, uScanCode | 0x80, pKeyState, (LPWORD)szLabelAnsi, 0, _lpCurKbdLayout->CurhKl);
  1629. if ( iRet == 2 )
  1630. {
  1631. // it is possible to have previous dead key, flush again.
  1632. iRet = ToAsciiEx(uVirtkey, uScanCode | 0x80, pKeyState, (LPWORD)szLabelAnsi, 0, _lpCurKbdLayout->CurhKl);
  1633. }
  1634. if ( iRet != 0 )
  1635. {
  1636. //
  1637. // Translate the ANSI label to Unicode based on ACP ... or other?
  1638. //
  1639. if ( iRet == -1 ) // dead key, one character is written to szLabelAnsi buffer.
  1640. szLabelAnsi[1] = '\0';
  1641. else
  1642. szLabelAnsi[iRet] = '\0';
  1643. iLabelSize = MultiByteToWideChar(CP_ACP, 0, szLabelAnsi, -1, szLabel, MAX_LABEL_LEN );
  1644. }
  1645. }
  1646. if ( iRet <= 0 )
  1647. {
  1648. iLabelSize = 1;
  1649. if ( iRet == 0 )
  1650. {
  1651. // Means no translation for this key at this shift state.
  1652. // We will display empty label, or space on the button.
  1653. szLabel[0] = 0x20;
  1654. }
  1655. }
  1656. szLabel[iLabelSize] = L'\0';
  1657. lpKeyMapList->lpKeyLabels[i].lppLabelText[iState] = SysAllocString(szLabel);
  1658. lpKeyMapList->lpKeyLabels[i].lpLabelType[iState] = LABEL_TEXT;
  1659. lpKeyMapList->lpKeyLabels[i].lpLabelDisp[iState] = LABEL_DISP_ACTIVE;
  1660. }
  1661. }
  1662. return hr;
  1663. }
  1664. /*******************************************************************************
  1665. *
  1666. * Method function: _GenerateUSStandardLabel( )
  1667. *
  1668. * Generate all mapping labels in different modifier status for US standard
  1669. * soft keyboard.
  1670. *
  1671. /********************************************************************************/
  1672. HRESULT CSoftKbd::_GenerateUSStandardLabel( )
  1673. {
  1674. //
  1675. // there are 4 different states for keyboard labels.
  1676. //
  1677. // state 0 : no any modifier key pressed
  1678. // state 1 : Caps On.
  1679. // state 2 : Shift pressed. Caps Off
  1680. // state 3 : Shift Pressed, Caps On
  1681. //
  1682. // check to see if this soft keyboard support specified HKL.
  1683. //
  1684. // ???
  1685. //
  1686. KEYMAP *lpKeyMapList;
  1687. HRESULT hr;
  1688. WORD wNumModComb, wNumOfKeys;
  1689. int i, j;
  1690. int iState;
  1691. BYTE lpKeyState[256], lpCurKeyState[256];
  1692. KBDLAYOUT *realKbdLayut;
  1693. hr = S_OK;
  1694. if ( _lpCurKbdLayout->lpKeyMapList != NULL )
  1695. {
  1696. // If the mapping table for the specified HKL has already been created,
  1697. // Just return it.
  1698. HKL CurhKl;
  1699. CurhKl = _lpCurKbdLayout->CurhKl;
  1700. lpKeyMapList = _lpCurKbdLayout->lpKeyMapList;
  1701. while ( lpKeyMapList != NULL )
  1702. {
  1703. if ( lpKeyMapList->hKl == CurhKl )
  1704. {
  1705. // The mapping table is already created,
  1706. return hr;
  1707. }
  1708. lpKeyMapList = lpKeyMapList->pNext;
  1709. }
  1710. }
  1711. realKbdLayut = &(_lpCurKbdLayout->kbdLayout);
  1712. lpKeyMapList = (KEYMAP *)cicMemAllocClear(sizeof(KEYMAP) );
  1713. if ( lpKeyMapList == NULL )
  1714. {
  1715. // there is not enough memory.
  1716. hr = E_OUTOFMEMORY;
  1717. return hr;
  1718. }
  1719. // we have four different states.
  1720. wNumModComb = 4;
  1721. wNumOfKeys = _lpCurKbdLayout->kbdLayout.wNumberOfKeys;
  1722. lpKeyMapList->wNumModComb = wNumModComb;
  1723. lpKeyMapList->wNumOfKeys = wNumOfKeys;
  1724. lpKeyMapList->hKl = _lpCurKbdLayout->CurhKl;
  1725. for ( i=0; i<wNumOfKeys; i++ )
  1726. {
  1727. BSTR *lppLabelText;
  1728. WORD *lpLabelType;
  1729. WORD *lpLabelDisp;
  1730. lppLabelText = (BSTR *)cicMemAllocClear(wNumModComb * sizeof(BSTR) );
  1731. if ( lppLabelText == NULL ) {
  1732. //
  1733. // there is not enough memory.
  1734. //
  1735. // release allocated memory and return
  1736. for ( j=0; j<i; j++ )
  1737. {
  1738. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lppLabelText);
  1739. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelType);
  1740. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelDisp);
  1741. }
  1742. SafeFreePointer(lpKeyMapList);
  1743. hr = E_OUTOFMEMORY;
  1744. return hr;
  1745. }
  1746. lpLabelType = (WORD *)cicMemAllocClear(wNumModComb * sizeof(WORD) );
  1747. if ( lpLabelType == NULL ) {
  1748. //
  1749. // there is not enough memory.
  1750. //
  1751. // release allocated memory and return
  1752. for ( j=0; j<i; j++ )
  1753. {
  1754. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lppLabelText);
  1755. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelType);
  1756. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelDisp);
  1757. }
  1758. SafeFreePointer(lppLabelText);
  1759. SafeFreePointer(lpKeyMapList);
  1760. hr = E_OUTOFMEMORY;
  1761. return hr;
  1762. }
  1763. lpLabelDisp = (WORD *)cicMemAllocClear(wNumModComb * sizeof(WORD) );
  1764. if ( lpLabelDisp == NULL ) {
  1765. //
  1766. // there is not enough memory.
  1767. //
  1768. // release allocated memory and return
  1769. for ( j=0; j<i; j++ )
  1770. {
  1771. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lppLabelText);
  1772. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelType);
  1773. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelDisp);
  1774. }
  1775. SafeFreePointer(lppLabelText);
  1776. SafeFreePointer(lpLabelType);
  1777. SafeFreePointer(lpKeyMapList);
  1778. hr = E_OUTOFMEMORY;
  1779. return hr;
  1780. }
  1781. lpKeyMapList->lpKeyLabels[i].lppLabelText = lppLabelText;
  1782. lpKeyMapList->lpKeyLabels[i].lpLabelType = lpLabelType;
  1783. lpKeyMapList->lpKeyLabels[i].lpLabelDisp = lpLabelDisp;
  1784. lpKeyMapList->lpKeyLabels[i].wNumModComb = wNumModComb;
  1785. }
  1786. // Keep the current keyboard states on Win9x
  1787. if ( !IsOnNT( ) )
  1788. {
  1789. if ( 0 == GetKeyboardState(lpCurKeyState) )
  1790. return E_FAIL;
  1791. }
  1792. iState = 0;
  1793. memset(lpKeyState, 0, 256);
  1794. CHECKHR(_SetStandardLabelText(lpKeyState, realKbdLayut,lpKeyMapList,iState));
  1795. iState = 1; // Caps On
  1796. memset(lpKeyState, 0, 256);
  1797. lpKeyState[VK_CAPITAL] = 0x01;
  1798. CHECKHR(_SetStandardLabelText(lpKeyState, realKbdLayut,lpKeyMapList,iState));
  1799. iState = 2; // Shift Down, Caps Off.
  1800. memset(lpKeyState, 0, 256);
  1801. lpKeyState[VK_SHIFT] = 0x80;
  1802. CHECKHR(_SetStandardLabelText(lpKeyState, realKbdLayut,lpKeyMapList,iState));
  1803. iState = 3; // Shift Down, Caps On
  1804. memset(lpKeyState, 0, 256);
  1805. lpKeyState[VK_CAPITAL] = 0x01;
  1806. lpKeyState[VK_SHIFT] = 0x80;
  1807. CHECKHR(_SetStandardLabelText(lpKeyState, realKbdLayut,lpKeyMapList,iState));
  1808. // Add the newly created KeyMapList to the head of the mapping table link.
  1809. lpKeyMapList->pNext = _lpCurKbdLayout->lpKeyMapList;
  1810. _lpCurKbdLayout->lpKeyMapList = lpKeyMapList;
  1811. CleanUp:
  1812. // Restore the current keyboard states on Win9x
  1813. if ( !IsOnNT( ) )
  1814. SetKeyboardState(lpCurKeyState);
  1815. return hr;
  1816. }
  1817. /*******************************************************************************
  1818. *
  1819. * Method function: _GenerateUSEnhanceLabel( )
  1820. *
  1821. * Generate all mapping labels in different modifier status for US enhanced
  1822. * soft keyboard.
  1823. *
  1824. /********************************************************************************/
  1825. HRESULT CSoftKbd::_GenerateUSEnhanceLabel( )
  1826. {
  1827. HRESULT hr;
  1828. hr = E_NOTIMPL;
  1829. // not yet implemented.
  1830. return hr;
  1831. }
  1832. /*******************************************************************************
  1833. *
  1834. * Method function: _GenerateEuroStandardLabel( )
  1835. *
  1836. * Generate all mapping labels in different modifier status for Euro standard
  1837. * soft keyboard. ( 102-key keyboard)
  1838. *
  1839. /********************************************************************************/
  1840. HRESULT CSoftKbd::_GenerateEuroStandardLabel( )
  1841. {
  1842. //
  1843. // there are 8 different states for keyboard labels.
  1844. //
  1845. // AltGr Shift Caps.
  1846. // Bit 2 1 0
  1847. //
  1848. // state 0 : no any modifier key pressed
  1849. // state 1 : Caps On.
  1850. // state 2 : Shift pressed. Caps Off
  1851. // state 3 : Shift Pressed, Caps On
  1852. //
  1853. // .........
  1854. KEYMAP *lpKeyMapList;
  1855. HRESULT hr;
  1856. WORD wNumModComb, wNumOfKeys;
  1857. int i, j;
  1858. int iState;
  1859. BYTE lpKeyState[256], lpCurKeyState[256];
  1860. KBDLAYOUT *realKbdLayut;
  1861. WORD BCaps, BShift, BAltGr;
  1862. BCaps = 1;
  1863. BShift = 2;
  1864. BAltGr = 4;
  1865. hr = S_OK;
  1866. if ( _lpCurKbdLayout->lpKeyMapList != NULL )
  1867. {
  1868. // If the mapping table for the specified HKL has already been created,
  1869. // Just return it.
  1870. HKL CurhKl;
  1871. CurhKl = _lpCurKbdLayout->CurhKl;
  1872. lpKeyMapList = _lpCurKbdLayout->lpKeyMapList;
  1873. while ( lpKeyMapList != NULL )
  1874. {
  1875. if ( lpKeyMapList->hKl == CurhKl )
  1876. {
  1877. // The mapping table is already created,
  1878. return hr;
  1879. }
  1880. lpKeyMapList = lpKeyMapList->pNext;
  1881. }
  1882. }
  1883. realKbdLayut = &(_lpCurKbdLayout->kbdLayout);
  1884. lpKeyMapList = (KEYMAP *)cicMemAllocClear(sizeof(KEYMAP) );
  1885. if ( lpKeyMapList == NULL )
  1886. {
  1887. // there is not enough memory.
  1888. hr = E_OUTOFMEMORY;
  1889. return hr;
  1890. }
  1891. // we have 8 different states.
  1892. wNumModComb = 8;
  1893. wNumOfKeys = _lpCurKbdLayout->kbdLayout.wNumberOfKeys;
  1894. lpKeyMapList->wNumModComb = wNumModComb;
  1895. lpKeyMapList->wNumOfKeys = wNumOfKeys;
  1896. lpKeyMapList->pNext = NULL;
  1897. lpKeyMapList->hKl = _lpCurKbdLayout->CurhKl;
  1898. for ( i=0; i<wNumOfKeys; i++ )
  1899. {
  1900. BSTR *lppLabelText=NULL;
  1901. WORD *lpLabelType=NULL;
  1902. WORD *lpLabelDisp=NULL;
  1903. lppLabelText = (BSTR *)cicMemAllocClear(wNumModComb * sizeof(BSTR) );
  1904. lpLabelType = (WORD *)cicMemAllocClear(wNumModComb * sizeof(WORD) );
  1905. lpLabelDisp = (WORD *)cicMemAllocClear(wNumModComb * sizeof(WORD) );
  1906. if ( (lpLabelDisp == NULL) || (lpLabelType== NULL) || (lppLabelText == NULL) ) {
  1907. //
  1908. // there is not enough memory.
  1909. //
  1910. // release allocated memory and return
  1911. for ( j=0; j<i; j++ )
  1912. {
  1913. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lppLabelText);
  1914. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelType);
  1915. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelDisp);
  1916. }
  1917. SafeFreePointer(lppLabelText);
  1918. SafeFreePointer(lpLabelType);
  1919. SafeFreePointer(lpKeyMapList);
  1920. hr = E_OUTOFMEMORY;
  1921. return hr;
  1922. }
  1923. lpKeyMapList->lpKeyLabels[i].lppLabelText = lppLabelText;
  1924. lpKeyMapList->lpKeyLabels[i].lpLabelType = lpLabelType;
  1925. lpKeyMapList->lpKeyLabels[i].lpLabelDisp = lpLabelDisp;
  1926. lpKeyMapList->lpKeyLabels[i].wNumModComb = wNumModComb;
  1927. }
  1928. // Keep the current keyboard states on Win9x.
  1929. if ( !IsOnNT( ) )
  1930. {
  1931. if ( 0 == GetKeyboardState(lpCurKeyState) )
  1932. return E_FAIL;
  1933. }
  1934. for (iState = 0; iState < wNumModComb; iState ++ )
  1935. {
  1936. memset(lpKeyState, 0, 256);
  1937. if ( iState & BCaps )
  1938. lpKeyState[VK_CAPITAL]=0x01;
  1939. if ( iState & BShift )
  1940. lpKeyState[VK_SHIFT] = 0x80;
  1941. if ( iState & BAltGr )
  1942. {
  1943. lpKeyState[VK_MENU] = 0x80;
  1944. lpKeyState[VK_CONTROL] = 0x80;
  1945. }
  1946. CHECKHR(_SetStandardLabelText(lpKeyState, realKbdLayut,lpKeyMapList,iState));
  1947. }
  1948. _lpCurKbdLayout->lpKeyMapList = lpKeyMapList;
  1949. CleanUp:
  1950. // Restore the current keyboard states on Win9x.
  1951. if ( ! IsOnNT( ) )
  1952. SetKeyboardState(lpCurKeyState);
  1953. return hr;
  1954. }
  1955. /*******************************************************************************
  1956. *
  1957. * Method function: _GenerateEuroEnhanceLabel( )
  1958. *
  1959. * Generate all mapping labels in different modifier status for Euro Enhanced
  1960. * soft keyboard. ( 102-key + NumPad )
  1961. *
  1962. /********************************************************************************/
  1963. HRESULT CSoftKbd::_GenerateEuroEnhanceLabel( )
  1964. {
  1965. HRESULT hr;
  1966. hr = E_NOTIMPL;
  1967. // not yet implemented.
  1968. return hr;
  1969. }
  1970. /*******************************************************************************
  1971. *
  1972. * Method function: _GenerateJpnStandardLabel( )
  1973. *
  1974. * Generate all mapping labels in different modifier status for JPN standard
  1975. * soft keyboard. ( 106-key)
  1976. *
  1977. /********************************************************************************/
  1978. HRESULT CSoftKbd::_GenerateJpnStandardLabel( )
  1979. {
  1980. //
  1981. // there are 16 different states for keyboard labels.
  1982. //
  1983. // Kana Alt Shift Caps.
  1984. // Bit 3 2 1 0
  1985. //
  1986. // state 0 : no any modifier key pressed
  1987. // state 1 : Caps On.
  1988. // state 2 : Shift pressed. Caps Off
  1989. // state 3 : Shift Pressed, Caps On
  1990. //
  1991. KEYMAP *lpKeyMapList;
  1992. HRESULT hr;
  1993. WORD wNumModComb, wNumOfKeys;
  1994. int i, j;
  1995. int iState;
  1996. BYTE lpKeyState[256], lpCurKeyState[256];
  1997. KBDLAYOUT *realKbdLayut;
  1998. WORD BCaps, BShift, BAlt, BKana;
  1999. BCaps = 1;
  2000. BShift = 2;
  2001. BAlt = 4;
  2002. BKana = 8;
  2003. hr = S_OK;
  2004. if ( _lpCurKbdLayout->lpKeyMapList != NULL )
  2005. {
  2006. return hr;
  2007. }
  2008. realKbdLayut = &(_lpCurKbdLayout->kbdLayout);
  2009. lpKeyMapList = (KEYMAP *)cicMemAllocClear(sizeof(KEYMAP) );
  2010. if ( lpKeyMapList == NULL )
  2011. {
  2012. // there is not enough memory.
  2013. hr = E_OUTOFMEMORY;
  2014. return hr;
  2015. }
  2016. // we have four different states.
  2017. wNumModComb = 16;
  2018. wNumOfKeys = _lpCurKbdLayout->kbdLayout.wNumberOfKeys;
  2019. lpKeyMapList->wNumModComb = wNumModComb;
  2020. lpKeyMapList->wNumOfKeys = wNumOfKeys;
  2021. lpKeyMapList->pNext = NULL;
  2022. lpKeyMapList->hKl = _lpCurKbdLayout->CurhKl;
  2023. for ( i=0; i<wNumOfKeys; i++ )
  2024. {
  2025. BSTR *lppLabelText;
  2026. WORD *lpLabelType;
  2027. WORD *lpLabelDisp;
  2028. lppLabelText = (BSTR *)cicMemAllocClear(wNumModComb * sizeof(BSTR) );
  2029. if ( lppLabelText == NULL ) {
  2030. //
  2031. // there is not enough memory.
  2032. //
  2033. // release allocated memory and return
  2034. for ( j=0; j<i; j++ )
  2035. {
  2036. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lppLabelText);
  2037. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelType);
  2038. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelDisp);
  2039. }
  2040. SafeFreePointer(lpKeyMapList);
  2041. hr = E_OUTOFMEMORY;
  2042. return hr;
  2043. }
  2044. lpLabelType = (WORD *)cicMemAllocClear(wNumModComb * sizeof(WORD) );
  2045. if ( lpLabelType == NULL ) {
  2046. //
  2047. // there is not enough memory.
  2048. //
  2049. // release allocated memory and return
  2050. for ( j=0; j<i; j++ )
  2051. {
  2052. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lppLabelText);
  2053. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelType);
  2054. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelDisp);
  2055. }
  2056. SafeFreePointer(lppLabelText);
  2057. SafeFreePointer(lpKeyMapList);
  2058. hr = E_OUTOFMEMORY;
  2059. return hr;
  2060. }
  2061. lpLabelDisp = (WORD *)cicMemAllocClear(wNumModComb * sizeof(WORD) );
  2062. if ( lpLabelDisp == NULL ) {
  2063. //
  2064. // there is not enough memory.
  2065. //
  2066. // release allocated memory and return
  2067. for ( j=0; j<i; j++ )
  2068. {
  2069. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lppLabelText);
  2070. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelType);
  2071. SafeFreePointer(lpKeyMapList->lpKeyLabels[j].lpLabelDisp);
  2072. }
  2073. SafeFreePointer(lppLabelText);
  2074. SafeFreePointer(lpLabelType);
  2075. SafeFreePointer(lpKeyMapList);
  2076. hr = E_OUTOFMEMORY;
  2077. return hr;
  2078. }
  2079. lpKeyMapList->lpKeyLabels[i].lppLabelText = lppLabelText;
  2080. lpKeyMapList->lpKeyLabels[i].lpLabelType = lpLabelType;
  2081. lpKeyMapList->lpKeyLabels[i].lpLabelDisp = lpLabelDisp;
  2082. lpKeyMapList->lpKeyLabels[i].wNumModComb = wNumModComb;
  2083. }
  2084. // Keep the current keyboard states on Win9x.
  2085. if ( !IsOnNT( ) )
  2086. {
  2087. if ( 0 == GetKeyboardState(lpCurKeyState) )
  2088. return E_FAIL;
  2089. }
  2090. for (iState = 0; iState < wNumModComb; iState ++ )
  2091. {
  2092. memset(lpKeyState, 0, 256);
  2093. if ( iState & BCaps )
  2094. lpKeyState[VK_CAPITAL] = 0x01;
  2095. if ( iState & BShift )
  2096. lpKeyState[VK_SHIFT] = 0x80;
  2097. if ( iState & BAlt )
  2098. lpKeyState[VK_MENU] = 0x80;
  2099. if ( iState & BKana )
  2100. lpKeyState[VK_KANA] = 0x01;
  2101. CHECKHR(_SetStandardLabelText(lpKeyState, realKbdLayut,lpKeyMapList,iState));
  2102. }
  2103. _lpCurKbdLayout->lpKeyMapList = lpKeyMapList;
  2104. CleanUp:
  2105. // Restore the current keyboard states on Win9x.
  2106. if ( ! IsOnNT( ) )
  2107. SetKeyboardState(lpCurKeyState);
  2108. return hr;
  2109. }
  2110. /*******************************************************************************
  2111. *
  2112. * Method function: _GenerateJpnEnhanceLabel( )
  2113. *
  2114. * Generate all mapping labels in different modifier status for JPN enhanced
  2115. * soft keyboard. (106-key + NumPad )
  2116. *
  2117. /********************************************************************************/
  2118. HRESULT CSoftKbd::_GenerateJpnEnhanceLabel( )
  2119. {
  2120. HRESULT hr;
  2121. hr = E_NOTIMPL;
  2122. // not yet implemented.
  2123. return hr;
  2124. }
  2125. /*******************************************************************************
  2126. *
  2127. * Method function: SetKeyboardLabelText( )
  2128. *
  2129. * Set the mapping label texts based on specified HKL.
  2130. *
  2131. /********************************************************************************/
  2132. STDMETHODIMP CSoftKbd::SetKeyboardLabelText(HKL hKl)
  2133. {
  2134. KBDLAYOUT *realKbdLayout;
  2135. HRESULT hr;
  2136. DWORD iModiCombState;
  2137. WORD iModifierStatus;
  2138. realKbdLayout = &(_lpCurKbdLayout->kbdLayout);
  2139. hr = S_OK;
  2140. if ( realKbdLayout->fStandard == FALSE ) {
  2141. //
  2142. // customized layout cannot accept HKL to change its keys' labels.
  2143. //
  2144. _lpCurKbdLayout->CurhKl = 0;
  2145. hr = E_FAIL;
  2146. return hr;
  2147. }
  2148. if ( ! IsOnNT( ) )
  2149. {
  2150. // We have to handle IME hkl specially on Win9x.
  2151. // For some reason, Win9x cannot receive IME HKL as parameter in MapVirtualKeyEx and ToAsciiEx.
  2152. INT_PTR iHkl;
  2153. iHkl = (INT_PTR)hKl;
  2154. if ( (iHkl & 0xF0000000) == 0xE0000000 )
  2155. {
  2156. // this is FE IME HKL.
  2157. iHkl = iHkl & 0x0000ffff;
  2158. hKl = (HKL) iHkl;
  2159. }
  2160. }
  2161. _lpCurKbdLayout->CurhKl = (HKL)hKl;
  2162. //
  2163. // check to see if current standard keyboard supports this HKL
  2164. //
  2165. switch ( _wCurKbdLayoutID ) {
  2166. case SOFTKBD_US_STANDARD :
  2167. CHECKHR(_GenerateUSStandardLabel( ));
  2168. break;
  2169. case SOFTKBD_US_ENHANCE :
  2170. CHECKHR(_GenerateUSEnhanceLabel( ));
  2171. break;
  2172. case SOFTKBD_EURO_STANDARD :
  2173. CHECKHR(_GenerateEuroStandardLabel( ));
  2174. break;
  2175. case SOFTKBD_EURO_ENHANCE :
  2176. CHECKHR(_GenerateEuroEnhanceLabel( ));
  2177. break;
  2178. case SOFTKBD_JPN_STANDARD :
  2179. CHECKHR(_GenerateJpnStandardLabel( ));
  2180. break;
  2181. case SOFTKBD_JPN_ENHANCE :
  2182. CHECKHR(_GenerateJpnEnhanceLabel( ));
  2183. break;
  2184. }
  2185. // set current Active mapping labels.
  2186. // Generate CurModiState based on current keyboard state
  2187. _GenerateCurModiState(&iModifierStatus, &iModiCombState);
  2188. _lpCurKbdLayout->ModifierStatus = iModifierStatus;
  2189. hr = SetKeyboardLabelTextCombination(iModiCombState);
  2190. CleanUp:
  2191. return hr;
  2192. }
  2193. /*******************************************************************************
  2194. *
  2195. * Method function: _SetKeyboardLabelTextCombination( )
  2196. *
  2197. * Set current effective modifier combination status, so that the correct
  2198. * mapping labels will be shown up.
  2199. *
  2200. /********************************************************************************/
  2201. STDMETHODIMP CSoftKbd::SetKeyboardLabelTextCombination(DWORD iModiCombState)
  2202. {
  2203. WORD wNumberOfKeys, i;
  2204. KEYMAP *lpKeyMapList;
  2205. HRESULT hr;
  2206. hr = S_OK;
  2207. if ( _lpCurKbdLayout == NULL )
  2208. {
  2209. hr = E_FAIL;
  2210. return hr;
  2211. }
  2212. if ( _lpCurKbdLayout->lpKeyMapList == NULL )
  2213. {
  2214. hr = E_FAIL;
  2215. return hr;
  2216. }
  2217. if ( (_lpCurKbdLayout->kbdLayout).fStandard )
  2218. {
  2219. // This is a standard keyboard layout, we need to
  2220. // find out the correct mapping table for the current
  2221. // specified HKL.
  2222. // Every mapping table is associated with a HKL.
  2223. // the current specified HKL is stored in _lpCurKbdLayout->CurhKl.
  2224. HKL CurhKl;
  2225. CurhKl = _lpCurKbdLayout->CurhKl;
  2226. lpKeyMapList = _lpCurKbdLayout->lpKeyMapList;
  2227. while ( lpKeyMapList->hKl != CurhKl )
  2228. {
  2229. lpKeyMapList = lpKeyMapList->pNext;
  2230. if ( lpKeyMapList == NULL )
  2231. {
  2232. // No mapping table is associated with the specified HKL.
  2233. // return error.
  2234. hr = E_FAIL;
  2235. return hr;
  2236. }
  2237. }
  2238. }
  2239. else
  2240. lpKeyMapList = _lpCurKbdLayout->lpKeyMapList;
  2241. if ( iModiCombState >= lpKeyMapList->wNumModComb)
  2242. {
  2243. hr = E_FAIL;
  2244. return hr;
  2245. }
  2246. _lpCurKbdLayout->CurModiState = iModiCombState;
  2247. // Now fill _CurLabel, Current Active label for every key.
  2248. wNumberOfKeys = (_lpCurKbdLayout->kbdLayout).wNumberOfKeys;
  2249. for ( i=0; i<wNumberOfKeys; i++)
  2250. {
  2251. int iState;
  2252. _CurLabel[i].keyId = lpKeyMapList->lpKeyLabels[i].keyId;
  2253. iState = iModiCombState;
  2254. if ( iModiCombState >= lpKeyMapList->lpKeyLabels[i].wNumModComb )
  2255. {
  2256. // there is not enough different states for this key
  2257. // just use state 0.
  2258. iState = 0;
  2259. }
  2260. _CurLabel[i].lpLabelText = lpKeyMapList->lpKeyLabels[i].lppLabelText[iState];
  2261. _CurLabel[i].LabelType = lpKeyMapList->lpKeyLabels[i].lpLabelType[iState];
  2262. _CurLabel[i].LabelDisp = lpKeyMapList->lpKeyLabels[i].lpLabelDisp[iState];
  2263. }
  2264. if ( _pSoftkbdUIWnd )
  2265. {
  2266. _pSoftkbdUIWnd->_SetKeyLabel( );
  2267. }
  2268. return hr;
  2269. }
  2270. /*******************************************************************************
  2271. *
  2272. * Method function: _GenerateCurModiState( )
  2273. *
  2274. * Generate Softkbd recognized ModifierStatus and CurModiState based on
  2275. * current keyboard states.
  2276. *
  2277. /********************************************************************************/
  2278. HRESULT CSoftKbd::_GenerateCurModiState(WORD *ModifierStatus, DWORD *CurModiState )
  2279. {
  2280. DWORD iModiCombState;
  2281. WORD iModifierStatus;
  2282. DWORD iTmp;
  2283. HRESULT hr = S_OK;
  2284. if ( !ModifierStatus || !CurModiState )
  2285. return E_FAIL;
  2286. if ( (_lpCurKbdLayout->kbdLayout).fStandard == FALSE )
  2287. return E_FAIL;
  2288. iModifierStatus = 0;
  2289. if ( GetKeyState(VK_CAPITAL) & 0x01 )
  2290. {
  2291. // Caps key is Toggled.
  2292. iModifierStatus |= MODIFIER_CAPSLOCK ;
  2293. }
  2294. if ( GetKeyState(VK_SHIFT) & 0x80 )
  2295. {
  2296. // Shift key is pressed.
  2297. iModifierStatus |= MODIFIER_SHIFT;
  2298. }
  2299. if ( GetKeyState(VK_CONTROL) & 0x80 )
  2300. {
  2301. // Ctrl key is pressed.
  2302. iModifierStatus |= MODIFIER_CTRL;
  2303. }
  2304. if ( GetKeyState(VK_LMENU) & 0x80 )
  2305. {
  2306. // Left Alt key is pressed.
  2307. iModifierStatus |= MODIFIER_ALT;
  2308. }
  2309. if ( GetKeyState(VK_RMENU) & 0x80 )
  2310. {
  2311. // Right Alt key is pressed.
  2312. iModifierStatus |= MODIFIER_ALTGR;
  2313. }
  2314. if ( GetKeyState(VK_KANA) & 0x01 )
  2315. {
  2316. // KANA key is Toggled.
  2317. iModifierStatus |= MODIFIER_KANA;
  2318. }
  2319. *ModifierStatus = iModifierStatus;
  2320. switch ( _wCurKbdLayoutID ) {
  2321. case SOFTKBD_US_STANDARD :
  2322. case SOFTKBD_US_ENHANCE :
  2323. // this is for US Standard keyboard.
  2324. // others may need to handle separately.
  2325. iModiCombState = (iModifierStatus) & (MODIFIER_CAPSLOCK | MODIFIER_SHIFT);
  2326. iModiCombState = iModiCombState >> 1;
  2327. // bit1 for Caps.
  2328. // bit2 for Shift
  2329. break;
  2330. case SOFTKBD_EURO_STANDARD :
  2331. case SOFTKBD_EURO_ENHANCE :
  2332. // this is for Euro 102 standard keyboard.
  2333. // How to map ModifierStatus -> CurModiState.
  2334. // bit 1 for Caps, bit2 for Shift, bit3 for AltGr.
  2335. iModiCombState = (iModifierStatus) & ( MODIFIER_CAPSLOCK | MODIFIER_SHIFT );
  2336. iModiCombState = iModiCombState >> 1;
  2337. iTmp = (iModifierStatus) & MODIFIER_ALTGR;
  2338. iTmp = iTmp >> 4;
  2339. iModiCombState += iTmp;
  2340. break;
  2341. case SOFTKBD_JPN_STANDARD :
  2342. case SOFTKBD_JPN_ENHANCE :
  2343. // How to map ModifierStatus -> CurModiState.
  2344. iModiCombState = (iModifierStatus) & ( MODIFIER_CAPSLOCK | MODIFIER_SHIFT );
  2345. iModiCombState = iModiCombState >> 1;
  2346. iTmp = (iModifierStatus) & (MODIFIER_ALT | MODIFIER_KANA);
  2347. iTmp = iTmp >> 2;
  2348. iModiCombState += iTmp;
  2349. break;
  2350. }
  2351. *CurModiState = iModiCombState;
  2352. return hr;
  2353. }
  2354. /*******************************************************************************
  2355. *
  2356. * Method function: ShowSoftKeyboard( )
  2357. *
  2358. * Show or Hide the soft keyboard window based on the specified parameter.
  2359. *
  2360. *
  2361. /********************************************************************************/
  2362. STDMETHODIMP CSoftKbd::ShowSoftKeyboard(INT iShow)
  2363. {
  2364. HRESULT hr;
  2365. hr = S_OK;
  2366. if (!_pSoftkbdUIWnd) {
  2367. hr = E_FAIL;
  2368. return hr;
  2369. }
  2370. // if client doesn't specify which layout is selected,
  2371. // we just select a default standard soft keyboard layout
  2372. // based on current thread keyboard layout.
  2373. // if current thread keyboard layout is JPN, use 106 key.
  2374. // others, use 101key.
  2375. // run SelectSoftKeyboard( SelectedID );
  2376. //
  2377. if ( _wCurKbdLayoutID == NON_KEYBOARD )
  2378. {
  2379. HKL hKl;
  2380. DWORD dwLayoutId;
  2381. LANGID langId;
  2382. hKl = GetKeyboardLayout(0);
  2383. langId = LOWORD( (DWORD)(UINT_PTR)hKl);
  2384. if ( langId == 0x0411 ) // Japanese keyboard
  2385. {
  2386. dwLayoutId = SOFTKBD_JPN_STANDARD;
  2387. }
  2388. else
  2389. dwLayoutId = SOFTKBD_US_STANDARD;
  2390. CHECKHR(SelectSoftKeyboard(dwLayoutId) );
  2391. CHECKHR(SetKeyboardLabelText(hKl));
  2392. }
  2393. _pSoftkbdUIWnd->Show(iShow);
  2394. _iShow = iShow;
  2395. CleanUp:
  2396. return hr;
  2397. }
  2398. /*******************************************************************************
  2399. *
  2400. * Method function: CreateSoftKeyboardWindow( )
  2401. *
  2402. * Create a real soft keyboard popup window.
  2403. *
  2404. /********************************************************************************/
  2405. STDMETHODIMP CSoftKbd::CreateSoftKeyboardWindow(HWND hOwner, TITLEBAR_TYPE Titlebar_type, INT xPos, INT yPos, INT width, INT height)
  2406. {
  2407. // TODO: Add your implementation code here
  2408. HRESULT hr;
  2409. hr = S_OK;
  2410. _hOwner = hOwner;
  2411. _xReal = xPos;
  2412. _yReal = yPos;
  2413. _widthReal = width;
  2414. _heightReal= height;
  2415. _TitleBar_Type = Titlebar_type; // temporal solution.
  2416. //
  2417. // generate realKbdLayout
  2418. //
  2419. CHECKHR(_GenerateRealKbdLayout( ));
  2420. if ( _pSoftkbdUIWnd != NULL )
  2421. delete _pSoftkbdUIWnd;
  2422. _pSoftkbdUIWnd = new CSoftkbdUIWnd(this, g_hInst, UIWINDOW_TOPMOST | UIWINDOW_WSDLGFRAME | UIWINDOW_HABITATINSCREEN);
  2423. if ( _pSoftkbdUIWnd != NULL )
  2424. {
  2425. _pSoftkbdUIWnd->Initialize( );
  2426. _pSoftkbdUIWnd->_CreateSoftkbdWindow(hOwner, Titlebar_type, xPos, yPos, width, height);
  2427. }
  2428. _iShow = 0;
  2429. CleanUp:
  2430. return hr;
  2431. }
  2432. /*******************************************************************************
  2433. *
  2434. * Method function: DestroySoftKeyboardWindow( )
  2435. *
  2436. * Destroy the soft keyboard window
  2437. *
  2438. *
  2439. /********************************************************************************/
  2440. STDMETHODIMP CSoftKbd::DestroySoftKeyboardWindow()
  2441. {
  2442. if ( _pSoftkbdUIWnd != NULL )
  2443. {
  2444. delete _pSoftkbdUIWnd;
  2445. _pSoftkbdUIWnd = NULL;
  2446. }
  2447. return S_OK;
  2448. }
  2449. /*******************************************************************************
  2450. *
  2451. * Method function: GetSoftKeyboardPosSize( )
  2452. *
  2453. * Return current soft keyboard window size and scrren position
  2454. *
  2455. /********************************************************************************/
  2456. STDMETHODIMP CSoftKbd::GetSoftKeyboardPosSize(POINT *lpStartPoint, WORD *lpwidth, WORD *lpheight)
  2457. {
  2458. HRESULT hr;
  2459. hr = S_OK;
  2460. if ( _pSoftkbdUIWnd == NULL )
  2461. {
  2462. hr = E_FAIL;
  2463. return hr;
  2464. }
  2465. if ( (lpStartPoint == NULL ) || ( lpwidth == NULL) || ( lpheight == NULL) )
  2466. {
  2467. hr = E_FAIL;
  2468. return hr;
  2469. }
  2470. lpStartPoint->x = _xReal;
  2471. lpStartPoint->y = _yReal;
  2472. *lpwidth = (WORD)_widthReal;
  2473. *lpheight = (WORD)_heightReal;
  2474. return hr;
  2475. }
  2476. /*******************************************************************************
  2477. *
  2478. * Method function: GetSoftKeyboardColors( )
  2479. *
  2480. * Return all different kinds of soft keyboard window colors.
  2481. *
  2482. /********************************************************************************/
  2483. STDMETHODIMP CSoftKbd::GetSoftKeyboardColors(COLORTYPE colorType, COLORREF *lpColor)
  2484. {
  2485. HRESULT hr;
  2486. hr = S_OK;
  2487. if ( _pSoftkbdUIWnd == NULL )
  2488. {
  2489. hr = E_FAIL;
  2490. return hr;
  2491. }
  2492. if ( lpColor == NULL )
  2493. {
  2494. hr = E_FAIL;
  2495. return hr;
  2496. }
  2497. *lpColor = _color[colorType];
  2498. return hr;
  2499. }
  2500. /*******************************************************************************
  2501. *
  2502. * Method function: GetSoftKeyboardTypeMode( )
  2503. *
  2504. * Return current Soft keyboard 's typing mode.
  2505. * this is for On Screen Keyboard.
  2506. *
  2507. *
  2508. /********************************************************************************/
  2509. STDMETHODIMP CSoftKbd::GetSoftKeyboardTypeMode(TYPEMODE *lpTypeMode)
  2510. {
  2511. HRESULT hr;
  2512. hr = S_OK;
  2513. if ( _pSoftkbdUIWnd == NULL )
  2514. {
  2515. hr = E_FAIL;
  2516. return hr;
  2517. }
  2518. if ( lpTypeMode == NULL )
  2519. {
  2520. hr = E_FAIL;
  2521. return hr;
  2522. }
  2523. //
  2524. //
  2525. return hr;
  2526. }
  2527. /*******************************************************************************
  2528. *
  2529. * Method function: GetSoftKeyboardTextFont( )
  2530. *
  2531. * Return current soft keyboard label font data.
  2532. *
  2533. *
  2534. /********************************************************************************/
  2535. STDMETHODIMP CSoftKbd::GetSoftKeyboardTextFont(LOGFONTW *pLogFont)
  2536. {
  2537. HRESULT hr;
  2538. hr = S_OK;
  2539. if ( _pSoftkbdUIWnd == NULL )
  2540. {
  2541. hr = E_FAIL;
  2542. return hr;
  2543. }
  2544. if ( pLogFont == NULL )
  2545. {
  2546. hr = E_FAIL;
  2547. return hr;
  2548. }
  2549. if ( _plfTextFont )
  2550. {
  2551. CopyMemory(pLogFont, _plfTextFont, sizeof(LOGFONTW) );
  2552. }
  2553. else
  2554. hr = S_FALSE;
  2555. return hr;
  2556. }
  2557. STDMETHODIMP CSoftKbd::SetSoftKeyboardPosSize(POINT StartPoint, WORD width, WORD height)
  2558. {
  2559. HRESULT hr;
  2560. hr = S_OK;
  2561. if ( _pSoftkbdUIWnd == NULL )
  2562. {
  2563. hr = E_FAIL;
  2564. return hr;
  2565. }
  2566. _xReal = StartPoint.x;
  2567. _yReal = StartPoint.y;
  2568. if ( width > 0 )
  2569. _widthReal = width;
  2570. if ( height > 0 )
  2571. _heightReal = height;
  2572. //
  2573. // generate realKbdLayout
  2574. //
  2575. CHECKHR(_GenerateRealKbdLayout( ));
  2576. _pSoftkbdUIWnd->Move(_xReal, _yReal, _widthReal, _heightReal);
  2577. if ( _iShow & SOFTKBD_SHOW )
  2578. {
  2579. CHECKHR(ShowSoftKeyboard(_iShow));
  2580. }
  2581. CleanUp:
  2582. return hr;
  2583. }
  2584. STDMETHODIMP CSoftKbd::SetSoftKeyboardColors(COLORTYPE colorType, COLORREF Color)
  2585. {
  2586. HRESULT hr;
  2587. hr = S_OK;
  2588. if ( _pSoftkbdUIWnd == NULL )
  2589. {
  2590. hr = E_FAIL;
  2591. return hr;
  2592. }
  2593. _color[colorType] = Color;
  2594. if ( _iShow & SOFTKBD_SHOW )
  2595. {
  2596. CHECKHR(ShowSoftKeyboard(_iShow));
  2597. }
  2598. CleanUp:
  2599. return hr;
  2600. }
  2601. STDMETHODIMP CSoftKbd::SetSoftKeyboardTypeMode(TYPEMODE TypeMode)
  2602. {
  2603. HRESULT hr;
  2604. hr = S_OK;
  2605. if ( _pSoftkbdUIWnd == NULL )
  2606. {
  2607. hr = E_FAIL;
  2608. return hr;
  2609. }
  2610. //
  2611. // Set type mode
  2612. //
  2613. if ( _iShow & SOFTKBD_SHOW )
  2614. {
  2615. CHECKHR(ShowSoftKeyboard(_iShow));
  2616. }
  2617. CleanUp:
  2618. return hr;
  2619. }
  2620. STDMETHODIMP CSoftKbd::SetSoftKeyboardTextFont(LOGFONTW *pLogFont)
  2621. {
  2622. HRESULT hr;
  2623. hr = S_OK;
  2624. if ( _pSoftkbdUIWnd == NULL )
  2625. {
  2626. hr = E_FAIL;
  2627. return hr;
  2628. }
  2629. if ( pLogFont == NULL )
  2630. return E_INVALIDARG;
  2631. //
  2632. // set font data
  2633. //
  2634. if ( _plfTextFont == NULL )
  2635. _plfTextFont = (LOGFONTW *)cicMemAllocClear( sizeof(LOGFONTW) );
  2636. if ( _plfTextFont )
  2637. {
  2638. CopyMemory( _plfTextFont, pLogFont, sizeof(LOGFONTW) );
  2639. _pSoftkbdUIWnd->UpdateFont( _plfTextFont );
  2640. if ( _iShow & SOFTKBD_SHOW )
  2641. {
  2642. _pSoftkbdUIWnd->CallOnPaint( );
  2643. }
  2644. }
  2645. else
  2646. hr = E_OUTOFMEMORY;
  2647. return hr;
  2648. }
  2649. STDMETHODIMP CSoftKbd::ShowKeysForKeyScanMode(KEYID *lpKeyID, INT iKeyNum, BOOL fHighL)
  2650. {
  2651. HRESULT hr;
  2652. hr = S_OK;
  2653. if ( _pSoftkbdUIWnd == NULL )
  2654. {
  2655. hr = E_FAIL;
  2656. return hr;
  2657. }
  2658. return hr;
  2659. }
  2660. /*******************************************************************************
  2661. *
  2662. * Method function: UnadviseSoftKeyboardEventSink( )
  2663. *
  2664. * Unadvise the previously advised soft keyboard event sink interface.
  2665. *
  2666. /********************************************************************************/
  2667. STDMETHODIMP CSoftKbd::UnadviseSoftKeyboardEventSink(/*[in] */DWORD dwCookie)
  2668. {
  2669. HRESULT hr;
  2670. KBDLAYOUTDES *pKbdLayout;
  2671. hr = S_OK;
  2672. // we assume dwCookie stands for the real soft keyboard Id.
  2673. if ( dwCookie == 0 )
  2674. {
  2675. hr = E_FAIL;
  2676. return hr;
  2677. }
  2678. if ( dwCookie == DWCOOKIE_SFTKBDWNDES )
  2679. {
  2680. SafeReleaseClear( _pskbdwndes );
  2681. return hr;
  2682. }
  2683. // Try to find the soft keyboard layout.
  2684. pKbdLayout = _lpKbdLayoutDesList;
  2685. while ( pKbdLayout != NULL ) {
  2686. if ( pKbdLayout->wKbdLayoutID == dwCookie )
  2687. break;
  2688. pKbdLayout = pKbdLayout->pNext;
  2689. }
  2690. if ( pKbdLayout == NULL )
  2691. {
  2692. //
  2693. // Cannot find this keyboard layout
  2694. //
  2695. hr = E_FAIL;
  2696. return hr;
  2697. }
  2698. if ( pKbdLayout->pskbes == NULL )
  2699. {
  2700. // this event sink has not be registered.
  2701. hr = E_FAIL;
  2702. return hr;
  2703. }
  2704. SafeReleaseClear(pKbdLayout->pskbes);
  2705. return hr;
  2706. }
  2707. /*******************************************************************************
  2708. *
  2709. * Method function: AdviseSoftKeyboardEventSink( )
  2710. *
  2711. * Register soft keyboard event sink interface for the client of this component
  2712. *
  2713. *
  2714. /********************************************************************************/
  2715. STDMETHODIMP CSoftKbd::AdviseSoftKeyboardEventSink(/*[in] */DWORD dwKeyboardId, /*[in]*/ REFIID riid, IUnknown *punk, /*[out] */DWORD *pdwCookie)
  2716. {
  2717. HRESULT hr;
  2718. KBDLAYOUTDES *pKbdLayout;
  2719. *pdwCookie = 0;
  2720. if ( ! IsEqualIID(riid, IID_ISoftKeyboardEventSink) && ! IsEqualIID(riid, IID_ISoftKbdWindowEventSink) )
  2721. return E_UNEXPECTED;
  2722. if ( IsEqualIID(riid, IID_ISoftKbdWindowEventSink) )
  2723. {
  2724. if ( _pskbdwndes != NULL )
  2725. return E_FAIL;
  2726. CHECKHR(punk->QueryInterface(riid, (void **)&_pskbdwndes) );
  2727. if ( pdwCookie != NULL )
  2728. *pdwCookie = DWCOOKIE_SFTKBDWNDES;
  2729. return hr;
  2730. }
  2731. // check to see if specified soft keyboard layout is already generated.
  2732. pKbdLayout = _lpKbdLayoutDesList;
  2733. while ( pKbdLayout != NULL ) {
  2734. if ( pKbdLayout->wKbdLayoutID == dwKeyboardId )
  2735. break;
  2736. pKbdLayout = pKbdLayout->pNext;
  2737. }
  2738. if ( pKbdLayout == NULL )
  2739. {
  2740. //
  2741. // Cannot find this keyboard layout
  2742. //
  2743. hr = E_FAIL;
  2744. return hr;
  2745. }
  2746. CHECKHR(punk->QueryInterface(riid, (void **)&(pKbdLayout->pskbes)) );
  2747. if ( pdwCookie != NULL )
  2748. *pdwCookie = dwKeyboardId;
  2749. CleanUp:
  2750. return hr == S_OK ? S_OK : E_UNEXPECTED;
  2751. }
  2752. HRESULT CSoftKbd::_HandleTitleBarEvent( DWORD dwId )
  2753. {
  2754. HRESULT hr = S_OK;
  2755. // dwId stands for IconId or CloseId.
  2756. // So far, we handle close button event only.
  2757. if (dwId == KID_CLOSE)
  2758. {
  2759. if (_pskbdwndes != NULL)
  2760. hr = _pskbdwndes->OnWindowClose( );
  2761. }
  2762. return hr;
  2763. }
  2764. HRESULT CSoftKbd::_HandleKeySelection(KEYID keyId)
  2765. {
  2766. HRESULT hr = S_OK;
  2767. int uKeyIndex, i;
  2768. KBDLAYOUT *realKbdLayout=NULL;
  2769. KBDLAYOUTDES *lpCurKbdLayout=NULL;
  2770. ACTIVELABEL *CurLabel=NULL;
  2771. BOOL fModifierSpecial = FALSE;
  2772. lpCurKbdLayout = _lpCurKbdLayout;
  2773. if ( lpCurKbdLayout == NULL ) return hr;
  2774. // Get the KeyIndex in the current layout's key description
  2775. realKbdLayout = &(lpCurKbdLayout->kbdLayout);
  2776. if ( realKbdLayout == NULL ) return hr;
  2777. CurLabel = _CurLabel;
  2778. uKeyIndex = -1;
  2779. for ( i=0; i<realKbdLayout->wNumberOfKeys; i++) {
  2780. if ( keyId == realKbdLayout->lpKeyDes[i].keyId )
  2781. {
  2782. uKeyIndex = i;
  2783. break;
  2784. }
  2785. }
  2786. if ( uKeyIndex == -1 )
  2787. {
  2788. // It is not a legal key, it is impossible, we just stop here.
  2789. return E_FAIL;
  2790. }
  2791. // set the modifier status
  2792. MODIFYTYPE tModifier;
  2793. tModifier = realKbdLayout->lpKeyDes[uKeyIndex].tModifier;
  2794. if ( tModifier != none )
  2795. {
  2796. lpCurKbdLayout->ModifierStatus ^= (1 << tModifier);
  2797. }
  2798. if (lpCurKbdLayout->pskbes != NULL )
  2799. {
  2800. int j;
  2801. WCHAR *lpszLabel;
  2802. WORD wNumOfKeys;
  2803. wNumOfKeys = realKbdLayout->wNumberOfKeys;
  2804. // Try to get the label text for this key.
  2805. for ( j=0; j< wNumOfKeys; j++ )
  2806. {
  2807. if ( CurLabel[j].keyId == keyId )
  2808. {
  2809. lpszLabel = CurLabel[j].lpLabelText;
  2810. break;
  2811. }
  2812. }
  2813. // Notify the client of key event.
  2814. (lpCurKbdLayout->pskbes)->OnKeySelection(keyId, lpszLabel);
  2815. }
  2816. else
  2817. {
  2818. // there is no event sink registered for this keyboard layout.
  2819. // this must be a standard keyboard layout.
  2820. // we will just simuate key stroke event for this key.
  2821. if ( realKbdLayout->fStandard == TRUE )
  2822. {
  2823. BYTE bVk, bScan;
  2824. int j, jIndex;
  2825. BOOL fExtendKey, fPictureKey;
  2826. PICTUREKEY *pPictureKeys;
  2827. switch ( _wCurKbdLayoutID ) {
  2828. case SOFTKBD_JPN_STANDARD :
  2829. case SOFTKBD_JPN_ENHANCE :
  2830. pPictureKeys = gJpnPictureKeys;
  2831. break;
  2832. case SOFTKBD_US_STANDARD :
  2833. case SOFTKBD_US_ENHANCE :
  2834. case SOFTKBD_EURO_STANDARD :
  2835. case SOFTKBD_EURO_ENHANCE :
  2836. pPictureKeys = gPictureKeys;
  2837. break;
  2838. }
  2839. fPictureKey = FALSE;
  2840. for ( j=0; j<NUM_PICTURE_KEYS; j++)
  2841. {
  2842. if ( pPictureKeys[j].uScanCode == keyId )
  2843. {
  2844. // This is a picture key.
  2845. // it may be a extended key.
  2846. jIndex = j;
  2847. fPictureKey = TRUE;
  2848. break;
  2849. }
  2850. if ( pPictureKeys[j].uScanCode == 0 )
  2851. {
  2852. // This is the last item in pPictureKeys.
  2853. break;
  2854. }
  2855. }
  2856. fExtendKey = FALSE;
  2857. if ( fPictureKey )
  2858. {
  2859. if ( (keyId & 0xFF00) == 0xE000 )
  2860. {
  2861. fExtendKey = TRUE;
  2862. bScan = (BYTE)(keyId & 0x000000ff);
  2863. }
  2864. else
  2865. {
  2866. fExtendKey = FALSE;
  2867. bScan = (BYTE)(keyId);
  2868. }
  2869. bVk = (BYTE)(pPictureKeys[jIndex].uVkey);
  2870. if ( bVk == 0 )
  2871. bVk = (BYTE)MapVirtualKeyEx((UINT)bScan, 1, lpCurKbdLayout->CurhKl);
  2872. }
  2873. else
  2874. {
  2875. bScan = (BYTE)keyId;
  2876. bVk = (BYTE)MapVirtualKeyEx((UINT)bScan, 1, lpCurKbdLayout->CurhKl);
  2877. }
  2878. if ( tModifier == none )
  2879. {
  2880. if ( fExtendKey )
  2881. {
  2882. keybd_event(bVk, bScan, (DWORD)KEYEVENTF_EXTENDEDKEY, 0);
  2883. keybd_event(bVk, bScan, (DWORD)(KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP), 0);
  2884. }
  2885. else
  2886. {
  2887. keybd_event(bVk, bScan, 0, 0);
  2888. keybd_event(bVk, bScan, (DWORD)KEYEVENTF_KEYUP, 0);
  2889. }
  2890. // if the Shift Key is pressed, we need to release this key.
  2891. if ( lpCurKbdLayout->ModifierStatus & MODIFIER_SHIFT)
  2892. {
  2893. fModifierSpecial = TRUE;
  2894. lpCurKbdLayout->ModifierStatus &= ~((WORD)MODIFIER_SHIFT);
  2895. // simulate the SHIFT-UP key event.
  2896. keybd_event((BYTE)VK_SHIFT, (BYTE)KID_LSHFT, (DWORD)KEYEVENTF_KEYUP, 0);
  2897. }
  2898. // if the Ctrl Key is pressed, we need to release this key.
  2899. if ( lpCurKbdLayout->ModifierStatus & MODIFIER_CTRL)
  2900. {
  2901. fModifierSpecial = TRUE;
  2902. lpCurKbdLayout->ModifierStatus &= ~((WORD)MODIFIER_CTRL);
  2903. // simulate the SHIFT-UP key event.
  2904. keybd_event((BYTE)VK_CONTROL, (BYTE)KID_CTRL, (DWORD)KEYEVENTF_KEYUP, 0);
  2905. }
  2906. // if the Shift Key is pressed, we need to release this key.
  2907. if ( lpCurKbdLayout->ModifierStatus & MODIFIER_ALT)
  2908. {
  2909. fModifierSpecial = TRUE;
  2910. lpCurKbdLayout->ModifierStatus &= ~((WORD)MODIFIER_ALT);
  2911. // simulate the SHIFT-UP key event.
  2912. keybd_event((BYTE)VK_MENU, (BYTE)KID_ALT, (DWORD)KEYEVENTF_KEYUP, 0);
  2913. }
  2914. // if the Right Alt Key is pressed, we need to release this key.
  2915. if ( lpCurKbdLayout->ModifierStatus & MODIFIER_ALTGR)
  2916. {
  2917. fModifierSpecial = TRUE;
  2918. lpCurKbdLayout->ModifierStatus &= ~((WORD)MODIFIER_ALTGR);
  2919. // simulate the SHIFT-UP key event.
  2920. keybd_event((BYTE)VK_RMENU, (BYTE)KID_RALT, (DWORD)KEYEVENTF_KEYUP, 0);
  2921. }
  2922. }
  2923. else
  2924. {
  2925. // specially handle Caps Lock
  2926. if ( keyId == KID_CAPS )
  2927. {
  2928. // this is a togglable key
  2929. keybd_event(bVk, bScan, 0, 0);
  2930. keybd_event(bVk, bScan, (DWORD)KEYEVENTF_KEYUP, 0);
  2931. }
  2932. else if (keyId == KID_KANA)
  2933. {
  2934. BYTE pKeyState[256];
  2935. memset(pKeyState, 0, sizeof(pKeyState) );
  2936. if ( lpCurKbdLayout->ModifierStatus & (1 << tModifier) )
  2937. pKeyState[VK_KANA] = 0x01;
  2938. SetKeyboardState(pKeyState);
  2939. }
  2940. else
  2941. {
  2942. if ( lpCurKbdLayout->ModifierStatus & (1 << tModifier) ) {
  2943. // This key is pressed now
  2944. keybd_event(bVk, bScan, 0, 0);
  2945. }
  2946. else
  2947. {
  2948. // This key is released now
  2949. keybd_event(bVk, bScan, (DWORD)KEYEVENTF_KEYUP, 0);
  2950. }
  2951. }
  2952. }
  2953. }
  2954. }
  2955. if ( (realKbdLayout->lpKeyDes[uKeyIndex].tModifier != none) || fModifierSpecial )
  2956. {
  2957. if ( realKbdLayout->fStandard == TRUE )
  2958. {
  2959. DWORD iModiCombState;
  2960. DWORD iTmp;
  2961. switch ( _wCurKbdLayoutID ) {
  2962. case SOFTKBD_US_STANDARD :
  2963. case SOFTKBD_US_ENHANCE :
  2964. // this is for US Standard keyboard.
  2965. // others may need to handle separately.
  2966. iModiCombState = (lpCurKbdLayout->ModifierStatus) & (MODIFIER_CAPSLOCK | MODIFIER_SHIFT);
  2967. iModiCombState = iModiCombState >> 1;
  2968. // bit1 for Caps.
  2969. // bit2 for Shift
  2970. break;
  2971. case SOFTKBD_EURO_STANDARD :
  2972. case SOFTKBD_EURO_ENHANCE :
  2973. // this is for Euro 102 standard keyboard.
  2974. // How to map ModifierStatus -> CurModiState.
  2975. // bit 1 for Caps, bit2 for Shift, bit3 for AltGr.
  2976. iModiCombState = (lpCurKbdLayout->ModifierStatus) & ( MODIFIER_CAPSLOCK | MODIFIER_SHIFT );
  2977. iModiCombState = iModiCombState >> 1;
  2978. iTmp = (lpCurKbdLayout->ModifierStatus) & MODIFIER_ALTGR;
  2979. iTmp = iTmp >> 4;
  2980. iModiCombState += iTmp;
  2981. break;
  2982. case SOFTKBD_JPN_STANDARD :
  2983. case SOFTKBD_JPN_ENHANCE :
  2984. // How to map ModifierStatus -> CurModiState.
  2985. iModiCombState = (lpCurKbdLayout->ModifierStatus) & ( MODIFIER_CAPSLOCK | MODIFIER_SHIFT );
  2986. iModiCombState = iModiCombState >> 1;
  2987. iTmp = (lpCurKbdLayout->ModifierStatus) & (MODIFIER_ALT | MODIFIER_KANA);
  2988. iTmp = iTmp >> 2;
  2989. iModiCombState += iTmp;
  2990. break;
  2991. }
  2992. SetKeyboardLabelTextCombination(iModiCombState);
  2993. ShowSoftKeyboard(TRUE);
  2994. }
  2995. }
  2996. return hr;
  2997. }
  2998. /*******************************************************************************
  2999. *
  3000. * Method function: _UnicodeToUtf8( )
  3001. *
  3002. * Convert unicode characters to UTF8.
  3003. *
  3004. * Result is NULL terminated if sufficient space in result
  3005. * buffer is available.
  3006. *
  3007. * Arguments:
  3008. *
  3009. * pwUnicode -- ptr to start of unicode buffer
  3010. * cchUnicode -- length of unicode buffer
  3011. * pchResult -- ptr to start of result buffer for UTF8 chars
  3012. * cchResult -- length of result buffer
  3013. *
  3014. * Return Value:
  3015. *
  3016. * Count of UTF8 characters in result, if successful.
  3017. * 0 on error. GetLastError() has error code.
  3018. *
  3019. *
  3020. /********************************************************************************/
  3021. DWORD CSoftKbd::_UnicodeToUtf8(PWCHAR pwUnicode, DWORD cchUnicode, PCHAR pchResult, DWORD cchResult)
  3022. {
  3023. WCHAR wch; // current unicode character being converted
  3024. DWORD lengthUtf8 = 0; // length of UTF8 result string
  3025. WORD lowSurrogate;
  3026. DWORD surrogateDword;
  3027. //
  3028. // loop converting unicode chars until run out or error
  3029. //
  3030. Assert( cchUnicode > 0 );
  3031. while ( cchUnicode-- )
  3032. {
  3033. wch = *pwUnicode++;
  3034. //
  3035. // ASCII character (7 bits or less) -- converts to directly
  3036. //
  3037. if ( wch < 0x80 )
  3038. {
  3039. lengthUtf8++;
  3040. if ( pchResult )
  3041. {
  3042. if ( lengthUtf8 >= cchResult )
  3043. {
  3044. goto OutOfBuffer;
  3045. }
  3046. *pchResult++ = (CHAR)wch;
  3047. }
  3048. continue;
  3049. }
  3050. //
  3051. // wide character less than 0x07ff (11bits) converts to two bytes
  3052. // - upper 5 bits in first byte
  3053. // - lower 6 bits in secondar byte
  3054. //
  3055. else if ( wch <= UTF8_2_MAX )
  3056. {
  3057. lengthUtf8 += 2;
  3058. if ( pchResult )
  3059. {
  3060. if ( lengthUtf8 >= cchResult )
  3061. {
  3062. goto OutOfBuffer;
  3063. }
  3064. *pchResult++ = UTF8_1ST_OF_2 | wch >> 6;
  3065. *pchResult++ = UTF8_TRAIL | LOW6BITS( (UCHAR)wch );
  3066. }
  3067. continue;
  3068. }
  3069. //
  3070. // surrogate pair
  3071. // - if have high surrogate followed by low surrogate then
  3072. // process as surrogate pair
  3073. // - otherwise treat character as ordinary unicode "three-byte"
  3074. // character, by falling through to below
  3075. //
  3076. else if ( wch >= HIGH_SURROGATE_START &&
  3077. wch <= HIGH_SURROGATE_END &&
  3078. cchUnicode &&
  3079. (lowSurrogate = *pwUnicode) &&
  3080. lowSurrogate >= LOW_SURROGATE_START &&
  3081. lowSurrogate <= LOW_SURROGATE_END )
  3082. {
  3083. // have a surrogate pair
  3084. // - pull up next unicode character (low surrogate of pair)
  3085. // - make full DWORD surrogate pair
  3086. // - then lay out four UTF8 bytes
  3087. // 1st of four, then three trail bytes
  3088. // 0x1111xxxx
  3089. // 0x10xxxxxx
  3090. // 0x10xxxxxx
  3091. // 0x10xxxxxx
  3092. pwUnicode++;
  3093. cchUnicode--;
  3094. lengthUtf8 += 4;
  3095. if ( pchResult )
  3096. {
  3097. if ( lengthUtf8 >= cchResult )
  3098. {
  3099. goto OutOfBuffer;
  3100. }
  3101. surrogateDword = (((wch-0xD800) << 10) + (lowSurrogate - 0xDC00) + 0x10000);
  3102. *pchResult++ = UTF8_1ST_OF_4 | (UCHAR) (surrogateDword >> 18);
  3103. *pchResult++ = UTF8_TRAIL | (UCHAR) LOW6BITS(surrogateDword >> 12);
  3104. *pchResult++ = UTF8_TRAIL | (UCHAR) LOW6BITS(surrogateDword >> 6);
  3105. *pchResult++ = UTF8_TRAIL | (UCHAR) LOW6BITS(surrogateDword);
  3106. }
  3107. }
  3108. //
  3109. // wide character (non-zero in top 5 bits) converts to three bytes
  3110. // - top 4 bits in first byte
  3111. // - middle 6 bits in second byte
  3112. // - low 6 bits in third byte
  3113. //
  3114. else
  3115. {
  3116. lengthUtf8 += 3;
  3117. if ( pchResult )
  3118. {
  3119. if ( lengthUtf8 >= cchResult )
  3120. {
  3121. goto OutOfBuffer;
  3122. }
  3123. *pchResult++ = UTF8_1ST_OF_3 | (wch >> 12);
  3124. *pchResult++ = UTF8_TRAIL | LOW6BITS( wch >> 6 );
  3125. *pchResult++ = UTF8_TRAIL | LOW6BITS( wch );
  3126. }
  3127. }
  3128. }
  3129. //
  3130. // NULL terminate buffer
  3131. // return UTF8 character count
  3132. //
  3133. if ( pchResult && lengthUtf8 < cchResult )
  3134. {
  3135. *pchResult = 0;
  3136. }
  3137. return( lengthUtf8 );
  3138. OutOfBuffer:
  3139. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  3140. return( 0 );
  3141. }
  3142. /*******************************************************************************
  3143. *
  3144. * Method function _Utf8ToUnicode( )
  3145. *
  3146. * Convert UTF8 characters to unicode.
  3147. *
  3148. * Result is NULL terminated if sufficient space in result
  3149. * buffer is available.
  3150. * Arguments:
  3151. *
  3152. * pwResult -- ptr to start of result buffer for unicode chars
  3153. * cwResult -- length of result buffer in WCHAR
  3154. * pwUtf8 -- ptr to start of UTF8 buffer
  3155. * cchUtf8 -- length of UTF8 buffer
  3156. *
  3157. * Return Value:
  3158. * Count of unicode characters in result, if successful.
  3159. * 0 on error. GetLastError() has error code.
  3160. *
  3161. *******************************************************************************/
  3162. DWORD CSoftKbd::_Utf8ToUnicode(PCHAR pchUtf8, DWORD cchUtf8, PWCHAR pwResult, DWORD cwResult)
  3163. {
  3164. CHAR ch; // current UTF8 character
  3165. WCHAR wch; // current unicode character
  3166. DWORD trailCount = 0; // count of UTF8 trail bytes to follow
  3167. DWORD lengthUnicode = 0; // length of unicode result string
  3168. BOOL bsurrogatePair = FALSE;
  3169. DWORD surrogateDword;
  3170. //
  3171. // loop converting UTF8 chars until run out or error
  3172. //
  3173. Assert( cchUtf8 > 0 );
  3174. while ( cchUtf8-- )
  3175. {
  3176. ch = *pchUtf8++;
  3177. //
  3178. // ASCII character -- just copy
  3179. //
  3180. if ( BIT7(ch) == 0 )
  3181. {
  3182. lengthUnicode++;
  3183. if ( pwResult )
  3184. {
  3185. if ( lengthUnicode >= cwResult )
  3186. {
  3187. goto OutOfBuffer;
  3188. }
  3189. *pwResult++ = (WCHAR)ch;
  3190. }
  3191. continue;
  3192. }
  3193. //
  3194. // UTF8 trail byte
  3195. // - if not expected, error
  3196. // - otherwise shift unicode character 6 bits and
  3197. // copy in lower six bits of UTF8
  3198. // - if last UTF8 byte, copy result to unicode string
  3199. //
  3200. else if ( BIT6(ch) == 0 )
  3201. {
  3202. if ( trailCount == 0 )
  3203. {
  3204. goto InvalidUtf8;
  3205. }
  3206. if ( !bsurrogatePair )
  3207. {
  3208. wch <<= 6;
  3209. wch |= LOW6BITS( ch );
  3210. if ( --trailCount == 0 )
  3211. {
  3212. lengthUnicode++;
  3213. if ( pwResult )
  3214. {
  3215. if ( lengthUnicode >= cwResult )
  3216. {
  3217. goto OutOfBuffer;
  3218. }
  3219. *pwResult++ = wch;
  3220. }
  3221. }
  3222. continue;
  3223. }
  3224. // surrogate pair
  3225. // - same as above EXCEPT build two unicode chars
  3226. // from surrogateDword
  3227. else
  3228. {
  3229. surrogateDword <<= 6;
  3230. surrogateDword |= LOW6BITS( ch );
  3231. if ( --trailCount == 0 )
  3232. {
  3233. lengthUnicode += 2;
  3234. if ( pwResult )
  3235. {
  3236. if ( lengthUnicode >= cwResult )
  3237. {
  3238. goto OutOfBuffer;
  3239. }
  3240. surrogateDword -= 0x10000;
  3241. *pwResult++ = (WCHAR) ((surrogateDword >> 10) + HIGH_SURROGATE_START);
  3242. *pwResult++ = (WCHAR) ((surrogateDword & 0x3ff) + LOW_SURROGATE_START);
  3243. }
  3244. bsurrogatePair = FALSE;
  3245. }
  3246. }
  3247. }
  3248. //
  3249. // UTF8 lead byte
  3250. // - if currently in extension, error
  3251. else
  3252. {
  3253. if ( trailCount != 0 )
  3254. {
  3255. goto InvalidUtf8;
  3256. }
  3257. // first of two byte character (110xxxxx)
  3258. if ( BIT5(ch) == 0 )
  3259. {
  3260. trailCount = 1;
  3261. wch = LOW5BITS(ch);
  3262. continue;
  3263. }
  3264. // first of three byte character (1110xxxx)
  3265. else if ( BIT4(ch) == 0 )
  3266. {
  3267. trailCount = 2;
  3268. wch = LOW4BITS(ch);
  3269. continue;
  3270. }
  3271. // first of four byte surrogate pair (11110xxx)
  3272. else if ( BIT3(ch) == 0 )
  3273. {
  3274. trailCount = 3;
  3275. surrogateDword = LOW4BITS(ch);
  3276. bsurrogatePair = TRUE;
  3277. }
  3278. else
  3279. {
  3280. goto InvalidUtf8;
  3281. }
  3282. }
  3283. }
  3284. // catch if hit end in the middle of UTF8 multi-byte character
  3285. if ( trailCount )
  3286. {
  3287. goto InvalidUtf8;
  3288. }
  3289. //
  3290. // NULL terminate buffer
  3291. // return the number of Unicode characters written.
  3292. //
  3293. if ( pwResult && lengthUnicode < cwResult )
  3294. {
  3295. *pwResult = 0;
  3296. }
  3297. return( lengthUnicode );
  3298. OutOfBuffer:
  3299. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  3300. return( 0 );
  3301. InvalidUtf8:
  3302. SetLastError( ERROR_INVALID_DATA );
  3303. return( 0 );
  3304. }