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.

2638 lines
80 KiB

  1. /**************************************************************************\
  2. * Module Name: jtranmsg.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains all the code for the Japanese translation subroutine.
  7. *
  8. * History:
  9. * 15-Aug-1995 kazum
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. UINT
  14. JTransCompositionA(
  15. LPINPUTCONTEXT lpIMC,
  16. LPCOMPOSITIONSTRING lpCompStrA,
  17. PTRANSMSG pTransMsgSrc,
  18. PTRANSMSG pTransMsgDest
  19. );
  20. UINT
  21. JTransCompositionW(
  22. LPINPUTCONTEXT lpIMC,
  23. LPCOMPOSITIONSTRING lpCompStrW,
  24. PTRANSMSG pTransMsgSrc,
  25. PTRANSMSG pTransMsgDest
  26. );
  27. DWORD
  28. CompStrWToUndetW(
  29. DWORD dwGCS,
  30. LPCOMPOSITIONSTRING lpCompStrW,
  31. LPUNDETERMINESTRUCT lpUndetW
  32. );
  33. DWORD
  34. CompStrWToUndetA(
  35. DWORD dwGCS,
  36. LPCOMPOSITIONSTRING lpCompStrW,
  37. LPUNDETERMINESTRUCT lpUndetA
  38. );
  39. DWORD
  40. CompStrWToStringExW(
  41. DWORD dwGCS,
  42. LPCOMPOSITIONSTRING lpCompStrW,
  43. LPSTRINGEXSTRUCT lpStringExW
  44. );
  45. DWORD
  46. CompStrWToStringExA(
  47. DWORD dwGCS,
  48. LPCOMPOSITIONSTRING lpCompStrW,
  49. LPSTRINGEXSTRUCT lpStringExA
  50. );
  51. DWORD
  52. CompStrWToStringW(
  53. LPCOMPOSITIONSTRING lpCompStrW,
  54. LPWSTR lpStringW
  55. );
  56. DWORD
  57. CompStrWToStringA(
  58. LPCOMPOSITIONSTRING lpCompStrW,
  59. LPSTR lpStringA
  60. );
  61. VOID
  62. CompStrWToCharW(
  63. HWND hWnd,
  64. LPCOMPOSITIONSTRING lpCompStrW
  65. );
  66. VOID
  67. CompStrWToCharA(
  68. HWND hWnd,
  69. LPCOMPOSITIONSTRING lpCompStrW
  70. );
  71. DWORD
  72. CompStrAToUndetA(
  73. DWORD dwGCS,
  74. LPCOMPOSITIONSTRING lpCompStrA,
  75. LPUNDETERMINESTRUCT lpUndetA,
  76. DWORD dwUndetABufferSize
  77. );
  78. DWORD
  79. CompStrAToUndetW(
  80. DWORD dwGCS,
  81. LPCOMPOSITIONSTRING lpCompStrA,
  82. LPUNDETERMINESTRUCT lpUndetW,
  83. DWORD dwUndetWBufferSize
  84. );
  85. DWORD
  86. CompStrAToStringExA(
  87. DWORD dwGCS,
  88. LPCOMPOSITIONSTRING lpCompStrA,
  89. LPSTRINGEXSTRUCT lpStringExA,
  90. DWORD dwStringExABufferSize
  91. );
  92. DWORD
  93. CompStrAToStringExW(
  94. DWORD dwGCS,
  95. LPCOMPOSITIONSTRING lpCompStrA,
  96. LPSTRINGEXSTRUCT lpStringExW,
  97. DWORD dwStringExWBufferSize
  98. );
  99. DWORD
  100. CompStrAToStringA(
  101. LPCOMPOSITIONSTRING lpCompStrA,
  102. LPSTR lpStringA,
  103. DWORD dwStringABufferSize
  104. );
  105. DWORD
  106. CompStrAToStringW(
  107. LPCOMPOSITIONSTRING lpCompStrA,
  108. LPWSTR lpStringW,
  109. DWORD dwStringWBufferSize
  110. );
  111. VOID
  112. CompStrAToCharA(
  113. HWND hWnd,
  114. LPCOMPOSITIONSTRING lpCompStrA
  115. );
  116. VOID
  117. CompStrAToCharW(
  118. HWND hWnd,
  119. LPCOMPOSITIONSTRING lpCompStrA
  120. );
  121. UINT
  122. JTransCompositionA(
  123. LPINPUTCONTEXT lpIMC,
  124. LPCOMPOSITIONSTRING lpCompStrA,
  125. PTRANSMSG pTransMsgSrc,
  126. PTRANSMSG pTransMsgDest
  127. )
  128. {
  129. UINT i = 0;
  130. int iNum = 0;
  131. DWORD dwSize;
  132. HWND hWnd;
  133. WORD wTextLen = 0;
  134. BOOL fDoneUndet = FALSE;
  135. BOOL fDoneDet = FALSE;
  136. DWORD dwGCS;
  137. BOOL bAnsiWnd;
  138. hWnd = (HWND)lpIMC->hWnd;
  139. if (!IsWindow(hWnd))
  140. return 0;
  141. bAnsiWnd = (! IsWindowUnicode(hWnd)) ? TRUE : FALSE;
  142. dwGCS = (DWORD)pTransMsgSrc->lParam;
  143. if (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN)
  144. {
  145. if (bAnsiWnd) {
  146. dwSize = CompStrAToUndetA(dwGCS, lpCompStrA, NULL, 0);
  147. if (dwSize != 0) {
  148. HGLOBAL hUndetA = NULL;
  149. LPUNDETERMINESTRUCT lpUndetA;
  150. if (hUndetA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  151. if (lpUndetA = (LPUNDETERMINESTRUCT)GlobalLock(hUndetA)) {
  152. if (CompStrAToUndetA(dwGCS, lpCompStrA, lpUndetA, dwSize)) {
  153. fDoneUndet = TRUE;
  154. GlobalUnlock(hUndetA);
  155. if (SendMessageA(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetA)) {
  156. GlobalFree(hUndetA);
  157. return 0;
  158. }
  159. }
  160. else
  161. GlobalUnlock(hUndetA);
  162. }
  163. GlobalFree(hUndetA);
  164. }
  165. }
  166. }
  167. else {
  168. dwSize = CompStrAToUndetW(dwGCS, lpCompStrA, NULL, 0);
  169. if (dwSize != 0) {
  170. HGLOBAL hUndetW = NULL;
  171. LPUNDETERMINESTRUCT lpUndetW;
  172. if (hUndetW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  173. if (lpUndetW = (LPUNDETERMINESTRUCT)GlobalLock(hUndetW)) {
  174. if (CompStrAToUndetW(dwGCS, lpCompStrA, lpUndetW, dwSize)) {
  175. fDoneUndet = TRUE;
  176. GlobalUnlock(hUndetW);
  177. if (SendMessageW(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetW)) {
  178. GlobalFree(hUndetW);
  179. return 0;
  180. }
  181. }
  182. else
  183. GlobalUnlock(hUndetW);
  184. }
  185. GlobalFree(hUndetW);
  186. }
  187. }
  188. }
  189. }
  190. //
  191. // This is generate result string routine.
  192. // This should be same as WINNLSSendString of WIN3.1.
  193. //
  194. if (dwGCS & GCS_RESULTSTR)
  195. {
  196. //
  197. // Can we generate IR_STRINGEX ?
  198. //
  199. if (dwGCS & GCS_RESULTREADSTR)
  200. {
  201. if (bAnsiWnd) {
  202. dwSize = CompStrAToStringExA(dwGCS, lpCompStrA, NULL, 0);
  203. if (dwSize != 0) {
  204. HGLOBAL hStringExA = NULL;
  205. LPSTRINGEXSTRUCT lpStringExA;
  206. if (hStringExA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  207. if (lpStringExA = (LPSTRINGEXSTRUCT)GlobalLock(hStringExA)) {
  208. if (CompStrAToStringExA(dwGCS, lpCompStrA, lpStringExA, dwSize)) {
  209. GlobalUnlock(hStringExA);
  210. if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExA))
  211. {
  212. GlobalFree(hStringExA);
  213. fDoneDet = TRUE;
  214. goto jtc_exit_30;
  215. }
  216. }
  217. else
  218. GlobalUnlock(hStringExA);
  219. }
  220. GlobalFree(hStringExA);
  221. }
  222. }
  223. }
  224. else {
  225. dwSize = CompStrAToStringExW(dwGCS, lpCompStrA, NULL, 0);
  226. if (dwSize != 0) {
  227. HGLOBAL hStringExW = NULL;
  228. LPSTRINGEXSTRUCT lpStringExW;
  229. if (hStringExW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  230. if (lpStringExW = (LPSTRINGEXSTRUCT)GlobalLock(hStringExW)) {
  231. if (CompStrAToStringExW(dwGCS, lpCompStrA, lpStringExW, dwSize)) {
  232. GlobalUnlock(hStringExW);
  233. if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExW))
  234. {
  235. GlobalFree(hStringExW);
  236. fDoneDet = TRUE;
  237. goto jtc_exit_30;
  238. }
  239. }
  240. else
  241. GlobalUnlock(hStringExW);
  242. }
  243. GlobalFree(hStringExW);
  244. }
  245. }
  246. }
  247. }
  248. //
  249. // generate IR_STRING
  250. //
  251. if (bAnsiWnd) {
  252. dwSize = CompStrAToStringA(lpCompStrA, NULL, 0);
  253. if (dwSize != 0) {
  254. HGLOBAL hStringA = NULL;
  255. LPSTR lpStringA;
  256. if (hStringA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  257. if (lpStringA = (LPSTR)GlobalLock(hStringA)) {
  258. if (CompStrAToStringA(lpCompStrA, lpStringA, dwSize)) {
  259. GlobalUnlock(hStringA);
  260. if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringA))
  261. {
  262. GlobalFree(hStringA);
  263. fDoneDet = TRUE;
  264. goto jtc_exit_30;
  265. }
  266. }
  267. else
  268. GlobalUnlock(hStringA);
  269. }
  270. GlobalFree(hStringA);
  271. }
  272. }
  273. else {
  274. return 0;
  275. }
  276. }
  277. else {
  278. dwSize = CompStrAToStringW(lpCompStrA, NULL, 0);
  279. if (dwSize != 0) {
  280. HGLOBAL hStringW = NULL;
  281. LPWSTR lpStringW;
  282. if (hStringW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  283. if (lpStringW = (LPWSTR)GlobalLock(hStringW)) {
  284. if (CompStrAToStringW(lpCompStrA, lpStringW, dwSize)) {
  285. GlobalUnlock(hStringW);
  286. if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringW))
  287. {
  288. GlobalFree(hStringW);
  289. fDoneDet = TRUE;
  290. goto jtc_exit_30;
  291. }
  292. }
  293. else
  294. GlobalUnlock(hStringW);
  295. }
  296. GlobalFree(hStringW);
  297. }
  298. }
  299. else {
  300. return 0;
  301. }
  302. }
  303. //
  304. // generate IR_DBCSCHAR/IR_STRINGSTART/WM_CHAR/IR_STRINGEND
  305. //
  306. if (bAnsiWnd) {
  307. CompStrAToCharA(hWnd, lpCompStrA);
  308. }
  309. else {
  310. CompStrAToCharW(hWnd, lpCompStrA);
  311. }
  312. fDoneDet = TRUE;
  313. }
  314. if (!fDoneUndet && !fDoneDet)
  315. {
  316. *pTransMsgDest = *pTransMsgSrc;
  317. iNum++;
  318. }
  319. jtc_exit_30:
  320. if (!fDoneUndet && fDoneDet && (dwGCS & GCS_COMPSTR))
  321. {
  322. pTransMsgDest->message = pTransMsgSrc->message;
  323. pTransMsgDest->wParam = pTransMsgSrc->wParam;
  324. pTransMsgDest->lParam = (LPARAM)(dwGCS & ~(GCS_RESULT | GCS_RESULTREAD));
  325. iNum++;
  326. }
  327. return iNum;
  328. }
  329. UINT
  330. JTransCompositionW(
  331. LPINPUTCONTEXT lpIMC,
  332. LPCOMPOSITIONSTRING lpCompStrW,
  333. PTRANSMSG pTransMsgSrc,
  334. PTRANSMSG pTransMsgDest
  335. )
  336. {
  337. UINT i = 0;
  338. int iNum = 0;
  339. DWORD dwSize;
  340. HWND hWnd;
  341. WORD wTextLen = 0;
  342. BOOL fDoneUndet = FALSE;
  343. BOOL fDoneDet = FALSE;
  344. DWORD dwGCS;
  345. BOOL bAnsiWnd;
  346. hWnd = (HWND)lpIMC->hWnd;
  347. if (!IsWindow(hWnd))
  348. return 0;
  349. bAnsiWnd = (! IsWindowUnicode(hWnd)) ? TRUE : FALSE;
  350. dwGCS = (DWORD)pTransMsgSrc->lParam;
  351. if (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN)
  352. {
  353. if (bAnsiWnd) {
  354. dwSize = CompStrWToUndetA(dwGCS, lpCompStrW, NULL);
  355. if (dwSize != 0) {
  356. HGLOBAL hUndetA = NULL;
  357. LPUNDETERMINESTRUCT lpUndetA;
  358. if (hUndetA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  359. if (lpUndetA = (LPUNDETERMINESTRUCT)GlobalLock(hUndetA)) {
  360. CompStrWToUndetA(dwGCS, lpCompStrW, lpUndetA);
  361. fDoneUndet = TRUE;
  362. GlobalUnlock(hUndetA);
  363. if (SendMessageA(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetA)) {
  364. GlobalFree(hUndetA);
  365. return 0;
  366. }
  367. }
  368. GlobalFree(hUndetA);
  369. }
  370. }
  371. }
  372. else {
  373. dwSize = CompStrWToUndetW(dwGCS, lpCompStrW, NULL);
  374. if (dwSize != 0) {
  375. HGLOBAL hUndetW = NULL;
  376. LPUNDETERMINESTRUCT lpUndetW;
  377. if (hUndetW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  378. if (lpUndetW = (LPUNDETERMINESTRUCT)GlobalLock(hUndetW)) {
  379. CompStrWToUndetW(dwGCS, lpCompStrW, lpUndetW);
  380. fDoneUndet = TRUE;
  381. GlobalUnlock(hUndetW);
  382. if (SendMessageW(hWnd,WM_IME_REPORT,IR_UNDETERMINE, (LPARAM)hUndetW)) {
  383. GlobalFree(hUndetW);
  384. return 0;
  385. }
  386. }
  387. GlobalFree(hUndetW);
  388. }
  389. }
  390. }
  391. }
  392. //
  393. // This is generate result string routine.
  394. // This should be same as WINNLSSendString of WIN3.1.
  395. //
  396. if (dwGCS & GCS_RESULTSTR)
  397. {
  398. //
  399. // Can we generate IR_STRINGEX ?
  400. //
  401. if (dwGCS & GCS_RESULTREADSTR)
  402. {
  403. if (bAnsiWnd) {
  404. dwSize = CompStrWToStringExA(dwGCS, lpCompStrW, NULL);
  405. if (dwSize != 0) {
  406. HGLOBAL hStringExA = NULL;
  407. LPSTRINGEXSTRUCT lpStringExA;
  408. if (hStringExA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  409. if (lpStringExA = (LPSTRINGEXSTRUCT)GlobalLock(hStringExA)) {
  410. CompStrWToStringExA(dwGCS, lpCompStrW, lpStringExA);
  411. GlobalUnlock(hStringExA);
  412. if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExA))
  413. {
  414. GlobalFree(hStringExA);
  415. fDoneDet = TRUE;
  416. goto jtc_exit_30;
  417. }
  418. }
  419. GlobalFree(hStringExA);
  420. }
  421. }
  422. }
  423. else {
  424. dwSize = CompStrWToStringExW(dwGCS, lpCompStrW, NULL);
  425. if (dwSize != 0) {
  426. HGLOBAL hStringExW = NULL;
  427. LPSTRINGEXSTRUCT lpStringExW;
  428. if (hStringExW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  429. if (lpStringExW = (LPSTRINGEXSTRUCT)GlobalLock(hStringExW)) {
  430. CompStrWToStringExW(dwGCS, lpCompStrW, lpStringExW);
  431. GlobalUnlock(hStringExW);
  432. if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRINGEX, (LPARAM)hStringExW))
  433. {
  434. GlobalFree(hStringExW);
  435. fDoneDet = TRUE;
  436. goto jtc_exit_30;
  437. }
  438. }
  439. GlobalFree(hStringExW);
  440. }
  441. }
  442. }
  443. }
  444. //
  445. // generate IR_STRING
  446. //
  447. if (bAnsiWnd) {
  448. dwSize = CompStrWToStringA(lpCompStrW, NULL);
  449. if (dwSize != 0) {
  450. HGLOBAL hStringA = NULL;
  451. LPSTR lpStringA;
  452. if (hStringA = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  453. if (lpStringA = (LPSTR)GlobalLock(hStringA)) {
  454. CompStrWToStringA(lpCompStrW, lpStringA);
  455. GlobalUnlock(hStringA);
  456. if (SendMessageA(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringA))
  457. {
  458. GlobalFree(hStringA);
  459. fDoneDet = TRUE;
  460. goto jtc_exit_30;
  461. }
  462. }
  463. GlobalFree(hStringA);
  464. }
  465. }
  466. else {
  467. return 0;
  468. }
  469. }
  470. else {
  471. dwSize = CompStrWToStringW(lpCompStrW, NULL);
  472. if (dwSize != 0) {
  473. HGLOBAL hStringW = NULL;
  474. LPWSTR lpStringW;
  475. if (hStringW = GlobalAlloc(GHND | GMEM_SHARE, dwSize)) {
  476. if (lpStringW = (LPWSTR)GlobalLock(hStringW)) {
  477. CompStrWToStringW(lpCompStrW, lpStringW);
  478. GlobalUnlock(hStringW);
  479. if (SendMessageW(hWnd,WM_IME_REPORT,IR_STRING, (LPARAM)hStringW))
  480. {
  481. GlobalFree(hStringW);
  482. fDoneDet = TRUE;
  483. goto jtc_exit_30;
  484. }
  485. }
  486. GlobalFree(hStringW);
  487. }
  488. }
  489. else {
  490. return 0;
  491. }
  492. }
  493. //
  494. // generate IR_DBCSCHAR/IR_STRINGSTART/WM_CHAR/IR_STRINGEND
  495. //
  496. if (bAnsiWnd) {
  497. CompStrWToCharA(hWnd, lpCompStrW);
  498. }
  499. else {
  500. CompStrWToCharW(hWnd, lpCompStrW);
  501. }
  502. fDoneDet = TRUE;
  503. }
  504. if (!fDoneUndet && !fDoneDet)
  505. {
  506. *pTransMsgDest = *pTransMsgSrc;
  507. iNum++;
  508. }
  509. jtc_exit_30:
  510. if (!fDoneUndet && fDoneDet && (dwGCS & GCS_COMPSTR))
  511. {
  512. pTransMsgDest->message = pTransMsgSrc->message;
  513. pTransMsgDest->wParam = pTransMsgSrc->wParam;
  514. pTransMsgDest->lParam = (LPARAM)(dwGCS & ~(GCS_RESULT | GCS_RESULTREAD));
  515. iNum++;
  516. }
  517. return iNum;
  518. }
  519. UINT
  520. WINNLSTranslateMessageJ(
  521. UINT uiNumMsg,
  522. PTRANSMSG pTransMsg,
  523. LPINPUTCONTEXT lpIMC,
  524. LPCOMPOSITIONSTRING lpCompStr,
  525. BOOL bAnsiIMC
  526. )
  527. /*++
  528. Routine Description:
  529. Arguments:
  530. Return Value:
  531. --*/
  532. {
  533. PTRANSMSG pTransMsgBuf, pTransMsgTemp;
  534. UINT uiNewNum = 0;
  535. UINT uiTempNum;
  536. DWORD dwTempSize;
  537. HWND hDefIMEWnd;
  538. UINT i;
  539. BOOL bAnsiWnd;
  540. hDefIMEWnd = ImmGetDefaultIMEWnd((HWND)lpIMC->hWnd);
  541. bAnsiWnd = (! IsWindowUnicode(lpIMC->hWnd)) ? TRUE : FALSE;
  542. dwTempSize = uiNumMsg * sizeof(TRANSMSG);
  543. //
  544. // Allocate one more TRANSMSG and ZEROINIT the whole thing!
  545. //
  546. pTransMsgBuf = (PTRANSMSG)ImmLocalAlloc( HEAP_ZERO_MEMORY,
  547. dwTempSize + sizeof(TRANSMSG)
  548. );
  549. if ( pTransMsgBuf == NULL )
  550. goto wtmsg2_j_10;
  551. RtlCopyMemory(pTransMsgBuf, pTransMsg, dwTempSize);
  552. pTransMsgTemp = pTransMsgBuf;
  553. //
  554. // When MCW_HIDDEN mode, WM_IME_ENDCOMPOSITION will be translated to
  555. // IR_UNDETERMINE with 0 string. So that, this message have to be
  556. // generated after all messages.
  557. //
  558. if (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) {
  559. for (i = 0; i < uiNumMsg; i++, pTransMsgTemp++) {
  560. if (pTransMsgTemp->message == WM_IME_ENDCOMPOSITION) {
  561. break;
  562. }
  563. }
  564. if (pTransMsgTemp->message == WM_IME_ENDCOMPOSITION) {
  565. PTRANSMSG pTransMsgSrc = pTransMsgTemp + 1;
  566. while (pTransMsgSrc->message != 0) {
  567. *pTransMsgTemp++ = *pTransMsgSrc++;
  568. }
  569. pTransMsgTemp->message = WM_IME_ENDCOMPOSITION;
  570. pTransMsgTemp->wParam = 0L;
  571. pTransMsgTemp->lParam = 0L;
  572. }
  573. pTransMsgTemp = pTransMsgBuf;
  574. }
  575. while (pTransMsgTemp->message != 0) {
  576. switch (pTransMsgTemp->message)
  577. {
  578. case WM_IME_COMPOSITION:
  579. if (bAnsiIMC)
  580. uiTempNum = JTransCompositionA(lpIMC,lpCompStr,pTransMsgTemp,pTransMsg);
  581. else
  582. uiTempNum = JTransCompositionW(lpIMC,lpCompStr,pTransMsgTemp,pTransMsg);
  583. uiNewNum += uiTempNum;
  584. pTransMsg += uiTempNum;
  585. if ( !(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) )
  586. {
  587. if ( lpIMC->cfCompForm.dwStyle != CFS_DEFAULT ) {
  588. SendMessage((HWND)lpIMC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0L);
  589. }
  590. }
  591. break;
  592. case WM_IME_STARTCOMPOSITION:
  593. if ( !(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) )
  594. {
  595. if ( lpIMC->cfCompForm.dwStyle != CFS_DEFAULT ) {
  596. SendMessage((HWND)lpIMC->hWnd, WM_IME_REPORT, IR_OPENCONVERT, 0L);
  597. }
  598. *pTransMsg++ = *pTransMsgTemp;
  599. uiNewNum++;
  600. }
  601. break;
  602. case WM_IME_ENDCOMPOSITION:
  603. if ( !(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN) )
  604. {
  605. if ( lpIMC->cfCompForm.dwStyle != CFS_DEFAULT ) {
  606. SendMessage((HWND)lpIMC->hWnd, WM_IME_REPORT, IR_CLOSECONVERT, 0L);
  607. }
  608. *pTransMsg++ = *pTransMsgTemp;
  609. uiNewNum++;
  610. }
  611. else {
  612. HWND hWnd = (HWND)lpIMC->hWnd;
  613. HGLOBAL hUndet = 0L;
  614. if (hUndet = GlobalAlloc(GHND | GMEM_SHARE, sizeof(UNDETERMINESTRUCT)))
  615. {
  616. if (! IsWindowUnicode(lpIMC->hWnd))
  617. SendMessageA(hWnd,WM_IME_REPORT, IR_UNDETERMINE, (LPARAM)hUndet);
  618. else
  619. SendMessageW(hWnd,WM_IME_REPORT, IR_UNDETERMINE, (LPARAM)hUndet);
  620. GlobalFree(hUndet);
  621. }
  622. }
  623. break;
  624. case WM_IME_NOTIFY:
  625. switch (pTransMsgTemp->wParam)
  626. {
  627. case IMN_OPENCANDIDATE:
  628. //
  629. // When 3.1 Application want to set MCW_HIDDEN,
  630. // the candidate window of Chicago IME go way
  631. // from the restangle of the composition string
  632. // that will be drawn by the application.
  633. //
  634. if (IsWindow((HWND)lpIMC->hWnd) &&
  635. (lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN)) {
  636. CANDIDATEFORM cfCandForm;
  637. DWORD i;
  638. DWORD dwNumCand = 0;
  639. for (i = 0; i < 32; i++)
  640. {
  641. //
  642. // Only the opened candidate should be updated.
  643. //
  644. if (!(pTransMsgTemp->lParam & (01L << i)))
  645. continue;
  646. cfCandForm.dwIndex = i;
  647. cfCandForm.dwStyle = CFS_EXCLUDE;
  648. cfCandForm.ptCurrentPos = lpIMC->cfCompForm.ptCurrentPos;
  649. cfCandForm.rcArea = lpIMC->cfCompForm.rcArea;
  650. SendMessage(hDefIMEWnd, WM_IME_CONTROL, IMC_SETCANDIDATEPOS,
  651. (LPARAM)(LPCANDIDATEFORM)&cfCandForm);
  652. }
  653. }
  654. break;
  655. default :
  656. break;
  657. }
  658. if (!(lpIMC->fdw31Compat & F31COMPAT_MCWHIDDEN)) {
  659. *pTransMsg++ = *pTransMsgTemp;
  660. uiNewNum++;
  661. }
  662. else {
  663. //
  664. // For win31 apps who set MCW_HIDDEN, we won't give them
  665. // IMN_OPENCANDIDATE here. Instead, send it directly to the
  666. // default IME window.
  667. //
  668. SendMessage( hDefIMEWnd,
  669. pTransMsgTemp->message,
  670. pTransMsgTemp->wParam,
  671. pTransMsgTemp->lParam
  672. );
  673. }
  674. break;
  675. default :
  676. *pTransMsg++ = *pTransMsgTemp;
  677. uiNewNum++;
  678. break;
  679. }
  680. pTransMsgTemp++;
  681. }
  682. ImmLocalFree(pTransMsgBuf);
  683. wtmsg2_j_10:
  684. return (uiNewNum);
  685. }
  686. DWORD
  687. CompStrAToUndetA(
  688. DWORD dwGCS,
  689. LPCOMPOSITIONSTRING lpCompStrA,
  690. LPUNDETERMINESTRUCT lpUndetA,
  691. DWORD dwUndetABufferSize
  692. )
  693. /*++
  694. Routine Description:
  695. Convert composition string (ANSI) to undetermine string (ANSI).
  696. Arguments:
  697. Return Value:
  698. --*/
  699. {
  700. DWORD dwPos;
  701. DWORD dwSize;
  702. UINT i;
  703. dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) +
  704. DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(CHAR))) +
  705. DWORD_ALIGN((lpCompStrA->dwResultClauseLen+1)) +
  706. DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(CHAR))) +
  707. DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen+1)) +
  708. DWORD_ALIGN((lpCompStrA->dwCompAttrLen+1)) +
  709. DWORD_ALIGN(((lpCompStrA->dwCompStrLen+1) * sizeof(CHAR)));
  710. if (lpUndetA == NULL) {
  711. return dwSize;
  712. }
  713. if (dwSize > dwUndetABufferSize) {
  714. // lpUndetA buffer is too small.
  715. return 0;
  716. }
  717. // Set actual lpUndetA buffer size in dwSize.
  718. dwSize = dwUndetABufferSize;
  719. dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1));
  720. lpUndetA->dwSize = dwSize;
  721. if (dwGCS & GCS_COMPSTR)
  722. {
  723. if (dwSize < dwPos) {
  724. // lpUndetA buffer is too small.
  725. return 0;
  726. }
  727. if (lpCompStrA->dwCompStrLen * sizeof(CHAR) > dwSize - dwPos) {
  728. // lpUndetA buffer is too small.
  729. return 0;
  730. }
  731. lpUndetA->uUndetTextLen = lpCompStrA->dwCompStrLen;
  732. lpUndetA->uUndetTextPos = dwPos;
  733. memcpy((PBYTE)lpUndetA + dwPos,
  734. (PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset,
  735. lpCompStrA->dwCompStrLen * sizeof(CHAR)
  736. );
  737. *(LPSTR)((PBYTE)lpUndetA + dwPos + lpCompStrA->dwCompStrLen*sizeof(CHAR)) = '\0';
  738. dwPos += DWORD_ALIGN(((lpUndetA->uUndetTextLen+1)*sizeof(CHAR)));
  739. // Sometime Chicago IME does not generate GCS_COMPATTR
  740. // with GCS_COMPSTR. But uUndetAttrPos should be filled
  741. // when the UndetText is updated.
  742. if (lpCompStrA->dwCompAttrLen && !(dwGCS & GCS_COMPATTR))
  743. dwGCS |= GCS_COMPATTR;
  744. }
  745. if (dwGCS & GCS_COMPATTR)
  746. {
  747. if (dwSize < dwPos) {
  748. // lpUndetA buffer is too small.
  749. return 0;
  750. }
  751. if (lpCompStrA->dwCompAttrLen > dwSize - dwPos) {
  752. // lpUndetA buffer is too small.
  753. return 0;
  754. }
  755. lpUndetA->uUndetAttrPos = dwPos;
  756. memcpy((PBYTE)lpUndetA + dwPos,
  757. (PBYTE)lpCompStrA + lpCompStrA->dwCompAttrOffset,
  758. lpCompStrA->dwCompAttrLen
  759. );
  760. dwPos += DWORD_ALIGN((lpUndetA->uUndetTextLen + 1));
  761. }
  762. if (dwGCS & GCS_CURSORPOS)
  763. {
  764. lpUndetA->uCursorPos = lpCompStrA->dwCursorPos;
  765. }
  766. if (dwGCS & GCS_DELTASTART)
  767. {
  768. lpUndetA->uDeltaStart = lpCompStrA->dwDeltaStart;
  769. }
  770. if (dwGCS & GCS_RESULTSTR)
  771. {
  772. if (dwSize < dwPos) {
  773. // lpUndetA buffer is too small.
  774. return 0;
  775. }
  776. if (lpCompStrA->dwResultStrLen * sizeof(CHAR) > dwSize - dwPos) {
  777. // lpUndetA buffer is too small.
  778. return 0;
  779. }
  780. lpUndetA->uDetermineTextLen = lpCompStrA->dwResultStrLen;
  781. lpUndetA->uDetermineTextPos = dwPos;
  782. memcpy((PBYTE)lpUndetA + dwPos,
  783. (PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset,
  784. lpCompStrA->dwResultStrLen * sizeof(CHAR)
  785. );
  786. *(LPSTR)((PBYTE)lpUndetA + dwPos + lpCompStrA->dwResultStrLen*sizeof(CHAR)) = '\0';
  787. dwPos += DWORD_ALIGN(((lpUndetA->uDetermineTextLen + 1)*sizeof(CHAR)));
  788. }
  789. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  790. (lpCompStrA->dwResultClauseLen > 0) )
  791. {
  792. LPDWORD lpw;
  793. LPDWORD lpdw;
  794. DWORD dwClauseAPos;
  795. if (dwSize < dwPos) {
  796. // lpUndetA buffer is too small.
  797. return 0;
  798. }
  799. dwClauseAPos = dwPos;
  800. lpUndetA->uDetermineDelimPos = dwPos;
  801. lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos);
  802. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset);
  803. for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) {
  804. *lpw++ = *lpdw++;
  805. dwClauseAPos += sizeof(*lpw);
  806. if (dwSize < dwClauseAPos) {
  807. // lpUndetA buffer is too small.
  808. return 0;
  809. }
  810. }
  811. dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1));
  812. }
  813. if (dwGCS & GCS_RESULTREADSTR)
  814. {
  815. if (dwSize < dwPos) {
  816. // lpUndetA buffer is too small.
  817. return 0;
  818. }
  819. if (lpCompStrA->dwResultReadStrLen * sizeof(CHAR) > dwSize - dwPos) {
  820. // lpUndetA buffer is too small.
  821. return 0;
  822. }
  823. lpUndetA->uYomiTextLen = lpCompStrA->dwResultReadStrLen;
  824. lpUndetA->uYomiTextPos = dwPos;
  825. memcpy((PBYTE)lpUndetA + dwPos,
  826. (PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset,
  827. lpCompStrA->dwResultReadStrLen * sizeof(CHAR)
  828. );
  829. *(LPSTR)((PBYTE)lpUndetA + dwPos + lpCompStrA->dwResultReadStrLen*sizeof(CHAR)) = '\0';
  830. dwPos += DWORD_ALIGN(((lpUndetA->uYomiTextLen + 1)*sizeof(CHAR)));
  831. }
  832. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  833. (lpCompStrA->dwResultReadClauseLen > 0) )
  834. {
  835. LPDWORD lpw;
  836. LPDWORD lpdw;
  837. DWORD dwClauseAPos;
  838. if (dwSize < dwPos) {
  839. // lpUndetA buffer is too small.
  840. return 0;
  841. }
  842. dwClauseAPos = dwPos;
  843. lpUndetA->uYomiDelimPos = dwPos;
  844. lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos);
  845. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset);
  846. for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) {
  847. *lpw++ = *lpdw++;
  848. dwClauseAPos += sizeof(*lpw);
  849. if (dwSize < dwClauseAPos) {
  850. // lpUndetA buffer is too small.
  851. return 0;
  852. }
  853. }
  854. dwPos += DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen + 1));
  855. }
  856. return dwSize;
  857. }
  858. DWORD
  859. CompStrAToUndetW(
  860. DWORD dwGCS,
  861. LPCOMPOSITIONSTRING lpCompStrA,
  862. LPUNDETERMINESTRUCT lpUndetW,
  863. DWORD dwUndetWBufferSize
  864. )
  865. /*++
  866. Routine Description:
  867. Convert composition string (ANSI) to undetermine string (Unicode).
  868. Arguments:
  869. Return Value:
  870. --*/
  871. {
  872. DWORD dwPos;
  873. DWORD dwSize;
  874. UINT i;
  875. dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) +
  876. DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(WCHAR))) +
  877. DWORD_ALIGN((lpCompStrA->dwResultClauseLen+1)) +
  878. DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(WCHAR))) +
  879. DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen+1)) +
  880. DWORD_ALIGN((lpCompStrA->dwCompAttrLen * 2)) +
  881. DWORD_ALIGN(((lpCompStrA->dwCompStrLen+1) * sizeof(WCHAR)));
  882. if (lpUndetW == NULL) {
  883. return dwSize;
  884. }
  885. if (dwSize > dwUndetWBufferSize) {
  886. // lpUndetW buffer is too small.
  887. return 0;
  888. }
  889. // Set actual lpUndetW buffer size in dwSize.
  890. dwSize = dwUndetWBufferSize;
  891. dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1));
  892. lpUndetW->dwSize = dwSize;
  893. if (dwGCS & GCS_COMPSTR)
  894. {
  895. if (dwSize < dwPos) {
  896. // lpUndetW buffer is too small.
  897. return 0;
  898. }
  899. i = MultiByteToWideChar( CP_ACP,
  900. (DWORD)MB_PRECOMPOSED,
  901. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset), // src
  902. (INT)lpCompStrA->dwCompStrLen,
  903. (LPWSTR)((PBYTE)lpUndetW + dwPos), // dest
  904. (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters.
  905. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) {
  906. // lpUndetW buffer doesn't hold NULL character terminator.
  907. return 0;
  908. }
  909. ((LPWSTR)((PBYTE)lpUndetW + dwPos))[i] = L'\0';
  910. lpUndetW->uUndetTextLen = i;
  911. lpUndetW->uUndetTextPos = dwPos;
  912. dwPos += DWORD_ALIGN(((lpUndetW->uUndetTextLen + 1)*sizeof(WCHAR)));
  913. // Sometime Chicago IME does not generate GCS_COMPATTR
  914. // with GCS_COMPSTR. But uUndetAttrPos should be filled
  915. // when the UndetText is updated.
  916. if (lpCompStrA->dwCompAttrLen && !(dwGCS & GCS_COMPATTR))
  917. dwGCS |= GCS_COMPATTR;
  918. }
  919. if (dwGCS & GCS_COMPATTR)
  920. {
  921. if (lpUndetW->uUndetTextLen != 0) {
  922. LPWSTR lpwszUndetText;
  923. PBYTE lpAttrW;
  924. PBYTE lpAttrA;
  925. WCHAR wc;
  926. ULONG MultiByteSize;
  927. DWORD dwAttrWPos;
  928. if (dwSize < dwPos) {
  929. // lpUndetW buffer is too small.
  930. return 0;
  931. }
  932. dwAttrWPos = dwPos;
  933. lpwszUndetText = (LPWSTR)((PBYTE)lpUndetW + lpUndetW->uUndetTextPos);
  934. lpAttrA = (PBYTE)lpCompStrA + lpCompStrA->dwCompAttrOffset;
  935. lpAttrW = (PBYTE)lpUndetW + dwPos;
  936. while (wc=*lpwszUndetText++) {
  937. RtlUnicodeToMultiByteSize(&MultiByteSize, &wc, sizeof(WCHAR));
  938. if (MultiByteSize == 2) {
  939. *lpAttrW++ = *lpAttrA;
  940. lpAttrA += 2;
  941. }
  942. else {
  943. *lpAttrW++ = *lpAttrA++;
  944. }
  945. dwAttrWPos += sizeof(*lpAttrW);
  946. if (dwSize < dwAttrWPos) {
  947. // lpUndetW buffer is too small.
  948. return 0;
  949. }
  950. }
  951. lpUndetW->uUndetAttrPos = dwPos;
  952. dwPos += DWORD_ALIGN((lpUndetW->uUndetTextLen + 1));
  953. }
  954. }
  955. if (dwGCS & GCS_CURSORPOS)
  956. {
  957. if (lpCompStrA->dwCursorPos != -1) {
  958. lpUndetW->uCursorPos = CalcCharacterPositionAtoW(lpCompStrA->dwCursorPos,
  959. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset),
  960. CP_ACP
  961. );
  962. }
  963. else {
  964. lpUndetW->uCursorPos = lpCompStrA->dwCursorPos;
  965. }
  966. }
  967. if (dwGCS & GCS_DELTASTART)
  968. {
  969. if (lpCompStrA->dwDeltaStart != -1) {
  970. lpUndetW->uDeltaStart = CalcCharacterPositionAtoW(lpCompStrA->dwDeltaStart,
  971. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwCompStrOffset),
  972. CP_ACP
  973. );
  974. }
  975. else {
  976. lpUndetW->uDeltaStart = lpCompStrA->dwDeltaStart;
  977. }
  978. }
  979. if (dwGCS & GCS_RESULTSTR)
  980. {
  981. if (dwSize < dwPos) {
  982. // lpUndetW buffer is too small.
  983. return 0;
  984. }
  985. i = MultiByteToWideChar( CP_ACP,
  986. (DWORD)MB_PRECOMPOSED,
  987. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset), // src
  988. (INT)lpCompStrA->dwResultStrLen,
  989. (LPWSTR)((PBYTE)lpUndetW + dwPos), // dest
  990. (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters.
  991. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) {
  992. // lpUndetW buffer doesn't hold NULL character terminator.
  993. return 0;
  994. }
  995. ((LPWSTR)((PBYTE)lpUndetW + dwPos))[i] = L'\0';
  996. lpUndetW->uDetermineTextLen = i;
  997. lpUndetW->uDetermineTextPos = dwPos;
  998. dwPos += DWORD_ALIGN(((lpUndetW->uDetermineTextLen + 1)*sizeof(WCHAR)));
  999. }
  1000. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  1001. (lpCompStrA->dwResultClauseLen > 0) )
  1002. {
  1003. if (lpUndetW->uDetermineTextLen != 0) {
  1004. LPDWORD lpw;
  1005. LPDWORD lpdw;
  1006. DWORD dwClauseWPos;
  1007. if (dwSize < dwPos) {
  1008. // lpUndetW buffer is too small.
  1009. return 0;
  1010. }
  1011. dwClauseWPos = dwPos;
  1012. lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos);
  1013. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset);
  1014. for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) {
  1015. *lpw++ = CalcCharacterPositionAtoW(*lpdw++,
  1016. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset),
  1017. CP_ACP
  1018. );
  1019. dwClauseWPos += sizeof(*lpw);
  1020. if (dwSize < dwClauseWPos) {
  1021. // lpUndetW buffer is too small.
  1022. return 0;
  1023. }
  1024. }
  1025. lpUndetW->uDetermineDelimPos = dwPos;
  1026. dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1));
  1027. }
  1028. }
  1029. if (dwGCS & GCS_RESULTREADSTR)
  1030. {
  1031. if (dwSize < dwPos) {
  1032. // lpUndetW buffer is too small.
  1033. return 0;
  1034. }
  1035. i = MultiByteToWideChar( CP_ACP,
  1036. (DWORD)MB_PRECOMPOSED,
  1037. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset), // src
  1038. (INT)lpCompStrA->dwResultReadStrLen,
  1039. (LPWSTR)((PBYTE)lpUndetW + dwPos), // dest
  1040. (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters.
  1041. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) {
  1042. // lpUndetW buffer doesn't hold NULL character terminator.
  1043. return 0;
  1044. }
  1045. ((LPWSTR)((PBYTE)lpUndetW + dwPos))[i] = L'\0';
  1046. lpUndetW->uYomiTextLen = i;
  1047. lpUndetW->uYomiTextPos = dwPos;
  1048. dwPos += DWORD_ALIGN(((lpUndetW->uYomiTextLen + 1)*sizeof(WCHAR)));
  1049. }
  1050. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  1051. (lpCompStrA->dwResultReadClauseLen > 0) )
  1052. {
  1053. if (lpUndetW->uYomiTextLen != 0) {
  1054. LPDWORD lpw;
  1055. LPDWORD lpdw;
  1056. DWORD dwClauseWPos;
  1057. if (dwSize < dwPos) {
  1058. // lpUndetW buffer is too small.
  1059. return 0;
  1060. }
  1061. dwClauseWPos = dwPos;
  1062. lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos);
  1063. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset);
  1064. for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) {
  1065. *lpw++ = CalcCharacterPositionAtoW(*lpdw++,
  1066. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset),
  1067. CP_ACP
  1068. );
  1069. dwClauseWPos += sizeof(*lpw);
  1070. if (dwSize < dwClauseWPos) {
  1071. // lpUndetW buffer is too small.
  1072. return 0;
  1073. }
  1074. }
  1075. lpUndetW->uYomiDelimPos = dwPos;
  1076. dwPos += DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen + 1));
  1077. }
  1078. }
  1079. return dwSize;
  1080. }
  1081. DWORD
  1082. CompStrAToStringExA(
  1083. DWORD dwGCS,
  1084. LPCOMPOSITIONSTRING lpCompStrA,
  1085. LPSTRINGEXSTRUCT lpStringExA,
  1086. DWORD dwStringExABufferSize
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. Convert composition string (ANSI) to StringEx (ANSI).
  1091. Arguments:
  1092. Return Value:
  1093. --*/
  1094. {
  1095. DWORD dwPos;
  1096. DWORD dwSize;
  1097. UINT i;
  1098. dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) +
  1099. DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(CHAR))) +
  1100. DWORD_ALIGN(lpCompStrA->dwResultClauseLen+1) +
  1101. DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(CHAR))) +
  1102. DWORD_ALIGN(lpCompStrA->dwResultReadClauseLen+1);
  1103. if (lpStringExA == NULL) {
  1104. return dwSize;
  1105. }
  1106. if (dwSize > dwStringExABufferSize) {
  1107. // lpStringExA buffer is too small.
  1108. return 0;
  1109. }
  1110. // Set actual lpStringExA buffer size in dwSize.
  1111. dwSize = dwStringExABufferSize;
  1112. dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1);
  1113. lpStringExA->dwSize = dwSize;
  1114. if (dwSize < dwPos) {
  1115. // lpStringExA buffer is too small.
  1116. return 0;
  1117. }
  1118. if (lpCompStrA->dwResultStrLen * sizeof(CHAR) > dwSize - dwPos) {
  1119. // lpStringExA buffer is too small.
  1120. return 0;
  1121. }
  1122. lpStringExA->uDeterminePos = dwPos;
  1123. memcpy((PBYTE)lpStringExA + dwPos,
  1124. (PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset,
  1125. lpCompStrA->dwResultStrLen * sizeof(CHAR)
  1126. );
  1127. *(LPSTR)((PBYTE)lpStringExA + dwPos + lpCompStrA->dwResultStrLen*sizeof(CHAR)) = '\0';
  1128. dwPos += DWORD_ALIGN(((lpCompStrA->dwResultStrLen + 1)*sizeof(CHAR)));
  1129. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  1130. (lpCompStrA->dwResultClauseLen > 0) )
  1131. {
  1132. LPDWORD lpw;
  1133. LPDWORD lpdw;
  1134. DWORD dwClauseAPos;
  1135. if (dwSize < dwPos) {
  1136. // lpStringExA buffer is too small.
  1137. return 0;
  1138. }
  1139. dwClauseAPos = dwPos;
  1140. lpStringExA->uDetermineDelimPos = dwPos;
  1141. lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos);
  1142. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset);
  1143. for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) {
  1144. *lpw++ = *lpdw++;
  1145. dwClauseAPos += sizeof(*lpw);
  1146. if (dwSize < dwClauseAPos) {
  1147. // lpStringExA buffer is too small.
  1148. return 0;
  1149. }
  1150. }
  1151. dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1));
  1152. }
  1153. if (dwSize < dwPos) {
  1154. // lpStringExA buffer is too small.
  1155. return 0;
  1156. }
  1157. if (lpCompStrA->dwResultReadStrLen * sizeof(CHAR) > dwSize - dwPos) {
  1158. // lpStringExA buffer is too small.
  1159. return 0;
  1160. }
  1161. lpStringExA->uYomiPos = dwPos;
  1162. memcpy((PBYTE)lpStringExA + dwPos,
  1163. (PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset,
  1164. lpCompStrA->dwResultReadStrLen * sizeof(CHAR)
  1165. );
  1166. *(LPSTR)((PBYTE)lpStringExA + dwPos + lpCompStrA->dwResultReadStrLen*sizeof(CHAR)) = '\0';
  1167. dwPos += DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen + 1)*sizeof(CHAR)));
  1168. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  1169. (lpCompStrA->dwResultReadClauseLen > 0) )
  1170. {
  1171. LPDWORD lpw;
  1172. LPDWORD lpdw;
  1173. DWORD dwClauseAPos;
  1174. if (dwSize < dwPos) {
  1175. // lpStringExA buffer is too small.
  1176. return 0;
  1177. }
  1178. dwClauseAPos = dwPos;
  1179. lpStringExA->uYomiDelimPos = dwPos;
  1180. lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos);
  1181. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset);
  1182. for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) {
  1183. *lpw++ = *lpdw++;
  1184. dwClauseAPos += sizeof(*lpw);
  1185. if (dwSize < dwClauseAPos) {
  1186. // lpStringExA buffer is too small.
  1187. return 0;
  1188. }
  1189. }
  1190. }
  1191. return dwSize;
  1192. }
  1193. DWORD
  1194. CompStrAToStringExW(
  1195. DWORD dwGCS,
  1196. LPCOMPOSITIONSTRING lpCompStrA,
  1197. LPSTRINGEXSTRUCT lpStringExW,
  1198. DWORD dwStringExWBufferSize
  1199. )
  1200. /*++
  1201. Routine Description:
  1202. Convert composition string (ANSI) to StringEx (Unicode).
  1203. Arguments:
  1204. Return Value:
  1205. --*/
  1206. {
  1207. DWORD dwPos;
  1208. DWORD dwSize;
  1209. DWORD dwLen;
  1210. UINT i;
  1211. dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) +
  1212. (lpCompStrA->dwResultStrLen > 0 ? DWORD_ALIGN(((lpCompStrA->dwResultStrLen+1) * sizeof(WCHAR))) : 0) +
  1213. (lpCompStrA->dwResultClauseLen > 0 ? DWORD_ALIGN(lpCompStrA->dwResultClauseLen+1) : 0) +
  1214. (lpCompStrA->dwResultReadStrLen > 0 ? DWORD_ALIGN(((lpCompStrA->dwResultReadStrLen+1) * sizeof(WCHAR))) : 0)+
  1215. (lpCompStrA->dwResultReadClauseLen > 0 ? DWORD_ALIGN(lpCompStrA->dwResultReadClauseLen+1) : 0);
  1216. if (lpStringExW == NULL) {
  1217. return dwSize;
  1218. }
  1219. if (dwSize > dwStringExWBufferSize) {
  1220. // lpStringExW buffer is too small.
  1221. return 0;
  1222. }
  1223. // Set actual lpStringExW buffer size in dwSize.
  1224. dwSize = dwStringExWBufferSize;
  1225. dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1);
  1226. lpStringExW->dwSize = dwSize;
  1227. if (lpCompStrA->dwResultStrLen > 0) {
  1228. if (dwSize < dwPos) {
  1229. // lpStringExW buffer is too small.
  1230. return 0;
  1231. }
  1232. i = MultiByteToWideChar( CP_ACP,
  1233. (DWORD)MB_PRECOMPOSED,
  1234. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset), // src
  1235. (INT)lpCompStrA->dwResultStrLen,
  1236. (LPWSTR)((PBYTE)lpStringExW + dwPos), // dest
  1237. (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters.
  1238. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) {
  1239. // lpStringExW buffer doesn't hold NULL character terminator.
  1240. return 0;
  1241. }
  1242. ((LPWSTR)((PBYTE)lpStringExW + dwPos))[i] = L'\0';
  1243. dwLen = i;
  1244. lpStringExW->uDeterminePos = dwPos;
  1245. dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(WCHAR)));
  1246. } else {
  1247. dwLen = 0;
  1248. lpStringExW->uDeterminePos = 0;
  1249. }
  1250. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  1251. (lpCompStrA->dwResultClauseLen > 0) )
  1252. {
  1253. if (dwLen != 0 && lpCompStrA->dwResultClauseLen > 0) {
  1254. LPDWORD lpw;
  1255. LPDWORD lpdw;
  1256. DWORD dwClauseWPos;
  1257. if (dwSize < dwPos) {
  1258. // lpStringExW buffer is too small.
  1259. return 0;
  1260. }
  1261. dwClauseWPos = dwPos;
  1262. lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos);
  1263. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultClauseOffset);
  1264. for (i = 0; i < (lpCompStrA->dwResultClauseLen / sizeof(DWORD)); i++) {
  1265. *lpw++ = CalcCharacterPositionAtoW(*lpdw++,
  1266. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset),
  1267. CP_ACP
  1268. );
  1269. dwClauseWPos += sizeof(*lpw);
  1270. if (dwSize < dwClauseWPos) {
  1271. // lpStringExW buffer is too small.
  1272. return 0;
  1273. }
  1274. }
  1275. lpStringExW->uDetermineDelimPos = dwPos;
  1276. dwPos += DWORD_ALIGN((lpCompStrA->dwResultClauseLen + 1));
  1277. }
  1278. }
  1279. if (lpCompStrA->dwResultReadStrLen > 0) {
  1280. if (dwSize < dwPos) {
  1281. // lpStringExW buffer is too small.
  1282. return 0;
  1283. }
  1284. i = MultiByteToWideChar( CP_ACP,
  1285. (DWORD)MB_PRECOMPOSED,
  1286. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset), // src
  1287. (INT)lpCompStrA->dwResultReadStrLen,
  1288. (LPWSTR)((PBYTE)lpStringExW + dwPos), // dest
  1289. (INT)(dwSize - dwPos)/sizeof(WCHAR)); // Specifies the size, in wide characters.
  1290. if (i >= (dwSize - dwPos)/sizeof(WCHAR)) {
  1291. // lpStringExW buffer doesn't hold NULL character terminator.
  1292. return 0;
  1293. }
  1294. ((LPWSTR)((PBYTE)lpStringExW + dwPos))[i] = L'\0';
  1295. dwLen = i;
  1296. lpStringExW->uYomiPos = dwPos;
  1297. dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(WCHAR)));
  1298. } else {
  1299. dwLen = 0;
  1300. lpStringExW->uYomiPos = 0;
  1301. }
  1302. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  1303. (lpCompStrA->dwResultReadClauseLen > 0) )
  1304. {
  1305. if (dwLen != 0 && lpCompStrA->dwResultReadClauseLen > 0) {
  1306. LPDWORD lpw;
  1307. LPDWORD lpdw;
  1308. DWORD dwClauseWPos;
  1309. if (dwSize < dwPos) {
  1310. // lpStringExW buffer is too small.
  1311. return 0;
  1312. }
  1313. dwClauseWPos = dwPos;
  1314. lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos);
  1315. lpdw = (LPDWORD)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadClauseOffset);
  1316. for (i = 0; i < (lpCompStrA->dwResultReadClauseLen / sizeof(DWORD)); i++) {
  1317. *lpw++ = CalcCharacterPositionAtoW(*lpdw++,
  1318. (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultReadStrOffset),
  1319. CP_ACP
  1320. );
  1321. dwClauseWPos += sizeof(*lpw);
  1322. if (dwSize < dwClauseWPos) {
  1323. // lpStringExW buffer is too small.
  1324. return 0;
  1325. }
  1326. }
  1327. lpStringExW->uYomiDelimPos = dwPos;
  1328. dwPos += DWORD_ALIGN((lpCompStrA->dwResultReadClauseLen + 1));
  1329. }
  1330. }
  1331. return dwSize;
  1332. }
  1333. DWORD
  1334. CompStrAToStringA(
  1335. LPCOMPOSITIONSTRING lpCompStrA,
  1336. LPSTR lpStringA,
  1337. DWORD dwStringABufferSize
  1338. )
  1339. /*++
  1340. Routine Description:
  1341. Convert composition string (ANSI) to String (ANSI).
  1342. Arguments:
  1343. Return Value:
  1344. --*/
  1345. {
  1346. LPSTR lpszString;
  1347. DWORD dwSize;
  1348. lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset);
  1349. dwSize = lpCompStrA->dwResultStrLen;
  1350. if (lpStringA == NULL) {
  1351. return ((dwSize + 1) * sizeof(CHAR));
  1352. }
  1353. if (dwSize > dwStringABufferSize) {
  1354. // lpStringA buffer is too small.
  1355. return 0;
  1356. }
  1357. memcpy((PBYTE)lpStringA,
  1358. (PBYTE)lpszString,
  1359. (dwSize * sizeof(CHAR))
  1360. );
  1361. lpStringA[dwSize] = '\0';
  1362. return ((dwSize + 1) * sizeof(CHAR));
  1363. }
  1364. DWORD
  1365. CompStrAToStringW(
  1366. LPCOMPOSITIONSTRING lpCompStrA,
  1367. LPWSTR lpStringW,
  1368. DWORD dwStringWBufferSize
  1369. )
  1370. /*++
  1371. Routine Description:
  1372. Convert composition string (ANSI) to String (Unicode).
  1373. Arguments:
  1374. Return Value:
  1375. --*/
  1376. {
  1377. LPSTR lpszString;
  1378. DWORD dwSize;
  1379. UINT i;
  1380. lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset);
  1381. i = MultiByteToWideChar( CP_ACP,
  1382. (DWORD)MB_PRECOMPOSED,
  1383. (LPSTR)lpszString, // src
  1384. (INT)lpCompStrA->dwResultStrLen,
  1385. (LPWSTR)lpStringW, // dest
  1386. (INT)0);
  1387. if (lpStringW == NULL) {
  1388. dwSize = (i+1) * sizeof(WCHAR);
  1389. }
  1390. else {
  1391. dwSize = (i+1) * sizeof(WCHAR);
  1392. if (dwSize > dwStringWBufferSize) {
  1393. // lpStringW buffer is too small.
  1394. return 0;
  1395. }
  1396. i = MultiByteToWideChar( CP_ACP,
  1397. (DWORD)MB_PRECOMPOSED,
  1398. (LPSTR)lpszString, // src
  1399. (INT)lpCompStrA->dwResultStrLen,
  1400. (LPWSTR)lpStringW, // dest
  1401. (INT)dwSize/sizeof(WCHAR)); // Specifies the size, in wide characters.
  1402. if (i >= dwSize/sizeof(WCHAR)) {
  1403. // lpStringW buffer doesn't hold NULL character terminator.
  1404. return 0;
  1405. }
  1406. lpStringW[i] = L'\0';
  1407. dwSize = (i+1) * sizeof(WCHAR);
  1408. }
  1409. return dwSize;
  1410. }
  1411. VOID
  1412. CompStrAToCharA(
  1413. HWND hWnd,
  1414. LPCOMPOSITIONSTRING lpCompStrA
  1415. )
  1416. /*++
  1417. Routine Description:
  1418. Convert composition string (ANSI) to WM_CHAR (ANSI).
  1419. Arguments:
  1420. Return Value:
  1421. --*/
  1422. {
  1423. LPSTR lpszString;
  1424. BOOL fDBCSWmChar = FALSE;
  1425. WORD wDBCSChar;
  1426. BYTE szAscii[3];
  1427. lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset);
  1428. // IR_DBCSCHAR: If the app reply to this message with TRUE, we can
  1429. // queue up double byte character in a WM_CHAR message.
  1430. if ( GetClientInfo()->dwExpWinVer >= 0x030A ) {
  1431. fDBCSWmChar = (BOOL)SendMessageA( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L);
  1432. }
  1433. // Send IR_STRINGSTART prior to anything.
  1434. PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L );
  1435. while(szAscii[0]=*lpszString)
  1436. {
  1437. if( *CharNextA(lpszString) == 0 )
  1438. {
  1439. PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L );
  1440. }
  1441. if( IsDBCSLeadByte( szAscii[0] ) )
  1442. {
  1443. szAscii[1] = *((PBYTE)(lpszString+1));
  1444. // If fDBCSWmChar==TRUE, The app can recieve WM_CHARs which
  1445. // have double byte code in wParam.
  1446. if ( fDBCSWmChar )
  1447. {
  1448. // It's necessary to swap bytes to put 1st byte into upper
  1449. // part of wParam, and 2nd byte into lower part.
  1450. wDBCSChar = MAKEWORD(szAscii[1], szAscii[0]);
  1451. PostMessageA( hWnd, WM_CHAR, (WPARAM)wDBCSChar|WMCR_IR_DBCSCHAR, 1L );
  1452. }
  1453. else
  1454. {
  1455. // Send each byte on a WM_CHAR
  1456. PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L);
  1457. PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[1]), 1L);
  1458. }
  1459. }
  1460. else
  1461. {
  1462. PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L);
  1463. }
  1464. lpszString = CharNextA(lpszString);
  1465. }
  1466. }
  1467. VOID
  1468. CompStrAToCharW(
  1469. HWND hWnd,
  1470. LPCOMPOSITIONSTRING lpCompStrA
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. Convert composition string (ANSI) to WM_CHAR (Unicode).
  1475. Arguments:
  1476. Return Value:
  1477. --*/
  1478. {
  1479. LPSTR lpszString;
  1480. UINT i;
  1481. BYTE c;
  1482. WCHAR wszUnicode[2];
  1483. lpszString = (LPSTR)((PBYTE)lpCompStrA + lpCompStrA->dwResultStrOffset);
  1484. // IR_DBCSCHAR: If the app reply to this message with TRUE, we can
  1485. // queue up double byte character in a WM_CHAR message.
  1486. // SendMessageW( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L);
  1487. // Send IR_STRINGSTART prior to anything.
  1488. PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L );
  1489. while(c=*lpszString)
  1490. {
  1491. if( *CharNextA(lpszString) == 0 )
  1492. {
  1493. PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L );
  1494. }
  1495. if( IsDBCSLeadByte( c ) ) {
  1496. i = MultiByteToWideChar( CP_ACP,
  1497. (DWORD)MB_PRECOMPOSED,
  1498. (LPSTR)lpszString, // src
  1499. (INT)2,
  1500. (LPWSTR)wszUnicode, // dest
  1501. (INT)ARRAY_SIZE(wszUnicode));
  1502. }
  1503. else {
  1504. i = MultiByteToWideChar( CP_ACP,
  1505. (DWORD)MB_PRECOMPOSED,
  1506. (LPSTR)lpszString, // src
  1507. (INT)1,
  1508. (LPWSTR)wszUnicode, // dest
  1509. (INT)ARRAY_SIZE(wszUnicode));
  1510. }
  1511. if (i != 0) {
  1512. PostMessageW( hWnd, WM_CHAR, (WPARAM)(wszUnicode[0]), 1L);
  1513. }
  1514. lpszString = CharNextA(lpszString);
  1515. }
  1516. }
  1517. DWORD
  1518. CompStrWToUndetW(
  1519. DWORD dwGCS,
  1520. LPCOMPOSITIONSTRING lpCompStrW,
  1521. LPUNDETERMINESTRUCT lpUndetW
  1522. )
  1523. /*++
  1524. Routine Description:
  1525. Convert composition string (Unicode) to undetermine string (Unicode).
  1526. Arguments:
  1527. Return Value:
  1528. --*/
  1529. {
  1530. DWORD dwPos;
  1531. DWORD dwSize;
  1532. UINT i;
  1533. dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) +
  1534. DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) +
  1535. DWORD_ALIGN((lpCompStrW->dwResultClauseLen+1)) +
  1536. DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) +
  1537. DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen+1)) +
  1538. DWORD_ALIGN((lpCompStrW->dwCompAttrLen+1)) +
  1539. DWORD_ALIGN(((lpCompStrW->dwCompStrLen+1) * sizeof(WCHAR)));
  1540. if (lpUndetW == NULL) {
  1541. return dwSize;
  1542. }
  1543. dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1));
  1544. lpUndetW->dwSize = dwSize;
  1545. if (dwGCS & GCS_COMPSTR)
  1546. {
  1547. lpUndetW->uUndetTextLen = lpCompStrW->dwCompStrLen;
  1548. lpUndetW->uUndetTextPos = dwPos;
  1549. memcpy((PBYTE)lpUndetW + dwPos,
  1550. (PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset,
  1551. lpCompStrW->dwCompStrLen * sizeof(WCHAR)
  1552. );
  1553. *(LPWSTR)((PBYTE)lpUndetW + dwPos + lpCompStrW->dwCompStrLen*sizeof(WCHAR)) = L'\0';
  1554. dwPos += DWORD_ALIGN(((lpUndetW->uUndetTextLen+1)*sizeof(WCHAR)));
  1555. // Sometime Chicago IME does not generate GCS_COMPATTR
  1556. // with GCS_COMPSTR. But uUndetAttrPos should be filled
  1557. // when the UndetText is updated.
  1558. if (lpCompStrW->dwCompAttrLen && !(dwGCS & GCS_COMPATTR))
  1559. dwGCS |= GCS_COMPATTR;
  1560. }
  1561. if (dwGCS & GCS_COMPATTR)
  1562. {
  1563. lpUndetW->uUndetAttrPos = dwPos;
  1564. memcpy((PBYTE)lpUndetW + dwPos,
  1565. (PBYTE)lpCompStrW + lpCompStrW->dwCompAttrOffset,
  1566. lpCompStrW->dwCompAttrLen
  1567. );
  1568. dwPos += DWORD_ALIGN((lpUndetW->uUndetTextLen + 1));
  1569. }
  1570. if (dwGCS & GCS_CURSORPOS)
  1571. {
  1572. lpUndetW->uCursorPos = lpCompStrW->dwCursorPos;
  1573. }
  1574. if (dwGCS & GCS_DELTASTART)
  1575. {
  1576. lpUndetW->uDeltaStart = lpCompStrW->dwDeltaStart;
  1577. }
  1578. if (dwGCS & GCS_RESULTSTR)
  1579. {
  1580. lpUndetW->uDetermineTextLen = lpCompStrW->dwResultStrLen;
  1581. lpUndetW->uDetermineTextPos = dwPos;
  1582. memcpy((PBYTE)lpUndetW + dwPos,
  1583. (PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset,
  1584. lpCompStrW->dwResultStrLen * sizeof(WCHAR)
  1585. );
  1586. *(LPWSTR)((PBYTE)lpUndetW + dwPos + lpCompStrW->dwResultStrLen*sizeof(WCHAR)) = L'\0';
  1587. dwPos += DWORD_ALIGN(((lpUndetW->uDetermineTextLen + 1)*sizeof(WCHAR)));
  1588. }
  1589. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  1590. (lpCompStrW->dwResultClauseLen > 0) )
  1591. {
  1592. LPDWORD lpw;
  1593. LPDWORD lpdw;
  1594. lpUndetW->uDetermineDelimPos = dwPos;
  1595. lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos);
  1596. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset);
  1597. for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++)
  1598. *lpw++ = *lpdw++;
  1599. dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1));
  1600. }
  1601. if (dwGCS & GCS_RESULTREADSTR)
  1602. {
  1603. lpUndetW->uYomiTextLen = lpCompStrW->dwResultReadStrLen;
  1604. lpUndetW->uYomiTextPos = dwPos;
  1605. memcpy((PBYTE)lpUndetW + dwPos,
  1606. (PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset,
  1607. lpCompStrW->dwResultReadStrLen * sizeof(WCHAR)
  1608. );
  1609. *(LPWSTR)((PBYTE)lpUndetW + dwPos + lpCompStrW->dwResultReadStrLen*sizeof(WCHAR)) = L'\0';
  1610. dwPos += DWORD_ALIGN(((lpUndetW->uYomiTextLen + 1)*sizeof(WCHAR)));
  1611. }
  1612. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  1613. (lpCompStrW->dwResultReadClauseLen > 0) )
  1614. {
  1615. LPDWORD lpw;
  1616. LPDWORD lpdw;
  1617. lpUndetW->uYomiDelimPos = dwPos;
  1618. lpw = (LPDWORD)((PBYTE)lpUndetW + dwPos);
  1619. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset);
  1620. for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++)
  1621. *lpw++ = *lpdw++;
  1622. dwPos += DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen + 1));
  1623. }
  1624. return dwSize;
  1625. }
  1626. DWORD
  1627. CompStrWToUndetA(
  1628. DWORD dwGCS,
  1629. LPCOMPOSITIONSTRING lpCompStrW,
  1630. LPUNDETERMINESTRUCT lpUndetA
  1631. )
  1632. /*++
  1633. Routine Description:
  1634. Convert composition string (Unicode) to undetermine string (ANSI).
  1635. Arguments:
  1636. Return Value:
  1637. --*/
  1638. {
  1639. DWORD dwPos;
  1640. DWORD dwSize;
  1641. UINT i;
  1642. BOOL bUDC;
  1643. dwSize = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT)+1)) +
  1644. DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) +
  1645. DWORD_ALIGN((lpCompStrW->dwResultClauseLen+1)) +
  1646. DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) +
  1647. DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen+1)) +
  1648. DWORD_ALIGN((lpCompStrW->dwCompAttrLen * 2)) +
  1649. DWORD_ALIGN(((lpCompStrW->dwCompStrLen+1) * sizeof(WCHAR)));
  1650. if (lpUndetA == NULL) {
  1651. return dwSize;
  1652. }
  1653. dwPos = DWORD_ALIGN((sizeof(UNDETERMINESTRUCT) + 1));
  1654. lpUndetA->dwSize = dwSize;
  1655. if (dwGCS & GCS_COMPSTR)
  1656. {
  1657. i = WideCharToMultiByte( CP_ACP,
  1658. (DWORD)0,
  1659. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset), // src
  1660. (INT)lpCompStrW->dwCompStrLen,
  1661. (LPSTR)((PBYTE)lpUndetA + dwPos), // dest
  1662. (INT)dwSize - dwPos,
  1663. (LPSTR)NULL,
  1664. (LPBOOL)&bUDC);
  1665. ((LPSTR)((PBYTE)lpUndetA + dwPos))[i] = '\0';
  1666. lpUndetA->uUndetTextLen = i;
  1667. lpUndetA->uUndetTextPos = dwPos;
  1668. dwPos += DWORD_ALIGN(((lpUndetA->uUndetTextLen + 1)*sizeof(CHAR)));
  1669. // Sometime Chicago IME does not generate GCS_COMPATTR
  1670. // with GCS_COMPSTR. But uUndetAttrPos should be filled
  1671. // when the UndetText is updated.
  1672. if (lpCompStrW->dwCompAttrLen && !(dwGCS & GCS_COMPATTR))
  1673. dwGCS |= GCS_COMPATTR;
  1674. }
  1675. if (dwGCS & GCS_COMPATTR)
  1676. {
  1677. if (lpUndetA->uUndetTextLen != 0) {
  1678. LPSTR lpszUndetText;
  1679. PBYTE lpAttrW;
  1680. PBYTE lpAttrA;
  1681. BYTE c;
  1682. lpszUndetText = (LPSTR)((PBYTE)lpUndetA + lpUndetA->uUndetTextPos);
  1683. lpAttrW = (PBYTE)lpCompStrW + lpCompStrW->dwCompAttrOffset;
  1684. lpAttrA = (PBYTE)lpUndetA + dwPos;
  1685. while (c=*lpszUndetText++) {
  1686. if (IsDBCSLeadByte(c)) {
  1687. *lpAttrA++ = *lpAttrW;
  1688. *lpAttrA++ = *lpAttrW;
  1689. lpszUndetText++;
  1690. }
  1691. else {
  1692. *lpAttrA++ = *lpAttrW;
  1693. }
  1694. lpAttrW++;
  1695. }
  1696. lpUndetA->uUndetAttrPos = dwPos;
  1697. dwPos += DWORD_ALIGN((lpUndetA->uUndetTextLen + 1));
  1698. }
  1699. }
  1700. if (dwGCS & GCS_CURSORPOS)
  1701. {
  1702. if (lpCompStrW->dwCursorPos != -1) {
  1703. lpUndetA->uCursorPos = CalcCharacterPositionWtoA(lpCompStrW->dwCursorPos,
  1704. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset),
  1705. CP_ACP
  1706. );
  1707. }
  1708. else {
  1709. lpUndetA->uCursorPos = lpCompStrW->dwCursorPos;
  1710. }
  1711. }
  1712. if (dwGCS & GCS_DELTASTART)
  1713. {
  1714. if (lpCompStrW->dwDeltaStart != -1) {
  1715. lpUndetA->uDeltaStart = CalcCharacterPositionWtoA(lpCompStrW->dwDeltaStart,
  1716. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwCompStrOffset),
  1717. CP_ACP
  1718. );
  1719. }
  1720. else {
  1721. lpUndetA->uDeltaStart = lpCompStrW->dwDeltaStart;
  1722. }
  1723. }
  1724. if (dwGCS & GCS_RESULTSTR)
  1725. {
  1726. i = WideCharToMultiByte( CP_ACP,
  1727. (DWORD)0,
  1728. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset), // src
  1729. (INT)lpCompStrW->dwResultStrLen,
  1730. (LPSTR)((PBYTE)lpUndetA + dwPos), // dest
  1731. (INT)dwSize - dwPos,
  1732. (LPSTR)NULL,
  1733. (LPBOOL)&bUDC);
  1734. ((LPSTR)((PBYTE)lpUndetA + dwPos))[i] = '\0';
  1735. lpUndetA->uDetermineTextLen = i;
  1736. lpUndetA->uDetermineTextPos = dwPos;
  1737. dwPos += DWORD_ALIGN(((lpUndetA->uDetermineTextLen + 1)*sizeof(CHAR)));
  1738. }
  1739. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  1740. (lpCompStrW->dwResultClauseLen > 0) )
  1741. {
  1742. if (lpUndetA->uDetermineTextLen != 0) {
  1743. LPDWORD lpw;
  1744. LPDWORD lpdw;
  1745. lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos);
  1746. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset);
  1747. for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++) {
  1748. *lpw++ = CalcCharacterPositionWtoA(*lpdw++,
  1749. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset),
  1750. CP_ACP
  1751. );
  1752. }
  1753. lpUndetA->uDetermineDelimPos = dwPos;
  1754. dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1));
  1755. }
  1756. }
  1757. if (dwGCS & GCS_RESULTREADSTR)
  1758. {
  1759. i = WideCharToMultiByte( CP_ACP,
  1760. (DWORD)0,
  1761. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset), // src
  1762. (INT)lpCompStrW->dwResultReadStrLen,
  1763. (LPSTR)((PBYTE)lpUndetA + dwPos), // dest
  1764. (INT)dwSize - dwPos,
  1765. (LPSTR)NULL,
  1766. (LPBOOL)&bUDC);
  1767. ((LPSTR)((PBYTE)lpUndetA + dwPos))[i] = '\0';
  1768. lpUndetA->uYomiTextLen = i;
  1769. lpUndetA->uYomiTextPos = dwPos;
  1770. dwPos += DWORD_ALIGN(((lpUndetA->uYomiTextLen + 1)*sizeof(CHAR)));
  1771. }
  1772. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  1773. (lpCompStrW->dwResultReadClauseLen > 0) )
  1774. {
  1775. if (lpUndetA->uYomiTextLen != 0) {
  1776. LPDWORD lpw;
  1777. LPDWORD lpdw;
  1778. lpw = (LPDWORD)((PBYTE)lpUndetA + dwPos);
  1779. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset);
  1780. for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++) {
  1781. *lpw++ = CalcCharacterPositionWtoA(*lpdw++,
  1782. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset),
  1783. CP_ACP
  1784. );
  1785. }
  1786. lpUndetA->uYomiDelimPos = dwPos;
  1787. dwPos += DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen + 1));
  1788. }
  1789. }
  1790. return dwSize;
  1791. }
  1792. DWORD
  1793. CompStrWToStringExW(
  1794. DWORD dwGCS,
  1795. LPCOMPOSITIONSTRING lpCompStrW,
  1796. LPSTRINGEXSTRUCT lpStringExW
  1797. )
  1798. /*++
  1799. Routine Description:
  1800. Convert composition string (Unicode) to StringEx (Unicode).
  1801. Arguments:
  1802. Return Value:
  1803. --*/
  1804. {
  1805. DWORD dwPos;
  1806. DWORD dwSize;
  1807. UINT i;
  1808. dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) +
  1809. DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) +
  1810. DWORD_ALIGN(lpCompStrW->dwResultClauseLen+1) +
  1811. DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) +
  1812. DWORD_ALIGN(lpCompStrW->dwResultReadClauseLen+1);
  1813. if (lpStringExW == NULL) {
  1814. return dwSize;
  1815. }
  1816. dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1);
  1817. lpStringExW->dwSize = dwSize;
  1818. lpStringExW->uDeterminePos = dwPos;
  1819. memcpy((PBYTE)lpStringExW + dwPos,
  1820. (PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset,
  1821. lpCompStrW->dwResultStrLen * sizeof(WCHAR)
  1822. );
  1823. *(LPWSTR)((PBYTE)lpStringExW + dwPos + lpCompStrW->dwResultStrLen*sizeof(WCHAR)) = L'\0';
  1824. dwPos += DWORD_ALIGN(((lpCompStrW->dwResultStrLen + 1)*sizeof(WCHAR)));
  1825. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  1826. (lpCompStrW->dwResultClauseLen > 0) )
  1827. {
  1828. LPDWORD lpw;
  1829. LPDWORD lpdw;
  1830. lpStringExW->uDetermineDelimPos = dwPos;
  1831. lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos);
  1832. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset);
  1833. for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++)
  1834. *lpw++ = *lpdw++;
  1835. dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1));
  1836. }
  1837. lpStringExW->uYomiPos = dwPos;
  1838. memcpy((PBYTE)lpStringExW + dwPos,
  1839. (PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset,
  1840. lpCompStrW->dwResultReadStrLen * sizeof(WCHAR)
  1841. );
  1842. *(LPWSTR)((PBYTE)lpStringExW + dwPos + lpCompStrW->dwResultReadStrLen*sizeof(WCHAR)) = L'\0';
  1843. dwPos += DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen + 1)*sizeof(WCHAR)));
  1844. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  1845. (lpCompStrW->dwResultReadClauseLen > 0) )
  1846. {
  1847. LPDWORD lpw;
  1848. LPDWORD lpdw;
  1849. lpStringExW->uYomiDelimPos = dwPos;
  1850. lpw = (LPDWORD)((PBYTE)lpStringExW + dwPos);
  1851. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset);
  1852. for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++)
  1853. *lpw++ = *lpdw++;
  1854. }
  1855. return dwSize;
  1856. }
  1857. DWORD
  1858. CompStrWToStringExA(
  1859. DWORD dwGCS,
  1860. LPCOMPOSITIONSTRING lpCompStrW,
  1861. LPSTRINGEXSTRUCT lpStringExA
  1862. )
  1863. /*++
  1864. Routine Description:
  1865. Convert composition string (Unicode) to StringEx (ANSI).
  1866. Arguments:
  1867. Return Value:
  1868. --*/
  1869. {
  1870. DWORD dwPos;
  1871. DWORD dwSize;
  1872. DWORD dwLen;
  1873. UINT i;
  1874. BOOL bUDC;
  1875. dwSize = DWORD_ALIGN((sizeof(STRINGEXSTRUCT)+1)) +
  1876. (lpCompStrW->dwResultStrLen > 0 ? DWORD_ALIGN(((lpCompStrW->dwResultStrLen+1) * sizeof(WCHAR))) : 0) +
  1877. (lpCompStrW->dwResultClauseLen > 0 ? DWORD_ALIGN(lpCompStrW->dwResultClauseLen+1) : 0) +
  1878. (lpCompStrW->dwResultReadStrLen > 0 ? DWORD_ALIGN(((lpCompStrW->dwResultReadStrLen+1) * sizeof(WCHAR))) : 0)+
  1879. (lpCompStrW->dwResultReadClauseLen > 0 ? DWORD_ALIGN(lpCompStrW->dwResultReadClauseLen+1) : 0);
  1880. if (lpStringExA == NULL) {
  1881. return dwSize;
  1882. }
  1883. dwPos = DWORD_ALIGN(sizeof(STRINGEXSTRUCT) + 1);
  1884. lpStringExA->dwSize = dwSize;
  1885. if (lpCompStrW->dwResultStrLen > 0) {
  1886. i = WideCharToMultiByte( CP_ACP,
  1887. (DWORD)0,
  1888. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset), // src
  1889. (INT)lpCompStrW->dwResultStrLen,
  1890. (LPSTR)((PBYTE)lpStringExA + dwPos), // dest
  1891. (INT)dwSize - dwPos,
  1892. (LPSTR)NULL,
  1893. (LPBOOL)&bUDC);
  1894. ((LPSTR)((PBYTE)lpStringExA + dwPos))[i] = '\0';
  1895. dwLen = i;
  1896. lpStringExA->uDeterminePos = dwPos;
  1897. dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(CHAR)));
  1898. } else {
  1899. dwLen = 0;
  1900. lpStringExA->uDeterminePos = 0;
  1901. }
  1902. if ( (dwGCS & GCS_RESULTCLAUSE) &&
  1903. (lpCompStrW->dwResultClauseLen > 0) )
  1904. {
  1905. if (dwLen != 0 && lpCompStrW->dwResultClauseLen > 0) {
  1906. LPDWORD lpw;
  1907. LPDWORD lpdw;
  1908. lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos);
  1909. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultClauseOffset);
  1910. for (i = 0; i < (lpCompStrW->dwResultClauseLen / sizeof(DWORD)); i++) {
  1911. *lpw++ = CalcCharacterPositionWtoA(*lpdw++,
  1912. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset),
  1913. CP_ACP
  1914. );
  1915. }
  1916. lpStringExA->uDetermineDelimPos = dwPos;
  1917. dwPos += DWORD_ALIGN((lpCompStrW->dwResultClauseLen + 1));
  1918. }
  1919. }
  1920. if (lpCompStrW->dwResultReadStrLen > 0) {
  1921. i = WideCharToMultiByte( CP_ACP,
  1922. (DWORD)0,
  1923. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset), // src
  1924. (INT)lpCompStrW->dwResultReadStrLen,
  1925. (LPSTR)((PBYTE)lpStringExA + dwPos), // dest
  1926. (INT)dwSize - dwPos,
  1927. (LPSTR)NULL,
  1928. (LPBOOL)&bUDC);
  1929. ((LPSTR)((PBYTE)lpStringExA + dwPos))[i] = '\0';
  1930. dwLen = i;
  1931. lpStringExA->uYomiPos = dwPos;
  1932. dwPos += DWORD_ALIGN(((dwLen + 1)*sizeof(CHAR)));
  1933. } else {
  1934. dwLen = 0;
  1935. lpStringExA->uYomiPos = 0;
  1936. }
  1937. if ( (dwGCS & GCS_RESULTREADCLAUSE) &&
  1938. (lpCompStrW->dwResultReadClauseLen > 0) )
  1939. {
  1940. if (dwLen != 0 && lpCompStrW->dwResultReadClauseLen > 0) {
  1941. LPDWORD lpw;
  1942. LPDWORD lpdw;
  1943. lpw = (LPDWORD)((PBYTE)lpStringExA + dwPos);
  1944. lpdw = (LPDWORD)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadClauseOffset);
  1945. for (i = 0; i < (lpCompStrW->dwResultReadClauseLen / sizeof(DWORD)); i++) {
  1946. *lpw++ = CalcCharacterPositionWtoA(*lpdw++,
  1947. (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultReadStrOffset),
  1948. CP_ACP
  1949. );
  1950. }
  1951. lpStringExA->uYomiDelimPos = dwPos;
  1952. dwPos += DWORD_ALIGN((lpCompStrW->dwResultReadClauseLen + 1));
  1953. }
  1954. }
  1955. return dwSize;
  1956. }
  1957. DWORD
  1958. CompStrWToStringW(
  1959. LPCOMPOSITIONSTRING lpCompStrW,
  1960. LPWSTR lpStringW
  1961. )
  1962. /*++
  1963. Routine Description:
  1964. Convert composition string (Unicode) to String (Unicode).
  1965. Arguments:
  1966. Return Value:
  1967. --*/
  1968. {
  1969. LPWSTR lpwszString;
  1970. DWORD dwSize;
  1971. lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset);
  1972. dwSize = lpCompStrW->dwResultStrLen;
  1973. if (lpStringW == NULL) {
  1974. return ((dwSize + 1) * sizeof(WCHAR));
  1975. }
  1976. memcpy((PBYTE)lpStringW,
  1977. (PBYTE)lpwszString,
  1978. (dwSize * sizeof(WCHAR))
  1979. );
  1980. lpStringW[dwSize] = L'\0';
  1981. return ((dwSize + 1) * sizeof(WCHAR));
  1982. }
  1983. DWORD
  1984. CompStrWToStringA(
  1985. LPCOMPOSITIONSTRING lpCompStrW,
  1986. LPSTR lpStringA
  1987. )
  1988. /*++
  1989. Routine Description:
  1990. Convert composition string (Unicode) to String (ANSI).
  1991. Arguments:
  1992. Return Value:
  1993. --*/
  1994. {
  1995. LPWSTR lpwszString;
  1996. DWORD dwSize;
  1997. UINT i;
  1998. BOOL bUDC;
  1999. lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset);
  2000. i = WideCharToMultiByte( CP_ACP,
  2001. (DWORD)0,
  2002. (LPWSTR)lpwszString, // src
  2003. (INT)lpCompStrW->dwResultStrLen,
  2004. (LPSTR)lpStringA, // dest
  2005. (INT)0,
  2006. (LPSTR)NULL,
  2007. (LPBOOL)&bUDC);
  2008. if (lpStringA == NULL) {
  2009. dwSize = (i+1) * sizeof(CHAR);
  2010. }
  2011. else {
  2012. dwSize = (i+1) * sizeof(CHAR);
  2013. i = WideCharToMultiByte( CP_ACP,
  2014. (DWORD)0,
  2015. (LPWSTR)lpwszString, // src
  2016. (INT)lpCompStrW->dwResultStrLen,
  2017. (LPSTR)lpStringA, // dest
  2018. (INT)dwSize,
  2019. (LPSTR)NULL,
  2020. (LPBOOL)&bUDC);
  2021. lpStringA[i] = '\0';
  2022. dwSize = (i+1) * sizeof(CHAR);
  2023. }
  2024. return dwSize;
  2025. }
  2026. VOID
  2027. CompStrWToCharW(
  2028. HWND hWnd,
  2029. LPCOMPOSITIONSTRING lpCompStrW
  2030. )
  2031. /*++
  2032. Routine Description:
  2033. Convert composition string (Unicode) to WM_CHAR (Unicode).
  2034. Arguments:
  2035. Return Value:
  2036. --*/
  2037. {
  2038. LPWSTR lpwszString;
  2039. lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset);
  2040. // IR_DBCSCHAR: If the app reply to this message with TRUE, we can
  2041. // queue up double byte character in a WM_CHAR message.
  2042. // SendMessageW( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L);
  2043. // Send IR_STRINGSTART prior to anything.
  2044. PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L );
  2045. while(*lpwszString)
  2046. {
  2047. if( *CharNextW(lpwszString) == 0 )
  2048. {
  2049. PostMessageW( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L );
  2050. }
  2051. PostMessageW( hWnd, WM_CHAR, *lpwszString, 1L);
  2052. lpwszString = CharNextW(lpwszString);
  2053. }
  2054. }
  2055. VOID
  2056. CompStrWToCharA(
  2057. HWND hWnd,
  2058. LPCOMPOSITIONSTRING lpCompStrW
  2059. )
  2060. /*++
  2061. Routine Description:
  2062. Convert composition string (Unicode) to WM_CHAR (ANSI).
  2063. Arguments:
  2064. Return Value:
  2065. --*/
  2066. {
  2067. LPWSTR lpwszString;
  2068. BOOL fDBCSWmChar = FALSE;
  2069. WORD wDBCSChar;
  2070. UINT i;
  2071. BOOL bUDC;
  2072. BYTE szAscii[3];
  2073. lpwszString = (LPWSTR)((PBYTE)lpCompStrW + lpCompStrW->dwResultStrOffset);
  2074. //
  2075. // IR_DBCSCHAR: If the app reply to this message with TRUE, we can
  2076. // queue up double byte character in a WM_CHAR message.
  2077. //
  2078. //
  2079. if ( GetClientInfo()->dwExpWinVer >= 0x030A ) {
  2080. fDBCSWmChar = (BOOL)SendMessageA( hWnd,WM_IME_REPORT,IR_DBCSCHAR, 0L);
  2081. }
  2082. //
  2083. // Send IR_STRINGSTART prior to anything.
  2084. //
  2085. PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGSTART, 0L );
  2086. while (*lpwszString) {
  2087. if ( *CharNextW(lpwszString) == 0 ) {
  2088. PostMessageA( hWnd, WM_IME_REPORT, IR_STRINGEND, 0L );
  2089. }
  2090. i = WideCharToMultiByte( CP_ACP,
  2091. (DWORD)0,
  2092. (LPWSTR)lpwszString, // src
  2093. (INT)1,
  2094. (LPSTR)szAscii, // dest
  2095. (INT)sizeof(szAscii),
  2096. (LPSTR)NULL,
  2097. (LPBOOL)&bUDC);
  2098. if (i != 0) {
  2099. if ( IsDBCSLeadByte( szAscii[0] ) ) {
  2100. //
  2101. // If fDBCSWmChar==TRUE, The app can recieve WM_CHARs which
  2102. // have double byte code in wParam.
  2103. //
  2104. if ( fDBCSWmChar )
  2105. {
  2106. //
  2107. // It's necessary to swap bytes to put 1st byte into upper
  2108. // part of wParam, and 2nd byte into lower part.
  2109. //
  2110. wDBCSChar = MAKEWORD(szAscii[1], szAscii[0]);
  2111. PostMessageA( hWnd, WM_CHAR, wDBCSChar|WMCR_IR_DBCSCHAR, 1L );
  2112. }
  2113. else
  2114. {
  2115. //
  2116. // Send each byte on a WM_CHAR
  2117. //
  2118. PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L);
  2119. PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[1]), 1L);
  2120. }
  2121. }
  2122. else
  2123. {
  2124. PostMessageA( hWnd, WM_CHAR, (WPARAM)(szAscii[0]), 1L);
  2125. }
  2126. }
  2127. lpwszString = CharNextW(lpwszString);
  2128. }
  2129. }