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.

1496 lines
44 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: transsub.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains the translation layer functions
  7. * of the sub functions of SendImeMessageEx.
  8. *
  9. * History:
  10. * 21-May-1996 takaok Created.
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. LRESULT TransSetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme );
  15. LRESULT TransSetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme );
  16. LRESULT TransGetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi );
  17. LRESULT TransGetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi );
  18. LRESULT TransMoveImeWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme);
  19. LRESULT TransSetConversionWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme );
  20. LRESULT TransSetConversionMode( HIMC hImc, LPIMESTRUCT lpIme );
  21. LRESULT TransGetMode( HIMC hImc );
  22. LRESULT TransGetConversionMode( HIMC hImc );
  23. LRESULT TransSetMode( HIMC hImc, LPIMESTRUCT lpIme );
  24. LRESULT TransSendVKey( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi );
  25. LRESULT TransEnterWordRegisterMode( HWND hWndApp, LPIMESTRUCT lpIme, BOOL fAnsi);
  26. LRESULT TransSetConversionFontEx( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi);
  27. LRESULT TransHanjaMode( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme);
  28. UINT Get31ModeFrom40ModeJ( DWORD fdwConversion );
  29. UINT Get31ModeFrom40ModeK( DWORD fdwConversion );
  30. LRESULT TransVKDBEMode( HIMC hImc, WPARAM wVKDBE );
  31. BOOL SetFontForMCWVERTICAL( HWND hWndApp, HIMC hImc, LPINPUTCONTEXT pInputContext, BOOL fVert );
  32. BOOL IsForegroundThread( HWND );
  33. BOOL FixLogfont( LPLOGFONTW lplfW, BOOL fVert );
  34. BOOL MySetCompFont( HWND, HIMC, LPLOGFONTW );
  35. BOOL MySetCompWindow( HWND, HIMC, LPCOMPOSITIONFORM );
  36. BOOL MySetCandidateWindow( HWND, HIMC, LPCANDIDATEFORM );
  37. BOOL MyPostImsMessage( HWND hWndApp, WPARAM wParam, LPARAM lParam);
  38. //===================================================================
  39. // TranslateIMESubFunctions
  40. //==========================
  41. //
  42. // KOREAN and JAPANESE common translate routine for the
  43. // sub functions of SendImeMessageEx.
  44. //
  45. // History:
  46. // 21-May-1996 takaok Created.
  47. //
  48. //===================================================================
  49. LRESULT TranslateIMESubFunctions(
  50. HWND hWndApp,
  51. LPIMESTRUCT lpIme,
  52. BOOL fAnsi)
  53. {
  54. HIMC hImc;
  55. LRESULT lRet;
  56. DWORD dwLangID;
  57. hImc = ImmGetSaveContext( hWndApp, IGSC_DEFIMCFALLBACK );
  58. if ( hImc == NULL_HIMC ) {
  59. return FALSE;
  60. }
  61. dwLangID = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID()));
  62. switch (lpIme->fnc) {
  63. case 0x03: // IME_QUERY, IME_GETIMECAPS: KOREAN & JAPANESE
  64. lRet = TRUE;
  65. break;
  66. case 0x04: // IME_SETOPEN: KOREAN & JAPANESE
  67. if ( dwLangID == LANG_KOREAN )
  68. lRet = TransSetOpenK( hWndApp, hImc, lpIme );
  69. else
  70. lRet = TransSetOpenJ( hWndApp, hImc, lpIme );
  71. break;
  72. case 0x05: // IME_GETOPEN: KOREAN & JAPANESE
  73. if ( dwLangID == LANG_KOREAN )
  74. lRet = TransGetOpenK( hWndApp, hImc, lpIme, fAnsi );
  75. else
  76. lRet = TransGetOpenJ( hWndApp, hImc, lpIme, fAnsi );
  77. break;
  78. case 0x06: // IME_ENABLEDOSIME, IME_ENABLE
  79. // internal functions are not supported
  80. lRet = FALSE;
  81. break;
  82. case 0x07: // IME_GETVERSION: KOREAN & JAPANESE
  83. lRet = IMEVER_31;
  84. break;
  85. case 0x08: // IME_MOVEIMEWINDOW, IME_SETCONVERSIONWINDOW: KOREAN & JAPANESE
  86. if ( dwLangID == LANG_KOREAN ) {
  87. //
  88. // IME_MOVEIMEWINDOW for KOREAN
  89. //
  90. lRet = TransMoveImeWindow(hWndApp, hImc, lpIme);
  91. } else {
  92. //
  93. // IME_MOVECONVERTWINDOW or IME_SETCONVERSIONWINDOW for JAPANESE
  94. //
  95. lRet = TransSetConversionWindow( hWndApp, hImc, lpIme );
  96. }
  97. break;
  98. // case 0x09: // undefined
  99. case 0x10: // IME_SETCONVERSIONMODE: JAPANESE
  100. if ( dwLangID == LANG_JAPANESE ) {
  101. lRet = TransSetConversionMode( hImc, lpIme );
  102. } else {
  103. lRet = FALSE;
  104. }
  105. break;
  106. case 0x11: // IME_GETCONVERSIONMODE, IME_GETMODE: // KOREAN & JAPANESE
  107. // Use hSaveIMC, If WINNSEnableIME(FALSE).
  108. if ( dwLangID == LANG_KOREAN ) {
  109. //
  110. // IME_GETMODE for KOREAN
  111. //
  112. lRet = TransGetMode( hImc );
  113. } else {
  114. //
  115. // IME_GETCONVERSIONMODE for JAPANESE
  116. //
  117. lRet = TransGetConversionMode( hImc );
  118. }
  119. break;
  120. case 0x12: // IME_SET_MODE, IME_SETFONT, IME_SETCONVERSIONFONT: KOREAN & JAPANESE
  121. if ( dwLangID == LANG_KOREAN ) {
  122. //
  123. // IME_SET_MODE for KOREAN
  124. //
  125. lRet = TransSetMode( hImc, lpIme );
  126. } else {
  127. //
  128. // IME_SETCONVERSIONFONT for JAPANESE
  129. //
  130. lRet = FALSE; // should not be called. use SETCONVERSIONFONTEX instead
  131. }
  132. break;
  133. case 0x13: // IME_SENDVKEY, IME_SENDKEY: JAPANESE only
  134. if ( dwLangID == LANG_JAPANESE ) {
  135. lRet = TransSendVKey( hWndApp, hImc, lpIme, fAnsi );
  136. } else {
  137. lRet = FALSE;
  138. }
  139. break;
  140. //
  141. // internal sub functions are not supported
  142. //
  143. // case 0x14: // IME_DESTROY, IME_DESTROYIME
  144. // case 0x15: // IME_PRIVATE
  145. // case 0x16: // IME_WINDOWUPDATE
  146. // case 0x17: // IME_SELECT
  147. case 0x18: // IME_ENTERWORDREGISTERMODE: JAPANESE only
  148. if ( dwLangID == LANG_JAPANESE ) {
  149. lRet = TransEnterWordRegisterMode( hWndApp, lpIme, fAnsi);
  150. } else {
  151. lRet = FALSE;
  152. }
  153. break;
  154. case 0x19: // IME_SETCONVERSIONFONTEX: JAPANESE only
  155. if ( dwLangID == LANG_JAPANESE ) {
  156. lRet = TransSetConversionFontEx( hWndApp, hImc, lpIme, fAnsi);
  157. } else {
  158. lRet = FALSE;
  159. }
  160. break;
  161. //
  162. // internal sub functions are not supported
  163. //
  164. // case 0x1A: // IME_DBCSNAME
  165. // case 0x1B: // IME_MAXKEY
  166. // case 0x1C: // IME_WINNLS_SK
  167. case 0x20: // IME_CODECONVERT: KOREAN only
  168. if ( dwLangID == LANG_KOREAN ) {
  169. if (TransCodeConvert( hImc, lpIme))
  170. lRet = lpIme->wParam;
  171. else
  172. lRet = 0;
  173. } else {
  174. lRet = 0;
  175. }
  176. break;
  177. case 0x21: // IME_CONVERTLIST: KOREAN only
  178. if ( dwLangID == LANG_KOREAN ) {
  179. lRet = TransConvertList( hImc, lpIme);
  180. } else {
  181. lRet = FALSE;
  182. }
  183. break;
  184. //
  185. // internal sub functions and undefined sub functions are not supported
  186. //
  187. // case 0x22: // IME_INPUTKEYTOSEQUENCE
  188. // case 0x23: // IME_SEQUENCETOINTERNAL
  189. // case 0x24: // IME_QUERYIMEINFO
  190. // case 0x25: // IME_DIALOG
  191. // case 0x26 - 0x2f: // undefined
  192. case 0x30: // IME_AUTOMATA: KOREAN only
  193. if ( dwLangID == LANG_KOREAN ) {
  194. lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_AUTOMATA, lpIme);
  195. } else {
  196. lRet = FALSE;
  197. }
  198. break;
  199. case 0x31: // IME_HANJAMODE: KOREAN only
  200. if ( dwLangID == LANG_KOREAN ) {
  201. lRet = TransHanjaMode( hWndApp, hImc, lpIme);
  202. } else {
  203. lRet = FALSE;
  204. }
  205. break;
  206. //
  207. // case 0x32 - 0x3f: // undefined
  208. //
  209. case 0x40: // IME_GETLEVEL: KOREAN only
  210. if ( dwLangID == LANG_KOREAN ) {
  211. lRet = TransGetLevel( hWndApp );
  212. } else {
  213. lRet = FALSE;
  214. }
  215. break;
  216. case 0x41: // IME_SETLEVEL: KOREAN only
  217. if ( dwLangID == LANG_KOREAN ) {
  218. lRet = TransSetLevel( hWndApp, lpIme);
  219. } else {
  220. lRet = FALSE;
  221. }
  222. break;
  223. case 0x42: // IME_GETMNTABLE: KOREAN only
  224. if ( dwLangID == LANG_KOREAN ) {
  225. lRet = TransGetMNTable( hImc, lpIme);
  226. } else {
  227. lRet = FALSE;
  228. }
  229. break;
  230. #if defined(PENAPI)
  231. case IME_SETUNDETERMINESTRING:
  232. lRet = FSetUndetermine( hImc, (HGLOBAL)lpIME->lParam1);
  233. break;
  234. case IME_SETCAPTURE:
  235. lRet = FEnablePenUi((HWND)lpIME->wParam, (lpIME->wParam != NULL));
  236. break;
  237. #endif
  238. #ifdef LATER // IME_NOTIFYWOWTASKEXIT
  239. case IME_NOTIFYWOWTASKEXIT:
  240. //
  241. // Destroy the default IME window of WOW 16bit
  242. // applications now. We should not wait for the
  243. // server wow thread clean up that will destroy the
  244. // IME window because usrsrv won't send WM_DESTROY
  245. // to non-server side window procedures. Some IMEs
  246. // must receive WM_DESTROY to free up 32 bit objects.
  247. //
  248. // kksuzuka #7982:IME memory leak on WOW16 applications.
  249. //
  250. PIMMTHREADINFO piti = PitiCurrent();
  251. if ( piti != NULL && IsWindow( piti->hwndDefaultIme ) ) {
  252. DestroyWindow( piti->hwndDefaultIme );
  253. }
  254. return TRUE;
  255. #endif
  256. default:
  257. //
  258. // private/internal/undefined functions are not supported
  259. //
  260. lRet = FALSE;
  261. break;
  262. }
  263. return (lRet);
  264. }
  265. //===================================================================
  266. // TransSetOpenK
  267. //===============
  268. //
  269. // KOREAN only
  270. //
  271. // History:
  272. // xx-xx-1995 xxx Created
  273. //
  274. //===================================================================
  275. LRESULT TransSetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme )
  276. {
  277. // NOTE: We will use this function instead of ImmEscape().
  278. LRESULT lRet;
  279. lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_SETOPEN, lpIme);
  280. return (lRet);
  281. UNREFERENCED_PARAMETER(hWndApp);
  282. }
  283. //===================================================================
  284. // TransSetOpenJ
  285. //===============
  286. //
  287. // Japanese only
  288. //
  289. // History:
  290. // 20-May-1996 takaok Created
  291. //
  292. //===================================================================
  293. LRESULT TransSetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme )
  294. {
  295. LRESULT lRet;
  296. lRet = ImmGetOpenStatus( hImc );
  297. //
  298. // if the owner thread of hIMC doesn't have the input focus,
  299. // we won't call UI.
  300. //
  301. if ( !IsForegroundThread( NULL ) && !GetFocus() ) {
  302. //
  303. // this thread doesn't have focus.
  304. // let's update the input context and return without calling UI
  305. //
  306. PINPUTCONTEXT pInputContext;
  307. if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
  308. if ( (pInputContext->fOpen && ! lpIme->wParam ) ||
  309. (!pInputContext->fOpen && lpIme->wParam ) )
  310. {
  311. pInputContext->fOpen = (BOOL)lpIme->wParam;
  312. ImmNotifyIME( hImc, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
  313. }
  314. ImmUnlockIMC( hImc );
  315. }
  316. } else {
  317. ImmSetOpenStatus( hImc, (BOOL)lpIme->wParam );
  318. }
  319. return lRet;
  320. UNREFERENCED_PARAMETER(hWndApp);
  321. }
  322. //===================================================================
  323. // TransGetOpenK
  324. //===============
  325. //
  326. // KOREAN only
  327. //
  328. // History:
  329. // xx-xx-1995 xxx Created
  330. //
  331. //===================================================================
  332. LRESULT TransGetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi )
  333. {
  334. // NOTE: We will use this function instead of ImmEscape().
  335. RECT rc;
  336. LPARAM lTemp;
  337. LRESULT lRet;
  338. lTemp = lpIme->lParam2;
  339. GetWindowRect(hWndApp, &rc);
  340. lpIme->lParam2 = MAKELONG(rc.top, rc.left);
  341. lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_GETOPEN, lpIme);
  342. lpIme->lParam2 = lTemp;
  343. return (lRet);
  344. UNREFERENCED_PARAMETER(fAnsi);
  345. }
  346. //===================================================================
  347. // TransGetOpenJ
  348. //===============
  349. //
  350. // Japanese only
  351. //
  352. // History:
  353. // 20-May-1996 takaok Created
  354. //
  355. //===================================================================
  356. LRESULT TransGetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi )
  357. {
  358. INT Count;
  359. LRESULT lRet;
  360. lRet = ImmGetOpenStatus( hImc );
  361. // lpIME->wCount is the length of the composition string.
  362. if ( fAnsi ) {
  363. Count= ImmGetCompositionStringA( hImc, GCS_COMPSTR, NULL, 0L );
  364. } else {
  365. Count= ImmGetCompositionStringW( hImc, GCS_COMPSTR, NULL, 0L );
  366. }
  367. lpIme->wCount = ( Count > 0 ) ? Count : 0;
  368. return lRet;
  369. UNREFERENCED_PARAMETER(hWndApp);
  370. }
  371. //===================================================================
  372. // TransMoveImeWindow
  373. //====================
  374. //
  375. // Korean only
  376. //
  377. //===================================================================
  378. LRESULT TransMoveImeWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme)
  379. {
  380. // NOTE: We will use this function instead of ImmEscape().
  381. POINT pt;
  382. LRESULT lRet;
  383. if (lpIme->wParam == MCW_WINDOW)
  384. {
  385. pt.x = GET_X_LPARAM(lpIme->lParam1);
  386. pt.y = GET_Y_LPARAM(lpIme->lParam1);
  387. ClientToScreen(hWndApp, &pt);
  388. lpIme->lParam1 = MAKELONG(pt.x, pt.y);
  389. }
  390. lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_MOVEIMEWINDOW, lpIme);
  391. return (lRet);
  392. }
  393. //===================================================================
  394. // TransSetConversionWindow
  395. //=========================
  396. //
  397. // Japanese only
  398. //
  399. //===================================================================
  400. LRESULT TransSetConversionWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme )
  401. {
  402. LPINPUTCONTEXT pInputContext;
  403. COMPOSITIONFORM cof;
  404. CANDIDATEFORM caf;
  405. POINT pt;
  406. RECT rt;
  407. INT i;
  408. if ( ! IsForegroundThread(NULL) && !GetFocus() ) {
  409. //
  410. // For win95 compatibility, we need to return TRUE though we
  411. // didn't really succeed. PP4 calls us when it doesn't have
  412. // the input focus to check if IME is capable to do the specfied
  413. // MCW_xxx. Returning TRUE here will make such application happy.
  414. //
  415. return ( TRUE );
  416. }
  417. pInputContext = ImmLockIMC( hImc );
  418. if ( pInputContext == NULL ) {
  419. return ( FALSE );
  420. }
  421. pt.x = GET_X_LPARAM(lpIme->lParam1);
  422. pt.y = GET_Y_LPARAM(lpIme->lParam1);
  423. rt.left = GET_X_LPARAM(lpIme->lParam2);
  424. rt.top = GET_Y_LPARAM(lpIme->lParam2);
  425. rt.right = GET_X_LPARAM(lpIme->lParam3);
  426. rt.bottom = GET_Y_LPARAM(lpIme->lParam3);
  427. cof.dwStyle = CFS_DEFAULT;
  428. if ( lpIme->wParam & MCW_HIDDEN ) {
  429. pInputContext->fdw31Compat |= F31COMPAT_MCWHIDDEN;
  430. ScreenToClient( pInputContext->hWnd, &pt );
  431. MapWindowPoints( HWND_DESKTOP, pInputContext->hWnd, (LPPOINT)&rt, 2);
  432. } else {
  433. pInputContext->fdw31Compat &= ~F31COMPAT_MCWHIDDEN;
  434. }
  435. if ( lpIme->wParam & MCW_WINDOW) {
  436. if ( !IsWndEqual(hWndApp, pInputContext->hWnd)) {
  437. ClientToScreen(hWndApp, &pt);
  438. ScreenToClient(pInputContext->hWnd, &pt);
  439. if (lpIme->wParam & MCW_RECT) {
  440. cof.dwStyle = CFS_RECT;
  441. MapWindowPoints(hWndApp, HWND_DESKTOP, (LPPOINT)&rt, 2);
  442. MapWindowPoints(HWND_DESKTOP, pInputContext->hWnd, (LPPOINT)&rt, 2);
  443. } else {
  444. cof.dwStyle = CFS_POINT;
  445. }
  446. } else {
  447. if ( lpIme->wParam & MCW_RECT) {
  448. cof.dwStyle = CFS_RECT;
  449. } else {
  450. cof.dwStyle = CFS_POINT;
  451. }
  452. }
  453. }
  454. // Because Chicago IME can not handle CFS_SCREEN. The points should be
  455. // converted to client point.
  456. // If these points are out of Client, HOW SHOULD WE DO????
  457. if ( lpIme->wParam & MCW_SCREEN ) {
  458. ScreenToClient( pInputContext->hWnd, &pt );
  459. if ( lpIme->wParam & CFS_RECT ) {
  460. cof.dwStyle = CFS_RECT;
  461. MapWindowPoints( HWND_DESKTOP, pInputContext->hWnd, (LPPOINT)&rt, 2 );
  462. }
  463. else {
  464. cof.dwStyle = CFS_POINT;
  465. }
  466. }
  467. if ( lpIme->wParam & MCW_VERTICAL) {
  468. if ( !(pInputContext->fdw31Compat & F31COMPAT_MCWVERTICAL) ) {
  469. pInputContext->fdw31Compat |= F31COMPAT_MCWVERTICAL;
  470. SetFontForMCWVERTICAL( hWndApp, hImc, pInputContext, TRUE);
  471. }
  472. } else {
  473. if (pInputContext->fdw31Compat & F31COMPAT_MCWVERTICAL) {
  474. pInputContext->fdw31Compat &= ~F31COMPAT_MCWVERTICAL;
  475. SetFontForMCWVERTICAL( hWndApp, hImc, pInputContext, FALSE);
  476. }
  477. }
  478. cof.ptCurrentPos = pt;
  479. cof.rcArea = rt;
  480. #if defined(PENAPI)
  481. if ( !FSetPosPenUi(&cof) )
  482. #endif
  483. if ( !(pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) ) {
  484. MySetCompWindow( hWndApp, hImc, (LPCOMPOSITIONFORM)&cof );
  485. } else {
  486. // Hack for 3.1 Apps. We save the exlude area into IMC.
  487. pInputContext->cfCompForm.ptCurrentPos = cof.ptCurrentPos;
  488. pInputContext->cfCompForm.rcArea = cof.rcArea;
  489. for ( i=0; i < 4; i++ ) {
  490. if ( pInputContext->cfCandForm[i].dwIndex != -1)
  491. {
  492. caf.dwIndex = i;
  493. caf.dwStyle = CFS_EXCLUDE;
  494. caf.ptCurrentPos = pt;
  495. caf.rcArea = rt;
  496. MySetCandidateWindow( hWndApp, hImc, (LPCANDIDATEFORM)&caf );
  497. }
  498. }
  499. }
  500. ImmUnlockIMC( hImc );
  501. return ( TRUE );
  502. }
  503. //===================================================================
  504. // TransSetConversionMode
  505. //=======================
  506. //
  507. // Japanese only
  508. //
  509. // History:
  510. // 31-May-1996 takaok Created.
  511. //
  512. //===================================================================
  513. LRESULT TransSetConversionMode( HIMC hImc, LPIMESTRUCT lpIme )
  514. {
  515. DWORD fdwConversion = 0, fdwSentence, fdwNewConversion, fdwMask;
  516. UINT uPrevMode;
  517. UINT u31Mode;
  518. //
  519. // Get current conversion mode and translate it to
  520. // the 3.1 style conversion mode.
  521. //
  522. ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
  523. uPrevMode = Get31ModeFrom40ModeJ( fdwConversion );
  524. //
  525. // translate requested 3.1 conversion mode to 4.0 conversion mode
  526. //
  527. fdwNewConversion = 0;
  528. u31Mode = (UINT)lpIme->wParam;
  529. switch ( u31Mode & 0x07 ) {
  530. case IME_MODE_ALPHANUMERIC:
  531. fdwNewConversion &= ~IME_CMODE_LANGUAGE;
  532. break;
  533. case IME_MODE_KATAKANA:
  534. fdwNewConversion |= IME_CMODE_NATIVE|IME_CMODE_KATAKANA;
  535. break;
  536. case IME_MODE_HIRAGANA:
  537. fdwNewConversion |= IME_CMODE_NATIVE;
  538. break;
  539. }
  540. if ( !(u31Mode & JAPAN_IME_MODE_SBCSCHAR) )
  541. fdwNewConversion |= IME_CMODE_FULLSHAPE;
  542. if ( u31Mode & IME_MODE_ROMAN )
  543. fdwNewConversion |= IME_CMODE_ROMAN;
  544. if ( u31Mode & IME_MODE_CODEINPUT )
  545. fdwNewConversion |= IME_CMODE_CHARCODE;
  546. //
  547. // compute the mask bit. we need to compute this because
  548. // application may set only bit needed to be changed.
  549. //
  550. fdwMask = 0;
  551. if ( u31Mode & (IME_MODE_ROMAN | IME_MODE_NOROMAN) )
  552. fdwMask |= IME_CMODE_ROMAN;
  553. if ( u31Mode & (IME_MODE_CODEINPUT|IME_MODE_NOCODEINPUT) )
  554. fdwMask |= IME_CMODE_CHARCODE;
  555. if ( u31Mode & 0x07 )
  556. fdwMask |= IME_CMODE_LANGUAGE;
  557. if ( u31Mode & (IME_MODE_DBCSCHAR|JAPAN_IME_MODE_SBCSCHAR) )
  558. fdwMask |= IME_CMODE_FULLSHAPE;
  559. //
  560. // set the new mode
  561. //
  562. fdwNewConversion = (fdwNewConversion & fdwMask) | (fdwConversion & ~fdwMask);
  563. if ( ImmSetConversionStatus( hImc, fdwNewConversion, fdwSentence) ) {
  564. return (LRESULT)uPrevMode;
  565. } else {
  566. return (LRESULT)0;
  567. }
  568. }
  569. //===================================================================
  570. // TransGetMode
  571. //==============
  572. //
  573. // Korean only
  574. //
  575. // translate 4.0 conversion mode into 3.1 conversion mode
  576. //
  577. // History:
  578. // 31-May-1996 takaok Created.
  579. //
  580. //===================================================================
  581. LRESULT TransGetMode( HIMC hImc )
  582. {
  583. DWORD fdwConversion = 0, fdwSentence;
  584. UINT u31Mode = 0;
  585. ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
  586. u31Mode= Get31ModeFrom40ModeK( fdwConversion );
  587. // HACK: To prevent 0 result from treating FALSE, we always set MSB
  588. return ( u31Mode | 0x80000000 );
  589. }
  590. //===================================================================
  591. // Get31ModeFrom40ModeK
  592. //=====================
  593. //
  594. // Korean only
  595. //
  596. // translate 4.0 conversion mode into 3.1 conversion mode
  597. //
  598. // History:
  599. // 31-May-1996 takaok Created.
  600. //
  601. //===================================================================
  602. UINT Get31ModeFrom40ModeK( DWORD fdwConversion )
  603. {
  604. UINT u31Mode = 0;
  605. if ( !(fdwConversion & IME_CMODE_NATIVE) ) {
  606. u31Mode |= IME_MODE_ALPHANUMERIC;
  607. }
  608. if ( !(fdwConversion & IME_CMODE_FULLSHAPE) ) {
  609. u31Mode |= KOREA_IME_MODE_SBCSCHAR;
  610. }
  611. if ( fdwConversion & IME_CMODE_HANJACONVERT ) {
  612. u31Mode |= IME_MODE_HANJACONVERT;
  613. }
  614. return u31Mode;
  615. }
  616. //===================================================================
  617. // TransGetConversionMode
  618. //========================
  619. //
  620. // Japanese only
  621. //
  622. // 4.0 conversion mode => 3.1 conversion mode
  623. //
  624. // History:
  625. // 31-May-1996 takaok Created.
  626. //
  627. //===================================================================
  628. LRESULT TransGetConversionMode( HIMC hImc )
  629. {
  630. DWORD fdwConversion = 0, fdwSentence;
  631. UINT u31Mode = 0;
  632. //
  633. // get the 4.0 style conversion mode
  634. //
  635. ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
  636. return Get31ModeFrom40ModeJ( fdwConversion );
  637. }
  638. //===================================================================
  639. // Get31ModeFrom40ModeJ
  640. //======================
  641. //
  642. // Japanese only
  643. //
  644. // 4.0 conversion mode => 3.1 conversion mode
  645. //
  646. // History:
  647. // 31-May-1996 takaok Created.
  648. //
  649. //===================================================================
  650. UINT Get31ModeFrom40ModeJ( DWORD fdwConversion )
  651. {
  652. UINT u31Mode = 0;
  653. //
  654. // translate the 4.0 style mode to the 3.x style conversion mode
  655. //
  656. if (fdwConversion & IME_CMODE_NATIVE) {
  657. if (fdwConversion & IME_CMODE_KATAKANA) {
  658. u31Mode |= IME_MODE_KATAKANA;
  659. } else {
  660. u31Mode |= IME_MODE_HIRAGANA;
  661. }
  662. } else {
  663. u31Mode |= IME_MODE_ALPHANUMERIC;
  664. }
  665. if (fdwConversion & IME_CMODE_FULLSHAPE) {
  666. u31Mode |= IME_MODE_DBCSCHAR;
  667. } else {
  668. u31Mode |= JAPAN_IME_MODE_SBCSCHAR;
  669. }
  670. if (fdwConversion & IME_CMODE_ROMAN) {
  671. u31Mode |= IME_MODE_ROMAN;
  672. } else {
  673. u31Mode |= IME_MODE_NOROMAN;
  674. }
  675. if (fdwConversion & IME_CMODE_CHARCODE) {
  676. u31Mode |= IME_MODE_CODEINPUT;
  677. } else {
  678. u31Mode |= IME_MODE_NOCODEINPUT;
  679. }
  680. return (u31Mode);
  681. }
  682. //===================================================================
  683. // TransSetMode
  684. //==============
  685. //
  686. // KOREAN only
  687. //
  688. //===================================================================
  689. LRESULT TransSetMode( HIMC hImc, LPIMESTRUCT lpIme )
  690. {
  691. DWORD fdwConversion = 0, fdwSentence, fdwNewConversion, fdwMask;
  692. UINT uPrevMode;
  693. UINT u31Mode;
  694. //
  695. // Get current conversion mode and translate it to
  696. // the 3.1 style conversion mode.
  697. //
  698. ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
  699. uPrevMode = Get31ModeFrom40ModeK( fdwConversion );
  700. //
  701. // translate requested 3.1 conversion mode to 4.0 conversion mode
  702. //
  703. fdwNewConversion = 0;
  704. u31Mode = (UINT)lpIme->wParam;
  705. if ( !(u31Mode & IME_MODE_ALPHANUMERIC) )
  706. fdwNewConversion |= IME_CMODE_HANGEUL;
  707. if ( !(u31Mode & KOREA_IME_MODE_SBCSCHAR) )
  708. fdwConversion |= IME_CMODE_FULLSHAPE;
  709. //
  710. // In HWin3.1 there is no "not modification mode"
  711. //
  712. fdwMask = IME_CMODE_LANGUAGE|IME_CMODE_FULLSHAPE|IME_CMODE_HANJACONVERT;
  713. //
  714. // set the new mode
  715. //
  716. fdwNewConversion = (fdwNewConversion & fdwMask) | (fdwConversion & ~fdwMask);
  717. if ( ImmSetConversionStatus( hImc, fdwNewConversion, fdwSentence) ) {
  718. return (LRESULT)uPrevMode;
  719. } else {
  720. return (LRESULT)0;
  721. }
  722. return FALSE;
  723. }
  724. //===================================================================
  725. // TransSendVKey
  726. //===============
  727. //
  728. // Japanese only
  729. //
  730. //===================================================================
  731. LRESULT TransSendVKey( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi )
  732. {
  733. LRESULT lRet;
  734. switch (lpIme->wParam)
  735. {
  736. // VK_DBE_xxx Support Check.
  737. case (DWORD)(-1):
  738. case (DWORD)(0x0000ffff): // from WOW16
  739. switch (lpIme->wCount)
  740. {
  741. case VK_DBE_ALPHANUMERIC:
  742. case VK_DBE_KATAKANA:
  743. case VK_DBE_HIRAGANA:
  744. case VK_DBE_SBCSCHAR:
  745. case VK_DBE_DBCSCHAR:
  746. case VK_DBE_ROMAN:
  747. case VK_DBE_NOROMAN:
  748. case VK_DBE_CODEINPUT:
  749. case VK_DBE_NOCODEINPUT:
  750. case VK_DBE_ENTERWORDREGISTERMODE:
  751. case VK_DBE_ENTERIMECONFIGMODE:
  752. case VK_DBE_ENTERDLGCONVERSIONMODE:
  753. case VK_DBE_DETERMINESTRING:
  754. case VK_DBE_FLUSHSTRING:
  755. case VK_CONVERT:
  756. lRet = TRUE;
  757. break;
  758. default:
  759. lRet = FALSE;
  760. break;
  761. }
  762. break;
  763. case VK_DBE_ALPHANUMERIC:
  764. case VK_DBE_KATAKANA:
  765. case VK_DBE_HIRAGANA:
  766. case VK_DBE_SBCSCHAR:
  767. case VK_DBE_DBCSCHAR:
  768. case VK_DBE_ROMAN:
  769. case VK_DBE_NOROMAN:
  770. case VK_DBE_CODEINPUT:
  771. case VK_DBE_NOCODEINPUT:
  772. lRet = TransVKDBEMode(hImc, lpIme->wParam);
  773. break;
  774. case VK_DBE_ENTERWORDREGISTERMODE:
  775. {
  776. HKL hkl = GetKeyboardLayout(0L);
  777. if ( fAnsi )
  778. lRet = ImmConfigureIMEA(hkl, hWndApp, IME_CONFIG_REGISTERWORD, NULL);
  779. else
  780. lRet = ImmConfigureIMEW(hkl, hWndApp, IME_CONFIG_REGISTERWORD, NULL);
  781. }
  782. break;
  783. case VK_DBE_ENTERIMECONFIGMODE:
  784. {
  785. HKL hkl = GetKeyboardLayout(0L);
  786. if (fAnsi)
  787. lRet = ImmConfigureIMEA(hkl, hWndApp, IME_CONFIG_GENERAL, NULL);
  788. else
  789. lRet = ImmConfigureIMEW(hkl, hWndApp, IME_CONFIG_GENERAL, NULL);
  790. }
  791. break;
  792. case VK_DBE_ENTERDLGCONVERSIONMODE:
  793. #if defined(PENAPI)
  794. FInitPenUi(hIMC);
  795. #endif
  796. lRet = FALSE;
  797. break;
  798. case VK_DBE_DETERMINESTRING:
  799. // Check there is the composition string or not.
  800. lRet = ImmNotifyIME( ImmGetContext(hWndApp),
  801. NI_COMPOSITIONSTR,
  802. CPS_COMPLETE,
  803. 0L);
  804. break;
  805. case VK_DBE_FLUSHSTRING:
  806. lRet = ImmNotifyIME( hImc, NI_COMPOSITIONSTR,CPS_CANCEL,0L);
  807. break;
  808. case VK_CONVERT:
  809. lRet = ImmNotifyIME( hImc, NI_COMPOSITIONSTR, CPS_CONVERT, 0L);
  810. break;
  811. default:
  812. lRet = FALSE;
  813. break;
  814. }
  815. return lRet;
  816. }
  817. //===================================================================
  818. // TransEnterWordRegisterMode
  819. //===========================
  820. //
  821. // Japanese only
  822. //
  823. //===================================================================
  824. LRESULT TransEnterWordRegisterMode( HWND hWndApp, LPIMESTRUCT lpIme, BOOL fAnsi)
  825. {
  826. LRESULT lRet;
  827. HKL hkl = GetKeyboardLayout(0L);
  828. if ( ! ImmIsIME(hkl) ) {
  829. return FALSE;
  830. }
  831. if ( fAnsi ) {
  832. //
  833. // ANSI
  834. //
  835. REGISTERWORDA stReg = {NULL, NULL};
  836. LPSTR lpsz1, lpsz2;
  837. if (lpIme->lParam1&&(lpsz1=GlobalLock((HGLOBAL)lpIme->lParam1))) {
  838. stReg.lpWord = lpsz1;
  839. }
  840. if (lpIme->lParam2&&(lpsz2=GlobalLock((HGLOBAL)lpIme->lParam2))) {
  841. stReg.lpReading = lpsz2;
  842. }
  843. lRet = ImmConfigureIMEA(hkl,hWndApp,IME_CONFIG_REGISTERWORD, (LPVOID)&stReg);
  844. if (lpIme->lParam1 && lpsz1)
  845. GlobalUnlock((HGLOBAL)lpIme->lParam1);
  846. if (lpIme->lParam2 && lpsz2)
  847. GlobalUnlock((HGLOBAL)lpIme->lParam2);
  848. } else {
  849. //
  850. // UNICODE
  851. //
  852. REGISTERWORDW stReg = {NULL, NULL};
  853. LPWSTR lpsz1, lpsz2;
  854. if (lpIme->lParam1&&(lpsz1=GlobalLock((HGLOBAL)lpIme->lParam1))) {
  855. stReg.lpWord = lpsz1;
  856. }
  857. if (lpIme->lParam2&&(lpsz2=GlobalLock((HGLOBAL)lpIme->lParam2))) {
  858. stReg.lpReading = lpsz2;
  859. }
  860. lRet = ImmConfigureIMEW(hkl,hWndApp,IME_CONFIG_REGISTERWORD, (LPVOID)&stReg);
  861. if (lpIme->lParam1 && lpsz1)
  862. GlobalUnlock((HGLOBAL)lpIme->lParam1);
  863. if (lpIme->lParam2 && lpsz2)
  864. GlobalUnlock((HGLOBAL)lpIme->lParam2);
  865. }
  866. return lRet;
  867. }
  868. //===================================================================
  869. // TransSetConversionFontEx
  870. //==========================
  871. //
  872. // Japanese only
  873. //
  874. //===================================================================
  875. LRESULT TransSetConversionFontEx( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi)
  876. {
  877. LPINPUTCONTEXT pInputContext;
  878. LRESULT lRet;
  879. LPLOGFONTW lplf;
  880. LOGFONTW lfw;
  881. pInputContext = ImmLockIMC( hImc );
  882. if ( pInputContext == NULL ) {
  883. return 0L;
  884. }
  885. lplf = (LPLOGFONTW)GlobalLock((HGLOBAL)lpIme->lParam1);
  886. if ( lplf == NULL )
  887. {
  888. ImmUnlockIMC( hImc );
  889. return 0L;
  890. }
  891. if ( fAnsi ) {
  892. memcpy( &lfw, lplf, sizeof(LOGFONTA) );
  893. MultiByteToWideChar( CP_ACP,
  894. 0,
  895. (LPCSTR)lplf->lfFaceName, // src
  896. LF_FACESIZE, // size of src
  897. lfw.lfFaceName, // destination buffer
  898. LF_FACESIZE ); // size of destination buffer
  899. } else {
  900. memcpy( &lfw, lplf, sizeof(LOGFONTW));
  901. }
  902. GlobalUnlock((HGLOBAL)lpIme->lParam1);
  903. if (( pInputContext->fdw31Compat & F31COMPAT_MCWVERTICAL)) {
  904. lRet = FixLogfont( &lfw, TRUE);
  905. } else {
  906. lRet = FixLogfont( &lfw, FALSE);
  907. }
  908. ImmUnlockIMC( hImc );
  909. if (lRet == FALSE ) {
  910. return FALSE;
  911. }
  912. return MySetCompFont( hWndApp, hImc, &lfw );
  913. }
  914. //===================================================================
  915. // TransHanjaMode
  916. //================
  917. //
  918. // Korean only
  919. //
  920. //===================================================================
  921. LRESULT TransHanjaMode( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme)
  922. {
  923. // NOTE We will use this function instead of ImmEscape().
  924. LRESULT lRet;
  925. PIMEDPI pImeDpi;
  926. DWORD dwThreadId = GetInputContextThread(hImc);
  927. if (dwThreadId == 0) {
  928. RIPMSG1(RIP_WARNING,
  929. "TransHanjaMode: GetInputContextThread(%lx) failed.", hImc);
  930. return FALSE;
  931. }
  932. pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId));
  933. if (pImeDpi == NULL)
  934. return FALSE;
  935. /*
  936. * Check if we need ANSI/Unicode conversion
  937. */
  938. if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) {
  939. WCHAR wUni;
  940. CHAR chAnsi[2];
  941. UINT i, dchSource;
  942. //The 4th word of imestruct32 contains dchSource
  943. dchSource = *((LPSTR)lpIme + 3 * sizeof(WORD));
  944. chAnsi[0] = *((LPSTR)lpIme + dchSource);
  945. chAnsi[1] = *((LPSTR)lpIme + dchSource + 1);
  946. i = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, chAnsi, 2, &wUni, 1);
  947. if (i) {
  948. *((LPSTR)lpIme + dchSource) = (CHAR)LOWORD(LOBYTE(wUni));
  949. *((LPSTR)lpIme + dchSource+1) = (CHAR)LOWORD(HIBYTE(wUni));
  950. }
  951. else {
  952. ImmUnlockImeDpi(pImeDpi);
  953. return FALSE;
  954. }
  955. }
  956. ImmUnlockImeDpi(pImeDpi);
  957. if (lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_HANJAMODE, lpIme))
  958. SendMessage(hWndApp, WM_IME_NOTIFY, IMN_OPENCANDIDATE, 1L);
  959. return (lRet);
  960. }
  961. //===================================================================
  962. // TransGetLevel
  963. //===============
  964. //
  965. // Korean only
  966. //
  967. //===================================================================
  968. LRESULT TransGetLevel( HWND hWndApp )
  969. {
  970. UINT lRet;
  971. if ( (lRet = NtUserGetAppImeLevel( hWndApp )) == 0 )
  972. lRet = 1; // default level
  973. return lRet;
  974. }
  975. //===================================================================
  976. // TransSetLevel
  977. //===============
  978. //
  979. // Korean only
  980. //
  981. //===================================================================
  982. LRESULT TransSetLevel( HWND hWndApp, LPIMESTRUCT lpIme)
  983. {
  984. DWORD dwLevel;
  985. dwLevel = (DWORD)lpIme->wParam;
  986. if ( dwLevel >= 1 && dwLevel <= 5 ) {
  987. if ( NtUserSetAppImeLevel(hWndApp, dwLevel) ) {
  988. return TRUE;
  989. }
  990. }
  991. return FALSE;
  992. }
  993. //===================================================================
  994. // TransVKDBEMode
  995. //================
  996. //
  997. // Japanese only
  998. //
  999. //===================================================================
  1000. LRESULT TransVKDBEMode( HIMC hImc, WPARAM wVKDBE )
  1001. {
  1002. DWORD fdwConversion,fdwSentence;
  1003. if (!ImmGetConversionStatus(hImc, &fdwConversion, &fdwSentence)) {
  1004. return FALSE;
  1005. }
  1006. switch (wVKDBE)
  1007. {
  1008. case VK_DBE_ALPHANUMERIC:
  1009. fdwConversion &= ~IME_CMODE_LANGUAGE;
  1010. break;
  1011. case VK_DBE_KATAKANA:
  1012. fdwConversion |= (IME_CMODE_JAPANESE | IME_CMODE_KATAKANA);
  1013. break;
  1014. case VK_DBE_HIRAGANA:
  1015. fdwConversion &= ~IME_CMODE_KATAKANA;
  1016. fdwConversion |= IME_CMODE_JAPANESE;
  1017. break;
  1018. case VK_DBE_SBCSCHAR:
  1019. fdwConversion &= ~IME_CMODE_FULLSHAPE;
  1020. break;
  1021. case VK_DBE_DBCSCHAR:
  1022. fdwConversion |= IME_CMODE_FULLSHAPE;
  1023. break;
  1024. case VK_DBE_ROMAN:
  1025. fdwConversion |= IME_CMODE_ROMAN;
  1026. break;
  1027. case VK_DBE_NOROMAN:
  1028. fdwConversion &= ~IME_CMODE_ROMAN;
  1029. break;
  1030. case VK_DBE_CODEINPUT:
  1031. fdwConversion |= IME_CMODE_CHARCODE;
  1032. break;
  1033. case VK_DBE_NOCODEINPUT:
  1034. fdwConversion &= ~IME_CMODE_CHARCODE;
  1035. break;
  1036. default:
  1037. break;
  1038. }
  1039. return ImmSetConversionStatus(hImc, fdwConversion, fdwSentence);
  1040. }
  1041. //===================================================================
  1042. // IsForegroundThread
  1043. //===================
  1044. //
  1045. // Check if the caller thread has the foreground window.
  1046. // If hwnd is specified, the function checks if the creator
  1047. // thread of the specified window has the foreground window.
  1048. //
  1049. //===================================================================
  1050. BOOL IsForegroundThread(HWND hwnd)
  1051. {
  1052. HWND hwndFG;
  1053. DWORD dwThreadId;
  1054. hwndFG = GetForegroundWindow();
  1055. if ( IsWindow( hwnd ) ) {
  1056. dwThreadId = GetWindowThreadProcessId( hwnd, NULL );
  1057. } else {
  1058. dwThreadId = GetCurrentThreadId();
  1059. }
  1060. return ( GetWindowThreadProcessId(hwndFG,NULL) == dwThreadId );
  1061. }
  1062. //===================================================================
  1063. // SetFontForMCWVERTICAL
  1064. //======================
  1065. //
  1066. // Japanese only
  1067. //
  1068. // set/reset vertical writing font
  1069. //
  1070. //===================================================================
  1071. BOOL SetFontForMCWVERTICAL( HWND hWndApp, HIMC hImc, LPINPUTCONTEXT pInputContext, BOOL fVert )
  1072. {
  1073. LOGFONTW lf;
  1074. PCLIENTIMC pClientImc;
  1075. if ( pInputContext->fdwInit & INIT_LOGFONT) {
  1076. //
  1077. // If a font has ever been set, use it
  1078. //
  1079. BOOL fAnsi;
  1080. memcpy(&lf,&pInputContext->lfFont.W,sizeof(LOGFONTW));
  1081. //
  1082. // check if the input context is unicode
  1083. //
  1084. pClientImc = ImmLockClientImc( hImc );
  1085. if (pClientImc == NULL) {
  1086. return FALSE;
  1087. }
  1088. fAnsi = ! TestICF( pClientImc, IMCF_UNICODE );
  1089. ImmUnlockClientImc( pClientImc );
  1090. if ( fAnsi ) {
  1091. CHAR FaceNameA[ LF_FACESIZE ];
  1092. //
  1093. // we need a temporary buffer because MultiByteToWideChar
  1094. // doesn't allow us to specify src==dest.
  1095. //
  1096. memcpy( FaceNameA, &lf.lfFaceName, LF_FACESIZE );
  1097. MultiByteToWideChar( CP_ACP,
  1098. 0,
  1099. FaceNameA, // src
  1100. LF_FACESIZE, // size of src
  1101. lf.lfFaceName, // destination buffer
  1102. LF_FACESIZE ); // size of destination buffer
  1103. }
  1104. } else {
  1105. //
  1106. // system font should be used as the default font
  1107. //
  1108. GetObjectW( GetStockObject(SYSTEM_FONT), sizeof(lf), (LPVOID)&lf );
  1109. }
  1110. //
  1111. // put/remove '@' from the font facename.
  1112. // "@facename" means vertical writing font
  1113. //
  1114. if ( FixLogfont( &lf, fVert ) == FALSE ) {
  1115. return FALSE;
  1116. }
  1117. return MySetCompFont( hWndApp, hImc, &lf );
  1118. }
  1119. //===================================================================
  1120. // FixLogfont
  1121. //============
  1122. //
  1123. // Japanese only
  1124. //
  1125. // put/remove '@' from the font facename.
  1126. // "@facename" means vertical writing font
  1127. //
  1128. //===================================================================
  1129. BOOL FixLogfont( LPLOGFONTW lplfW, BOOL fVert )
  1130. {
  1131. int i;
  1132. if ( fVert ) {
  1133. //
  1134. // convert the specified font to vertical writing font
  1135. //
  1136. lplfW->lfEscapement = 2700;
  1137. lplfW->lfOrientation = 2700;
  1138. if ((lplfW->lfCharSet == SHIFTJIS_CHARSET) && (lplfW->lfFaceName[0] != L'@')) {
  1139. for(i=0;lplfW->lfFaceName[i];++i) // Search NULL
  1140. if (i > (LF_FACESIZE-2)) // if not remain 2 char
  1141. return FALSE; // then error
  1142. // Because insert @ char
  1143. for( ; i>=0 ; --i ) // Copy facename from tail
  1144. lplfW->lfFaceName[i+1] = lplfW->lfFaceName[i];
  1145. lplfW->lfFaceName[0] = L'@'; // insert @ character
  1146. }
  1147. } else {
  1148. //
  1149. // convert the specified font to normal font
  1150. //
  1151. lplfW->lfEscapement = 0;
  1152. lplfW->lfOrientation = 0;
  1153. if ((lplfW->lfCharSet == SHIFTJIS_CHARSET) && (lplfW->lfFaceName[0] == L'@'))
  1154. lstrcpynW(lplfW->lfFaceName,&(lplfW->lfFaceName[1]),LF_FACESIZE-1);
  1155. }
  1156. return TRUE;
  1157. }
  1158. //===================================================================
  1159. // MySetCompFont
  1160. //==============
  1161. //
  1162. // Japanese only
  1163. //
  1164. //===================================================================
  1165. BOOL MySetCompFont( HWND hWndApp, HIMC hImc, LPLOGFONTW lplf )
  1166. {
  1167. BOOL lRet = FALSE;
  1168. DWORD dwCompat;
  1169. PINPUTCONTEXT pInputContext;
  1170. PCLIENTIMC pClientImc;
  1171. LOGFONTW lfw;
  1172. LPLOGFONTW lplfw = &lfw;
  1173. BOOL fUnicode;
  1174. // BOGUS!!
  1175. // Some application call SendIMEMessage(IME_SETCONVERSIONFONT)
  1176. // when the apps is handling WM_PAINT.
  1177. // New Win95 IME try to draw the UI during calling ImmSetCompositionFont,
  1178. // and WM_PAINT will be sent in the API....
  1179. // To avoid this thing, WINNLS makes the notification to IME and APPS later.
  1180. // ........
  1181. if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
  1182. dwCompat = ImmGetAppCompatFlags( hImc );
  1183. pClientImc = ImmLockClientImc(hImc);
  1184. if (pClientImc != NULL) {
  1185. fUnicode = TestICF(pClientImc, IMCF_UNICODE);
  1186. ImmUnlockClientImc(pClientImc);
  1187. if ( fUnicode )
  1188. lplfw = &(pInputContext->lfFont.W);
  1189. else
  1190. LFontAtoLFontW( &(pInputContext->lfFont.A), lplfw );
  1191. if ( RtlEqualMemory(lplfw, lplf, sizeof(LOGFONTA)-LF_FACESIZE)
  1192. && !lstrcmp(lplfw->lfFaceName, lplf->lfFaceName) ) {
  1193. /*
  1194. * Don't inform IME ahd UI when logfont is not changed.
  1195. */
  1196. lRet = TRUE;
  1197. } else if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG ) {
  1198. memcpy( &(pInputContext->lfFont.W), lplf, sizeof(LOGFONT));
  1199. if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG2 )
  1200. /*
  1201. * BOGUS!! for PageMaker5J
  1202. */
  1203. lRet = PostMessage( hWndApp, WM_IME_SYSTEM, IMS_SETCOMPOSITIONFONT, 0 );
  1204. else
  1205. lRet = MyPostImsMessage( hWndApp, IMS_SETCOMPOSITIONFONT, 0);
  1206. } else {
  1207. lRet = ImmSetCompositionFont( hImc, lplf );
  1208. }
  1209. }
  1210. ImmUnlockIMC( hImc );
  1211. }
  1212. return lRet;
  1213. }
  1214. //===================================================================
  1215. // MySetCompWindow
  1216. //================
  1217. //
  1218. // Japanese only
  1219. //
  1220. //===================================================================
  1221. BOOL MySetCompWindow(
  1222. HWND hWndApp,
  1223. HIMC hImc,
  1224. LPCOMPOSITIONFORM lpcof
  1225. )
  1226. {
  1227. BOOL fRet = FALSE;
  1228. DWORD dwCompat;
  1229. PINPUTCONTEXT pInputContext;
  1230. // BOGUS!!
  1231. // Some application call SendIMEMessage(IME_SETCONVERSIONWINDOW)
  1232. // when the apps is handling WM_PAINT.
  1233. // New Win95 IME try to draw the UI during calling ImmSetCompositionWindow,
  1234. // and WM_PAINT will be sent in the API....
  1235. // To avoid this thing, WINNLS makes the notification to IME and APPS later.
  1236. // ........
  1237. if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
  1238. dwCompat = ImmGetAppCompatFlags( hImc );
  1239. if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG ) {
  1240. memcpy( &(pInputContext->cfCompForm), lpcof, sizeof(COMPOSITIONFORM));
  1241. if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG2 ) {
  1242. /*
  1243. * BOGUS!! for PageMaker5J
  1244. */
  1245. fRet = PostMessage( hWndApp, WM_IME_SYSTEM, IMS_SETCOMPOSITIONWINDOW, 0 );
  1246. } else {
  1247. fRet = MyPostImsMessage( hWndApp, IMS_SETCOMPOSITIONWINDOW, 0 );
  1248. }
  1249. } else {
  1250. pInputContext->fdw31Compat |= F31COMPAT_CALLFROMWINNLS;
  1251. fRet = ImmSetCompositionWindow( hImc, lpcof );
  1252. }
  1253. ImmUnlockIMC( hImc );
  1254. }
  1255. return fRet;
  1256. }
  1257. //===================================================================
  1258. // MySetCandidateWindow
  1259. //=====================
  1260. //
  1261. // Japanese only
  1262. //
  1263. //===================================================================
  1264. BOOL MySetCandidateWindow( HWND hWndApp, HIMC hImc, LPCANDIDATEFORM lpcaf)
  1265. {
  1266. BOOL fRet = FALSE;
  1267. DWORD dwCompat;
  1268. PINPUTCONTEXT pInputContext;
  1269. // BOGUS!!
  1270. // Some application call SendIMEMessage(IME_SETCONVERSIONWINDOW)
  1271. // when the apps is handling WM_PAINT.
  1272. // New Win95 IME try to draw the UI during calling ImmSetCandidateWindow,
  1273. // and WM_PAINT will be sent in the API....
  1274. // To avoid this thing, WINNLS makes the notification to IME and APPS later.
  1275. // ........
  1276. if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
  1277. dwCompat = ImmGetAppCompatFlags( hImc );
  1278. if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG ) {
  1279. memcpy( &(pInputContext->cfCandForm[lpcaf->dwIndex]), lpcaf, sizeof(CANDIDATEFORM));
  1280. fRet = MyPostImsMessage( hWndApp, IMS_SETCANDIDATEPOS, lpcaf->dwIndex );
  1281. } else {
  1282. fRet = ImmSetCandidateWindow( hImc, lpcaf );
  1283. }
  1284. ImmUnlockIMC( hImc );
  1285. }
  1286. return fRet;
  1287. }
  1288. //===================================================================
  1289. // MyPostImsMessage
  1290. //==================
  1291. //
  1292. // Japanese only
  1293. //
  1294. // BOGUS!!
  1295. // Some application call SendIMEMessage(IME_SETCONVERSIONWINDOW)
  1296. // when the apps is handling WM_PAINT.
  1297. // New Win95 IME try to draw the UI during calling ImmSetCompositionWindow,
  1298. // and WM_PAINT will be sent in the API....
  1299. // To avoid this thing, WINNLS makes the notification to IME and APPS later.
  1300. // ........
  1301. //===================================================================
  1302. BOOL MyPostImsMessage( HWND hWndApp, WPARAM wParam, LPARAM lParam )
  1303. {
  1304. HWND hDefIMEWnd;
  1305. BOOL fRet = FALSE;
  1306. hDefIMEWnd = ImmGetDefaultIMEWnd(hWndApp);
  1307. if ( hDefIMEWnd != NULL ) {
  1308. if ( PostMessage( hDefIMEWnd, WM_IME_SYSTEM, wParam, lParam) ) {
  1309. fRet = TRUE;
  1310. }
  1311. }
  1312. return fRet;
  1313. }