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.

855 lines
22 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. imewndhd.cpp
  5. Abstract:
  6. This file implements the IME window handler Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #include "private.h"
  12. #include "defs.h"
  13. #include "cdimm.h"
  14. #include "imewndhd.h"
  15. #include "globals.h"
  16. LPCTSTR IMEWndHandlerName = TEXT("IMEWindowHandler");
  17. CIMEWindowHandler::CIMEWindowHandler(
  18. HWND hwnd,
  19. BOOL fDefault
  20. )
  21. {
  22. m_imeui.hImeWnd = hwnd;
  23. m_imeui.hIMC = NULL;
  24. m_imeui.nCntInIMEProc = 0;
  25. m_imeui.fDefault = fDefault;
  26. CActiveIMM *_pActiveIMM = GetTLS();
  27. if (_pActiveIMM == NULL)
  28. return;
  29. _pActiveIMM->_GetKeyboardLayout(&m_hKL_UnSelect);
  30. }
  31. CIMEWindowHandler::~CIMEWindowHandler(
  32. )
  33. {
  34. }
  35. LRESULT
  36. CIMEWindowHandler::ImeWndProcWorker(
  37. UINT uMsg,
  38. WPARAM wParam,
  39. LPARAM lParam,
  40. BOOL fUnicode
  41. )
  42. {
  43. LRESULT lr;
  44. CActiveIMM *_pActiveIMM = GetTLS();
  45. if (_pActiveIMM == NULL)
  46. return 0L;
  47. lr = _ImeWndProcWorker(uMsg, wParam, lParam, fUnicode, _pActiveIMM);
  48. return lr;
  49. }
  50. LRESULT
  51. CIMEWindowHandler::_ImeWndProcWorker(
  52. UINT uMsg,
  53. WPARAM wParam,
  54. LPARAM lParam,
  55. BOOL fUnicode,
  56. CActiveIMM* pActiveIMM
  57. )
  58. {
  59. /*
  60. * This is necessary to avoid recursion call from IME UI.
  61. */
  62. if (IsIMEHandler() > 1) {
  63. TraceMsg(TF_API, "ImeWndProcWorker: Recursive for hwnd=%08x, msg=%08x, wp=%08x, lp=%08x", m_imeui.hImeWnd, uMsg, wParam, lParam);
  64. switch (uMsg) {
  65. case WM_IME_STARTCOMPOSITION:
  66. case WM_IME_ENDCOMPOSITION:
  67. case WM_IME_COMPOSITION:
  68. case WM_IME_SETCONTEXT:
  69. case WM_IME_NOTIFY:
  70. case WM_IME_CONTROL:
  71. case WM_IME_COMPOSITIONFULL:
  72. case WM_IME_SELECT:
  73. case WM_IME_CHAR:
  74. case WM_IME_REQUEST:
  75. return 0L;
  76. default:
  77. return pActiveIMM->_CallWindowProc(m_imeui.hImeWnd, uMsg, wParam, lParam);
  78. }
  79. }
  80. switch (uMsg) {
  81. case WM_CREATE:
  82. ImeWndCreateHandler((LPCREATESTRUCT)lParam);
  83. break;
  84. case WM_DESTROY:
  85. /*
  86. * We are destroying the IME window,
  87. * destroy any UI window that it owns.
  88. */
  89. ImeWndDestroyHandler();
  90. break;
  91. case WM_NCDESTROY:
  92. /* case WM_FINALDESTROY: */
  93. pActiveIMM->_CallWindowProc(m_imeui.hImeWnd, uMsg, wParam, lParam);
  94. ImeWndFinalDestroyHandler();
  95. return 0L;
  96. case WM_IME_SYSTEM:
  97. if (ImeSystemHandler(uMsg, wParam, lParam, fUnicode, pActiveIMM))
  98. return 0L;
  99. break;
  100. case WM_IME_SELECT:
  101. ImeSelectHandler(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  102. break;
  103. case WM_IME_CONTROL:
  104. ImeControlHandler(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  105. break;
  106. case WM_IME_SETCONTEXT:
  107. ImeSetContextHandler(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  108. break;
  109. case WM_IME_NOTIFY:
  110. ImeNotifyHandler(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  111. break;
  112. case WM_IME_REQUEST:
  113. break;
  114. case WM_IME_COMPOSITION:
  115. case WM_IME_ENDCOMPOSITION:
  116. case WM_IME_STARTCOMPOSITION:
  117. {
  118. LRESULT lret;
  119. lret = SendMessageToUI(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  120. if (!pActiveIMM->_IsRealIme())
  121. return lret;
  122. break;
  123. }
  124. default:
  125. if (IsMsImeMessage(uMsg)) {
  126. if (! pActiveIMM->_IsRealIme()) {
  127. return ImeMsImeHandler(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  128. }
  129. }
  130. break;
  131. }
  132. return pActiveIMM->_CallWindowProc(m_imeui.hImeWnd, uMsg, wParam, lParam);
  133. }
  134. LRESULT
  135. CIMEWindowHandler::ImeWndCreateHandler(
  136. DWORD style,
  137. HIMC hDefIMC
  138. )
  139. {
  140. if ( !(style & WS_POPUP) || !(style & WS_DISABLED)) {
  141. TraceMsg(TF_WARNING, "IME should have WS_POPUP and WS_DISABLED!!");
  142. return -1L;
  143. }
  144. CActiveIMM *_pActiveIMM = GetTLS();
  145. if (_pActiveIMM == NULL)
  146. return 0L;
  147. /*
  148. */
  149. if (hDefIMC != NULL) {
  150. if (ImeIsUsableContext(m_imeui.hImeWnd, hDefIMC, _pActiveIMM)) {
  151. /*
  152. * Store it for later use.
  153. */
  154. ImeSetImc(hDefIMC, _pActiveIMM);
  155. }
  156. else {
  157. ImeSetImc(NULL, _pActiveIMM);
  158. }
  159. }
  160. else {
  161. ImeSetImc(NULL, _pActiveIMM);
  162. }
  163. return 0L;
  164. }
  165. LRESULT
  166. CIMEWindowHandler::ImeWndCreateHandler(
  167. LPCREATESTRUCT lpcs
  168. )
  169. {
  170. HIMC hIMC;
  171. if (lpcs->hwndParent != NULL) {
  172. CActiveIMM *_pActiveIMM = GetTLS();
  173. if (_pActiveIMM == NULL)
  174. return 0L;
  175. _pActiveIMM->GetContextInternal(lpcs->hwndParent, &hIMC, FALSE);
  176. }
  177. else if (lpcs->lpCreateParams) {
  178. hIMC = (HIMC)lpcs->lpCreateParams;
  179. }
  180. else
  181. hIMC = NULL;
  182. return ImeWndCreateHandler(lpcs->style, hIMC);
  183. }
  184. VOID
  185. CIMEWindowHandler::ImeWndDestroyHandler(
  186. )
  187. {
  188. }
  189. VOID
  190. CIMEWindowHandler::ImeWndFinalDestroyHandler(
  191. )
  192. {
  193. CActiveIMM *_pActiveIMM = GetTLS();
  194. if (_pActiveIMM == NULL)
  195. return;
  196. _pActiveIMM->_ImeWndFinalDestroyHandler();
  197. SetProp(m_imeui.hImeWnd, IMEWndHandlerName, NULL);
  198. delete this;
  199. }
  200. LRESULT
  201. CIMEWindowHandler::ImeSystemHandler(
  202. UINT uMsg,
  203. WPARAM wParam,
  204. LPARAM lParam,
  205. BOOL fUnicode,
  206. CActiveIMM* pActiveIMM
  207. )
  208. {
  209. LRESULT dwRet = 0L;
  210. switch (wParam) {
  211. case IMS_ACTIVATETHREADLAYOUT:
  212. return ImeActivateLayout((HKL)lParam, pActiveIMM);
  213. #ifdef CICERO_3564
  214. case IMS_FINALIZE_COMPSTR:
  215. if (! pActiveIMM->_IsRealIme())
  216. {
  217. /*
  218. * KOREAN:
  219. * Finalize current composition string
  220. */
  221. HIMC hIMC = ImeGetImc();
  222. pActiveIMM->NotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
  223. }
  224. break;
  225. #endif // CICERO_3564
  226. }
  227. return dwRet;
  228. }
  229. LRESULT
  230. CIMEWindowHandler::ImeSelectHandler(
  231. UINT uMsg,
  232. WPARAM wParam,
  233. LPARAM lParam,
  234. BOOL fUnicode,
  235. CActiveIMM* pActiveIMM
  236. )
  237. {
  238. /*
  239. * Deliver this message to other IME windows in this thread.
  240. */
  241. if (! pActiveIMM->_IsRealIme((HKL)lParam) && m_imeui.fDefault)
  242. ImeBroadCastMsg(uMsg, wParam, lParam, fUnicode);
  243. /*
  244. * We must re-create UI window of newly selected IME.
  245. */
  246. return pActiveIMM->_ImeSelectHandler(uMsg, wParam, lParam, fUnicode, ImeGetImc());
  247. }
  248. LRESULT
  249. CIMEWindowHandler::ImeControlHandler(
  250. UINT uMsg,
  251. WPARAM wParam,
  252. LPARAM lParam,
  253. BOOL fUnicode,
  254. CActiveIMM* pActiveIMM
  255. )
  256. {
  257. /*
  258. * Do nothing with NULL hIMC.
  259. */
  260. HIMC hIMC = ImeGetImc();
  261. switch (wParam) {
  262. case IMC_OPENSTATUSWINDOW:
  263. case IMC_CLOSESTATUSWINDOW:
  264. pActiveIMM->HideOrRestoreToolbarWnd(IMC_OPENSTATUSWINDOW == wParam);
  265. break;
  266. /*
  267. * ------------------------------------------------
  268. * IMC_SETCOMPOSITIONFONT,
  269. * IMC_SETCONVERSIONMODE,
  270. * IMC_SETOPENSTATUS
  271. * ------------------------------------------------
  272. * Don't pass these WM_IME_CONTROLs to UI window.
  273. * Call Imm in order to process these requests instead.
  274. * It makes message flows simpler.
  275. */
  276. case IMC_SETCOMPOSITIONFONT:
  277. if (hIMC != NULL)
  278. {
  279. LOGFONTAW* lplf = (LOGFONTAW*)lParam;
  280. if (fUnicode)
  281. {
  282. if (FAILED(pActiveIMM->SetCompositionFontW(hIMC, (LOGFONTW *)lplf)))
  283. return 1L;
  284. }
  285. else
  286. {
  287. if (FAILED(pActiveIMM->SetCompositionFontA(hIMC, (LOGFONTA *)lplf)))
  288. return 1L;
  289. }
  290. }
  291. break;
  292. case IMC_SETCONVERSIONMODE:
  293. if (hIMC != NULL)
  294. {
  295. DWORD dwConversion, dwSentence;
  296. if (FAILED(pActiveIMM->GetConversionStatus(hIMC, &dwConversion, &dwSentence)) ||
  297. FAILED(pActiveIMM->SetConversionStatus(hIMC, (DWORD)lParam, dwSentence)))
  298. return 1L;
  299. }
  300. break;
  301. case IMC_SETSENTENCEMODE:
  302. if (hIMC != NULL)
  303. {
  304. DWORD dwConversion, dwSentence;
  305. if (FAILED(pActiveIMM->GetConversionStatus(hIMC, &dwConversion, &dwSentence)) ||
  306. FAILED(pActiveIMM->SetConversionStatus(hIMC, dwConversion, (DWORD)lParam)))
  307. return 1L;
  308. }
  309. break;
  310. case IMC_SETOPENSTATUS:
  311. if (hIMC != NULL)
  312. {
  313. if (FAILED(pActiveIMM->SetOpenStatus(hIMC, (int)lParam)))
  314. return 1L;
  315. }
  316. break;
  317. #if 0 // internal
  318. case IMC_GETCONVERSIONMODE:
  319. if (hIMC != NULL)
  320. {
  321. DWORD dwConversion, dwSentence;
  322. if (FAILED(GetTeb()->GetConversionStatus(hIMC, &dwConversion, &dwSentence)))
  323. return 1L;
  324. return dwConversion;
  325. }
  326. case IMC_GETSENTENCEMODE:
  327. if (hIMC != NULL)
  328. {
  329. DWORD dwConversion, dwSentence;
  330. if (FAILED(GetTeb()->GetConversionStatus(hIMC, &dwConversion, &dwSentence)))
  331. return 1L;
  332. return dwSentence;
  333. }
  334. case IMC_GETOPENSTATUS:
  335. if (hIMC != NULL)
  336. return GetTeb()->GetOpenStatus(hIMC);
  337. #endif
  338. case IMC_GETCOMPOSITIONFONT:
  339. if (hIMC != NULL)
  340. {
  341. LOGFONTAW* lplf = (LOGFONTAW*)lParam;
  342. if (fUnicode)
  343. {
  344. if (FAILED(pActiveIMM->GetCompositionFontW(hIMC, (LOGFONTW *)lplf)))
  345. return 1L;
  346. }
  347. else
  348. {
  349. if (FAILED(pActiveIMM->GetCompositionFontA(hIMC, (LOGFONTA *)lplf)))
  350. return 1L;
  351. }
  352. }
  353. break;
  354. case IMC_SETCOMPOSITIONWINDOW:
  355. if (hIMC != NULL)
  356. {
  357. if (FAILED(pActiveIMM->SetCompositionWindow(hIMC, (LPCOMPOSITIONFORM)lParam)))
  358. return 1L;
  359. }
  360. break;
  361. case IMC_SETSTATUSWINDOWPOS:
  362. if (hIMC != NULL)
  363. {
  364. POINT ppt;
  365. ppt.x = (LONG)((LPPOINTS)&lParam)->x;
  366. ppt.y = (LONG)((LPPOINTS)&lParam)->y;
  367. if (FAILED(pActiveIMM->SetStatusWindowPos(hIMC, &ppt)))
  368. return 1L;
  369. }
  370. break;
  371. case IMC_SETCANDIDATEPOS:
  372. if (hIMC != NULL)
  373. {
  374. if (FAILED(pActiveIMM->SetCandidateWindow(hIMC, (LPCANDIDATEFORM)lParam)))
  375. return 1L;
  376. }
  377. break;
  378. /*
  379. * Followings are the messages to be sent to UI.
  380. */
  381. case IMC_GETCANDIDATEPOS:
  382. case IMC_GETSTATUSWINDOWPOS:
  383. case IMC_GETCOMPOSITIONWINDOW:
  384. case IMC_GETSOFTKBDPOS:
  385. case IMC_SETSOFTKBDPOS:
  386. if (hIMC != NULL)
  387. return SendMessageToUI(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  388. default:
  389. break;
  390. }
  391. return 0L;
  392. }
  393. LRESULT
  394. CIMEWindowHandler::ImeSetContextHandler(
  395. UINT uMsg,
  396. WPARAM wParam,
  397. LPARAM lParam,
  398. BOOL fUnicode,
  399. CActiveIMM* pActiveIMM
  400. )
  401. {
  402. if (wParam) {
  403. /*
  404. * if it's being activated
  405. */
  406. if (GetWindowThreadProcessId(m_imeui.hImeWnd, NULL) != GetCurrentThreadId()) {
  407. TraceMsg(TF_WARNING, "ImeSetContextHandler: Can not access other thread's hIMC");
  408. return 0L;
  409. }
  410. HWND hwndFocus = GetFocus();
  411. HIMC hFocusImc;
  412. //
  413. // hFocusImc always need to set some valid hIMC for SetUIWindowContext().
  414. // When sets NULL hIMC in SetUIWindowContext(), message deliver to UI window
  415. // has been stop.
  416. //
  417. if (FAILED(pActiveIMM->GetContextInternal(hwndFocus, &hFocusImc, TRUE))) {
  418. TraceMsg(TF_WARNING, "ImeSetContextHandler: No hFocusImc");
  419. return 0L;
  420. }
  421. /*
  422. * Cannot share input context with other IME window.
  423. */
  424. if (hFocusImc != NULL &&
  425. ! ImeIsUsableContext(m_imeui.hImeWnd, hFocusImc, pActiveIMM)) {
  426. ImeSetImc(NULL, pActiveIMM);
  427. return 0L;
  428. }
  429. ImeSetImc(hFocusImc, pActiveIMM);
  430. /*
  431. * Store it to the window memory
  432. */
  433. pActiveIMM->SetUIWindowContext(hFocusImc);
  434. }
  435. return SendMessageToUI(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  436. }
  437. LRESULT
  438. CIMEWindowHandler::ImeNotifyHandler(
  439. UINT uMsg,
  440. WPARAM wParam,
  441. LPARAM lParam,
  442. BOOL fUnicode,
  443. CActiveIMM* pActiveIMM
  444. )
  445. {
  446. LRESULT lRet = 0L;
  447. switch (wParam) {
  448. case IMN_PRIVATE:
  449. break;
  450. case IMN_SETCONVERSIONMODE:
  451. case IMN_SETOPENSTATUS:
  452. //
  453. // notify shell and keyboard the conversion mode change
  454. //
  455. /*** FALL THROUGH ***/
  456. default:
  457. lRet = SendMessageToUI(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  458. }
  459. return lRet;
  460. }
  461. LRESULT
  462. CIMEWindowHandler::ImeMsImeHandler(
  463. UINT uMsg,
  464. WPARAM wParam,
  465. LPARAM lParam,
  466. BOOL fUnicode,
  467. CActiveIMM* pActiveIMM
  468. )
  469. {
  470. return SendMessageToUI(uMsg, wParam, lParam, fUnicode, pActiveIMM);
  471. }
  472. LRESULT
  473. CIMEWindowHandler::SendMessageToUI(
  474. UINT uMsg,
  475. WPARAM wParam,
  476. LPARAM lParam,
  477. BOOL fUnicode,
  478. CActiveIMM* pActiveIMM
  479. )
  480. {
  481. LRESULT lRet;
  482. InterlockedIncrement(&m_imeui.nCntInIMEProc); // Mark to avoid recursion.
  483. lRet = pActiveIMM->_SendUIMessage(uMsg, wParam, lParam);
  484. InterlockedDecrement(&m_imeui.nCntInIMEProc);
  485. return lRet;
  486. }
  487. LRESULT
  488. CIMEWindowHandler::ImeActivateLayout(
  489. HKL hSelKL,
  490. CActiveIMM* pActiveIMM
  491. )
  492. {
  493. if (hSelKL == m_hKL_UnSelect)
  494. //
  495. // Apps startup time, msctf!PostInputLangRequest may calls ActivateKeyboardLayout
  496. // with Cicero's hKL (04110411 or 08040804).
  497. // However, CIMEWindowHandle::m_hKL_UnSelect also have Cicero's hKL because
  498. // this class ask to ITfInputProcessorProfile.
  499. //
  500. return TRUE;
  501. HKL hUnSelKL = m_hKL_UnSelect;
  502. /*
  503. * Save IME_CMODE_GUID_NULL and IME_SMODE_GUID_NULL bit in the CContextList
  504. * When hSelKL is regacy IME, IMM32 SelectInputContext reset this flag.
  505. */
  506. CContextList _hIMC_MODE_GUID_NULL;
  507. Interface<IEnumInputContext> EnumInputContext;
  508. HRESULT hr = pActiveIMM->EnumInputContext(0, // 0 = Current Thread
  509. EnumInputContext);
  510. if (SUCCEEDED(hr)) {
  511. CEnumrateValue<IEnumInputContext,
  512. HIMC,
  513. CContextList> Enumrate(EnumInputContext,
  514. EnumInputContextCallback,
  515. &_hIMC_MODE_GUID_NULL);
  516. Enumrate.DoEnumrate();
  517. }
  518. /*
  519. * Deactivate layout (hUnSelKL).
  520. */
  521. pActiveIMM->_DeactivateLayout(hSelKL, hUnSelKL);
  522. IMTLS *ptls;
  523. LANGID langid;
  524. if ((ptls = IMTLS_GetOrAlloc()) != NULL)
  525. {
  526. ptls->pAImeProfile->GetLangId(&langid);
  527. if (PRIMARYLANGID(langid) == LANG_KOREAN)
  528. {
  529. //
  530. // Save open and conversion status for Korean
  531. //
  532. if (_hIMC_MODE_GUID_NULL.GetCount() > 0)
  533. {
  534. POSITION pos = _hIMC_MODE_GUID_NULL.GetStartPosition();
  535. int index;
  536. for (index = 0; index < _hIMC_MODE_GUID_NULL.GetCount(); index++)
  537. {
  538. HIMC hIMC;
  539. CContextList::CLIENT_IMC_FLAG client_flag;
  540. _hIMC_MODE_GUID_NULL.GetNextHimc(pos, &hIMC, &client_flag);
  541. if (client_flag & (CContextList::IMCF_CMODE_GUID_NULL |
  542. CContextList::IMCF_SMODE_GUID_NULL ))
  543. {
  544. DIMM_IMCLock imc(hIMC);
  545. if (SUCCEEDED(imc.GetResult()))
  546. imc->fdwHangul = imc->fdwConversion;
  547. }
  548. }
  549. }
  550. }
  551. }
  552. // /*
  553. // * If either hKL are regacy IME, then should call IMM32's handler.
  554. // */
  555. // if (_pThread->IsRealIme(hSelKL) || _pThread->IsRealIme(hUnSelKL))
  556. pActiveIMM->_CallWindowProc(m_imeui.hImeWnd,
  557. WM_IME_SYSTEM,
  558. IMS_ACTIVATETHREADLAYOUT,
  559. (LPARAM)hSelKL);
  560. /*
  561. * Activate layout (hSelKL).
  562. */
  563. pActiveIMM->_ActivateLayout(hSelKL, hUnSelKL);
  564. /*
  565. * Restore CContextList's IME_CMODE_GUID_NULL and IME_SMODE_GUID_NULL to each hIMC
  566. */
  567. if (_hIMC_MODE_GUID_NULL.GetCount() > 0) {
  568. POSITION pos = _hIMC_MODE_GUID_NULL.GetStartPosition();
  569. int index;
  570. for (index = 0; index < _hIMC_MODE_GUID_NULL.GetCount(); index++) {
  571. HIMC hIMC;
  572. CContextList::CLIENT_IMC_FLAG client_flag;
  573. _hIMC_MODE_GUID_NULL.GetNextHimc(pos, &hIMC, &client_flag);
  574. if (client_flag & (CContextList::IMCF_CMODE_GUID_NULL |
  575. CContextList::IMCF_SMODE_GUID_NULL )) {
  576. DIMM_IMCLock imc(hIMC);
  577. if (SUCCEEDED(imc.GetResult())) {
  578. if (PRIMARYLANGID(langid) == LANG_KOREAN) {
  579. //
  580. // Restore open and conversion status value by changing IMM32
  581. //
  582. imc->fdwConversion = imc->fdwHangul;
  583. if (imc->fdwConversion &
  584. (IME_CMODE_HANGUL | IME_CMODE_FULLSHAPE))
  585. imc->fOpen = TRUE;
  586. else
  587. imc->fOpen = FALSE;
  588. }
  589. if (client_flag & CContextList::IMCF_CMODE_GUID_NULL)
  590. imc->fdwConversion |= IME_CMODE_GUID_NULL;
  591. if (client_flag & CContextList::IMCF_SMODE_GUID_NULL)
  592. imc->fdwSentence |= IME_SMODE_GUID_NULL;
  593. }
  594. }
  595. }
  596. }
  597. /*
  598. * Set unselect hKL value
  599. */
  600. m_hKL_UnSelect = hSelKL;
  601. return TRUE;
  602. }
  603. VOID
  604. CIMEWindowHandler::ImeSetImc(
  605. HIMC hIMC,
  606. CActiveIMM* pActiveIMM
  607. )
  608. {
  609. HIMC hOldImc = ImeGetImc();
  610. /*
  611. * return if nothing to change.
  612. */
  613. if (hIMC == hOldImc)
  614. return;
  615. /*
  616. * Unmark the old input context.
  617. */
  618. if (hOldImc != NULL)
  619. ImeMarkUsedContext(NULL, hOldImc, pActiveIMM);
  620. /*
  621. * Update the in use input context for this IME window.
  622. */
  623. m_imeui.hIMC = hIMC;
  624. /*
  625. * Mark the new input context.
  626. */
  627. if (hIMC != NULL)
  628. ImeMarkUsedContext(m_imeui.hImeWnd, hIMC, pActiveIMM);
  629. }
  630. VOID
  631. CIMEWindowHandler::ImeMarkUsedContext(
  632. HWND hImeWnd,
  633. HIMC hIMC,
  634. CActiveIMM* pActiveIMM
  635. )
  636. /*+++
  637. Some IME windows can not share same input context.
  638. This function marks the specified hIMC to be in used by the specified IME window.
  639. ---*/
  640. {
  641. HWND hImcImeWnd;
  642. if (! pActiveIMM->_ContextLookup(hIMC, &hImcImeWnd)) {
  643. TraceMsg(TF_WARNING, "ImeMarkUsedContext: Invalid hImc (=%lx).", hIMC);
  644. return;
  645. }
  646. /*
  647. * Nothing to change?
  648. */
  649. if (hImcImeWnd == hImeWnd)
  650. return;
  651. pActiveIMM->_ContextUpdate(hIMC, hImeWnd);
  652. return;
  653. }
  654. BOOL
  655. CIMEWindowHandler::ImeIsUsableContext(
  656. HWND hImeWnd,
  657. HIMC hIMC,
  658. CActiveIMM* pActiveIMM
  659. )
  660. /*+++
  661. Some IME windows can not share the same input context.
  662. This function checks whether the specified hIMC can be used (means 'Set activated')
  663. by the specified IME window.
  664. Return: TRUE - OK to use the hIMC by hImeWnd.
  665. FALSE - otherwise.
  666. ---*/
  667. {
  668. HWND hImcImeWnd;
  669. if (! pActiveIMM->_ContextLookup(hIMC, &hImcImeWnd)) {
  670. TraceMsg(TF_WARNING, "ImeIsUsableContext: Invalid hIMC (=%lx).", hIMC);
  671. return FALSE;
  672. }
  673. if (hImcImeWnd == NULL ||
  674. hImcImeWnd == hImeWnd ||
  675. ! IsWindow(hImcImeWnd))
  676. return TRUE;
  677. else
  678. return FALSE;
  679. }
  680. BOOL
  681. CIMEWindowHandler::ImeBroadCastMsg(
  682. UINT uMsg,
  683. WPARAM wParam,
  684. LPARAM lParam,
  685. BOOL fUnicode
  686. )
  687. {
  688. return TRUE;
  689. }
  690. ENUM_RET
  691. CIMEWindowHandler::EnumInputContextCallback(
  692. HIMC hIMC,
  693. CContextList* pList
  694. )
  695. {
  696. DIMM_IMCLock imc(hIMC);
  697. if (SUCCEEDED(imc.GetResult())) {
  698. CContextList::CLIENT_IMC_FLAG client_flag = CContextList::IMCF_NONE;
  699. if (imc->fdwConversion & IME_CMODE_GUID_NULL)
  700. client_flag = (CContextList::CLIENT_IMC_FLAG)(client_flag | CContextList::IMCF_CMODE_GUID_NULL);
  701. if (imc->fdwSentence & IME_SMODE_GUID_NULL)
  702. client_flag = (CContextList::CLIENT_IMC_FLAG)(client_flag | CContextList::IMCF_SMODE_GUID_NULL);
  703. pList->SetAt(hIMC, client_flag);
  704. }
  705. return ENUM_CONTINUE;
  706. }
  707. CIMEWindowHandler*
  708. GetImeWndHandler(
  709. HWND hwnd,
  710. BOOL fDefault
  711. )
  712. {
  713. CIMEWindowHandler* pimeui = static_cast<CIMEWindowHandler*>(GetProp(hwnd, IMEWndHandlerName));
  714. if (pimeui == NULL) {
  715. pimeui = new CIMEWindowHandler(hwnd, fDefault);
  716. if (pimeui == NULL) {
  717. return NULL;
  718. }
  719. SetProp(hwnd, IMEWndHandlerName, pimeui);
  720. }
  721. pimeui->ImeSetWnd(hwnd);
  722. return pimeui;
  723. }