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.

2406 lines
69 KiB

  1. /*++
  2. Copyright (c) 2001, Microsoft Corporation
  3. Module Name:
  4. cic.cpp
  5. Abstract:
  6. This file implements the CicBridge Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #include "private.h"
  12. #include "globals.h"
  13. #include "template.h"
  14. #include "cic.h"
  15. #include "context.h"
  16. #include "profile.h"
  17. #include "funcprv.h"
  18. #include "korimx.h"
  19. #include "delay.h"
  20. #include "tls.h"
  21. //+---------------------------------------------------------------------------
  22. //
  23. // CicBridge::IUnknown::QueryInterface
  24. // CicBridge::IUnknown::AddRef
  25. // CicBridge::IUnknown::Release
  26. //
  27. //----------------------------------------------------------------------------
  28. HRESULT
  29. CicBridge::QueryInterface(
  30. REFIID riid,
  31. void** ppvObj)
  32. {
  33. *ppvObj = NULL;
  34. if (IsEqualIID(riid, IID_ITfSysHookSink))
  35. {
  36. *ppvObj = static_cast<ITfSysHookSink*>(this);
  37. }
  38. if (*ppvObj) {
  39. AddRef();
  40. return S_OK;
  41. }
  42. return E_NOINTERFACE;
  43. }
  44. ULONG
  45. CicBridge::AddRef(
  46. )
  47. {
  48. return InterlockedIncrement(&m_ref);
  49. }
  50. ULONG
  51. CicBridge::Release(
  52. )
  53. {
  54. ULONG cr = InterlockedDecrement(&m_ref);
  55. if (cr == 0) {
  56. delete this;
  57. }
  58. return cr;
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // CicBridge::ITfSysHookSink::OnPreFocusDIM
  63. // CicBridge::ITfSysHookSink::OnSysShellProc
  64. //
  65. //----------------------------------------------------------------------------
  66. HRESULT
  67. CicBridge::OnPreFocusDIM(
  68. HWND hWnd)
  69. {
  70. return S_OK;
  71. }
  72. HRESULT
  73. CicBridge::OnSysShellProc(
  74. int nCode,
  75. WPARAM wParam,
  76. LPARAM lParam)
  77. {
  78. return S_OK;
  79. }
  80. //+---------------------------------------------------------------------------
  81. //
  82. // CicBridge::ITfSysHookSink::OnSysKeyboardProc
  83. //
  84. //----------------------------------------------------------------------------
  85. const DWORD TRANSMSGCOUNT = 256;
  86. HRESULT
  87. CicBridge::OnSysKeyboardProc(
  88. WPARAM wParam,
  89. LPARAM lParam)
  90. {
  91. TLS* ptls = TLS::GetTLS();
  92. if (ptls == NULL)
  93. {
  94. DebugMsg(TF_ERROR, TEXT("CicBridge::OnSysKeyboardProc. ptls==NULL."));
  95. return S_FALSE;
  96. }
  97. ITfThreadMgr_P* ptim_P = ptls->GetTIM();
  98. if (ptim_P == NULL)
  99. {
  100. DebugMsg(TF_ERROR, TEXT("CicBridge::OnSysKeyboardProc. ptim_P==NULL"));
  101. return S_FALSE;
  102. }
  103. BOOL fKeystrokeFeed;
  104. if (FAILED(ptim_P->IsKeystrokeFeedEnabled(&fKeystrokeFeed)))
  105. {
  106. DebugMsg(TF_ERROR, TEXT("CicBridge::OnSysKeyboardProc. IsKeystrokeFeedEnabled return error."));
  107. return S_FALSE;
  108. }
  109. if (!fKeystrokeFeed)
  110. {
  111. return S_FALSE;
  112. }
  113. HWND hWnd = GetFocus();
  114. if (hWnd != NULL)
  115. {
  116. Interface<ITfDocumentMgr> pdimAssoc;
  117. ptim_P->GetFocus(pdimAssoc);
  118. if ((ITfDocumentMgr*)pdimAssoc) {
  119. //
  120. // Check if it is our dim or app dim.
  121. //
  122. if (IsOwnDim((ITfDocumentMgr*)pdimAssoc))
  123. {
  124. //
  125. // Call ImmGetAppCompatFlags with NULL to get the global app compat flag.
  126. //
  127. DWORD dwImeCompatFlags = ImmGetAppCompatFlags(NULL);
  128. if (dwImeCompatFlags & (IMECOMPAT_AIMM12 | IMECOMPAT_AIMM_LEGACY_CLSID | IMECOMPAT_AIMM12_TRIDENT))
  129. {
  130. //
  131. // AIMM aware apps.
  132. //
  133. HIMC hIMC = ImmGetContext(hWnd);
  134. if (hIMC == NULL)
  135. {
  136. return S_FALSE;
  137. }
  138. #if 0
  139. IMCLock imc(hIMC);
  140. if (FAILED(imc.GetResult()))
  141. {
  142. return S_FALSE;
  143. }
  144. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  145. if (FAILED(imc_ctfime.GetResult()))
  146. {
  147. return S_FALSE;
  148. }
  149. if (DefaultKeyHandling(ptls, imc, imc_ctfime->m_pCicContext, (UINT)wParam), lParam)
  150. {
  151. return S_OK;
  152. }
  153. #else
  154. BYTE abKbdState[256];
  155. if (!GetKeyboardState(abKbdState))
  156. return S_FALSE;
  157. DWORD fdwProperty = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY);
  158. if ((HIWORD(lParam) & KF_MENUMODE) ||
  159. ((HIWORD(lParam) & KF_UP) && (fdwProperty & IME_PROP_IGNORE_UPKEYS)) ||
  160. ((HIWORD(lParam) & KF_ALTDOWN) && !(fdwProperty & IME_PROP_NEED_ALTKEY)))
  161. return S_FALSE;
  162. HRESULT hr;
  163. hr = ProcessKey(ptls, ptim_P, hIMC, (UINT)wParam, lParam, abKbdState) ? S_OK : S_FALSE;
  164. if (hr == S_OK)
  165. {
  166. UINT uVirKey = (UINT)wParam & 0xffff;
  167. INT iNum;
  168. if (fdwProperty & IME_PROP_KBD_CHAR_FIRST)
  169. {
  170. if (fdwProperty & IME_PROP_UNICODE)
  171. {
  172. WCHAR wc;
  173. iNum = ToUnicode(uVirKey, // virtual-key code
  174. HIWORD(lParam), // scan code
  175. abKbdState, // key-state array
  176. &wc, // translated key buffer
  177. 1, // size
  178. 0); // function option
  179. if (iNum == 1)
  180. {
  181. //
  182. // hi word : unicode character code
  183. // hi byte of lo word : zero
  184. // lo byte of lo word : virtual key
  185. //
  186. uVirKey = (uVirKey & 0x00ff) | ((UINT)wc << 16);
  187. }
  188. }
  189. else
  190. Assert(0); // should have IME_PROP_UNICODE
  191. }
  192. DWORD dwSize = FIELD_OFFSET(TRANSMSGLIST, TransMsg)
  193. + TRANSMSGCOUNT * sizeof(TRANSMSG);
  194. LPTRANSMSGLIST lpTransMsgList = (LPTRANSMSGLIST) new BYTE[dwSize];
  195. if (lpTransMsgList == NULL)
  196. return S_FALSE;
  197. lpTransMsgList->uMsgCount = TRANSMSGCOUNT;
  198. hr = ToAsciiEx(ptls, ptim_P, uVirKey, HIWORD(lParam), abKbdState, lpTransMsgList, 0, hIMC, (UINT *) &iNum);
  199. if (iNum > TRANSMSGCOUNT)
  200. {
  201. //
  202. // The message buffer is not big enough. IME put messages
  203. // into hMsgBuf in the input context.
  204. //
  205. IMCLock imc(hIMC);
  206. if (FAILED(imc.GetResult()))
  207. {
  208. delete [] lpTransMsgList;
  209. return S_FALSE;
  210. }
  211. IMCCLock<TRANSMSG> pdw(imc->hMsgBuf);
  212. if (FAILED(pdw.GetResult()))
  213. {
  214. delete [] lpTransMsgList;
  215. return S_FALSE;
  216. }
  217. PostTransMsg(GetFocus(), iNum, pdw);
  218. }
  219. else if (iNum > 0)
  220. {
  221. IMCLock imc(hIMC);
  222. if (FAILED(imc.GetResult()))
  223. {
  224. delete [] lpTransMsgList;
  225. return S_FALSE;
  226. }
  227. PostTransMsg(GetFocus(), iNum, &lpTransMsgList->TransMsg[0]);
  228. }
  229. delete [] lpTransMsgList;
  230. }
  231. return hr;
  232. #endif
  233. }
  234. }
  235. }
  236. }
  237. return S_FALSE;
  238. }
  239. //+---------------------------------------------------------------------------
  240. //
  241. // CicBridge::InitIMMX
  242. //
  243. //----------------------------------------------------------------------------
  244. HRESULT
  245. CicBridge::InitIMMX(
  246. TLS* ptls)
  247. {
  248. DebugMsg(TF_FUNC, TEXT("CicBridge::InitIMMX entered."));
  249. if (m_fCicInit.IsSetFlag())
  250. return S_OK;
  251. //
  252. // Create ITfThreadMgr instance.
  253. //
  254. HRESULT hr;
  255. if (ptls->GetTIM() == NULL)
  256. {
  257. ITfThreadMgr* ptim;
  258. ITfThreadMgr_P* ptim_P;
  259. //
  260. // ITfThreadMgr is per thread instance.
  261. //
  262. hr = TF_CreateThreadMgr(&ptim);
  263. if (hr != S_OK)
  264. {
  265. DebugMsg(TF_ERROR, TEXT("CicBridge::InitIMMX. TF_CreateThreadMgr==NULL"));
  266. Assert(0); // couldn't create tim!
  267. goto ExitError;
  268. }
  269. hr = ptim->QueryInterface(IID_ITfThreadMgr_P, (void **)&ptim_P);
  270. ptim->Release();
  271. if (hr != S_OK)
  272. {
  273. DebugMsg(TF_ERROR, TEXT("CicBridge::InitIMMX. IID_ITfThreadMgr_P==NULL"));
  274. Assert(0); // couldn't find ITfThreadMgr_P
  275. goto ExitError;
  276. }
  277. Assert(ptls->GetTIM() == NULL);
  278. ptls->SetTIM(ptim_P); // Set ITfThreadMgr instance in the TLS data.
  279. //
  280. // Create Thread Manager Event Sink Callback for detect Cicero Aware Apps.
  281. //
  282. if (m_pDIMCallback == NULL) {
  283. m_pDIMCallback = new CThreadMgrEventSink_DIMCallBack();
  284. if (m_pDIMCallback == NULL) {
  285. DebugMsg(TF_ERROR, TEXT("CicBridge::InitIMMX. CThreadMgrEventSink_DIMCallBack==NULL"));
  286. Assert(0); // couldn't create CThreadMgrEventSink_DIMCallBack
  287. goto ExitError;
  288. }
  289. m_pDIMCallback->SetCallbackDataPointer(m_pDIMCallback);
  290. m_pDIMCallback->_Advise(ptim_P);
  291. }
  292. }
  293. //
  294. // Create CicProfile instance.
  295. //
  296. if (ptls->GetCicProfile() == NULL)
  297. {
  298. //
  299. // ITfInputProcessorProfiles is per thread instance.
  300. //
  301. CicProfile* pProfile = new CicProfile;
  302. if (pProfile == NULL)
  303. {
  304. DebugMsg(TF_ERROR, TEXT("CicBridge::InitIMMX. pProfile==NULL"));
  305. Assert(0); // couldn't create profile
  306. goto ExitError;
  307. }
  308. ptls->SetCicProfile(pProfile);
  309. hr = pProfile->InitProfileInstance(ptls);
  310. if (FAILED(hr))
  311. {
  312. DebugMsg(TF_ERROR, TEXT("CicBridge::InitIMMX. InitProfileInstance==NULL"));
  313. Assert(0); // couldn't create profile
  314. goto ExitError;
  315. }
  316. }
  317. //
  318. // get the keystroke manager ready
  319. //
  320. if (FAILED(::GetService(ptls->GetTIM(), IID_ITfKeystrokeMgr_P, (IUnknown **)&m_pkm_P))) {
  321. DebugMsg(TF_ERROR, TEXT("CicBridge::InitIMMX. IID_ITfKeystrokeMgr==NULL"));
  322. Assert(0); // couldn't get ksm!
  323. goto ExitError;
  324. }
  325. // cleanup/error code assumes this is the last thing we do, doesn't call
  326. // UninitDAL on error
  327. if (FAILED(InitDisplayAttrbuteLib(&_libTLS)))
  328. {
  329. DebugMsg(TF_ERROR, TEXT("CicBridge::InitIMMX. InitDisplayAttributeLib==NULL"));
  330. Assert(0); // couldn't init lib!
  331. goto ExitError;
  332. }
  333. m_fCicInit.SetFlag();
  334. //
  335. // Start Edit Subclasss.
  336. //
  337. // StartEditSubClass();
  338. return S_OK;
  339. ExitError:
  340. UnInitIMMX(ptls);
  341. return E_FAIL;
  342. }
  343. //+---------------------------------------------------------------------------
  344. //
  345. // CicBridge::UnInitIMMX
  346. //
  347. //----------------------------------------------------------------------------
  348. BOOL
  349. CicBridge::UnInitIMMX(
  350. TLS* ptls)
  351. {
  352. DebugMsg(TF_FUNC, TEXT("CicBridge::UnInitIMMX"));
  353. // clear the display lib
  354. UninitDisplayAttrbuteLib(&_libTLS);
  355. TFUninitLib_Thread(&_libTLS);
  356. // clear the keystroke mgr
  357. SafeReleaseClear(m_pkm_P);
  358. // clear the profile
  359. CicProfile* pProfile;
  360. if ((pProfile=ptls->GetCicProfile()) != NULL)
  361. {
  362. pProfile->Release();
  363. ptls->SetCicProfile(NULL);
  364. }
  365. // clear Thread Manager Event Sink Callback for detect Cicero Aware Apps.
  366. if (m_pDIMCallback) {
  367. m_pDIMCallback->_Unadvise();
  368. m_pDIMCallback->Release();
  369. m_pDIMCallback = NULL;
  370. }
  371. // clear the thread mgr
  372. ITfThreadMgr_P* ptim_P;
  373. if ((ptim_P=ptls->GetTIM()) != NULL)
  374. {
  375. SafeReleaseClear(ptim_P);
  376. ptls->SetTIM(NULL);
  377. }
  378. m_fCicInit.ResetFlag();
  379. return TRUE;
  380. }
  381. //+---------------------------------------------------------------------------
  382. //
  383. // CicBridge::ActivateMMX
  384. //
  385. //----------------------------------------------------------------------------
  386. HRESULT
  387. CicBridge::ActivateIMMX(
  388. TLS *ptls,
  389. ITfThreadMgr_P* ptim_P)
  390. {
  391. DebugMsg(TF_FUNC, TEXT("CicBridge::ActivateIMMX"));
  392. //
  393. // Activate thread manager
  394. //
  395. Assert(m_tfClientId == TF_CLIENTID_NULL);
  396. HRESULT hr;
  397. hr = ptim_P->ActivateEx(&m_tfClientId, TF_TMAE_NOACTIVATETIP);
  398. if (hr != S_OK)
  399. {
  400. DebugMsg(TF_ERROR, TEXT("CicBridge::ActivateIMMX. ptim_P->Activate==NULL"));
  401. Assert(0); // couldn't activate thread!
  402. m_tfClientId = TF_CLIENTID_NULL;
  403. return E_FAIL;
  404. }
  405. m_lCicActive++;
  406. if (m_lCicActive == 1)
  407. {
  408. Interface<ITfSourceSingle> SourceSingle;
  409. hr = ptim_P->QueryInterface(IID_ITfSourceSingle, (void**)SourceSingle);
  410. if (hr != S_OK)
  411. {
  412. DebugMsg(TF_ERROR, TEXT("CicBridge::ActivateIMMX. IID_ITfSourceSingle==NULL"));
  413. Assert(0);
  414. DeactivateIMMX(ptls, ptim_P);
  415. return E_FAIL;
  416. }
  417. CFunctionProvider* pFunc = new CFunctionProvider(m_tfClientId);
  418. if (pFunc == NULL)
  419. {
  420. DebugMsg(TF_ERROR, TEXT("CicBridge::ActivateIMMX. pFunc==NULL"));
  421. Assert(0);
  422. DeactivateIMMX(ptls, ptim_P);
  423. return E_FAIL;
  424. }
  425. SourceSingle->AdviseSingleSink(m_tfClientId, IID_ITfFunctionProvider, (ITfFunctionProvider*)pFunc);
  426. pFunc->Release();
  427. if (m_dimEmpty == NULL)
  428. {
  429. hr = ptim_P->CreateDocumentMgr(&m_dimEmpty);
  430. if (FAILED(hr))
  431. {
  432. DebugMsg(TF_ERROR, TEXT("CicBridge::ActivateIMMX. m_dimEmpty==NULL"));
  433. Assert(0);
  434. DeactivateIMMX(ptls, ptim_P);
  435. return E_FAIL;
  436. }
  437. //
  438. // mark this is an owned dim.
  439. //
  440. SetCompartmentDWORD(m_tfClientId, m_dimEmpty,
  441. GUID_COMPARTMENT_CTFIME_DIMFLAGS,
  442. COMPDIMFLAG_OWNEDDIM, FALSE);
  443. }
  444. //
  445. // set ITfSysHookSink
  446. //
  447. ptim_P->SetSysHookSink(this);
  448. if (ptls->IsDeactivatedOnce())
  449. {
  450. ENUMIMC edimc;
  451. edimc.ptls = ptls;
  452. edimc._this = this;
  453. ImmEnumInputContext(0,
  454. EnumCreateInputContextCallback,
  455. (LPARAM)&edimc);
  456. }
  457. }
  458. return hr;
  459. }
  460. //+---------------------------------------------------------------------------
  461. //
  462. // CicBridge::DeactivateMMX
  463. //
  464. //----------------------------------------------------------------------------
  465. HRESULT
  466. CicBridge::DeactivateIMMX(
  467. TLS *ptls,
  468. ITfThreadMgr_P* ptim_P)
  469. {
  470. DebugMsg(TF_FUNC, TEXT("CicBridge::DeactivateIMMX"));
  471. if (m_fInDeactivate.IsSetFlag())
  472. {
  473. //
  474. // Prevent recursive call of CicBridge::DeactivateIMMX().
  475. // ptim_P->Deactivate() might call DestroyWindow() via some TIP's deactivation,
  476. // then imm32 ! CtfImmLastEnabledWndDestroy will call and this functoin also call again.
  477. // In this case, this function return S_FALSE. Caller won't call UninitIMMX.
  478. //
  479. return S_FALSE;
  480. }
  481. m_fInDeactivate.SetFlag();
  482. // Deactivate thread manager.
  483. if (m_tfClientId != TF_CLIENTID_NULL)
  484. {
  485. ENUMIMC edimc;
  486. edimc.ptls = ptls;
  487. edimc._this = this;
  488. ImmEnumInputContext(0,
  489. EnumDestroyInputContextCallback,
  490. (LPARAM)&edimc);
  491. ptls->SetDeactivatedOnce();
  492. Interface<ITfSourceSingle> SourceSingle;
  493. if (ptim_P->QueryInterface(IID_ITfSourceSingle, (void**)SourceSingle) == S_OK)
  494. {
  495. SourceSingle->UnadviseSingleSink(m_tfClientId, IID_ITfFunctionProvider);
  496. }
  497. m_tfClientId = TF_CLIENTID_NULL;
  498. while (m_lCicActive)
  499. {
  500. m_lCicActive--;
  501. ptim_P->Deactivate();
  502. }
  503. }
  504. //
  505. // clear empty dim
  506. //
  507. // Release DIM should after tim->Deactivate. #480603
  508. //
  509. // If msctf ! DLL_THREAD_DETACH already runs before this DeactivateIMMX via msctfime ! DLL_THREAD_DETACH (depended DLL_THREAD_DETACH calling order).
  510. // then msctf ! SYSTHREAD is already released by msctf ! FreeSYSTHREAD.
  511. //
  512. // In this time, msctf lost TIM list in SYSTHREAD then CThreadInputMgr::*_GetThis() returns NULL.
  513. // And below Release DIM, dtor CDocumentInputManager doesn't remove DIM object from tim->_rgdim array.
  514. // If Release DIM is before tim->Deactivate, some TIM might access DIM by tim->_rgdim array. But it DIM already released.
  515. //
  516. SafeReleaseClear(m_dimEmpty);
  517. //
  518. // reset ITfSysHookSink
  519. //
  520. ptim_P->SetSysHookSink(NULL);
  521. Assert(!m_lCicActive);
  522. m_fInDeactivate.ResetFlag();
  523. return S_OK;
  524. }
  525. //+---------------------------------------------------------------------------
  526. //
  527. // CicBridge::CreateInputContext
  528. //
  529. //----------------------------------------------------------------------------
  530. HRESULT
  531. CicBridge::CreateInputContext(
  532. TLS* ptls,
  533. HIMC hImc)
  534. {
  535. DebugMsg(TF_FUNC, TEXT("CicBridge::CreateInputContext"));
  536. HRESULT hr;
  537. IMCLock imc(hImc);
  538. if (FAILED(hr=imc.GetResult()))
  539. {
  540. DebugMsg(TF_ERROR, TEXT("CicBridge::CreateInputContext. imc==NULL"));
  541. return hr;
  542. }
  543. if (imc->hCtfImeContext == NULL)
  544. {
  545. HIMCC h = ImmCreateIMCC(sizeof(CTFIMECONTEXT));
  546. if (h == NULL)
  547. {
  548. DebugMsg(TF_ERROR, TEXT("CicBridge::CreateInputContext. hCtfImeContext==NULL"));
  549. return E_OUTOFMEMORY;
  550. }
  551. imc->hCtfImeContext = h;
  552. }
  553. {
  554. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  555. if (FAILED(hr=imc_ctfime.GetResult()))
  556. {
  557. DebugMsg(TF_ERROR, TEXT("CicBridge::CreateInputContext. imc_ctfime==NULL"));
  558. return hr;
  559. }
  560. if (imc_ctfime->m_pCicContext)
  561. {
  562. hr = S_OK;
  563. }
  564. else
  565. {
  566. CicInputContext* _pCicContext = new CicInputContext(_GetClientId(), _GetLibTLS(), hImc);
  567. if (_pCicContext == NULL)
  568. {
  569. DebugMsg(TF_ERROR, TEXT("CicBridge::CreateInputContext. _pCicContext==NULL"));
  570. hr = E_OUTOFMEMORY;
  571. goto out_of_block;
  572. }
  573. ITfThreadMgr_P* ptim_P;
  574. if ((ptim_P=ptls->GetTIM()) == NULL)
  575. {
  576. DebugMsg(TF_ERROR, TEXT("CicBridge::CreateInputContext. ptim_P==NULL"));
  577. _pCicContext->Release();
  578. imc_ctfime->m_pCicContext = NULL;
  579. hr = E_NOINTERFACE;
  580. goto out_of_block;
  581. }
  582. imc_ctfime->m_pCicContext = _pCicContext;
  583. hr = _pCicContext->CreateInputContext(ptim_P, imc);
  584. if (FAILED(hr))
  585. {
  586. DebugMsg(TF_ERROR, TEXT("CicBridge::CreateInputContext. _pCicContext->CreateInputContext==NULL"));
  587. _pCicContext->Release();
  588. imc_ctfime->m_pCicContext = NULL;
  589. goto out_of_block;
  590. }
  591. //
  592. // If this himc is already activated, we need to associate now.
  593. // IMM32 won't call ImmSetActiveContext().
  594. //
  595. if (imc->hWnd && (imc->hWnd == ::GetFocus()))
  596. {
  597. Interface_Attach<ITfDocumentMgr> dim(GetDocumentManager(imc_ctfime));
  598. SetAssociate(ptls, imc->hWnd, ptim_P, dim.GetPtr());
  599. }
  600. }
  601. } // dtor imc_ctfime
  602. out_of_block:
  603. if (FAILED(hr))
  604. {
  605. DestroyInputContext(ptls, hImc);
  606. }
  607. return hr;
  608. }
  609. //+---------------------------------------------------------------------------
  610. //
  611. // CicBridge::DestroyInputContext
  612. //
  613. //----------------------------------------------------------------------------
  614. HRESULT
  615. CicBridge::DestroyInputContext(
  616. TLS* ptls,
  617. HIMC hImc)
  618. {
  619. DebugMsg(TF_FUNC, TEXT("CicBridge::DestroyInputContext"));
  620. HRESULT hr;
  621. IMCLock imc(hImc);
  622. if (FAILED(hr=imc.GetResult()))
  623. {
  624. DebugMsg(TF_ERROR, TEXT("CicBridge::DestroyInputContext. imc==NULL"));
  625. return hr;
  626. }
  627. {
  628. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  629. if (FAILED(hr=imc_ctfime.GetResult()))
  630. {
  631. DebugMsg(TF_ERROR, TEXT("CicBridge::DestroyInputContext. imc_ctfime==NULL"));
  632. goto out_of_block;
  633. }
  634. //
  635. // #548378
  636. //
  637. // stop resursion call of _pCicContext->DestroyInputContext().
  638. if (imc_ctfime->m_fInDestroy)
  639. {
  640. hr = S_OK;
  641. goto exit;
  642. }
  643. imc_ctfime->m_fInDestroy = TRUE;
  644. // imc->m_pContext may be NULL if ITfThreadMgr::Activate has not been called
  645. if (imc_ctfime->m_pCicContext == NULL)
  646. goto out_of_block;
  647. CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
  648. imc_ctfime->m_pCicContext = NULL;
  649. hr = _pCicContext->DestroyInputContext();
  650. _pCicContext->Release();
  651. imc_ctfime->m_pCicContext = NULL;
  652. } // dtor imc_ctfime
  653. out_of_block:
  654. if (imc->hCtfImeContext != NULL)
  655. {
  656. ImmDestroyIMCC(imc->hCtfImeContext);
  657. imc->hCtfImeContext = NULL;
  658. hr = S_OK;
  659. }
  660. exit:
  661. return hr;
  662. }
  663. //+---------------------------------------------------------------------------
  664. //
  665. // CicBridge::SelectEx
  666. //
  667. //----------------------------------------------------------------------------
  668. HRESULT
  669. CicBridge::SelectEx(
  670. TLS* ptls,
  671. ITfThreadMgr_P* ptim_P, // using private for RequestPostponedLock
  672. HIMC hImc,
  673. BOOL fSelect,
  674. HKL hKL)
  675. {
  676. DebugMsg(TF_FUNC, TEXT("CicBridge::SelectEx(hImc=%x, fSelect=%x, hKL=%x)"), hImc, fSelect, hKL);
  677. HRESULT hr;
  678. IMCLock imc(hImc);
  679. if (FAILED(hr = imc.GetResult()))
  680. {
  681. DebugMsg(TF_ERROR, TEXT("CicBridge::SelectEx. imc==NULL"));
  682. return hr;
  683. }
  684. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  685. if (FAILED(hr=imc_ctfime.GetResult()))
  686. {
  687. DebugMsg(TF_ERROR, TEXT("CicBridge::SelectEx. imc_ctfime==NULL"));
  688. return hr;
  689. }
  690. #ifdef UNSELECTCHECK
  691. if (_pAImeContext)
  692. _pAImeContext->m_fSelected = (dwFlags & AIMMP_SE_SELECT) ? TRUE : FALSE;
  693. #endif UNSELECTCHECK
  694. CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
  695. if (_pCicContext)
  696. _pCicContext->m_fSelectingInSelectEx.SetFlag();
  697. if (fSelect)
  698. {
  699. if (_pCicContext)
  700. _pCicContext->m_fOpenCandidateWindow.ResetFlag(); // TRUE: opening candidate list window.
  701. //
  702. // #501445
  703. //
  704. // If imc is open, update GUID_COMPARTMENT_KEYBOARD_OPENCLOSE.
  705. //
  706. if (imc->fOpen)
  707. OnSetOpenStatus(ptim_P, imc, *_pCicContext);
  708. }
  709. else { // being unselected
  710. Interface_Attach<ITfContext> ic(GetInputContext(imc_ctfime));
  711. if (ic.Valid())
  712. {
  713. ptim_P->RequestPostponedLock(ic.GetPtr());
  714. }
  715. }
  716. if (_pCicContext)
  717. _pCicContext->m_fSelectingInSelectEx.ResetFlag();
  718. return hr;
  719. }
  720. //+---------------------------------------------------------------------------
  721. //
  722. // CicBridge::SetActiveContextAlways
  723. //
  724. //----------------------------------------------------------------------------
  725. HRESULT
  726. CicBridge::SetActiveContextAlways(
  727. TLS* ptls,
  728. HIMC hImc,
  729. BOOL fOn,
  730. HWND hWnd,
  731. HKL hKL)
  732. {
  733. DebugMsg(TF_FUNC, TEXT("CicBridge::SetActiveContextEx(hImc=%x, fOn=%x, hWnd=%x)"), hImc, fOn, hWnd);
  734. ITfThreadMgr_P* ptim_P = ptls->GetTIM();
  735. if (ptim_P == NULL)
  736. {
  737. DebugMsg(TF_ERROR, TEXT("CicBridge::SetActiveContextEx. ptim_P==NULL"));
  738. return E_OUTOFMEMORY;
  739. }
  740. if (fOn && hImc != NULL)
  741. {
  742. HRESULT hr;
  743. IMCLock imc(hImc);
  744. if (FAILED(hr = imc.GetResult()))
  745. {
  746. DebugMsg(TF_ERROR, TEXT("CicBridge::SetActiveContextEx. imc==NULL"));
  747. return hr;
  748. }
  749. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  750. if (FAILED(hr=imc_ctfime.GetResult()))
  751. {
  752. DebugMsg(TF_ERROR, TEXT("CicBridge::SetActiveContextEx. imc_ctfime==NULL"));
  753. return hr;
  754. }
  755. if (hImc == ImmGetContext(hWnd)) {
  756. /*
  757. * Selecting hIMC has been current active hIMC,
  758. * then associate this DIM with the TIM.
  759. */
  760. Interface_Attach<ITfDocumentMgr> dim(GetDocumentManager(imc_ctfime));
  761. SetAssociate(ptls, imc->hWnd, ptim_P, dim.GetPtr());
  762. }
  763. }
  764. else
  765. {
  766. //
  767. // When focus killed, composition string should completed.
  768. //
  769. // This is just for non-EA keyboard layouts. For example, we don't
  770. // have a specific way to finilize the composition string like
  771. // we use Enter key on EA kayboard layout. So we need to have
  772. // a service to finalize the composition string at focus change
  773. // automatically. (This is similar to Korean behaviour.)
  774. //
  775. if (!fOn && hImc && !IS_EA_KBDLAYOUT(hKL))
  776. {
  777. HRESULT hr;
  778. IMCLock imc(hImc);
  779. if (FAILED(hr = imc.GetResult()))
  780. {
  781. DebugMsg(TF_ERROR, TEXT("CicBridge::SetActiveContextEx. imc==NULL"));
  782. return hr;
  783. }
  784. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  785. if (FAILED(hr=imc_ctfime.GetResult()))
  786. {
  787. DebugMsg(TF_ERROR, TEXT("CicBridge::SetActiveContextEx. imc_ctfime==NULL"));
  788. return hr;
  789. }
  790. //
  791. // #482346
  792. //
  793. // If we are updating compstr, we don't have to complete it.
  794. // App change the focus druing it handles WM_IME_xxx messages.
  795. //
  796. if (imc_ctfime->m_pCicContext->m_fInCompComplete.IsResetFlag() &&
  797. imc_ctfime->m_pCicContext->m_fInUpdateComposition.IsResetFlag())
  798. ImmNotifyIME(hImc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
  799. }
  800. //
  801. // #501449
  802. //
  803. // When Win32k.sys generates IMS_DEACTIVATECONTEXT, it does not
  804. // guarantee to generate IMS_ACTIVATECONTEXT. It always checks
  805. // (pwndReceive == pti->pq->spwndFocus) in xxxSendFocusMessage().
  806. //
  807. if (!fOn && (::GetFocus() == hWnd) &&
  808. hImc && (hImc == ImmGetContext(hWnd)))
  809. {
  810. return S_OK;
  811. }
  812. //
  813. // this new focus change performance improvement breaks some
  814. // assumption of IsRealIME() in AssociateContext in dimm\immapp.cpp.
  815. // Associate NULL dim under IsPresent() window has not been the case
  816. // AIMM1.2 handles. In fact, this breaks IE that calls
  817. // AssociateContext on the focus window that is IsPresent().
  818. //
  819. #ifdef FOCUSCHANGE_PERFORMANCE
  820. //
  821. // set empty dim so no text store to simulate NULL-HIMC.
  822. //
  823. BOOL fUseEmptyDIM = FALSE;
  824. ITfDocumentMgr *pdimPrev; // just to receive prev for now
  825. if (SUCCEEDED(m_tim->GetFocus(&pdimPrev)) && pdimPrev)
  826. {
  827. fUseEmptyDIM = TRUE;
  828. pdimPrev->Release();
  829. }
  830. SetAssociate(hWnd, fUseEmptyDIM ? m_dimEmpty : NULL);
  831. #else
  832. SetAssociate(ptls, hWnd, ptim_P, m_dimEmpty);
  833. #endif
  834. }
  835. return S_OK;
  836. }
  837. //+---------------------------------------------------------------------------
  838. //
  839. // CicBridge::IsDefaultIMCDim
  840. //
  841. //----------------------------------------------------------------------------
  842. BOOL CicBridge::IsDefaultIMCDim(ITfDocumentMgr *pdim)
  843. {
  844. HWND hDefImeWnd = ImmGetDefaultIMEWnd(NULL);
  845. HRESULT hr;
  846. //
  847. // Get the default hIMC of this thread.
  848. //
  849. // Assume none associate any hIMC to the default IME window.
  850. //
  851. IMCLock imc(ImmGetContext(hDefImeWnd));
  852. if (FAILED(hr = imc.GetResult()))
  853. {
  854. DebugMsg(TF_ERROR, TEXT("CicBridge::SetActiveContextEx. imc==NULL"));
  855. return FALSE;
  856. }
  857. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  858. if (FAILED(hr=imc_ctfime.GetResult()))
  859. {
  860. DebugMsg(TF_ERROR, TEXT("CicBridge::SetActiveContextEx. imc_ctfime==NULL"));
  861. return FALSE;
  862. }
  863. Interface_Attach<ITfDocumentMgr> dim(GetDocumentManager(imc_ctfime));
  864. if (dim.GetPtr() == pdim)
  865. return TRUE;
  866. return FALSE;
  867. }
  868. //+---------------------------------------------------------------------------
  869. //
  870. // CicBridge::SetAssociate
  871. //
  872. //----------------------------------------------------------------------------
  873. VOID
  874. CicBridge::SetAssociate(
  875. TLS* ptls,
  876. HWND hWnd,
  877. ITfThreadMgr_P* ptim_P,
  878. ITfDocumentMgr* pdim)
  879. {
  880. DebugMsg(TF_FUNC, TEXT("CicBridge::SetAssociate"));
  881. if (m_fOnSetAssociate.IsSetFlag()) {
  882. /*
  883. * Prevent reentrance call from m_tim->AssociateFocus.
  884. */
  885. return;
  886. }
  887. m_fOnSetAssociate.SetFlag();
  888. if (::IsWindow(hWnd) && m_fCicInit.IsSetFlag()) {
  889. ITfDocumentMgr *pdimPrev = NULL; // just to receive prev for now
  890. ITfDocumentMgr *pdimAssoc = NULL;
  891. BOOL fIsAssociated = FALSE;
  892. ptim_P->GetAssociated(hWnd, &pdimAssoc);
  893. if (pdimAssoc) {
  894. //
  895. // Check if it is our dim or app dim.
  896. //
  897. if (!IsOwnDim(pdimAssoc))
  898. fIsAssociated = TRUE;
  899. SafeReleaseClear(pdimAssoc);
  900. }
  901. //
  902. // If an app dim is associated to hWnd, msctf.dll will do SetAssociate().
  903. //
  904. if (!fIsAssociated)
  905. {
  906. ptim_P->AssociateFocus(hWnd, pdim, &pdimPrev);
  907. //
  908. // #610113
  909. //
  910. // if pdimPrev is DIM for the default hIMC, we need to associate
  911. // a window to the dim. If the dim is not associated to any
  912. // window, Cicero thinks it is the dim for Cicero native app
  913. // so it skips to do _SetFocus().
  914. //
  915. if (pdimPrev)
  916. {
  917. if (IsDefaultIMCDim(pdimPrev))
  918. {
  919. ITfDocumentMgr *pdimDefPrev = NULL;
  920. HWND hDefImeWnd = ImmGetDefaultIMEWnd(NULL);
  921. ptim_P->AssociateFocus(hDefImeWnd, pdimPrev, &pdimDefPrev);
  922. if (pdimDefPrev)
  923. pdimDefPrev->Release();
  924. }
  925. pdimPrev->Release();
  926. }
  927. //
  928. // If pdim is the focus dim, we call CTFDetection() to check
  929. // the focus change between AIMM12, Cicero controls.
  930. //
  931. Interface<ITfDocumentMgr> pdimFocus;
  932. ptim_P->GetFocus(pdimFocus);
  933. if ((ITfDocumentMgr *)pdimFocus == pdim)
  934. CTFDetection(ptls, pdim);
  935. }
  936. }
  937. m_fOnSetAssociate.ResetFlag();
  938. }
  939. //+---------------------------------------------------------------------------
  940. //
  941. // CicBridge::IsOwnDim
  942. //
  943. //----------------------------------------------------------------------------
  944. BOOL CicBridge::IsOwnDim(ITfDocumentMgr *pdim)
  945. {
  946. HRESULT hr;
  947. DWORD dwFlags;
  948. hr = GetCompartmentDWORD(pdim, GUID_COMPARTMENT_CTFIME_DIMFLAGS,
  949. &dwFlags, FALSE);
  950. if (SUCCEEDED(hr))
  951. return (dwFlags & COMPDIMFLAG_OWNEDDIM) ? TRUE : FALSE;
  952. return FALSE;
  953. }
  954. //+---------------------------------------------------------------------------
  955. //
  956. // CicBridge::ProcessKey
  957. //
  958. //----------------------------------------------------------------------------
  959. BOOL
  960. CicBridge::ProcessKey(
  961. TLS* ptls,
  962. ITfThreadMgr_P* ptim_P, // using private for RequestPostponedLock
  963. HIMC hIMC,
  964. UINT uVirtKey,
  965. LPARAM lParam,
  966. CONST LPBYTE lpbKeyState)
  967. {
  968. DebugMsg(TF_FUNC, TEXT("CicBridge::ProcessKey"));
  969. BOOL fEaten;
  970. BOOL fKeysEnabled;
  971. HRESULT hr;
  972. BOOL fRet;
  973. #if 0
  974. // has anyone disabled system key feeding?
  975. if (ptim_P->IsKeystrokeFeedEnabled(&fKeysEnabled) == S_OK && !fKeysEnabled)
  976. return FALSE;
  977. #endif
  978. if (uVirtKey == VK_PROCESSKEY)
  979. {
  980. LANGID langid;
  981. CicProfile* _pProfile = ptls->GetCicProfile();
  982. if (_pProfile == NULL)
  983. {
  984. DebugMsg(TF_ERROR, TEXT("CicBridge::ProcessKey. _pProfile==NULL."));
  985. }
  986. else
  987. {
  988. _pProfile->GetLangId(&langid);
  989. if (PRIMARYLANGID(langid) == LANG_KOREAN)
  990. {
  991. return TRUE;
  992. }
  993. }
  994. }
  995. hr = m_pkm_P->KeyDownUpEx(uVirtKey, lParam, (DWORD)TF_KEY_MSCTFIME | TF_KEY_TEST, &fEaten);
  996. if (hr == S_OK && fEaten) {
  997. return TRUE;
  998. }
  999. IMCLock imc(hIMC);
  1000. if (FAILED(hr=imc.GetResult()))
  1001. {
  1002. return FALSE;
  1003. }
  1004. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  1005. if (FAILED(hr=imc_ctfime.GetResult()))
  1006. {
  1007. return FALSE;
  1008. }
  1009. //
  1010. // m_fGeneratedEndComposition should be set only when m_fInProcessKey
  1011. // is set.
  1012. //
  1013. Assert(imc_ctfime->m_pCicContext->m_fGeneratedEndComposition.IsResetFlag());
  1014. imc_ctfime->m_pCicContext->m_fInProcessKey.SetFlag();
  1015. if (!fEaten)
  1016. {
  1017. if (imc_ctfime->m_pCicContext &&
  1018. ptim_P != NULL)
  1019. {
  1020. ptim_P->RequestPostponedLock(imc_ctfime->m_pCicContext->GetInputContext());
  1021. }
  1022. }
  1023. if ((HIWORD(lParam) & KF_UP) ||
  1024. (HIWORD(lParam) & KF_ALTDOWN)) {
  1025. fRet = FALSE;
  1026. }
  1027. else
  1028. fRet = DefaultKeyHandling(ptls, imc, imc_ctfime->m_pCicContext, uVirtKey, lParam);
  1029. imc_ctfime->m_pCicContext->m_fGeneratedEndComposition.ResetFlag();
  1030. imc_ctfime->m_pCicContext->m_fInProcessKey.ResetFlag();
  1031. return fRet;
  1032. }
  1033. //+---------------------------------------------------------------------------
  1034. //
  1035. // CicBridge::ToAsciiEx
  1036. //
  1037. //----------------------------------------------------------------------------
  1038. HRESULT
  1039. CicBridge::ToAsciiEx(
  1040. TLS* ptls,
  1041. ITfThreadMgr_P* ptim_P, // using private for RequestPostponedLock
  1042. UINT uVirtKey,
  1043. UINT uScanCode,
  1044. CONST LPBYTE lpbKeyState,
  1045. LPTRANSMSGLIST lpTransBuf,
  1046. UINT fuState,
  1047. HIMC hIMC,
  1048. UINT *uNum)
  1049. {
  1050. DebugMsg(TF_FUNC, TEXT("CicBridge::ToAsciiEx"));
  1051. BOOL fEaten;
  1052. HRESULT hr;
  1053. *uNum = 0;
  1054. Assert(ptim_P);
  1055. IMCLock imc(hIMC);
  1056. if (FAILED(hr=imc.GetResult()))
  1057. {
  1058. DebugMsg(TF_ERROR, TEXT("CicBridge::ToAsciiEx. imc==NULL"));
  1059. return hr;
  1060. }
  1061. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  1062. if (FAILED(hr=imc_ctfime.GetResult()))
  1063. {
  1064. DebugMsg(TF_ERROR, TEXT("CicBridge::ToAsciiEx. imc_ctfime==NULL"));
  1065. return hr;
  1066. }
  1067. CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
  1068. ASSERT(_pCicContext != NULL);
  1069. if (! _pCicContext)
  1070. {
  1071. DebugMsg(TF_ERROR, TEXT("CicBridge::ToAsciiEx. _pCicContext==NULL"));
  1072. return S_FALSE;
  1073. }
  1074. //
  1075. // Backup the m_fOpenCandidateWindow flag.
  1076. // If open the candidate list and press "Cancel" key, Kana TIP would want to
  1077. // close candidate UI window in the KeyDown() action.
  1078. // Candidate UI calss maybe call m_pdim->Pop() and this function notify to
  1079. // the ThreadMgrEventSinkCallback.
  1080. // Win32 layer advised this callback and toggled m_fOpenCandidateWindow flag.
  1081. // Win32 layer doesn't know candidate status after KeyDown() call.
  1082. //
  1083. BOOL fOpenCandidateWindow = _pCicContext->m_fOpenCandidateWindow.IsSetFlag();
  1084. //
  1085. // If candidate window were open, send IMN_CHANGECANDIDATE message.
  1086. // In the case of PPT's centering composition string, it expect IMN_CHANGECANDIDATE.
  1087. //
  1088. if (fOpenCandidateWindow &&
  1089. *uNum < lpTransBuf->uMsgCount) {
  1090. TRANSMSG* pTransMsg = &lpTransBuf->TransMsg[*uNum];
  1091. pTransMsg->message = WM_IME_NOTIFY;
  1092. pTransMsg->wParam = IMN_CHANGECANDIDATE;
  1093. pTransMsg->lParam = 1; // bit 0 to first candidate list.
  1094. (*uNum)++;
  1095. }
  1096. //
  1097. // AIMM put char code in hiword. So we need to bail it out.
  1098. //
  1099. // if we don't need charcode, we may want to
  1100. // remove IME_PROP_KBD_CHAR_FIRST.
  1101. //
  1102. uVirtKey = uVirtKey & 0xffff;
  1103. if (uVirtKey == VK_PROCESSKEY)
  1104. {
  1105. /*
  1106. * KOREAN:
  1107. * Finalize current composition string
  1108. */
  1109. LANGID langid;
  1110. CicProfile* _pProfile = ptls->GetCicProfile();
  1111. if (_pProfile == NULL)
  1112. {
  1113. DebugMsg(TF_ERROR, TEXT("CicBridge::ToAsciiEx. _pProfile==NULL."));
  1114. }
  1115. else
  1116. {
  1117. _pProfile->GetLangId(&langid);
  1118. if (PRIMARYLANGID(langid) == LANG_KOREAN)
  1119. {
  1120. //
  1121. // Composition complete.
  1122. //
  1123. _pCicContext->EscbCompComplete(imc);
  1124. //
  1125. // #506324
  1126. //
  1127. // we don't want to eat this VK_PROCESSKEY. So we don't
  1128. // stop generating VK_LBUTTONDOWN.
  1129. // Because we don't generate any message here, it is ok
  1130. // to return S_FALSE;
  1131. //
  1132. return S_FALSE;
  1133. }
  1134. }
  1135. }
  1136. Interface<ITfContext_P> icp;
  1137. hr = _pCicContext->GetInputContext()->QueryInterface(IID_ITfContext_P,
  1138. (void **)icp);
  1139. if (hr != S_OK)
  1140. {
  1141. DebugMsg(TF_ERROR, TEXT("CicBridge::ToAsciiEx. QueryInterface failed"));
  1142. return hr;
  1143. }
  1144. imc_ctfime->m_pCicContext->m_fInToAsciiEx.SetFlag();
  1145. //
  1146. // stop posting LockRequest message and we call RequestPostponedLock
  1147. // forcefully so we don't have to have unnecessary PostThreadMessage().
  1148. //
  1149. // some application detect the unknown message in the queue and
  1150. // do much
  1151. //
  1152. icp->EnableLockRequestPosting(FALSE);
  1153. //
  1154. // consider: dimm12 set high bit oflower WORD at keyup.
  1155. //
  1156. hr = m_pkm_P->KeyDownUpEx(uVirtKey, (uScanCode << 16), TF_KEY_MSCTFIME, &fEaten);
  1157. icp->EnableLockRequestPosting(TRUE);
  1158. //
  1159. // enpty the edit session queue of the ic.
  1160. //
  1161. ptim_P->RequestPostponedLock(icp);
  1162. imc_ctfime->m_pCicContext->m_fInToAsciiEx.ResetFlag();
  1163. return hr;
  1164. }
  1165. //+---------------------------------------------------------------------------
  1166. //
  1167. // CicBridge::ProcessCicHotkey
  1168. //
  1169. //----------------------------------------------------------------------------
  1170. BOOL
  1171. CicBridge::ProcessCicHotkey(
  1172. TLS* ptls,
  1173. ITfThreadMgr_P* ptim_P, // using private for RequestPostponedLock
  1174. HIMC hIMC,
  1175. UINT uVirtKey,
  1176. LPARAM lParam)
  1177. {
  1178. if (!CtfImmIsCiceroStartedInThread()) {
  1179. DebugMsg(TF_ERROR, TEXT("CicBridge::ProcessCicHotkey. StopImm32HotkeyHandler returns Error."));
  1180. return FALSE;
  1181. }
  1182. HRESULT hr;
  1183. BOOL bHandled;
  1184. hr = ptim_P->CallImm32HotkeyHanlder((WPARAM)uVirtKey, lParam, &bHandled);
  1185. if (FAILED(hr)) {
  1186. DebugMsg(TF_ERROR, TEXT("CicBridge::ProcessCicHotkey. CallImm32HotkeyHandler returns Error."));
  1187. return FALSE;
  1188. }
  1189. return bHandled;
  1190. }
  1191. //+---------------------------------------------------------------------------
  1192. //
  1193. // CicBridge::Notify
  1194. //
  1195. //----------------------------------------------------------------------------
  1196. HRESULT
  1197. CicBridge::Notify(
  1198. TLS* ptls,
  1199. ITfThreadMgr_P* ptim_P,
  1200. HIMC hIMC,
  1201. DWORD dwAction,
  1202. DWORD dwIndex,
  1203. DWORD dwValue)
  1204. {
  1205. DebugMsg(TF_FUNC, TEXT("CicBridge::Notify(hIMC=%x, dwAction=%x, dwIndex=%x, dwValue=%x)"), hIMC, dwAction, dwIndex, dwValue);
  1206. HRESULT hr;
  1207. IMCLock imc(hIMC);
  1208. if (FAILED(hr=imc.GetResult()))
  1209. {
  1210. DebugMsg(TF_ERROR, TEXT("CicBridge::Notify. imc==NULL"));
  1211. return hr;
  1212. }
  1213. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  1214. if (FAILED(hr=imc_ctfime.GetResult()))
  1215. {
  1216. DebugMsg(TF_ERROR, TEXT("CicBridge::Notify. imc_ctfime==NULL"));
  1217. return hr;
  1218. }
  1219. CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
  1220. if (_pCicContext == NULL)
  1221. {
  1222. DebugMsg(TF_ERROR, TEXT("CicBridge::Notify. _pCicContext==NULL."));
  1223. return E_OUTOFMEMORY;
  1224. }
  1225. LANGID langid;
  1226. CicProfile* _pProfile = ptls->GetCicProfile();
  1227. if (_pProfile == NULL)
  1228. {
  1229. DebugMsg(TF_ERROR, TEXT("CicBridge::Notify. _pProfile==NULL."));
  1230. return E_OUTOFMEMORY;
  1231. }
  1232. _pProfile->GetLangId(&langid);
  1233. switch (dwAction) {
  1234. case NI_CONTEXTUPDATED:
  1235. switch (dwValue) {
  1236. case IMC_SETOPENSTATUS:
  1237. return OnSetOpenStatus(ptim_P, imc, *_pCicContext);
  1238. case IMC_SETCONVERSIONMODE:
  1239. case IMC_SETSENTENCEMODE:
  1240. return OnSetConversionSentenceMode(ptim_P, imc, *_pCicContext, dwValue, langid);
  1241. case IMC_SETCOMPOSITIONWINDOW:
  1242. case IMC_SETCOMPOSITIONFONT:
  1243. return E_NOTIMPL;
  1244. case IMC_SETCANDIDATEPOS:
  1245. return _pCicContext->OnSetCandidatePos(ptls, imc);
  1246. default:
  1247. return E_FAIL;
  1248. }
  1249. break;
  1250. case NI_COMPOSITIONSTR:
  1251. switch (dwIndex) {
  1252. case CPS_COMPLETE:
  1253. _pCicContext->EscbCompComplete(imc);
  1254. return S_OK;
  1255. case CPS_CONVERT:
  1256. case CPS_REVERT:
  1257. return E_NOTIMPL;
  1258. case CPS_CANCEL:
  1259. _pCicContext->EscbCompCancel(imc);
  1260. return S_OK;
  1261. default:
  1262. return E_FAIL;
  1263. }
  1264. break;
  1265. case NI_OPENCANDIDATE:
  1266. if (PRIMARYLANGID(langid) == LANG_KOREAN)
  1267. {
  1268. if (DoOpenCandidateHanja(ptim_P, imc, *_pCicContext))
  1269. return S_OK;
  1270. else
  1271. return E_FAIL;
  1272. }
  1273. case NI_CLOSECANDIDATE:
  1274. case NI_SELECTCANDIDATESTR:
  1275. case NI_CHANGECANDIDATELIST:
  1276. case NI_SETCANDIDATE_PAGESIZE:
  1277. case NI_SETCANDIDATE_PAGESTART:
  1278. case NI_IMEMENUSELECTED:
  1279. return E_NOTIMPL;
  1280. default:
  1281. break;
  1282. }
  1283. return E_FAIL;
  1284. }
  1285. //+---------------------------------------------------------------------------
  1286. //
  1287. // CicBridge::OnSetOpenStatus
  1288. //
  1289. //----------------------------------------------------------------------------
  1290. HRESULT
  1291. CicBridge::OnSetOpenStatus(
  1292. ITfThreadMgr_P* ptim_P,
  1293. IMCLock& imc,
  1294. CicInputContext& CicContext)
  1295. {
  1296. DebugMsg(TF_FUNC, TEXT("CicBridge::OnSetOpenStatus"));
  1297. if (! imc->fOpen && imc.ValidCompositionString())
  1298. {
  1299. //
  1300. // #503401 - Finalize the composition string.
  1301. //
  1302. CicContext.EscbCompComplete(imc);
  1303. }
  1304. CicContext.m_fOpenStatusChanging.SetFlag();
  1305. HRESULT hr = SetCompartmentDWORD(m_tfClientId,
  1306. ptim_P,
  1307. GUID_COMPARTMENT_KEYBOARD_OPENCLOSE,
  1308. imc->fOpen,
  1309. FALSE);
  1310. CicContext.m_fOpenStatusChanging.ResetFlag();
  1311. return hr;
  1312. }
  1313. //+---------------------------------------------------------------------------
  1314. //
  1315. // CicBridge::OnSetConversionSentenceMode
  1316. //
  1317. //----------------------------------------------------------------------------
  1318. HRESULT
  1319. CicBridge::OnSetConversionSentenceMode(
  1320. ITfThreadMgr_P* ptim_P,
  1321. IMCLock& imc,
  1322. CicInputContext& CicContext,
  1323. DWORD dwValue,
  1324. LANGID langid)
  1325. {
  1326. DebugMsg(TF_FUNC, TEXT("CicBridge::OnSetConversionSentenceMode"));
  1327. CicContext.m_fOnceModeChanged.SetFlag();
  1328. CicContext.m_fConversionSentenceModeChanged.SetFlag();
  1329. Interface_Attach<ITfContextOwnerServices> iccb(CicContext.GetInputContextOwnerSink());
  1330. if (dwValue == IMC_SETCONVERSIONMODE)
  1331. {
  1332. CicContext.m_nInConversionModeChangingRef++;
  1333. if (PRIMARYLANGID(langid) == LANG_JAPANESE)
  1334. {
  1335. if (imc->fdwSentence == IME_SMODE_PHRASEPREDICT) {
  1336. CicContext.m_nInConversionModeResetRef++;
  1337. iccb->OnAttributeChange(GUID_PROP_MODEBIAS);
  1338. CicContext.m_nInConversionModeResetRef--;
  1339. }
  1340. }
  1341. }
  1342. //
  1343. // If we're in EscHanjaMode, we already makes Reconversion. So
  1344. // we don't have to make AttributeChange for IMC_CMODE_HANJACONVERT.
  1345. //
  1346. BOOL fSkipOnAttributeChange = FALSE;
  1347. if ((PRIMARYLANGID(langid) == LANG_KOREAN) &&
  1348. CicContext.m_fHanjaReConversion.IsSetFlag())
  1349. {
  1350. fSkipOnAttributeChange = TRUE;
  1351. }
  1352. // let cicero know the mode bias has changed
  1353. // consider: perf: we could try to filter out false-positives here
  1354. // (sometimes a bit that cicero ignores changes, we could check and avoid the call,
  1355. // but it would complicate the code)
  1356. if (!fSkipOnAttributeChange)
  1357. iccb->OnAttributeChange(GUID_PROP_MODEBIAS);
  1358. //
  1359. // let Korean Tip sync up the current mode status changing...
  1360. //
  1361. if (PRIMARYLANGID(langid) == LANG_KOREAN)
  1362. {
  1363. OnSetKorImxConversionMode(ptim_P, imc, CicContext);
  1364. }
  1365. if (dwValue == IMC_SETCONVERSIONMODE)
  1366. CicContext.m_nInConversionModeChangingRef--;
  1367. return S_OK;
  1368. }
  1369. //+---------------------------------------------------------------------------
  1370. //
  1371. // CicBridge::OnSetKorImxConversionMode
  1372. //
  1373. //----------------------------------------------------------------------------
  1374. HRESULT
  1375. CicBridge::OnSetKorImxConversionMode(
  1376. ITfThreadMgr_P* ptim_P,
  1377. IMCLock& imc,
  1378. CicInputContext& CicContext)
  1379. {
  1380. DebugMsg(TF_FUNC, TEXT("CicBridge::OnSetKorImxConversionMode"));
  1381. DWORD fdwConvMode = 0;
  1382. CicContext.m_fKorImxModeChanging.SetFlag();
  1383. if (imc->fdwConversion & IME_CMODE_HANGUL)
  1384. {
  1385. if (imc->fdwConversion & IME_CMODE_FULLSHAPE)
  1386. fdwConvMode = KORIMX_HANGULJUNJA_MODE;
  1387. else
  1388. fdwConvMode = KORIMX_HANGUL_MODE;
  1389. }
  1390. else
  1391. {
  1392. if (imc->fdwConversion & IME_CMODE_FULLSHAPE)
  1393. fdwConvMode = KORIMX_JUNJA_MODE;
  1394. else
  1395. fdwConvMode = KORIMX_ALPHANUMERIC_MODE;
  1396. }
  1397. HRESULT hr = SetCompartmentDWORD(m_tfClientId,
  1398. ptim_P,
  1399. GUID_COMPARTMENT_KORIMX_CONVMODE,
  1400. fdwConvMode,
  1401. FALSE);
  1402. CicContext.m_fKorImxModeChanging.ResetFlag();
  1403. return hr;
  1404. }
  1405. //+---------------------------------------------------------------------------
  1406. //
  1407. // CicBridge::ConfigureGeneral
  1408. //
  1409. //----------------------------------------------------------------------------
  1410. HRESULT
  1411. CicBridge::ConfigureGeneral(
  1412. TLS* ptls,
  1413. ITfThreadMgr_P* ptim_P,
  1414. HKL hKL,
  1415. HWND hAppWnd)
  1416. {
  1417. DebugMsg(TF_FUNC, TEXT("CicBridge::ConfigureGeneral"));
  1418. TF_LANGUAGEPROFILE LanguageProfile;
  1419. CicProfile* _pProfile = ptls->GetCicProfile();
  1420. if (_pProfile == NULL)
  1421. {
  1422. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureGeneral. _pProfile==NULL."));
  1423. return E_OUTOFMEMORY;
  1424. }
  1425. HRESULT hr;
  1426. hr = _pProfile->GetActiveLanguageProfile(hKL,
  1427. GUID_TFCAT_TIP_KEYBOARD,
  1428. &LanguageProfile);
  1429. if (FAILED(hr))
  1430. {
  1431. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureGeneral. LanguageProfile==NULL."));
  1432. return hr;
  1433. }
  1434. Interface<ITfFunctionProvider> pFuncProv;
  1435. hr = ptim_P->GetFunctionProvider(LanguageProfile.clsid, // CLSID of tip
  1436. pFuncProv);
  1437. if (FAILED(hr))
  1438. {
  1439. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureGeneral. pFuncProv==NULL."));
  1440. return hr;
  1441. }
  1442. Interface<ITfFnConfigure> pFnConfigure;
  1443. hr = pFuncProv->GetFunction(GUID_NULL,
  1444. IID_ITfFnConfigure,
  1445. (IUnknown**)(ITfFnConfigure**)pFnConfigure);
  1446. if (FAILED(hr))
  1447. {
  1448. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureGeneral. pFnCofigure==NULL."));
  1449. return hr;
  1450. }
  1451. hr = pFnConfigure->Show(hAppWnd,
  1452. LanguageProfile.langid,
  1453. LanguageProfile.guidProfile);
  1454. return hr;
  1455. }
  1456. //+---------------------------------------------------------------------------
  1457. //
  1458. // CicBridge::ConfigureGeneral
  1459. //
  1460. //----------------------------------------------------------------------------
  1461. HRESULT
  1462. CicBridge::ConfigureRegisterWord(
  1463. TLS* ptls,
  1464. ITfThreadMgr_P* ptim_P,
  1465. HKL hKL,
  1466. HWND hAppWnd,
  1467. REGISTERWORDW* pRegisterWord)
  1468. {
  1469. DebugMsg(TF_FUNC, TEXT("CicBridge::ConfigureRegisterWord"));
  1470. TF_LANGUAGEPROFILE LanguageProfile;
  1471. CicProfile* _pProfile = ptls->GetCicProfile();
  1472. if (_pProfile == NULL)
  1473. {
  1474. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureRegisterWord. _pProfile==NULL."));
  1475. return E_OUTOFMEMORY;
  1476. }
  1477. HRESULT hr;
  1478. hr = _pProfile->GetActiveLanguageProfile(hKL,
  1479. GUID_TFCAT_TIP_KEYBOARD,
  1480. &LanguageProfile);
  1481. if (FAILED(hr))
  1482. {
  1483. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureRegisterWord. LanguageProfile==NULL."));
  1484. return hr;
  1485. }
  1486. Interface<ITfFunctionProvider> pFuncProv;
  1487. hr = ptim_P->GetFunctionProvider(LanguageProfile.clsid, // CLSID of tip
  1488. pFuncProv);
  1489. if (FAILED(hr))
  1490. {
  1491. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureRegisterWord. pFuncProv==NULL."));
  1492. return hr;
  1493. }
  1494. Interface<ITfFnConfigureRegisterWord> pFnRegisterWord;
  1495. hr = pFuncProv->GetFunction(GUID_NULL,
  1496. IID_ITfFnConfigureRegisterWord,
  1497. (IUnknown**)(ITfFnConfigureRegisterWord**)pFnRegisterWord);
  1498. if (FAILED(hr))
  1499. {
  1500. DebugMsg(TF_ERROR, TEXT("CicBridge::ConfigureRegisterWord. pFnRegisterWord==NULL."));
  1501. return hr;
  1502. }
  1503. if (!pRegisterWord || !pRegisterWord->lpWord)
  1504. {
  1505. hr = pFnRegisterWord->Show(hAppWnd,
  1506. LanguageProfile.langid,
  1507. LanguageProfile.guidProfile,
  1508. NULL);
  1509. }
  1510. else
  1511. {
  1512. BSTR bstrWord = SysAllocString(pRegisterWord->lpWord);
  1513. if (!bstrWord)
  1514. return E_OUTOFMEMORY;
  1515. hr = pFnRegisterWord->Show(hAppWnd,
  1516. LanguageProfile.langid,
  1517. LanguageProfile.guidProfile,
  1518. bstrWord);
  1519. SysFreeString(bstrWord);
  1520. }
  1521. return hr;
  1522. }
  1523. //+---------------------------------------------------------------------------
  1524. //
  1525. // CicBridge::EscapeKorean
  1526. //
  1527. //----------------------------------------------------------------------------
  1528. LRESULT
  1529. CicBridge::EscapeKorean(
  1530. TLS* ptls,
  1531. HIMC hImc,
  1532. UINT uSubFunc,
  1533. LPVOID lpData)
  1534. {
  1535. DebugMsg(TF_FUNC, TEXT("CicBridge::EscapeKorean"));
  1536. switch (uSubFunc)
  1537. {
  1538. case IME_ESC_QUERY_SUPPORT:
  1539. switch (*(LPUINT)lpData)
  1540. {
  1541. case IME_ESC_HANJA_MODE: return TRUE;
  1542. default: return FALSE;
  1543. }
  1544. break;
  1545. case IME_ESC_HANJA_MODE:
  1546. return EscHanjaMode(ptls, hImc, (LPWSTR)lpData);
  1547. }
  1548. return FALSE;
  1549. }
  1550. //+---------------------------------------------------------------------------
  1551. //
  1552. // CicBridge::EscHanjaMode
  1553. //
  1554. //----------------------------------------------------------------------------
  1555. LRESULT
  1556. CicBridge::EscHanjaMode(
  1557. TLS* ptls,
  1558. HIMC hImc,
  1559. LPWSTR lpwStr)
  1560. {
  1561. DebugMsg(TF_FUNC, TEXT("CicBridge::EscHanjaMode"));
  1562. HRESULT hr;
  1563. IMCLock imc(hImc);
  1564. if (FAILED(hr=imc.GetResult()))
  1565. {
  1566. DebugMsg(TF_ERROR, TEXT("CicBridge::EscHanjaMode. imc==NULL"));
  1567. return FALSE;
  1568. }
  1569. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  1570. if (FAILED(hr=imc_ctfime.GetResult()))
  1571. {
  1572. DebugMsg(TF_ERROR, TEXT("CicBridge::EscHanjaMode. imc_ctfime==NULL"));
  1573. return FALSE;
  1574. }
  1575. CicInputContext* pCicContext = imc_ctfime->m_pCicContext;
  1576. if (pCicContext)
  1577. {
  1578. //
  1579. // This is for only Excel since Excel calling Hanja escape function two
  1580. // times. we going to just ignore the second request not to close Hanja
  1581. // candidate window.
  1582. //
  1583. if (pCicContext->m_fOpenCandidateWindow.IsSetFlag())
  1584. {
  1585. //
  1586. // Need to set the result value since some apps(Trident) also call
  1587. // Escape() twice and expect the right result value.
  1588. //
  1589. return TRUE;
  1590. }
  1591. pCicContext->m_fHanjaReConversion.SetFlag();
  1592. }
  1593. CWReconvertString wReconvStr(imc);
  1594. wReconvStr.WriteCompData(lpwStr, 1);
  1595. BOOL fCompMem = FALSE;
  1596. LPRECONVERTSTRING lpReconvertString = NULL;
  1597. DWORD dwLen = wReconvStr.ReadCompData();
  1598. if (dwLen) {
  1599. lpReconvertString = (LPRECONVERTSTRING) new BYTE[ dwLen ];
  1600. if (lpReconvertString) {
  1601. fCompMem = TRUE;
  1602. wReconvStr.ReadCompData(lpReconvertString, dwLen);
  1603. }
  1604. }
  1605. LRESULT ret;
  1606. ret = ImmSetCompositionStringW(hImc, SCS_QUERYRECONVERTSTRING, lpReconvertString, dwLen, NULL, 0);
  1607. if (ret) {
  1608. ret = ImmSetCompositionStringW(hImc, SCS_SETRECONVERTSTRING, lpReconvertString, dwLen, NULL, 0);
  1609. if (ret) {
  1610. ret = ImmSetConversionStatus(hImc, imc->fdwConversion | IME_CMODE_HANJACONVERT,
  1611. imc->fdwSentence);
  1612. }
  1613. }
  1614. if (pCicContext)
  1615. {
  1616. //
  1617. // enpty the edit session queue of the ic.
  1618. //
  1619. ITfThreadMgr_P* ptim_P;
  1620. if (ptls != NULL && ((ptim_P = ptls->GetTIM()) != NULL))
  1621. {
  1622. Interface<ITfContext_P> icp;
  1623. hr = pCicContext->GetInputContext()->QueryInterface(IID_ITfContext_P,
  1624. (void **)icp);
  1625. if (hr == S_OK)
  1626. ptim_P->RequestPostponedLock(icp);
  1627. else
  1628. DebugMsg(TF_ERROR, TEXT("CicBridge::EscHanjaMode. QueryInterface is failed"));
  1629. }
  1630. else
  1631. {
  1632. DebugMsg(TF_ERROR, TEXT("CicBridge::EscHanjaMode. ptls or ptim_P==NULL"));
  1633. }
  1634. pCicContext->m_fHanjaReConversion.ResetFlag();
  1635. }
  1636. if (fCompMem)
  1637. delete [] lpReconvertString;
  1638. return ret;
  1639. }
  1640. //+---------------------------------------------------------------------------
  1641. //
  1642. // CicBridge::DoOpenCandidateHanja
  1643. //
  1644. //----------------------------------------------------------------------------
  1645. LRESULT
  1646. CicBridge::DoOpenCandidateHanja(
  1647. ITfThreadMgr_P* ptim_P,
  1648. IMCLock& imc,
  1649. CicInputContext& CicContext)
  1650. {
  1651. BOOL fRet = FALSE;
  1652. DebugMsg(TF_FUNC, TEXT("CicBridge::DoOpenCandidateHanja"));
  1653. IMCCLock<COMPOSITIONSTRING> comp(imc->hCompStr);
  1654. if (SUCCEEDED(comp.GetResult()) && comp->dwCompStrLen)
  1655. {
  1656. //
  1657. // This is for only Excel since Excel calling Hanja escape function two
  1658. // times. we going to just ignore the second request not to close Hanja
  1659. // candidate window.
  1660. //
  1661. if (CicContext.m_fOpenCandidateWindow.IsSetFlag())
  1662. {
  1663. //
  1664. // Need to set the result value since some apps(Trident) also call
  1665. // Escape() twice and expect the right result value.
  1666. //
  1667. return TRUE;
  1668. }
  1669. CicContext.m_fHanjaReConversion.SetFlag();
  1670. HRESULT hr;
  1671. Interface<ITfRange> Selection;
  1672. Interface<ITfFunctionProvider> FuncProv;
  1673. Interface<ITfFnReconversion> Reconversion;
  1674. hr = CicContext.EscbGetSelection(imc, &Selection);
  1675. if (FAILED(hr))
  1676. {
  1677. DebugMsg(TF_ERROR, TEXT("CicBridge::DoOpenCandidateHanja. EscbGetSelection failed"));
  1678. goto Exit;
  1679. }
  1680. hr = ptim_P->GetFunctionProvider(GUID_SYSTEM_FUNCTIONPROVIDER, FuncProv);
  1681. if (FAILED(hr))
  1682. {
  1683. DebugMsg(TF_ERROR, TEXT("CicBridge::DoOpenCandidateHanja. FuncProv==NULL"));
  1684. goto Exit;
  1685. }
  1686. hr = FuncProv->GetFunction(GUID_NULL,
  1687. IID_ITfFnReconversion,
  1688. (IUnknown**)(ITfFnReconversion**)Reconversion);
  1689. if (SUCCEEDED(hr))
  1690. {
  1691. Interface<ITfRange> RangeNew;
  1692. BOOL fConvertable;
  1693. hr = Reconversion->QueryRange(Selection, RangeNew, &fConvertable);
  1694. if (SUCCEEDED(hr) && fConvertable)
  1695. {
  1696. //
  1697. // Tip has a chance to close Hanja candidate UI window during
  1698. // the changes of conversion mode, so update conversion status
  1699. // first.
  1700. //
  1701. ImmSetConversionStatus(imc, imc->fdwConversion | IME_CMODE_HANJACONVERT,
  1702. imc->fdwSentence);
  1703. hr = Reconversion->Reconvert(RangeNew);
  1704. if (FAILED(hr))
  1705. {
  1706. ImmSetConversionStatus(imc,
  1707. imc->fdwConversion & ~IME_CMODE_HANJACONVERT,
  1708. imc->fdwSentence);
  1709. }
  1710. }
  1711. else
  1712. {
  1713. DebugMsg(TF_ERROR, TEXT("CicBridge::DoOpenCandidateHanja. QueryRange failed so the compoisiton string will be completed."));
  1714. CicContext.EscbCompComplete(imc);
  1715. goto Exit;
  1716. }
  1717. }
  1718. fRet = TRUE;
  1719. Exit:
  1720. CicContext.m_fHanjaReConversion.ResetFlag();
  1721. }
  1722. return fRet;
  1723. }
  1724. //+---------------------------------------------------------------------------
  1725. //
  1726. // CicBridge::SetCompositionString
  1727. //
  1728. //----------------------------------------------------------------------------
  1729. BOOL
  1730. CicBridge::SetCompositionString(
  1731. TLS* ptls,
  1732. ITfThreadMgr_P* ptim_P,
  1733. HIMC hImc,
  1734. DWORD dwIndex,
  1735. void* pComp,
  1736. DWORD dwCompLen,
  1737. void* pRead,
  1738. DWORD dwReadLen)
  1739. {
  1740. DebugMsg(TF_FUNC, TEXT("CicBridge::SetCompositionString"));
  1741. HRESULT hr;
  1742. IMCLock imc(hImc);
  1743. if (FAILED(hr=imc.GetResult()))
  1744. {
  1745. DebugMsg(TF_ERROR, TEXT("CicBridge::SetCompositionString. imc==NULL"));
  1746. return FALSE;
  1747. }
  1748. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  1749. if (FAILED(hr=imc_ctfime.GetResult()))
  1750. {
  1751. DebugMsg(TF_ERROR, TEXT("CicBridge::SetCompositionString. imc_ctfime==NULL"));
  1752. return FALSE;
  1753. }
  1754. CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
  1755. if (_pCicContext == NULL)
  1756. {
  1757. DebugMsg(TF_ERROR, TEXT("CicBridge::SetCompositionString. _pCicContext==NULL."));
  1758. return FALSE;
  1759. }
  1760. UINT cp;
  1761. CicProfile* _pProfile = ptls->GetCicProfile();
  1762. if (_pProfile == NULL)
  1763. {
  1764. DebugMsg(TF_ERROR, TEXT("CicBridge::SetCompositionString. _pProfile==NULL."));
  1765. return FALSE;
  1766. }
  1767. _pProfile->GetCodePageA(&cp);
  1768. if (dwIndex == SCS_SETSTR &&
  1769. pComp != NULL && (*(LPWSTR)pComp) == L'\0' && dwCompLen != 0)
  1770. {
  1771. LANGID langid;
  1772. hr = _pProfile->GetLangId(&langid);
  1773. //
  1774. // Bug#580455 - Some korean specific apps calls it for completing
  1775. // the current composition immediately.
  1776. //
  1777. if (SUCCEEDED(hr) && PRIMARYLANGID(langid) == LANG_KOREAN)
  1778. {
  1779. if (imc->fdwConversion & IME_CMODE_HANGUL)
  1780. {
  1781. ImmNotifyIME(hImc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
  1782. return TRUE;
  1783. }
  1784. else
  1785. {
  1786. return FALSE;
  1787. }
  1788. }
  1789. }
  1790. return _pCicContext->SetCompositionString(imc, ptim_P, dwIndex, pComp, dwCompLen, pRead, dwReadLen, cp);
  1791. }
  1792. //+---------------------------------------------------------------------------
  1793. //
  1794. // CicBridge::GetGuidAtom
  1795. //
  1796. //----------------------------------------------------------------------------
  1797. HRESULT
  1798. CicBridge::GetGuidAtom(
  1799. TLS* ptls,
  1800. HIMC hImc,
  1801. BYTE bAttr,
  1802. TfGuidAtom* atom)
  1803. {
  1804. DebugMsg(TF_FUNC, TEXT("CicBridge::GetGuidAtom"));
  1805. HRESULT hr;
  1806. IMCLock imc(hImc);
  1807. if (FAILED(hr=imc.GetResult()))
  1808. {
  1809. DebugMsg(TF_ERROR, TEXT("CicBridge::GetGuidAtom. imc==NULL"));
  1810. return hr;
  1811. }
  1812. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  1813. if (FAILED(hr=imc_ctfime.GetResult()))
  1814. {
  1815. DebugMsg(TF_ERROR, TEXT("CicBridge::GetGuidAtom. imc_ctfime==NULL"));
  1816. return hr;
  1817. }
  1818. CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
  1819. if (_pCicContext == NULL)
  1820. {
  1821. DebugMsg(TF_ERROR, TEXT("CicBridge::GetGuidAtom. _pCicContext==NULL."));
  1822. return E_OUTOFMEMORY;
  1823. }
  1824. return _pCicContext->GetGuidAtom(imc, bAttr, atom);
  1825. }
  1826. //+---------------------------------------------------------------------------
  1827. //
  1828. // CicBridge::GetDisplayAttributeInfo
  1829. //
  1830. //----------------------------------------------------------------------------
  1831. HRESULT
  1832. CicBridge::GetDisplayAttributeInfo(
  1833. TfGuidAtom atom,
  1834. TF_DISPLAYATTRIBUTE* da)
  1835. {
  1836. HRESULT hr = E_FAIL;
  1837. GUID guid;
  1838. GetGUIDFromGUIDATOM(&_libTLS, atom, &guid);
  1839. Interface<ITfDisplayAttributeInfo> dai;
  1840. CLSID clsid;
  1841. ITfDisplayAttributeMgr* dam = GetDAMLib(&_libTLS);
  1842. if (dam != NULL)
  1843. {
  1844. if (SUCCEEDED(hr=dam->GetDisplayAttributeInfo(guid, dai, &clsid)))
  1845. {
  1846. dai->GetAttributeInfo(da);
  1847. }
  1848. }
  1849. return hr;
  1850. }
  1851. //+---------------------------------------------------------------------------
  1852. //
  1853. // CicBridge::DefaultKeyHandling
  1854. //
  1855. //----------------------------------------------------------------------------
  1856. BOOL
  1857. CicBridge::DefaultKeyHandling(
  1858. TLS* ptls,
  1859. IMCLock& imc,
  1860. CicInputContext* CicContext,
  1861. UINT uVirtKey,
  1862. LPARAM lParam)
  1863. {
  1864. if (CicContext == NULL)
  1865. return FALSE;
  1866. LANGID langid;
  1867. CicProfile* _pProfile = ptls->GetCicProfile();
  1868. if (_pProfile == NULL)
  1869. {
  1870. DebugMsg(TF_ERROR, TEXT("CicBridge::DefaultKeyHandling. _pProfile==NULL."));
  1871. return FALSE;
  1872. }
  1873. HRESULT hr = _pProfile->GetLangId(&langid);
  1874. if (SUCCEEDED(hr) && PRIMARYLANGID(langid) == LANG_KOREAN)
  1875. {
  1876. if (!MsimtfIsWindowFiltered(::GetFocus()) &&
  1877. (CicContext->m_fGeneratedEndComposition.IsSetFlag() || uVirtKey == VK_HANJA))
  1878. {
  1879. //
  1880. // Korean IME alwaus generate WM_IME_KEYDOWN message
  1881. // if it finalizes the interim char in order to keep message
  1882. // order.
  1883. //
  1884. PostMessage(imc->hWnd, WM_IME_KEYDOWN, uVirtKey, lParam);
  1885. return TRUE;
  1886. }
  1887. //
  1888. // Korean won't _WantThisKey / _HandleThisKey
  1889. //
  1890. return FALSE;
  1891. }
  1892. if (! (HIWORD(uVirtKey) & KF_UP)) {
  1893. if (CicContext->WantThisKey(uVirtKey)) {
  1894. CicContext->EscbHandleThisKey(imc, uVirtKey);
  1895. return TRUE;
  1896. }
  1897. }
  1898. return FALSE;
  1899. }
  1900. //+---------------------------------------------------------------------------
  1901. //
  1902. // CicBridge::CTFDetection
  1903. //
  1904. //----------------------------------------------------------------------------
  1905. BOOL
  1906. CicBridge::CTFDetection(
  1907. TLS* ptls,
  1908. ITfDocumentMgr* dim)
  1909. {
  1910. HRESULT hr;
  1911. //
  1912. // Get TIM
  1913. //
  1914. ITfThreadMgr_P* ptim_P;
  1915. if ((ptim_P=ptls->GetTIM()) == NULL)
  1916. {
  1917. DebugMsg(TF_ERROR, TEXT("CThreadMgrEventSink_DIMCallBack::DIMCallback. ptim_P==NULL"));
  1918. return FALSE;
  1919. }
  1920. //
  1921. // Get cskf
  1922. //
  1923. Interface<ITfConfigureSystemKeystrokeFeed> cskf;
  1924. hr = ptim_P->QueryInterface(IID_ITfConfigureSystemKeystrokeFeed, (void**)cskf);
  1925. if (hr != S_OK)
  1926. {
  1927. DebugMsg(TF_ERROR, TEXT("CThreadMgrEventSink_DIMCallBack::DIMCallback. IID_ITfConfigureSystemKeystrokeFeed==NULL"));
  1928. return FALSE;
  1929. }
  1930. BOOL fEnableKeystrokeFeed = FALSE;
  1931. //
  1932. // Cicero aware application detection...
  1933. //
  1934. // if dim is NULL, it is not Ciceor aware apps document.
  1935. //
  1936. if (!dim || IsOwnDim(dim))
  1937. {
  1938. //
  1939. // CTFIME owns document
  1940. //
  1941. fEnableKeystrokeFeed = FALSE;
  1942. ptls->ResetCTFAware();
  1943. }
  1944. else
  1945. {
  1946. fEnableKeystrokeFeed = TRUE;
  1947. ptls->SetCTFAware();
  1948. }
  1949. //
  1950. // Call ImmGetAppCompatFlags with NULL to get the global app compat flag.
  1951. //
  1952. DWORD dwImeCompatFlags = ImmGetAppCompatFlags(NULL);
  1953. if (dwImeCompatFlags & (IMECOMPAT_AIMM12 | IMECOMPAT_AIMM_LEGACY_CLSID | IMECOMPAT_AIMM12_TRIDENT))
  1954. {
  1955. //
  1956. // we want to get hwnd from hIMC that is associated to dim.
  1957. // Now we don't have a back pointer to hIMC in dim.
  1958. //
  1959. HWND hwndFocus = ::GetFocus();
  1960. if (hwndFocus && MsimtfIsWindowFiltered(hwndFocus))
  1961. {
  1962. //
  1963. // AIMM aware apps. Never processing ImeProcessKey
  1964. //
  1965. fEnableKeystrokeFeed = TRUE;
  1966. ptls->SetAIMMAware();
  1967. }
  1968. else
  1969. {
  1970. ptls->ResetAIMMAware();
  1971. }
  1972. }
  1973. //
  1974. // Enable or disable keystroke feed if necessary.
  1975. //
  1976. if (ptls->IsEnabledKeystrokeFeed() && !fEnableKeystrokeFeed)
  1977. {
  1978. hr = cskf->DisableSystemKeystrokeFeed();
  1979. if (hr != S_OK)
  1980. {
  1981. DebugMsg(TF_ERROR, TEXT("CThreadMgrEventSink_DIMCallBack::CTFDetection. DisableSystemKeystrokeFeed==NULL"));
  1982. }
  1983. ptls->ResetEnabledKeystrokeFeed();
  1984. }
  1985. else if (!ptls->IsEnabledKeystrokeFeed() && fEnableKeystrokeFeed)
  1986. {
  1987. hr = cskf->EnableSystemKeystrokeFeed();
  1988. if (hr != S_OK)
  1989. {
  1990. DebugMsg(TF_ERROR, TEXT("CThreadMgrEventSink_DIMCallBack::CTFDetection. EnableSystemKeystrokeFeed==NULL"));
  1991. }
  1992. ptls->SetEnabledKeystrokeFeed();
  1993. }
  1994. return TRUE;
  1995. }
  1996. //+---------------------------------------------------------------------------
  1997. //
  1998. // CicBridge::PostTransMsg
  1999. //
  2000. //----------------------------------------------------------------------------
  2001. VOID
  2002. CicBridge::PostTransMsg(
  2003. HWND hwnd,
  2004. INT iNum,
  2005. LPTRANSMSG lpTransMsg)
  2006. {
  2007. while (iNum--)
  2008. {
  2009. PostMessageW(hwnd,
  2010. lpTransMsg->message,
  2011. lpTransMsg->wParam,
  2012. lpTransMsg->lParam);
  2013. lpTransMsg++;
  2014. }
  2015. }
  2016. //+---------------------------------------------------------------------------
  2017. //
  2018. // CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam)
  2019. //
  2020. //----------------------------------------------------------------------------
  2021. BOOL
  2022. CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam)
  2023. {
  2024. ENUMIMC *pedimc = (ENUMIMC *)lParam;
  2025. pedimc->_this->CreateInputContext(pedimc->ptls, hIMC);
  2026. return TRUE;
  2027. }
  2028. //+---------------------------------------------------------------------------
  2029. //
  2030. // CicBridge::EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam)
  2031. //
  2032. //----------------------------------------------------------------------------
  2033. BOOL
  2034. CicBridge::EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam)
  2035. {
  2036. ENUMIMC *pedimc = (ENUMIMC *)lParam;
  2037. pedimc->_this->DestroyInputContext(pedimc->ptls, hIMC);
  2038. return TRUE;
  2039. }