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.

728 lines
22 KiB

  1. /*++
  2. Copyright (c) 2001, Microsoft Corporation
  3. Module Name:
  4. reconv.cpp
  5. Abstract:
  6. This file implements part of Reconversion in the CicInputContext Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #include "private.h"
  12. #include "context.h"
  13. #include "ctxtcomp.h"
  14. #include "delay.h"
  15. //+---------------------------------------------------------------------------
  16. //
  17. // CicInputContext::SetupReconvertString
  18. //
  19. //
  20. // Setup reconversion string
  21. //
  22. // This function called from
  23. // 1. CFnDocFeed::StartReconvert
  24. // 2. CStartReconversionNotifySink::StartReconversion
  25. // 3. CIMEUIWindowHandler::ImeUIMsImeHandler(WM_MSIME_RECONVERTREQUEST)
  26. //
  27. // If Cicero's text store were not cleared, then compositioning and unessential query
  28. // RECONVERTSTRING to apprication. Also edit session (ImmIfReconvertString::ReconvertString)
  29. // doesn't set RECONVERTSTRING text string to hIMC's text store.
  30. //
  31. //----------------------------------------------------------------------------
  32. HRESULT
  33. CicInputContext::SetupReconvertString(
  34. IMCLock& imc,
  35. ITfThreadMgr_P* ptim_P,
  36. UINT cp,
  37. UINT uPrivMsg, // is WM_MSIME_RECONVERTREQUEST or 0
  38. BOOL fUndoComposition)
  39. {
  40. DebugMsg(TF_FUNC, TEXT("CicInputContext::SetupReconvertString"));
  41. m_fInReconvertEditSession.SetFlag();
  42. if (m_fStartComposition.IsSetFlag())
  43. return _ReconvertStringTextStore(imc, ptim_P, uPrivMsg);
  44. else
  45. return _ReconvertStringNegotiation(imc, ptim_P, cp, uPrivMsg, fUndoComposition);
  46. }
  47. //+---------------------------------------------------------------------------
  48. //
  49. // CicInputContext::EndReconvertString
  50. //
  51. //+---------------------------------------------------------------------------
  52. HRESULT
  53. CicInputContext::EndReconvertString(
  54. IMCLock& imc)
  55. {
  56. DebugMsg(TF_FUNC, TEXT("CicInputContext::EndReconvertString"));
  57. m_fInReconvertEditSession.ResetFlag();
  58. return S_OK;
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // CicInputContext::_ReconvertStringNegotiation
  63. //
  64. //+---------------------------------------------------------------------------
  65. HRESULT
  66. CicInputContext::_ReconvertStringNegotiation(
  67. IMCLock& imc,
  68. ITfThreadMgr_P* ptim_P,
  69. UINT cp,
  70. UINT uPrivMsg,
  71. BOOL fUndoComposition)
  72. {
  73. DebugMsg(TF_FUNC, TEXT("CicInputContext::_ReconvertStringNegotiation"));
  74. RECONVERTSTRING *pReconv = NULL;
  75. HRESULT hr = E_FAIL;
  76. int nSize;
  77. UINT uReconvMsg = uPrivMsg != 0 ? uPrivMsg : WM_IME_REQUEST;
  78. Assert(IsWindow(imc->hWnd));
  79. //
  80. // We don't have to do "VK_BACK" hack for UndoComposition under AIMM12
  81. // applications.
  82. //
  83. if (!fUndoComposition || MsimtfIsWindowFiltered(imc->hWnd))
  84. {
  85. nSize = (int)SendMessageW(imc->hWnd, uReconvMsg, IMR_RECONVERTSTRING, NULL);
  86. if (!nSize)
  87. {
  88. return S_OK;
  89. }
  90. pReconv = (RECONVERTSTRING *)cicMemAllocClear(nSize);
  91. if (!pReconv)
  92. {
  93. return E_OUTOFMEMORY;
  94. }
  95. pReconv->dwSize = nSize;
  96. //
  97. // #480459
  98. //
  99. // Hanako11 may change the focus by showing MessageBox during
  100. // this SendMessageW(). We need to save the current focus
  101. // dim now. So Internal_QueryReconvertString() won't break the
  102. // current focus dim. Internal_QueryReconvertString() save the current
  103. // focus dim in there to work with temp DIM.
  104. //
  105. Interface<ITfDocumentMgr> priv_dim;
  106. if (FAILED(hr = ptim_P->GetFocus(priv_dim)))
  107. {
  108. return hr;
  109. }
  110. hr = S_OK;
  111. if (SendMessageW(imc->hWnd, uReconvMsg, IMR_RECONVERTSTRING, (LPARAM)pReconv) ||
  112. (uPrivMsg != 0 && pReconv->dwCompStrLen > 0))
  113. {
  114. //
  115. // NT4 and Win2K doesn't have thunk routine of WM_IME_REQUEST message.
  116. // Any string data doesn't convert between ASCII <--> Unicode.
  117. // Responsibility of string data type have receiver window proc (imc->hWnd) of this message.
  118. // If ASCII wnd proc, then returns ASCII string.
  119. // Otherwise if Unicode wnd proc, returns Unicode string.
  120. //
  121. BOOL fNeedAW = ( !(IsWindowUnicode(imc->hWnd)) && uPrivMsg == 0);
  122. //
  123. // backup RECOVNERTSTRING in case IMR_CONFIRMCONVERTSTRING fails.
  124. //
  125. RECONVERTSTRING rsBackUp;
  126. memcpy(&rsBackUp, pReconv, sizeof(RECONVERTSTRING));
  127. // AdjustZeroCompLenReconvertString(pReconv, cp, fNeedAW);
  128. hr = Internal_QueryReconvertString(imc, ptim_P, pReconv, cp, fNeedAW);
  129. if (FAILED(hr))
  130. goto Exit;
  131. if (!SendMessageW(imc->hWnd, uReconvMsg, IMR_CONFIRMRECONVERTSTRING, (LPARAM)pReconv))
  132. {
  133. memcpy(pReconv, &rsBackUp, sizeof(RECONVERTSTRING));
  134. }
  135. CWReconvertString wReconvStr(imc,
  136. !fNeedAW ? pReconv : NULL,
  137. !fNeedAW ? nSize : 0);
  138. if (fNeedAW)
  139. {
  140. //
  141. // convert Ansi to Unicode.
  142. //
  143. CBReconvertString bReconvStr(imc, pReconv, nSize);
  144. bReconvStr.SetCodePage(cp);
  145. wReconvStr = bReconvStr;
  146. }
  147. hr = MakeReconversionFuncCall(imc, ptim_P, wReconvStr, (uPrivMsg != 0));
  148. }
  149. ptim_P->SetFocus(priv_dim);
  150. }
  151. else
  152. {
  153. //
  154. // release control and shift keys. So the application can handle
  155. // VK_BACK corectly.
  156. //
  157. if (GetKeyState(VK_CONTROL) & 0x8000)
  158. keybd_event((BYTE)VK_CONTROL, (BYTE)0, KEYEVENTF_KEYUP, 0);
  159. if (GetKeyState(VK_SHIFT) & 0x8000)
  160. keybd_event((BYTE)VK_SHIFT, (BYTE)0, KEYEVENTF_KEYUP, 0);
  161. //
  162. // Generate VK_BACK key events.
  163. //
  164. int i;
  165. for (i = 0; i < m_PrevResultStr.GetSize(); i++)
  166. {
  167. keybd_event((BYTE)VK_BACK, (BYTE)0, 0, 0);
  168. keybd_event((BYTE)VK_BACK, (BYTE)0, KEYEVENTF_KEYUP, 0);
  169. }
  170. //
  171. // SendMessage() to start a timer for DelayedReconvertFuncCall.
  172. //
  173. HWND hDefImeWnd;
  174. if (IsWindow(hDefImeWnd=ImmGetDefaultIMEWnd(NULL)))
  175. SendMessage(hDefImeWnd,
  176. WM_IME_NOTIFY,
  177. IMN_PRIVATE_DELAYRECONVERTFUNCCALL,
  178. 0);
  179. }
  180. Exit:
  181. if (pReconv)
  182. cicMemFree(pReconv);
  183. return hr;
  184. }
  185. //+---------------------------------------------------------------------------
  186. //
  187. // CicInputContext::DelayedReconversionFuncCall
  188. //
  189. //+---------------------------------------------------------------------------
  190. HRESULT
  191. CicInputContext::DelayedReconvertFuncCall(IMCLock &imc)
  192. {
  193. RECONVERTSTRING *pReconv;
  194. HRESULT hr;
  195. int nSize;
  196. TLS* ptls = TLS::GetTLS();
  197. if (ptls == NULL)
  198. {
  199. DebugMsg(TF_ERROR, TEXT("CicInputContext::UndoReconvertFuncCall. ptls==NULL."));
  200. return S_FALSE;
  201. }
  202. ITfThreadMgr_P* ptim_P = ptls->GetTIM();
  203. if (ptim_P == NULL)
  204. {
  205. DebugMsg(TF_ERROR, TEXT("CicInputContext::UndoReconvertFuncCall. ptim_P==NULL"));
  206. return S_FALSE;
  207. }
  208. ptim_P->RequestPostponedLock(GetInputContext());
  209. nSize = sizeof(RECONVERTSTRING);
  210. nSize += (m_PrevResultStr.GetSize() + 1) * sizeof(WCHAR);
  211. pReconv = (RECONVERTSTRING *)cicMemAllocClear(nSize);
  212. if (!pReconv)
  213. {
  214. return E_OUTOFMEMORY;
  215. }
  216. pReconv->dwSize = (DWORD)nSize;
  217. pReconv->dwVersion = 1;
  218. pReconv->dwStrLen =
  219. pReconv->dwCompStrLen =
  220. pReconv->dwTargetStrLen = (DWORD)m_PrevResultStr.GetSize();
  221. pReconv->dwStrOffset = sizeof(RECONVERTSTRING);
  222. pReconv->dwCompStrOffset =
  223. pReconv->dwTargetStrOffset = 0;
  224. memcpy(((BYTE *)pReconv) + sizeof(RECONVERTSTRING),
  225. (void *)m_PrevResultStr,
  226. m_PrevResultStr.GetSize() * sizeof(WCHAR));
  227. CWReconvertString wReconvStr(imc, pReconv, nSize);
  228. BOOL fInReconvertEditSession;
  229. fInReconvertEditSession = m_fInReconvertEditSession.IsSetFlag();
  230. if (!fInReconvertEditSession)
  231. m_fInReconvertEditSession.SetFlag();
  232. hr = MakeReconversionFuncCall(imc, ptim_P, wReconvStr, TRUE);
  233. if (!fInReconvertEditSession)
  234. m_fInReconvertEditSession.ResetFlag();
  235. if (pReconv)
  236. cicMemFree(pReconv);
  237. return hr;
  238. }
  239. //+---------------------------------------------------------------------------
  240. //
  241. // CicInputContext::MakeReconversionFuncCall
  242. //
  243. //+---------------------------------------------------------------------------
  244. HRESULT
  245. CicInputContext::MakeReconversionFuncCall(
  246. IMCLock& imc,
  247. ITfThreadMgr_P* ptim_P,
  248. CWReconvertString &wReconvStr,
  249. BOOL fCallFunc)
  250. {
  251. HRESULT hr;
  252. Interface<ITfRange> Selection;
  253. hr = EscbReconvertString(imc, &wReconvStr, &Selection, FALSE);
  254. if (S_OK == hr && fCallFunc)
  255. {
  256. Interface<ITfFunctionProvider> FuncProv;
  257. Interface<ITfFnReconversion> Reconversion;
  258. hr = ptim_P->GetFunctionProvider(GUID_SYSTEM_FUNCTIONPROVIDER, FuncProv);
  259. if (S_OK == hr)
  260. {
  261. hr = FuncProv->GetFunction(GUID_NULL,
  262. IID_ITfFnReconversion,
  263. (IUnknown**)(ITfFnReconversion**)Reconversion);
  264. }
  265. if (S_OK == hr) {
  266. Interface<ITfRange> RangeNew;
  267. BOOL fConvertable;
  268. hr = Reconversion->QueryRange(Selection, RangeNew, &fConvertable);
  269. if (SUCCEEDED(hr) && fConvertable) {
  270. hr = Reconversion->Reconvert(RangeNew);
  271. }
  272. else {
  273. EscbCompComplete(imc);
  274. }
  275. }
  276. }
  277. return hr;
  278. }
  279. //+---------------------------------------------------------------------------
  280. //
  281. // CicInputContext::_ReconvertStringTextStore
  282. //
  283. //+---------------------------------------------------------------------------
  284. HRESULT
  285. CicInputContext::_ReconvertStringTextStore(
  286. IMCLock& imc,
  287. ITfThreadMgr_P* ptim_P,
  288. UINT uPrivMsg)
  289. {
  290. DebugMsg(TF_FUNC, TEXT("CicInputContext::_ReconvertStringTextStore"));
  291. //
  292. // Clear DocFeed buffer
  293. //
  294. EscbClearDocFeedBuffer(imc);
  295. if (uPrivMsg != 0) {
  296. HRESULT hr;
  297. Interface<ITfRange> Selection;
  298. hr = EscbGetSelection(imc, &Selection);
  299. if (S_OK == hr)
  300. {
  301. Interface<ITfFunctionProvider> FuncProv;
  302. Interface<ITfFnReconversion> Reconversion;
  303. hr = ptim_P->GetFunctionProvider(GUID_SYSTEM_FUNCTIONPROVIDER, FuncProv);
  304. if (S_OK == hr)
  305. {
  306. hr = FuncProv->GetFunction(GUID_NULL,
  307. IID_ITfFnReconversion,
  308. (IUnknown**)(ITfFnReconversion**)Reconversion);
  309. }
  310. if (S_OK == hr) {
  311. Interface<ITfRange> RangeNew;
  312. BOOL fConvertable;
  313. hr = Reconversion->QueryRange(Selection, RangeNew, &fConvertable);
  314. if (SUCCEEDED(hr) && fConvertable) {
  315. hr = Reconversion->Reconvert(RangeNew);
  316. }
  317. else {
  318. EscbCompComplete(imc);
  319. return E_FAIL;
  320. }
  321. }
  322. }
  323. }
  324. return S_OK;
  325. }
  326. //+---------------------------------------------------------------------------
  327. //
  328. // CicInputContext::Internal_QueryReconvertString_ICOwnerSink
  329. //
  330. //+---------------------------------------------------------------------------
  331. // static
  332. HRESULT
  333. CicInputContext::Internal_QueryReconvertString_ICOwnerSink(
  334. UINT uCode,
  335. ICOARGS *pargs,
  336. VOID *pv)
  337. {
  338. DebugMsg(TF_FUNC, TEXT("CicInputContext::Internal_QueryReconvertString_ICOwnerSink"));
  339. switch (uCode)
  340. {
  341. case ICO_STATUS:
  342. pargs->status.pdcs->dwDynamicFlags = 0;
  343. pargs->status.pdcs->dwStaticFlags = TF_SS_TRANSITORY;
  344. break;
  345. }
  346. return S_OK;
  347. }
  348. //+---------------------------------------------------------------------------
  349. //
  350. // CicInputContext::Internal_QueryReconvertString
  351. //
  352. //+---------------------------------------------------------------------------
  353. HRESULT
  354. CicInputContext::Internal_QueryReconvertString(
  355. IMCLock& imc,
  356. ITfThreadMgr_P* ptim_P, // using private for RequestPostponedLock
  357. RECONVERTSTRING *pReconv,
  358. UINT cp,
  359. BOOL fNeedAW)
  360. {
  361. DebugMsg(TF_FUNC, TEXT("CicInputContext::Internal_QueryReconvertString"));
  362. HRESULT hr;
  363. CWReconvertString wReconvStr(imc,
  364. !fNeedAW ? pReconv : NULL,
  365. !fNeedAW ? pReconv->dwSize : 0);
  366. if (fNeedAW)
  367. {
  368. //
  369. // convert Ansi to Unicode.
  370. //
  371. CBReconvertString bReconvStr(imc, pReconv, pReconv->dwSize);
  372. bReconvStr.SetCodePage(cp);
  373. wReconvStr = bReconvStr;
  374. }
  375. //
  376. // Create document manager.
  377. //
  378. Interface<ITfDocumentMgr> pdim; // Document Manager
  379. if (FAILED(hr = ptim_P->CreateDocumentMgr(pdim)))
  380. return hr;
  381. //
  382. // Create input context
  383. //
  384. Interface<ITfContext> pic; // Input Context
  385. TfEditCookie ecTmp;
  386. hr = pdim->CreateContext(m_tid, 0, NULL, pic, &ecTmp);
  387. if (FAILED(hr))
  388. return hr;
  389. //
  390. // associate CicInputContext in PIC.
  391. //
  392. Interface<IUnknown> punk;
  393. if (SUCCEEDED(QueryInterface(IID_IUnknown, punk))) {
  394. SetCompartmentUnknown(m_tid, pic,
  395. GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT,
  396. punk);
  397. }
  398. //
  399. // Create Input Context Owner Callback
  400. //
  401. CInputContextOwner *_pICOwnerSink; // IC owner call back
  402. _pICOwnerSink = new CInputContextOwner(Internal_QueryReconvertString_ICOwnerSink, NULL);
  403. if (_pICOwnerSink == NULL) {
  404. DebugMsg(TF_ERROR, TEXT("Couldn't create ICOwnerSink tim!"));
  405. Assert(0); // couldn't activate thread!
  406. return E_FAIL;
  407. }
  408. //
  409. // Advise IC.
  410. //
  411. _pICOwnerSink->_Advise(pic);
  412. //
  413. // Push IC.
  414. //
  415. hr = pdim->Push(pic);
  416. if (SUCCEEDED(hr)) {
  417. Interface<ITfDocumentMgr> priv_dim;
  418. if (SUCCEEDED(hr=ptim_P->GetFocus(priv_dim)) &&
  419. SUCCEEDED(hr=ptim_P->SetFocus(pdim)))
  420. {
  421. Interface_Attach<ITfContext> _pic(pic);
  422. Interface<ITfRange> Selection;
  423. hr = EscbQueryReconvertString(imc, _pic, &wReconvStr, &Selection);
  424. if (S_OK == hr)
  425. {
  426. Interface<ITfFunctionProvider> FuncProv;
  427. Interface<ITfFnReconversion> Reconversion;
  428. hr = ptim_P->GetFunctionProvider(GUID_SYSTEM_FUNCTIONPROVIDER, FuncProv);
  429. if (S_OK == hr)
  430. {
  431. hr = FuncProv->GetFunction(GUID_NULL,
  432. IID_ITfFnReconversion,
  433. (IUnknown**)(ITfFnReconversion**)Reconversion);
  434. }
  435. if (S_OK == hr) {
  436. Interface<ITfRange> RangeNew;
  437. BOOL fConvertable;
  438. hr = Reconversion->QueryRange(Selection, RangeNew, &fConvertable);
  439. if (SUCCEEDED(hr) && fConvertable) {
  440. //
  441. // Calcurate start position of RangeNew on text store
  442. //
  443. hr = EscbCalcRangePos(imc, _pic, &wReconvStr, &RangeNew);
  444. }
  445. else {
  446. hr = E_FAIL;
  447. }
  448. }
  449. }
  450. }
  451. if (S_OK == hr)
  452. {
  453. if (fNeedAW) {
  454. //
  455. // Back to convert Unicode to Ansi.
  456. //
  457. CBReconvertString bReconvStr(imc, NULL, 0);
  458. wReconvStr.SetCodePage(cp);
  459. bReconvStr = wReconvStr;
  460. bReconvStr.ReadCompData(pReconv, pReconv->dwSize);
  461. }
  462. else {
  463. wReconvStr.ReadCompData(pReconv, pReconv->dwSize);
  464. }
  465. }
  466. ptim_P->SetFocus(priv_dim);
  467. ptim_P->RequestPostponedLock(pic);
  468. ptim_P->RequestPostponedLock(GetInputContext());
  469. pdim->Pop(TF_POPF_ALL);
  470. //
  471. // un-associate CicInputContext in PIC.
  472. //
  473. Interface<IUnknown> punk;
  474. if (SUCCEEDED(QueryInterface(IID_IUnknown, punk))) {
  475. ClearCompartment(m_tid, pic,
  476. GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT,
  477. FALSE);
  478. }
  479. }
  480. // ic owner is auto unadvised during the Pop by cicero
  481. // in any case, it must not be unadvised before the pop
  482. // since it will be used to handle mouse sinks, etc.
  483. if (_pICOwnerSink) {
  484. _pICOwnerSink->_Unadvise();
  485. _pICOwnerSink->Release();
  486. _pICOwnerSink = NULL;
  487. }
  488. return hr;
  489. }
  490. //+---------------------------------------------------------------------------
  491. //
  492. // CicInputContext::Internal_ReconvertString
  493. //
  494. //+---------------------------------------------------------------------------
  495. HRESULT
  496. CicInputContext::Internal_ReconvertString(
  497. IMCLock& imc,
  498. ITfThreadMgr_P* ptim_P,
  499. CWReconvertString& wReconvStr,
  500. CWReconvertString& wReconvReadStr)
  501. {
  502. DebugMsg(TF_FUNC, TEXT("CicInputContext::Internal_ResonvertString"));
  503. m_fInReconvertEditSession.SetFlag();
  504. Interface<ITfRange> Selection;
  505. Interface<ITfFunctionProvider> FuncProv;
  506. Interface<ITfFnReconversion> Reconversion;
  507. HRESULT hr;
  508. hr = EscbReconvertString(imc, &wReconvStr, &Selection, FALSE);
  509. if (FAILED(hr))
  510. {
  511. DebugMsg(TF_ERROR, TEXT("CicInputContext::Internal_ResonvertString. EscbReconvertString fail."));
  512. goto Exit;
  513. }
  514. hr = ptim_P->GetFunctionProvider(GUID_SYSTEM_FUNCTIONPROVIDER, FuncProv);
  515. if (FAILED(hr))
  516. {
  517. DebugMsg(TF_ERROR, TEXT("CicInputContext::Internal_ResonvertString. FuncProv==NULL"));
  518. goto Exit;
  519. }
  520. hr = FuncProv->GetFunction(GUID_NULL,
  521. IID_ITfFnReconversion,
  522. (IUnknown**)(ITfFnReconversion**)Reconversion);
  523. if (SUCCEEDED(hr)) {
  524. Interface<ITfRange> RangeNew;
  525. BOOL fConvertable;
  526. hr = Reconversion->QueryRange(Selection, RangeNew, &fConvertable);
  527. if (SUCCEEDED(hr) && fConvertable) {
  528. hr = Reconversion->Reconvert(RangeNew);
  529. }
  530. else {
  531. DebugMsg(TF_ERROR, TEXT("CicInputContext::Internal_ReconvertString: QueryRange failed so the compoisiton stri ng will be completed."));
  532. EscbCompComplete(imc);
  533. hr = E_FAIL;
  534. }
  535. }
  536. Exit:
  537. m_fInReconvertEditSession.ResetFlag();
  538. return hr;
  539. }
  540. //+---------------------------------------------------------------------------
  541. //
  542. // CicInputContext::Internal_SetCompositionString
  543. //
  544. //+---------------------------------------------------------------------------
  545. HRESULT
  546. CicInputContext::Internal_SetCompositionString(
  547. IMCLock& imc,
  548. CWCompString& wCompStr,
  549. CWCompString& wCompReadStr)
  550. {
  551. DebugMsg(TF_FUNC, TEXT("CicInputContext::Internal_SetCompositionString"));
  552. HRESULT hr;
  553. hr = EscbReplaceWholeText(imc, &wCompStr);
  554. if (FAILED(hr))
  555. return hr;
  556. return EscbUpdateCompositionString(imc);
  557. }
  558. //+---------------------------------------------------------------------------
  559. //
  560. // CicInputContext::SetupDocFeedString
  561. //
  562. //+---------------------------------------------------------------------------
  563. HRESULT
  564. CicInputContext::SetupDocFeedString(
  565. IMCLock& imc,
  566. UINT cp)
  567. {
  568. DebugMsg(TF_FUNC, TEXT("CicInputContext::SetupDocFeedString"));
  569. RECONVERTSTRING *pReconv = NULL;
  570. HRESULT hr = E_FAIL;
  571. int nSize;
  572. Assert(IsWindow(imc->hWnd));
  573. nSize = (int)SendMessageW(imc->hWnd, WM_IME_REQUEST, IMR_DOCUMENTFEED, NULL);
  574. if (!nSize)
  575. {
  576. return S_OK;
  577. }
  578. pReconv = (RECONVERTSTRING *)cicMemAllocClear(nSize);
  579. if (!pReconv)
  580. {
  581. return E_OUTOFMEMORY;
  582. }
  583. if (SendMessageW(imc->hWnd, WM_IME_REQUEST, IMR_DOCUMENTFEED, (LPARAM)pReconv))
  584. {
  585. Interface<ITfRange> Selection;
  586. //
  587. // NT4 and Win2K doesn't have thunk routine of WM_IME_REQUEST message.
  588. // Any string data doesn't convert between ASCII <--> Unicode.
  589. // Responsibility of string data type have receiver window proc (imc->hWnd) of this message.
  590. // If ASCII wnd proc, then returns ASCII string.
  591. // Otherwise if Unicode wnd proc, returns Unicode string.
  592. //
  593. BOOL fNeedAW = !(IsWindowUnicode(imc->hWnd));
  594. CWReconvertString wReconvStr(imc,
  595. !fNeedAW ? pReconv : NULL,
  596. !fNeedAW ? nSize : 0);
  597. if (fNeedAW)
  598. {
  599. //
  600. // convert Ansi to Unicode.
  601. //
  602. CBReconvertString bReconvStr(imc, pReconv, nSize);
  603. bReconvStr.SetCodePage(cp);
  604. wReconvStr = bReconvStr;
  605. }
  606. hr = EscbReconvertString(imc, &wReconvStr, &Selection, TRUE);
  607. }
  608. if (pReconv)
  609. cicMemFree(pReconv);
  610. return hr;
  611. }