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.

1012 lines
28 KiB

  1. /*++
  2. Copyright (c) 2001, Microsoft Corporation
  3. Module Name:
  4. context.cpp
  5. Abstract:
  6. This file implements the CicInputContext Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #include "private.h"
  12. #include "context.h"
  13. #include "globals.h"
  14. #include "msime.h"
  15. #include "icocb.h"
  16. #include "txtevcb.h"
  17. #include "tmgrevcb.h"
  18. #include "cmpevcb.h"
  19. #include "reconvcb.h"
  20. #include "korimx.h"
  21. #include "profile.h"
  22. #include "delay.h"
  23. //+---------------------------------------------------------------------------
  24. //
  25. // CicInputContext::IUnknown::QueryInterface
  26. // CicInputContext::IUnknown::AddRef
  27. // CicInputContext::IUnknown::Release
  28. //
  29. //----------------------------------------------------------------------------
  30. HRESULT
  31. CicInputContext::QueryInterface(
  32. REFIID riid,
  33. void** ppvObj)
  34. {
  35. *ppvObj = NULL;
  36. if (IsEqualIID(riid, IID_ITfCleanupContextSink))
  37. {
  38. *ppvObj = static_cast<ITfCleanupContextSink*>(this);
  39. }
  40. else if (IsEqualGUID(riid, IID_ITfContextOwnerCompositionSink))
  41. {
  42. *ppvObj = static_cast<ITfContextOwnerCompositionSink*>(this);
  43. }
  44. else if (IsEqualGUID(riid, IID_IUnknown))
  45. {
  46. *ppvObj = this;
  47. }
  48. if (*ppvObj) {
  49. AddRef();
  50. return S_OK;
  51. }
  52. return E_NOINTERFACE;
  53. }
  54. ULONG
  55. CicInputContext::AddRef(
  56. )
  57. {
  58. return InterlockedIncrement(&m_ref);
  59. }
  60. ULONG
  61. CicInputContext::Release(
  62. )
  63. {
  64. ULONG cr = InterlockedDecrement(&m_ref);
  65. if (cr == 0) {
  66. delete this;
  67. }
  68. return cr;
  69. }
  70. //+---------------------------------------------------------------------------
  71. //
  72. // CicInputContext::ITfCleanupContextSink::OnCleanupContext
  73. //
  74. //----------------------------------------------------------------------------
  75. HRESULT
  76. CicInputContext::OnCleanupContext(
  77. TfEditCookie ecWrite,
  78. ITfContext* pic)
  79. {
  80. DebugMsg(TF_FUNC, TEXT("CicInputContext::OnCleanupContext"));
  81. TLS* ptls = TLS::ReferenceTLS(); // Should not allocate TLS. ie. TLS::GetTLS
  82. // DllMain -> ImeDestroy -> DeactivateIMMX -> Deactivate
  83. if (ptls == NULL)
  84. {
  85. DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. ptls==NULL."));
  86. return E_OUTOFMEMORY;
  87. }
  88. LANGID langid;
  89. CicProfile* _pProfile = ptls->GetCicProfile();
  90. if (_pProfile == NULL)
  91. {
  92. DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. _pProfile==NULL."));
  93. return E_OUTOFMEMORY;
  94. }
  95. _pProfile->GetLangId(&langid);
  96. IMEINFO ImeInfo;
  97. WCHAR szWndCls[MAX_PATH];
  98. if (Inquire(&ImeInfo, szWndCls, 0, (HKL)UlongToHandle(langid)) != S_OK)
  99. {
  100. DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. ImeInfo==NULL."));
  101. return E_FAIL;
  102. }
  103. if (ImeInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT)
  104. {
  105. #if 0
  106. ImmIfCompositionComplete *pImmIfCallBack = new ImmIfCompositionComplete;
  107. if (!pImmIfCallBack)
  108. return E_OUTOFMEMORY;
  109. pImmIfCallBack->CompComplete(ecWrite, m_hImc, FALSE, pic, m_pImmIfIME);
  110. delete pImmIfCallBack;
  111. #else
  112. //
  113. // Remove GUID_PROP_COMPOSING
  114. //
  115. ITfRange *rangeFull = NULL;
  116. ITfProperty *prop;
  117. ITfRange *rangeTmp;
  118. if (SUCCEEDED(pic->GetProperty(GUID_PROP_COMPOSING, &prop)))
  119. {
  120. IEnumTfRanges *enumranges;
  121. if (SUCCEEDED(prop->EnumRanges(ecWrite, &enumranges, rangeFull)))
  122. {
  123. while (enumranges->Next(1, &rangeTmp, NULL) == S_OK)
  124. {
  125. VARIANT var;
  126. QuickVariantInit(&var);
  127. prop->GetValue(ecWrite, rangeTmp, &var);
  128. if ((var.vt == VT_I4) && (var.lVal != 0))
  129. {
  130. prop->Clear(ecWrite, rangeTmp);
  131. }
  132. rangeTmp->Release();
  133. }
  134. enumranges->Release();
  135. }
  136. prop->Release();
  137. }
  138. #endif
  139. }
  140. return S_OK;
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // CicInputContext::ITfContextOwnerCompositionSink::OnStartComposition
  145. // CicInputContext::ITfContextOwnerCompositionSink::OnUpdateComposition
  146. // CicInputContext::ITfContextOwnerCompositionSink::OnEndComposition
  147. //
  148. //----------------------------------------------------------------------------
  149. HRESULT
  150. CicInputContext::OnStartComposition(
  151. ITfCompositionView* pComposition,
  152. BOOL* pfOk)
  153. {
  154. DebugMsg(TF_FUNC, TEXT("CicInputContext::OnStartComposition"));
  155. if (m_cCompositions > 0 && m_fModifyingDoc.IsResetFlag())
  156. {
  157. *pfOk = FALSE;
  158. }
  159. else
  160. {
  161. *pfOk = TRUE;
  162. m_cCompositions++;
  163. }
  164. return S_OK;
  165. }
  166. HRESULT
  167. CicInputContext::OnUpdateComposition(
  168. ITfCompositionView* pComposition,
  169. ITfRange* pRangeNew)
  170. {
  171. DebugMsg(TF_FUNC, TEXT("CicInputContext::OnUpdateComposition"));
  172. return S_OK;
  173. }
  174. HRESULT
  175. CicInputContext::OnEndComposition(
  176. ITfCompositionView* pComposition)
  177. {
  178. DebugMsg(TF_FUNC, TEXT("CicInputContext::OnEndComposition"));
  179. m_cCompositions--;
  180. return S_OK;
  181. }
  182. //+---------------------------------------------------------------------------
  183. //
  184. // CicInputContext::ITfCompositionSink::OnCompositionTerminated
  185. //
  186. //----------------------------------------------------------------------------
  187. HRESULT
  188. CicInputContext::OnCompositionTerminated(
  189. TfEditCookie ecWrite,
  190. ITfComposition* pComposition)
  191. {
  192. DebugMsg(TF_FUNC, TEXT("CicInputContext::OnCompositionTerminated"));
  193. return S_OK;
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // CicInputContext::CreateInputContext
  198. //
  199. //----------------------------------------------------------------------------
  200. HRESULT
  201. CicInputContext::CreateInputContext(
  202. ITfThreadMgr_P* ptim_P,
  203. IMCLock& imc)
  204. {
  205. DebugMsg(TF_FUNC, TEXT("CicInputContext::CreateInputContext"));
  206. // do this once for the life time of this context
  207. m_fStartComposition.ResetFlag();
  208. HRESULT hr;
  209. //
  210. // Create document manager.
  211. //
  212. if (m_pdim == NULL) {
  213. if (FAILED(hr = ptim_P->CreateDocumentMgr(&m_pdim)))
  214. {
  215. return hr;
  216. }
  217. //
  218. // mark this is an owned dim.
  219. //
  220. SetCompartmentDWORD(m_tid, m_pdim, GUID_COMPARTMENT_CTFIME_DIMFLAGS,
  221. COMPDIMFLAG_OWNEDDIM, FALSE);
  222. }
  223. //
  224. // Create input context
  225. //
  226. TfEditCookie ecTmp;
  227. hr = m_pdim->CreateContext(m_tid, 0, (ITfContextOwnerCompositionSink*)this, &m_pic, &ecTmp);
  228. if (FAILED(hr)) {
  229. DestroyInputContext();
  230. return hr;
  231. }
  232. //
  233. // associate CicInputContext in PIC.
  234. //
  235. Interface<IUnknown> punk;
  236. if (SUCCEEDED(QueryInterface(IID_IUnknown, punk))) {
  237. SetCompartmentUnknown(m_tid, m_pic,
  238. GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT,
  239. punk);
  240. }
  241. //
  242. // set AppProp mapping
  243. //
  244. ITfContext_P *picp;
  245. if (SUCCEEDED(m_pic->QueryInterface(IID_ITfContext_P, (void **)&picp)))
  246. {
  247. picp->MapAppProperty(TSATTRID_Text_ReadOnly, GUID_PROP_MSIMTF_READONLY);
  248. picp->Release();
  249. }
  250. //
  251. // Create Input Context Owner Callback
  252. //
  253. if (m_pICOwnerSink == NULL) {
  254. m_pICOwnerSink = new CInputContextOwnerCallBack(m_tid, m_pic, m_pLibTLS);
  255. if (m_pICOwnerSink == NULL) {
  256. DebugMsg(TF_ERROR, TEXT("Couldn't create ICOwnerSink tim!"));
  257. Assert(0); // couldn't activate thread!
  258. DestroyInputContext();
  259. return E_FAIL;
  260. }
  261. if (!m_pICOwnerSink->Init()) {
  262. DebugMsg(TF_ERROR, TEXT("Couldn't initialize ICOwnerSink tim!"));
  263. Assert(0); // couldn't activate thread!
  264. DestroyInputContext();
  265. return E_FAIL;
  266. }
  267. m_pICOwnerSink->SetCallbackDataPointer(m_pICOwnerSink);
  268. }
  269. //
  270. // Advise IC.
  271. //
  272. m_pICOwnerSink->_Advise(m_pic);
  273. Interface<ITfSourceSingle> SourceSingle;
  274. if (m_pic->QueryInterface(IID_ITfSourceSingle, (void **)SourceSingle) == S_OK)
  275. {
  276. // setup a cleanup callback
  277. // nb: a real tip doesn't need to be this aggressive, for instance
  278. // kimx probably only needs this sink on the focus ic.
  279. SourceSingle->AdviseSingleSink(m_tid, IID_ITfCleanupContextSink, (ITfCleanupContextSink *)this);
  280. }
  281. //
  282. // Push IC.
  283. //
  284. hr = m_pdim->Push(m_pic);
  285. if (m_piccb == NULL) {
  286. m_pic->QueryInterface(IID_ITfContextOwnerServices,
  287. (void **)&m_piccb);
  288. }
  289. //
  290. // Create Text Event Sink Callback
  291. //
  292. if (m_pTextEventSink == NULL) {
  293. m_pTextEventSink = new CTextEventSinkCallBack((HIMC)imc, m_tid, m_pic, m_pLibTLS);
  294. if (m_pTextEventSink == NULL) {
  295. DestroyInputContext();
  296. return E_FAIL;
  297. }
  298. m_pTextEventSink->SetCallbackDataPointer(m_pTextEventSink);
  299. Interface_Attach<ITfContext> ic(GetInputContext());
  300. m_pTextEventSink->_Advise(ic.GetPtr(), ICF_TEXTDELTA);
  301. }
  302. //
  303. // Create KBD TIP Open/Close Compartment Event Sink Callback
  304. //
  305. if (m_pKbdOpenCloseEventSink == NULL) {
  306. m_pKbdOpenCloseEventSink = new CKbdOpenCloseEventSink(m_tid, (HIMC)imc, m_pic, m_pLibTLS);
  307. if (m_pKbdOpenCloseEventSink == NULL) {
  308. DestroyInputContext();
  309. return E_FAIL;
  310. }
  311. m_pKbdOpenCloseEventSink->SetCallbackDataPointer(m_pKbdOpenCloseEventSink);
  312. m_pKbdOpenCloseEventSink->_Advise(ptim_P, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, FALSE);
  313. m_pKbdOpenCloseEventSink->_Advise(ptim_P, GUID_COMPARTMENT_KORIMX_CONVMODE, FALSE);
  314. }
  315. //
  316. // Create Candidate UI Window Open/Close Compartment Event Sink Callback
  317. //
  318. if (m_pCandidateWndOpenCloseEventSink == NULL) {
  319. m_pCandidateWndOpenCloseEventSink = new CCandidateWndOpenCloseEventSink(m_tid, (HIMC)imc, m_pic, m_pLibTLS);
  320. if (m_pCandidateWndOpenCloseEventSink == NULL) {
  321. DestroyInputContext();
  322. return E_FAIL;
  323. }
  324. m_pCandidateWndOpenCloseEventSink->SetCallbackDataPointer(m_pCandidateWndOpenCloseEventSink);
  325. m_pCandidateWndOpenCloseEventSink->_Advise(m_pic, GUID_COMPARTMENT_MSCANDIDATEUI_WINDOW, FALSE);
  326. }
  327. //
  328. // Create Start reconversion notify Sink
  329. //
  330. if (m_pStartReconvSink == NULL) {
  331. m_pStartReconvSink = new CStartReconversionNotifySink((HIMC)imc);
  332. if (m_pStartReconvSink == NULL) {
  333. DestroyInputContext();
  334. return E_FAIL;
  335. }
  336. m_pStartReconvSink->_Advise(m_pic);
  337. }
  338. //
  339. // Create Message Buffer
  340. //
  341. if (m_pMessageBuffer == NULL) {
  342. m_pMessageBuffer = new CFirstInFirstOut<TRANSMSG, TRANSMSG>;
  343. if (m_pMessageBuffer == NULL) {
  344. DestroyInputContext();
  345. return E_FAIL;
  346. }
  347. }
  348. return hr;
  349. }
  350. //+---------------------------------------------------------------------------
  351. //
  352. // CicInputContext::DestroyInputContext
  353. //
  354. //----------------------------------------------------------------------------
  355. HRESULT
  356. CicInputContext::DestroyInputContext()
  357. {
  358. DebugMsg(TF_FUNC, TEXT("CicInputContext::DestroyInputContext"));
  359. Interface<ITfSourceSingle> SourceSingle;
  360. if (m_pic && m_pic->QueryInterface(IID_ITfSourceSingle, (void **)SourceSingle) == S_OK)
  361. {
  362. SourceSingle->UnadviseSingleSink(m_tid, IID_ITfCleanupContextSink);
  363. }
  364. if (m_pMessageBuffer) {
  365. delete m_pMessageBuffer;
  366. m_pMessageBuffer = NULL;
  367. }
  368. if (m_pTextEventSink) {
  369. m_pTextEventSink->_Unadvise();
  370. m_pTextEventSink->Release();
  371. m_pTextEventSink = NULL;
  372. }
  373. if (m_pCandidateWndOpenCloseEventSink) {
  374. m_pCandidateWndOpenCloseEventSink->_Unadvise();
  375. m_pCandidateWndOpenCloseEventSink->Release();
  376. m_pCandidateWndOpenCloseEventSink = NULL;
  377. }
  378. if (m_pKbdOpenCloseEventSink) {
  379. m_pKbdOpenCloseEventSink->_Unadvise();
  380. m_pKbdOpenCloseEventSink->Release();
  381. m_pKbdOpenCloseEventSink = NULL;
  382. }
  383. if (m_pStartReconvSink) {
  384. m_pStartReconvSink->_Unadvise();
  385. m_pStartReconvSink->Release();
  386. m_pStartReconvSink = NULL;
  387. }
  388. HRESULT hr;
  389. if (m_pdim)
  390. {
  391. hr = m_pdim->Pop(TF_POPF_ALL);
  392. }
  393. //
  394. // un-associate CicInputContext in PIC.
  395. //
  396. if (m_pic) {
  397. ClearCompartment(m_tid, m_pic,
  398. GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT,
  399. FALSE);
  400. }
  401. if (m_pic) {
  402. m_pic->Release();
  403. m_pic = NULL;
  404. }
  405. if (m_piccb) {
  406. m_piccb->Release();
  407. m_piccb = NULL;
  408. }
  409. // ic owner is auto unadvised during the Pop by cicero
  410. // in any case, it must not be unadvised before the pop
  411. // since it will be used to handle mouse sinks, etc.
  412. if (m_pICOwnerSink) {
  413. m_pICOwnerSink->_Unadvise();
  414. m_pICOwnerSink->Release();
  415. m_pICOwnerSink = NULL;
  416. }
  417. if (m_pdim)
  418. {
  419. m_pdim->Release();
  420. m_pdim = NULL;
  421. }
  422. return S_OK;
  423. }
  424. //+---------------------------------------------------------------------------
  425. //
  426. // CicInputContext::GenerateMessage
  427. //
  428. //----------------------------------------------------------------------------
  429. void
  430. CicInputContext::GenerateMessage(
  431. IMCLock& imc)
  432. {
  433. DebugMsg(TF_FUNC, TEXT("CicInputContext::GenerateMessage"));
  434. TranslateImeMessage(imc);
  435. if (FAILED(imc.GetResult()))
  436. {
  437. DebugMsg(TF_ERROR, TEXT("CicInputContext::GenerateMessage. imc==NULL"));
  438. }
  439. IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
  440. DWORD dwImeCompatFlags = ImmGetAppCompatFlags(NULL);
  441. BOOL fSendMsg;
  442. CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
  443. if (_pCicContext == NULL)
  444. return;
  445. if (!(_pCicContext->m_fInToAsciiEx.IsSetFlag() ||
  446. _pCicContext->m_fInProcessKey.IsSetFlag() ) ||
  447. _pCicContext->m_fInDocFeedReconvert.IsSetFlag() ||
  448. MsimtfIsWindowFiltered(::GetFocus()))
  449. {
  450. //
  451. // Generate SendMessage.
  452. //
  453. fSendMsg = TRUE;
  454. CtfImmGenerateMessage((HIMC)imc, fSendMsg);
  455. }
  456. else
  457. {
  458. //
  459. // Generate PostMessage.
  460. //
  461. fSendMsg = FALSE;
  462. CtfImmGenerateMessage((HIMC)imc, fSendMsg);
  463. }
  464. }
  465. //+---------------------------------------------------------------------------
  466. //
  467. // CicInputContext::TranslateImeMessage
  468. //
  469. //----------------------------------------------------------------------------
  470. UINT
  471. CicInputContext::TranslateImeMessage(
  472. IMCLock& imc,
  473. TRANSMSGLIST* lpTransMsgList) // default = NULL
  474. {
  475. DebugMsg(TF_FUNC, TEXT("CicInputContext::TranslateImeMessage"));
  476. if (m_pMessageBuffer == NULL)
  477. return 0;
  478. INT_PTR NumMsg = m_pMessageBuffer->GetSize();
  479. if (NumMsg == 0)
  480. return 0;
  481. UINT retNumMsg = 0;
  482. if (lpTransMsgList && NumMsg < (INT_PTR)lpTransMsgList->uMsgCount) {
  483. LPTRANSMSG lpTransMsg = &lpTransMsgList->TransMsg[0];
  484. while (NumMsg--) {
  485. if (! m_pMessageBuffer->GetData(*lpTransMsg++))
  486. break;
  487. retNumMsg++;
  488. }
  489. }
  490. else {
  491. if (imc->hMsgBuf == NULL) {
  492. imc->hMsgBuf = ImmCreateIMCC((DWORD)(NumMsg * sizeof(TRANSMSG)));
  493. }
  494. else if (ImmGetIMCCSize(imc->hMsgBuf) < NumMsg * sizeof(TRANSMSG)) {
  495. imc->hMsgBuf = ImmReSizeIMCC(imc->hMsgBuf, (DWORD)(NumMsg * sizeof(TRANSMSG)));
  496. }
  497. imc->dwNumMsgBuf = 0;
  498. IMCCLock<TRANSMSG> pdw(imc->hMsgBuf);
  499. if (pdw.Valid()) {
  500. LPTRANSMSG lpTransMsg = pdw;
  501. while (NumMsg--) {
  502. if (! m_pMessageBuffer->GetData(*lpTransMsg++))
  503. break;
  504. retNumMsg++;
  505. }
  506. imc->dwNumMsgBuf = retNumMsg;
  507. }
  508. }
  509. return retNumMsg;
  510. }
  511. //+---------------------------------------------------------------------------
  512. //
  513. // CicInputContext::InquireIMECharPosition
  514. //
  515. //----------------------------------------------------------------------------
  516. HRESULT
  517. CicInputContext::InquireIMECharPosition(
  518. LANGID langid,
  519. IMCLock& imc,
  520. IME_QUERY_POS* pfQueryPos)
  521. {
  522. DebugMsg(TF_FUNC, TEXT("CicInputContext::InquireIMECharPosition"));
  523. if (m_fQueryPos == IME_QUERY_POS_UNKNOWN) {
  524. //
  525. // Bug#500488 - Don't WM_MSIME_QUERYPOSITION for Korea
  526. //
  527. DWORD dwImeCompatFlags = ImmGetAppCompatFlags(NULL);
  528. if ((PRIMARYLANGID(langid) != LANG_KOREAN) ||
  529. ((PRIMARYLANGID(langid) == LANG_KOREAN) &&
  530. (dwImeCompatFlags & (IMECOMPAT_AIMM12 | IMECOMPAT_AIMM_LEGACY_CLSID | IMECOMPAT_AIMM12_TRIDENT)))
  531. ) {
  532. //
  533. // Is apps support "query positioning" ?
  534. //
  535. IMECHARPOSITION ip = {0};
  536. ip.dwSize = sizeof(IMECHARPOSITION);
  537. m_fQueryPos = QueryCharPos(imc, &ip) ? IME_QUERY_POS_YES : IME_QUERY_POS_NO;
  538. #ifdef DEBUG
  539. //
  540. // if QeuryCharPos() fails, the candidate window pos won't be correct.
  541. //
  542. if (m_fQueryPos == IME_QUERY_POS_NO)
  543. {
  544. Assert(0);
  545. }
  546. #endif
  547. }
  548. }
  549. if (pfQueryPos) {
  550. *pfQueryPos = m_fQueryPos;
  551. }
  552. return S_OK;
  553. }
  554. //+---------------------------------------------------------------------------
  555. //
  556. // CicInputContext::RetrieveIMECharPosition
  557. //
  558. //----------------------------------------------------------------------------
  559. HRESULT
  560. CicInputContext::RetrieveIMECharPosition(
  561. IMCLock& imc,
  562. IMECHARPOSITION* ip)
  563. {
  564. return QueryCharPos(imc, ip) ? S_OK : E_FAIL;
  565. }
  566. //+---------------------------------------------------------------------------
  567. //
  568. // CicInputContext::QueryCharPos
  569. //
  570. //----------------------------------------------------------------------------
  571. BOOL
  572. CicInputContext::QueryCharPos(
  573. IMCLock& imc,
  574. IMECHARPOSITION* position)
  575. {
  576. LRESULT lRet;
  577. //
  578. // First Step. Query by local method.
  579. //
  580. lRet = ::SendMessage(imc->hWnd,
  581. WM_MSIME_QUERYPOSITION,
  582. VERSION_QUERYPOSITION,
  583. (LPARAM)position);
  584. if (lRet) {
  585. return TRUE;
  586. }
  587. //
  588. // Second Step. Query by IMM method.
  589. // (IsOnNT5() || IsOn98())
  590. //
  591. if (ImmRequestMessage((HIMC)imc,
  592. IMR_QUERYCHARPOSITION,
  593. (LPARAM)position)) {
  594. return TRUE;
  595. }
  596. return FALSE;
  597. }
  598. //+---------------------------------------------------------------------------
  599. //
  600. // CicInputContext::MsImeMouseHandler
  601. //
  602. //----------------------------------------------------------------------------
  603. LRESULT
  604. CicInputContext::MsImeMouseHandler(
  605. ULONG uEdge,
  606. ULONG uQuadrant,
  607. ULONG dwBtnStatus,
  608. IMCLock& imc)
  609. {
  610. DebugMsg(TF_FUNC, TEXT("CicInputContext::MsImeMouseHandler"));
  611. LRESULT ret = m_pICOwnerSink->MsImeMouseHandler(uEdge, uQuadrant, dwBtnStatus, imc);
  612. if (dwBtnStatus & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
  613. EscbUpdateCompositionString(imc);
  614. }
  615. return ret;
  616. }
  617. //+---------------------------------------------------------------------------
  618. //
  619. // CicInputContext::SetCompositionString
  620. //
  621. //----------------------------------------------------------------------------
  622. BOOL
  623. CicInputContext::SetCompositionString(
  624. IMCLock& imc,
  625. ITfThreadMgr_P* ptim_P,
  626. DWORD dwIndex,
  627. void* pComp,
  628. DWORD dwCompLen,
  629. void* pRead,
  630. DWORD dwReadLen,
  631. UINT cp)
  632. {
  633. DebugMsg(TF_FUNC, TEXT("CicInputContext::SetCompositionString"));
  634. HRESULT hr;
  635. switch (dwIndex)
  636. {
  637. case SCS_SETSTR:
  638. {
  639. CWCompString wCompStr(imc, (LPWSTR)pComp, dwCompLen / sizeof(WCHAR)); // dwCompLen is byte count.
  640. CWCompString wCompReadStr(imc, (LPWSTR)pRead, dwReadLen / sizeof(WCHAR)); // dwReadLen is byte count.
  641. hr = Internal_SetCompositionString(imc, wCompStr, wCompReadStr);
  642. if (SUCCEEDED(hr))
  643. return TRUE;
  644. }
  645. break;
  646. case SCS_CHANGEATTR:
  647. case SCS_CHANGECLAUSE:
  648. return FALSE;
  649. case SCS_SETRECONVERTSTRING:
  650. {
  651. CWReconvertString wReconvStr(imc, (LPRECONVERTSTRING)pComp, dwCompLen);
  652. CWReconvertString wReconvReadStr(imc, (LPRECONVERTSTRING)pRead, dwReadLen);
  653. hr = Internal_ReconvertString(imc, ptim_P, wReconvStr, wReconvReadStr);
  654. if (SUCCEEDED(hr))
  655. return TRUE;
  656. }
  657. break;
  658. case SCS_QUERYRECONVERTSTRING:
  659. // AdjustZeroCompLenReconvertString((LPRECONVERTSTRING)pComp, cp, FALSE);
  660. // hr = S_OK;
  661. hr = Internal_QueryReconvertString(imc, ptim_P, (LPRECONVERTSTRING)pComp, cp, FALSE);
  662. if (SUCCEEDED(hr))
  663. return TRUE;
  664. break;
  665. }
  666. return FALSE;
  667. }
  668. //+---------------------------------------------------------------------------
  669. //
  670. // CicInputContext::GetGuidAtom
  671. //
  672. //----------------------------------------------------------------------------
  673. HRESULT
  674. CicInputContext::GetGuidAtom(
  675. IMCLock& imc,
  676. BYTE bAttr,
  677. TfGuidAtom* atom)
  678. {
  679. HRESULT hr;
  680. IMCCLock<COMPOSITIONSTRING> comp(imc->hCompStr);
  681. if (FAILED(hr=comp.GetResult()))
  682. {
  683. DebugMsg(TF_ERROR, TEXT("CicInputContext::GetGuidAtom. comp==NULL"));
  684. return hr;
  685. }
  686. if (bAttr < usGuidMapSize)
  687. {
  688. *atom = aGuidMap[bAttr];
  689. return S_OK;
  690. }
  691. return E_FAIL;
  692. }
  693. //+---------------------------------------------------------------------------
  694. //
  695. // CicInputContext::MapAttributes
  696. //
  697. //----------------------------------------------------------------------------
  698. HRESULT
  699. CicInputContext::MapAttributes(
  700. IMCLock& imc)
  701. {
  702. HRESULT hr;
  703. IMCCLock<COMPOSITIONSTRING> comp(imc->hCompStr);
  704. if (FAILED(hr=comp.GetResult()))
  705. {
  706. DebugMsg(TF_ERROR, TEXT("CicInputContext::MapAttributes. comp==NULL"));
  707. return hr;
  708. }
  709. GuidMapAttribute guid_map(GuidMapAttribute::GetData(comp));
  710. if (guid_map.Invalid())
  711. {
  712. DebugMsg(TF_ERROR, TEXT("CicInputContext::MapAttributes. guid_map==NULL"));
  713. return E_OUTOFMEMORY;
  714. }
  715. if (usGuidMapSize == 0)
  716. {
  717. //
  718. // Make transration table.
  719. //
  720. usGuidMapSize = ATTR_LAYER_GUID_START;
  721. for (USHORT i = 0; i < guid_map->dwTfGuidAtomLen; ++i)
  722. {
  723. //
  724. // Check if this GUID is already registered
  725. //
  726. for (USHORT j = ATTR_LAYER_GUID_START; j < usGuidMapSize; ++j)
  727. {
  728. if (aGuidMap[j] == ((TfGuidAtom*)guid_map.GetOffsetPointer(guid_map->dwTfGuidAtomOffset))[i])
  729. {
  730. break;
  731. }
  732. }
  733. BYTE bAttr;
  734. if (j >= usGuidMapSize)
  735. {
  736. //
  737. // Couldn't find the GUID registered.
  738. //
  739. if (usGuidMapSize < ARRAYSIZE(aGuidMap) - 1)
  740. {
  741. bAttr = static_cast<BYTE>(usGuidMapSize);
  742. aGuidMap[usGuidMapSize++] = ((TfGuidAtom*)guid_map.GetOffsetPointer(guid_map->dwTfGuidAtomOffset))[i];
  743. }
  744. else
  745. {
  746. // # of GUID exceeds the # of available attribute...
  747. // Maybe it should fail, but for now give it a bogus attirbute.
  748. bAttr = ATTR_TARGET_CONVERTED;
  749. }
  750. }
  751. else
  752. {
  753. bAttr = static_cast<BYTE>(j);
  754. }
  755. ((BYTE*)guid_map.GetOffsetPointer(guid_map->dwGuidMapAttrOffset))[i] = bAttr;
  756. }
  757. guid_map->dwGuidMapAttrLen = guid_map->dwTfGuidAtomLen;
  758. }
  759. return S_OK;
  760. }
  761. //+---------------------------------------------------------------------------
  762. //
  763. // CicInputContext::WantThisKey
  764. //
  765. //----------------------------------------------------------------------------
  766. BOOL
  767. CicInputContext::WantThisKey(
  768. UINT uVirtKey)
  769. {
  770. if (! IsTopNow())
  771. {
  772. return FALSE;
  773. }
  774. switch (BYTE(uVirtKey))
  775. {
  776. case VK_RETURN:
  777. case VK_ESCAPE:
  778. case VK_BACK:
  779. case VK_DELETE:
  780. case VK_LEFT:
  781. case VK_RIGHT:
  782. case VK_UP:
  783. case VK_DOWN:
  784. case VK_HOME:
  785. case VK_END:
  786. /*
  787. * If we don't have a composition string, then we should return FALSE.
  788. */
  789. if (m_fStartComposition.IsResetFlag())
  790. {
  791. return FALSE;
  792. }
  793. return TRUE;
  794. }
  795. return FALSE;
  796. }
  797. //+---------------------------------------------------------------------------
  798. //
  799. // OnSetCandidatePos
  800. //
  801. //----------------------------------------------------------------------------
  802. HRESULT
  803. CicInputContext::OnSetCandidatePos(
  804. TLS* ptls,
  805. IMCLock& imc)
  806. {
  807. DebugMsg(TF_FUNC, TEXT("CicBridge::OnSetCandidatePos"));
  808. RECT rcAppPosForCandidatePos = {0};
  809. RECT rcAppCandidatePos = {0};
  810. //
  811. // #510404
  812. //
  813. // check the previous candidate pos and we don't have to move them
  814. // if it is not changed.
  815. //
  816. GetWindowRect(imc->hWnd, &rcAppPosForCandidatePos);
  817. if ((imc->hWnd == m_hwndPrevCandidatePos) &&
  818. !memcmp(&rcAppPosForCandidatePos,
  819. &m_rcPrevAppPosForCandidatePos, sizeof(RECT)))
  820. {
  821. BOOL fCheckQueryCharPos = FALSE;
  822. if (!memcmp(&imc->cfCandForm[0],
  823. &m_cfPrevCandidatePos, sizeof(CANDIDATEFORM)))
  824. {
  825. LANGID langid;
  826. CicProfile* _pProfile = ptls->GetCicProfile();
  827. if (_pProfile == NULL)
  828. {
  829. DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. _pProfile==NULL."));
  830. return E_OUTOFMEMORY;
  831. }
  832. _pProfile->GetLangId(&langid);
  833. CCandidatePosition cand_pos(m_tid, m_pic, m_pLibTLS);
  834. if (SUCCEEDED(cand_pos.GetRectFromApp(imc, *this, langid, &rcAppCandidatePos)))
  835. {
  836. if (!memcmp(&rcAppCandidatePos,
  837. &m_rcPrevAppCandidatePos, sizeof(RECT)))
  838. return S_OK;
  839. }
  840. else
  841. return S_OK;
  842. }
  843. }
  844. HWND hDefImeWnd;
  845. //
  846. // When this is in the reconvert session, candidate window position is
  847. // not caret position of cfCandForm->ptCurrentPos.
  848. //
  849. if (m_fInReconvertEditSession.IsResetFlag() &&
  850. IsWindow(hDefImeWnd=ImmGetDefaultIMEWnd(NULL)) &&
  851. ptls->IsCTFUnaware() // bug:5213 WinWord
  852. // WinWord10 calls ImmSetCandidateWindow() while receive WM_LBUTTONUP.
  853. )
  854. {
  855. /*
  856. * A-Synchronize call ITfContextOwnerServices::OnLayoutChange
  857. * because this method had a protected.
  858. */
  859. PostMessage(hDefImeWnd, WM_IME_NOTIFY, IMN_PRIVATE_STARTLAYOUTCHANGE, 0);
  860. }
  861. m_hwndPrevCandidatePos = imc->hWnd;
  862. memcpy(&m_rcPrevAppPosForCandidatePos, &rcAppPosForCandidatePos, sizeof(RECT));
  863. memcpy(&m_cfPrevCandidatePos, &imc->cfCandForm[0], sizeof(CANDIDATEFORM));
  864. memcpy(&m_rcPrevAppCandidatePos, &rcAppCandidatePos, sizeof(RECT));
  865. return S_OK;
  866. }