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.

1762 lines
64 KiB

  1. /****************************************************************************
  2. APIENTRY.CPP
  3. Owner: cslim
  4. Copyright (c) 1997-1999 Microsoft Corporation
  5. API entries between IMM32 and IME
  6. History:
  7. 14-JUL-1999 cslim Copied from IME98 source tree
  8. *****************************************************************************/
  9. #include "precomp.h"
  10. #include "apientry.h"
  11. #include "common.h"
  12. #include "ui.h"
  13. #include "hauto.h"
  14. #include "dllmain.h"
  15. #include "hanja.h"
  16. #include "escape.h"
  17. #include "config.h"
  18. #include "names.h"
  19. #include "winex.h"
  20. #include "hanja.h"
  21. #include "cpadsvr.h"
  22. #include "debug.h"
  23. ///////////////////////////////////////////////////////////////////////////////
  24. // ImeMenu Define
  25. #define NUM_ROOT_MENU_L 4
  26. #define NUM_ROOT_MENU_R 1
  27. #define NUM_SUB_MENU_L 0
  28. #define NUM_SUB_MENU_R 0
  29. #define IDIM_ROOT_ML_1 0x10
  30. #define IDIM_ROOT_ML_2 0x11
  31. #define IDIM_ROOT_ML_3 0x12
  32. #define IDIM_ROOT_ML_4 0x13
  33. #define IDIM_ROOT_MR_1 0x30
  34. ///////////////////////////////////////////////////////////////////////////////
  35. // Private function Declarations
  36. PRIVATE BOOL IsInSystemSetupMode();
  37. PRIVATE BOOL IsRunningAsLocalSystem();
  38. PRIVATE BOOL IsRunningInOOBE();
  39. PRIVATE BOOL PASCAL Select(HIMC hImc, BOOL fSelect);
  40. PRIVATE VOID PASCAL UpdateOpenCloseState(PCIMECtx pImeCtx);
  41. PRIVATE VOID PASCAL ToAsciiExHangulMode(PCIMECtx pImeCtx, UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState);
  42. PRIVATE BOOL PASCAL ToAsciiExHanja(PCIMECtx pImeCtx, UINT uVirKey, CONST LPBYTE lpbKeyState);
  43. PRIVATE WCHAR PASCAL Banja2Junja(WCHAR bChar);
  44. PRIVATE BOOL PASCAL IsKSC5601(WCHAR wcCur);
  45. /*----------------------------------------------------------------------------
  46. ImeInquire
  47. This function handle initialization of IME. It also returns IMEINFO structure
  48. and UI class name of IME
  49. ----------------------------------------------------------------------------*/
  50. BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPTSTR lpszWndClass, DWORD dwSystemInfoFlags)
  51. {
  52. BOOL fRet = fFalse;
  53. Dbg(DBGID_API, TEXT("ImeInquire():lpIMEInfo = 0x%08lX, dwSystemInfoFlags = 0x%08lX"), lpIMEInfo, dwSystemInfoFlags);
  54. if (lpIMEInfo)
  55. {
  56. lpIMEInfo->dwPrivateDataSize = sizeof(IMCPRIVATE); // The private data in an IME context.
  57. lpIMEInfo->fdwProperty = IME_PROP_AT_CARET // IME conversion window is at caret position.
  58. | IME_PROP_NEED_ALTKEY // ALT key pass into ImeProcessKey
  59. | IME_PROP_CANDLIST_START_FROM_1 // Candidate list start from 1
  60. | IME_PROP_END_UNLOAD;
  61. if (IsMemphis() || IsWinNT5orUpper())
  62. lpIMEInfo->fdwProperty |= IME_PROP_COMPLETE_ON_UNSELECT; // Complete when IME unselected.
  63. lpIMEInfo->fdwConversionCaps = IME_CMODE_NATIVE // IMEs in NATIVE mode else ALPHANUMERIC mode
  64. | IME_CMODE_FULLSHAPE // else in SBCS mode
  65. | IME_CMODE_HANJACONVERT;// Hangul hanja conversion
  66. lpIMEInfo->fdwSentenceCaps = 0; // IME sentence mode capability
  67. lpIMEInfo->fdwUICaps = 0;
  68. lpIMEInfo->fdwSCSCaps = SCS_CAP_COMPSTR; // IME can generate the composition string by SCS_SETSTR
  69. lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; // ImeSetCompositionString capability
  70. // Set Unicode flag if system support it
  71. if (vfUnicode == fTrue)
  72. lpIMEInfo->fdwProperty |= IME_PROP_UNICODE; // String content of the Input Context will be UNICODE
  73. // NT5 Unicode injection through VK_PACKET
  74. if (IsWinNT5orUpper())
  75. lpIMEInfo->fdwProperty |= IME_PROP_ACCEPT_WIDE_VKEY;
  76. // Return Unicode string for Unicode environment
  77. #ifndef UNDER_CE // Windows CE always Unicode
  78. if (vfUnicode == fTrue)
  79. StrCopyW((LPWSTR)lpszWndClass, wszUIClassName);
  80. else
  81. lstrcpyA(lpszWndClass, szUIClassName);
  82. #else // UNDER_CE
  83. lstrcpyW(lpszWndClass, wszUIClassName);
  84. #endif // UNDER_CE
  85. fRet = fTrue;
  86. }
  87. //////////////////////////////////////////////////////////////////////////
  88. // 16 bit application check
  89. // If client is 16 bit Apps, only allow KS C-5601 chars.
  90. if (IsWinNT())
  91. {
  92. // Win98 does not pass dwSystemInfoFlags;
  93. vpInstData->dwSystemInfoFlags = dwSystemInfoFlags;
  94. if (dwSystemInfoFlags & IME_SYSINFO_WOW16)
  95. vpInstData->f16BitApps = fTrue;
  96. // If in MT setup mode(system setup, upgrading and OOBE), display IME status window.
  97. if (IsInSystemSetupMode())
  98. vpInstData->dwSystemInfoFlags |= IME_SYSINFO_WINLOGON;
  99. }
  100. else
  101. {
  102. // user GetProcessVersion
  103. DWORD dwVersion = GetProcessVersion(GetCurrentProcessId());
  104. // Windowss 3.x
  105. if (HIWORD(dwVersion) <= 3)
  106. {
  107. vpInstData->f16BitApps = fTrue;
  108. #ifdef DEBUG
  109. DebugOutT(TEXT("!!! 16bit Apps running under Win9x !!!\r\n"));
  110. #endif
  111. }
  112. }
  113. // If 16bit apps, always disable ISO10646(full range Hangul)
  114. if (vpInstData->f16BitApps == fTrue)
  115. vpInstData->fISO10646 = fFalse;
  116. return fRet;
  117. }
  118. /*----------------------------------------------------------------------------
  119. ImeConversionList
  120. obtain the list of candidate list from one character
  121. ----------------------------------------------------------------------------*/
  122. DWORD WINAPI ImeConversionList(HIMC hIMC, LPCTSTR lpSource, LPCANDIDATELIST lpDest, DWORD dwBufLen, UINT uFlag)
  123. {
  124. WCHAR wchHanja;
  125. Dbg(DBGID_API, TEXT("ImeConversionList():hIMC = 0x%08lX, *lpSource = %04X, dwBufLen =%08lX"), hIMC, *(LPWSTR)lpSource, dwBufLen);
  126. if (hIMC == NULL)
  127. return 0;
  128. if (lpSource == NULL || *(LPWSTR)lpSource == 0)
  129. return 0;
  130. // If dwBufLen==0 then should return buffer size
  131. if (dwBufLen && lpDest == NULL)
  132. return 0;
  133. //
  134. // Code Conversion
  135. //
  136. // CONFIRM: Win98 send Unicode or not?
  137. if (IsMemphis() || IsWinNT())
  138. wchHanja = *(LPWSTR)lpSource;
  139. else
  140. {
  141. if (MultiByteToWideChar(CP_KOREA, MB_PRECOMPOSED, lpSource, 2, &wchHanja, 1) == 0)
  142. return 0;
  143. }
  144. switch (uFlag)
  145. {
  146. case GCL_CONVERSION:
  147. return GetConversionList(wchHanja, lpDest, dwBufLen);
  148. break;
  149. case GCL_REVERSECONVERSION:
  150. case GCL_REVERSE_LENGTH:
  151. break;
  152. default:
  153. DbgAssert(0);
  154. }
  155. return (0);
  156. }
  157. /*----------------------------------------------------------------------------
  158. ImeConfigure
  159. Open IME configuration DLG
  160. ----------------------------------------------------------------------------*/
  161. BOOL WINAPI ImeConfigure(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
  162. {
  163. BOOL fRet = fFalse;
  164. Dbg (DBGID_API, TEXT("ImeConfigure():hKL = 0x%08lX, dwMode = 0x%08lX"), hKL, dwMode);
  165. switch (dwMode)
  166. {
  167. case IME_CONFIG_GENERAL:
  168. if (ConfigDLG(hWnd))
  169. fRet = fTrue;
  170. break;
  171. default:
  172. break;
  173. }
  174. return fRet;
  175. }
  176. /*----------------------------------------------------------------------------
  177. ImeDestroy
  178. ----------------------------------------------------------------------------*/
  179. BOOL WINAPI ImeDestroy(UINT uReserved)
  180. {
  181. Dbg(DBGID_API, TEXT("ImeDestroy(): Bye *-<\r\nSee Again !"));
  182. if (uReserved)
  183. return (fFalse);
  184. else
  185. return (fTrue);
  186. }
  187. /*----------------------------------------------------------------------------
  188. ImeEscape
  189. Support Korean IME escape functions
  190. ----------------------------------------------------------------------------*/
  191. LRESULT WINAPI ImeEscape(HIMC hIMC, UINT uSubFunc, LPVOID lpData)
  192. {
  193. PCIMECtx pImeCtx = GetIMECtx(hIMC);
  194. LRESULT lRet;
  195. if (lpData == NULL || pImeCtx == NULL)
  196. return 0;
  197. Dbg(DBGID_API, TEXT("ImeEscape():hIMC = 0x%08lX, uSubFunc = 0x%08lX"), hIMC, uSubFunc);
  198. switch (uSubFunc)
  199. {
  200. case IME_ESC_AUTOMATA:
  201. lRet = EscAutomata(pImeCtx, (LPIMESTRUCT32)lpData, fTrue);
  202. break;
  203. case IME_AUTOMATA:
  204. lRet = EscAutomata(pImeCtx, (LPIMESTRUCT32)lpData, fFalse);
  205. break;
  206. case IME_GETOPEN:
  207. lRet = EscGetOpen(pImeCtx, (LPIMESTRUCT32)lpData);
  208. break;
  209. // Popup Hanja candidate window
  210. case IME_ESC_HANJA_MODE:
  211. if (lRet = EscHanjaMode(pImeCtx, (LPSTR)lpData, fTrue))
  212. {
  213. pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
  214. pImeCtx->GenerateMessage();
  215. }
  216. break;
  217. // 16bit apps(Win 3.1) compatibility
  218. case IME_HANJAMODE:
  219. if (lRet = EscHanjaMode(pImeCtx, (LPSTR)lpData, fFalse))
  220. {
  221. pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
  222. pImeCtx->GenerateMessage();
  223. }
  224. break;
  225. case IME_SETOPEN:
  226. lRet = EscSetOpen(pImeCtx, (LPIMESTRUCT32)lpData);
  227. break;
  228. case IME_MOVEIMEWINDOW:
  229. lRet = EscMoveIMEWindow(pImeCtx, (LPIMESTRUCT32)lpData);
  230. break;
  231. case 0x1100:
  232. lRet = EscGetIMEKeyLayout(pImeCtx, (LPIMESTRUCT32)lpData);
  233. break;
  234. default:
  235. Dbg(DBGID_Misc, TEXT("Unknown ImeEscape() subfunc(#0x%X) is called."), uSubFunc);
  236. return (0);
  237. }
  238. return (lRet);
  239. }
  240. /*----------------------------------------------------------------------------
  241. ImeSetActiveContext
  242. ----------------------------------------------------------------------------*/
  243. BOOL WINAPI ImeSetActiveContext(HIMC hIMC, BOOL fActive)
  244. {
  245. Dbg(DBGID_API, TEXT("ImeSetActiveContext():hIMC = 0x%08lX, fActive = 0x%d"), hIMC, fActive);
  246. // Initialize composition context. For Korean IME, don't need to kee composition str,
  247. // when context changed.
  248. //if (pImeCtx)
  249. //{
  250. //pImeCtx->ClearCompositionStrBuffer();
  251. //pImeCtx->GetAutomata()->InitState();
  252. //pImeCtx->ResetComposition();
  253. //}
  254. // CONFIRM: Is this really safe to disable?
  255. #if 0
  256. LPINPUTCONTEXT lpIMC;
  257. LPCOMPOSITIONSTRING lpCompStr;
  258. Dbg(DBGID_API, _T("ImeSetActiveContext():hIMC = 0x%08lX, fActive = 0x%d"), hIMC, fActive);
  259. if (!hIMC)
  260. return fFalse;
  261. lpIMC = ImmLockIMC(hIMC);
  262. if (!lpIMC)
  263. return fFalse;
  264. if (fActive)
  265. {
  266. if (lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr))
  267. {
  268. if (lpCompStr->dwCompStrLen)
  269. {
  270. CIMEData ImeData;
  271. // if composition character mismatched with Automata object's reset with lpCompStr
  272. // I'm really suspicious when this situation occurs. I think never occur... -cslim
  273. if (pInstData->pMachine->GetCompositionChar()
  274. != *(LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset))
  275. {
  276. pInstData->pMachine->InitState();
  277. pInstData->pMachine->
  278. SetCompositionChar(*(LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset));
  279. }
  280. }
  281. ImmUnlockIMCC(lpIMC->hCompStr);
  282. }
  283. }
  284. ImmUnlockIMC(hIMC);
  285. #endif
  286. return fTrue;
  287. }
  288. /*----------------------------------------------------------------------------
  289. ImeProcessKey
  290. Return fTrue if IME should process the key
  291. ----------------------------------------------------------------------------*/
  292. BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT uVirKey, LPARAM lParam, CONST LPBYTE lpbKeyState)
  293. {
  294. PCIMECtx pImeCtx;
  295. WORD uScanCode;
  296. BOOL fRet = fFalse;
  297. Dbg(DBGID_API, TEXT("ImeProcessKey():hIMC=0x%08lX, uVKey=0x%04X, lParam=0x%08lX"), hIMC, uVirKey, lParam);
  298. if (lpbKeyState == NULL)
  299. return fFalse;
  300. // NT5 Unicode injection
  301. uVirKey = (UINT)LOWORD(uVirKey);
  302. uScanCode = HIWORD(lParam);
  303. if (uVirKey == VK_PROCESSKEY) // Mouse button clicked
  304. {
  305. Dbg(DBGID_Key, TEXT("ImeProcessKey : return fTrue - Mouse Button Pressed"));
  306. return fTrue;
  307. }
  308. else if (uScanCode & KF_UP)
  309. {
  310. Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - KF_UP"));
  311. return (fFalse);
  312. }
  313. else if (uVirKey == VK_SHIFT) // no SHIFT key
  314. {
  315. Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - VK_SHIFT"));
  316. return (fFalse);
  317. }
  318. else if (uVirKey == VK_CONTROL) // no CTRL key
  319. {
  320. Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - VK_CONTROL"));
  321. return (fFalse);
  322. }
  323. else if (uVirKey == VK_HANGUL || uVirKey == VK_JUNJA || uVirKey == VK_HANJA)
  324. {
  325. Dbg(DBGID_Key, TEXT("ImeProcessKey : return fTrue - VK_HANGUL, VK_JUNJA, VK_HANJA"));
  326. return (fTrue);
  327. }
  328. else
  329. {
  330. // need more check
  331. }
  332. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  333. return fFalse;
  334. // If IME close, return with no action.
  335. if (pImeCtx->IsOpen() == fFalse)
  336. {
  337. Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - IME closed"));
  338. return fFalse;
  339. }
  340. // If Hanja conv mode return fTrue. ImeToAsciiEx will handle.
  341. if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
  342. {
  343. return fTrue;
  344. }
  345. // If interim state
  346. if (pImeCtx->GetCompBufLen())
  347. {
  348. // If ALT key down and in composition process, finalize it.
  349. if (uVirKey == VK_MENU)
  350. {
  351. Dbg(DBGID_Key, TEXT("ImeProcessKey : Finalize and return fFalse - VK_MENU"));
  352. pImeCtx->FinalizeCurCompositionChar();
  353. pImeCtx->GenerateMessage();
  354. }
  355. else
  356. {
  357. Dbg(DBGID_Key, TEXT("ImeProcessKey : Interim state. Key pressed except ALT"));
  358. fRet = fTrue;
  359. }
  360. }
  361. else // If composition string does not exist,
  362. {
  363. // if Ctrl+xx key, do not process in non-interim mode
  364. if (IsControlKeyPushed(lpbKeyState) == fFalse)
  365. {
  366. // If Hangul mode
  367. if (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)
  368. { // Start of hangul composition
  369. WORD wcCur = 0;
  370. if (pImeCtx->GetAutomata() != NULL)
  371. {
  372. wcCur = pImeCtx->GetAutomata()->GetKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 );
  373. }
  374. // 2beolsik Alphanumeric keys have same layout as English key
  375. // So we don't need process when user pressed Alphanumeric key under 2beolsik
  376. if ( (wcCur && pImeCtx->GetGData() && pImeCtx->GetGData()->GetCurrentBeolsik() != KL_2BEOLSIK) || (wcCur & H_HANGUL) )
  377. fRet = fTrue;
  378. }
  379. // if IME_CMODE_FULLSHAPE
  380. if (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE)
  381. {
  382. if (CHangulAutomata::GetEnglishKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0))
  383. fRet = fTrue;
  384. }
  385. }
  386. }
  387. // NT 5 Unicode injection
  388. if (uVirKey == VK_PACKET)
  389. {
  390. Dbg(DBGID_Key, TEXT("ImeProcessKey : VK_PACKET"));
  391. fRet = fTrue;
  392. }
  393. Dbg(DBGID_Key, TEXT("ImeProcessKey : return value = %d"), fRet);
  394. return fRet;
  395. }
  396. /*----------------------------------------------------------------------------
  397. NotifyIME
  398. Change the status of IME according to the given parameter
  399. ----------------------------------------------------------------------------*/
  400. BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
  401. {
  402. PCIMECtx pImeCtx;
  403. BOOL fRet = fFalse;
  404. Dbg(DBGID_API, TEXT("NotifyIME():hIMC = 0x%08lX, dwAction = 0x%08lX, dwIndex = 0x%08lX, dwValue = 0x%08lX"), hIMC, dwAction, dwIndex, dwValue);
  405. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  406. return fFalse;
  407. switch (dwAction)
  408. {
  409. case NI_COMPOSITIONSTR:
  410. switch (dwIndex)
  411. {
  412. //////////////////////////////////////////////////////////
  413. case CPS_COMPLETE:
  414. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_COMPOSITIONSTR-CPS_COMPLETE"));
  415. // If composition state
  416. if (pImeCtx->GetCompBufLen())
  417. {
  418. // For ESC_HANJAMODE call this, we should reset comp str.
  419. pImeCtx->ResetComposition();
  420. pImeCtx->SetResultStr(pImeCtx->GetCompBufStr());
  421. pImeCtx->SetEndComposition(fTrue);
  422. pImeCtx->StoreComposition();
  423. // Raid #104
  424. if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
  425. {
  426. // Cancel Hanja change mode
  427. pImeCtx->SetConversionMode(pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT);
  428. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
  429. }
  430. // Clear all automata states
  431. pImeCtx->GetAutomata()->InitState();
  432. pImeCtx->GenerateMessage();
  433. fRet = fTrue;
  434. }
  435. break;
  436. //////////////////////////////////////////////////////////
  437. case CPS_CANCEL:
  438. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_COMPOSITIONSTR-CPS_CANCEL"));
  439. // if composition string exist, remove it and send WM_IME_ENDCOMPOSITION
  440. if (pImeCtx->GetCompBufLen())
  441. {
  442. pImeCtx->SetEndComposition(fTrue);
  443. pImeCtx->GenerateMessage();
  444. pImeCtx->ClearCompositionStrBuffer();
  445. fRet = fTrue;
  446. }
  447. break;
  448. //////////////////////////////////////////////////////////
  449. case CPS_CONVERT:
  450. case CPS_REVERT:
  451. default:
  452. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_COMPOSITIONSTR-CPS_CONVERT or CPS_REVERT !!! NOT IMPMLEMENTED !!!"));
  453. break;
  454. } // switch (dwIndex)
  455. break;
  456. case NI_OPENCANDIDATE:
  457. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_OPENCANDIDATE"));
  458. // if not Hanja mocde
  459. if (!(pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT))
  460. {
  461. if (pImeCtx->GetCompBufLen() && GenerateHanjaCandList(pImeCtx))
  462. {
  463. pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
  464. // Set Hanja conv mode
  465. pImeCtx->SetConversionMode(pImeCtx->GetConversionMode() | IME_CMODE_HANJACONVERT);
  466. OurSendMessage(pImeCtx->GetAppWnd(), WM_IME_NOTIFY, IMN_SETCONVERSIONMODE, 0L);
  467. pImeCtx->GenerateMessage();
  468. fRet = fTrue;
  469. }
  470. }
  471. break;
  472. case NI_CLOSECANDIDATE:
  473. if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
  474. {
  475. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
  476. // Set clear Hanja conv mode
  477. pImeCtx->SetConversionMode(pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT);
  478. // To Notify to UI wnd
  479. OurSendMessage(pImeCtx->GetAppWnd(), WM_IME_NOTIFY, IMN_SETCONVERSIONMODE, 0L);
  480. pImeCtx->GenerateMessage();
  481. fRet = fTrue;
  482. }
  483. break;
  484. case NI_SELECTCANDIDATESTR:
  485. case NI_SETCANDIDATE_PAGESTART:
  486. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_SETCANDIDATE_PAGESTART"));
  487. if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
  488. {
  489. pImeCtx->SetCandStrSelection(dwValue);
  490. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CHANGECAND);
  491. pImeCtx->GenerateMessage();
  492. fRet = fTrue;
  493. }
  494. break;
  495. case NI_CONTEXTUPDATED:
  496. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED"));
  497. switch (dwValue)
  498. {
  499. case IMC_SETOPENSTATUS:
  500. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED - IMC_SETOPENSTATUS"));
  501. Dbg(DBGID_IMENotify, TEXT("pImeCtx->GetConversionMode() = 0x%08lX"), pImeCtx->GetConversionMode());
  502. UpdateOpenCloseState(pImeCtx);
  503. fRet = fTrue;
  504. break;
  505. case IMC_SETCONVERSIONMODE:
  506. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED - IMC_SETCONVERSIONMODE"));
  507. Dbg(DBGID_IMENotify, TEXT("pImeCtx->GetConversionMode() = 0x%08lX"), pImeCtx->GetConversionMode());
  508. UpdateOpenCloseState(pImeCtx);
  509. fRet = fTrue;
  510. break;
  511. //case IMC_SETSTATUSWINDOWPOS:
  512. case IMC_SETCANDIDATEPOS:
  513. case IMC_SETCOMPOSITIONFONT:
  514. case IMC_SETCOMPOSITIONWINDOW:
  515. //DbgAssert(0);
  516. fRet = fTrue;
  517. break;
  518. default:
  519. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED - Unhandeled IMC value = 0x%08lX"), dwValue);
  520. break;
  521. } // switch (dwValue)
  522. break;
  523. case NI_IMEMENUSELECTED:
  524. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_IMEMENUSELECTED"));
  525. switch (dwIndex)
  526. {
  527. case IDIM_ROOT_MR_1:
  528. // BUGBUG: NT Bug #379149
  529. // Because Internat uses SendMessage, If user does not cancel the DLG, Deadlock occurs.
  530. // ImeConfigure(GetKeyboardLayout(NULL), pImeCtx->GetAppWnd(), IME_CONFIG_GENERAL, NULL);
  531. OurPostMessage(GetActiveUIWnd(), WM_MSIME_PROPERTY, 0L, IME_CONFIG_GENERAL);
  532. break;
  533. case IDIM_ROOT_ML_4:
  534. fRet = OurImmSetConversionStatus(hIMC,
  535. (pImeCtx->GetConversionMode() & ~IME_CMODE_HANGUL) | IME_CMODE_FULLSHAPE,
  536. pImeCtx->GetSentenceMode());
  537. break;
  538. case IDIM_ROOT_ML_3:
  539. fRet = OurImmSetConversionStatus(hIMC,
  540. pImeCtx->GetConversionMode() & ~(IME_CMODE_HANGUL | IME_CMODE_FULLSHAPE),
  541. pImeCtx->GetSentenceMode());
  542. break;
  543. case IDIM_ROOT_ML_2:
  544. fRet = OurImmSetConversionStatus(hIMC,
  545. pImeCtx->GetConversionMode() | IME_CMODE_HANGUL | IME_CMODE_FULLSHAPE,
  546. pImeCtx->GetSentenceMode());
  547. break;
  548. case IDIM_ROOT_ML_1:
  549. fRet = OurImmSetConversionStatus(hIMC,
  550. (pImeCtx->GetConversionMode() | IME_CMODE_HANGUL) & ~IME_CMODE_FULLSHAPE,
  551. pImeCtx->GetSentenceMode());
  552. break;
  553. } // switch (dwIndex)
  554. break;
  555. case NI_CHANGECANDIDATELIST:
  556. case NI_FINALIZECONVERSIONRESULT:
  557. case NI_SETCANDIDATE_PAGESIZE:
  558. default:
  559. Dbg(DBGID_IMENotify, TEXT("NotifyIME(): Unhandeled NI_ value = 0x%08lX"), dwAction);
  560. break;
  561. } // switch (dwAction)
  562. return fRet;
  563. }
  564. /*----------------------------------------------------------------------------
  565. ImeSelect
  566. Initialize/Uninitialize IME private context
  567. ----------------------------------------------------------------------------*/
  568. BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) // fTrue-initialize, fFalse-uninitialize(free resource)
  569. {
  570. BOOL fRet = fFalse;
  571. Dbg(DBGID_API, TEXT("ImeSelect():hIMC = 0x%08lX, fSelect = 0x%d"), hIMC, fSelect);
  572. if (!hIMC) // if invalid input context handle
  573. {
  574. DbgAssert(0);
  575. return fFalse;
  576. }
  577. // If DLL_PROCESS_DETACH already called once.
  578. if (vfDllDetachCalled)
  579. {
  580. return fFalse;
  581. }
  582. fRet = Select(hIMC, fSelect);
  583. return fRet;
  584. }
  585. /*----------------------------------------------------------------------------
  586. ImeSetCompositionString
  587. ----------------------------------------------------------------------------*/
  588. BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPVOID lpComp,
  589. DWORD dwCompLen, LPVOID lpRead, DWORD dwReadLen)
  590. {
  591. PCIMECtx pImeCtx;
  592. WCHAR wcComp;
  593. BOOL fSendStart,
  594. fRet = fFalse;
  595. Dbg(DBGID_API|DBGID_SetComp, TEXT("ImeSetCompositionString():hIMC = 0x%08lX, dwIndex = 0x%08lX, lpComp = 0x%04X"), hIMC, dwIndex, *(LPWSTR)lpComp);
  596. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  597. return fFalse;
  598. if (dwIndex == SCS_SETSTR)
  599. {
  600. // Conv mode check
  601. if ((pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)==0)
  602. {
  603. Dbg(DBGID_API|DBGID_SetComp, TEXT("!!! WARNING !!!: ImeSetCompositionString(): English mode"));
  604. return fFalse;
  605. }
  606. // Send WM_IME_STARTCOMPOSITION if not interim state.
  607. fSendStart = pImeCtx->GetCompBufLen() ? fFalse : fTrue;
  608. wcComp = L'\0';
  609. // Parameter check
  610. if (lpComp != NULL && *(LPWSTR)lpComp != L'\0' && dwCompLen != 0)
  611. {
  612. if (pImeCtx->IsUnicodeEnv())
  613. wcComp = *(LPWSTR)lpComp;
  614. else
  615. if (MultiByteToWideChar(CP_KOREA, MB_PRECOMPOSED, (LPSTR)lpComp, 2, &wcComp, 1) == 0)
  616. {
  617. DbgAssert(0);
  618. wcComp = 0;
  619. }
  620. // Hangul range check
  621. if ( (wcComp > 0x3130 && wcComp < 0x3164) ||
  622. (wcComp >= 0xAC00 && wcComp < 0xD7A4) )
  623. {
  624. pImeCtx->SetCompositionStr(wcComp);
  625. pImeCtx->StoreComposition();
  626. }
  627. else
  628. {
  629. Dbg(DBGID_SetComp, TEXT("!!! WARNING !!!: lpComp is null or Input character is not Hangul"));
  630. DbgAssert(0);
  631. wcComp = 0;
  632. }
  633. }
  634. // Send WM_IME_STARTCOMPOSITION
  635. if (fSendStart)
  636. pImeCtx->SetStartComposition(fTrue);
  637. // REVIEW: Even if wcComp ==0, Should send WM_IME_COMPOSITION
  638. // Send composition char
  639. //SetTransBuffer(lpTransMsg, WM_IME_COMPOSITION,
  640. // (WPARAM)wcComp, (GCS_COMPSTR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
  641. // Set Automata state if non-null comp char
  642. if (wcComp)
  643. pImeCtx->GetAutomata()->SetCompositionChar(wcComp);
  644. else
  645. {
  646. // REVIEW: Even if wcComp ==0, Should send WM_IME_COMPOSITION
  647. pImeCtx->ClearCompositionStrBuffer();
  648. pImeCtx->AddMessage(WM_IME_COMPOSITION, 0, (GCS_COMPSTR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
  649. pImeCtx->SetEndComposition(fTrue);
  650. pImeCtx->GetAutomata()->InitState();
  651. }
  652. // Generate IME message
  653. pImeCtx->GenerateMessage();
  654. fRet = fTrue;
  655. }
  656. return fRet;
  657. }
  658. /*----------------------------------------------------------------------------
  659. ImeToAsciiEx
  660. ----------------------------------------------------------------------------*/
  661. UINT WINAPI ImeToAsciiEx(UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState,
  662. LPTRANSMSGLIST lpTransBuf, UINT fuState, HIMC hIMC)
  663. {
  664. PCIMECtx pImeCtx;
  665. UINT uNumMsg=0;
  666. WORD bKeyCode;
  667. Dbg(DBGID_API, TEXT("ImeToAsciiEx(): hIMC = 0x%08lX, uVirKey = 0x%04X, uScanCode = 0x%04X"), hIMC, uVirKey, uScanCode);
  668. Dbg(DBGID_Key, TEXT("lpbKeyState = 0x%08lX, lpdwTransBuf = 0x%08lX, fuState = 0x%04X"), lpbKeyState, lpTransBuf, fuState);
  669. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  670. return 0;
  671. // Start process key
  672. pImeCtx->SetProcessKeyStatus(fTrue);
  673. // special message buffer for ToAsciiEx()
  674. pImeCtx->SetTransMessage(lpTransBuf);
  675. ///////////////////////////////////////////////////////////////////////////
  676. // If Hanja conv mode
  677. if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
  678. {
  679. if (ToAsciiExHanja(pImeCtx, uVirKey, lpbKeyState) == fFalse)
  680. goto ToAsciiExExit_NoMsg;
  681. }
  682. else
  683. {
  684. ///////////////////////////////////////////////////////////////////////////
  685. // W2K specific - Unicode injection
  686. if (LOWORD(uVirKey) == VK_PACKET)
  687. {
  688. WCHAR wch = HIWORD(uVirKey);
  689. Dbg(DBGID_Key, TEXT("ImeToAsciiEx: VK_PACKET arrived(NonHanja conv mode)"));
  690. // If composition char exist, first finalize and append injection char, then send all.
  691. if (pImeCtx->GetCompBufLen())
  692. {
  693. pImeCtx->FinalizeCurCompositionChar();
  694. pImeCtx->AppendResultStr(wch);
  695. }
  696. else
  697. // If no composition char exist, just insert injection char as finalized char.
  698. pImeCtx->SetResultStr(wch);
  699. goto ToAsciiExExit;
  700. }
  701. ///////////////////////////////////////////////////////////////////////////
  702. // If Non-Hanja conv mode
  703. switch (uVirKey)
  704. {
  705. case VK_PROCESSKEY: // if mouse button clicked
  706. Dbg(DBGID_Key, TEXT("ImeToAsciiEx : VK_PROCESSKEY"));
  707. if (pImeCtx->GetCompBufLen())
  708. pImeCtx->FinalizeCurCompositionChar();
  709. break;
  710. case VK_HANGUL :
  711. Dbg(DBGID_Key, " - VK_HANGUL");
  712. if (pImeCtx->GetCompBufLen())
  713. pImeCtx->FinalizeCurCompositionChar();
  714. OurImmSetConversionStatus(hIMC,
  715. pImeCtx->GetConversionMode()^IME_CMODE_HANGUL,
  716. pImeCtx->GetSentenceMode());
  717. UpdateOpenCloseState(pImeCtx);
  718. break;
  719. case VK_JUNJA :
  720. Dbg(DBGID_Key, TEXT(" - VK_JUNJA"));
  721. if (pImeCtx->GetCompBufLen())
  722. pImeCtx->FinalizeCurCompositionChar();
  723. pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
  724. OurImmSetConversionStatus(hIMC,
  725. pImeCtx->GetConversionMode()^IME_CMODE_FULLSHAPE,
  726. pImeCtx->GetSentenceMode());
  727. UpdateOpenCloseState(pImeCtx);
  728. break;
  729. case VK_HANJA :
  730. Dbg(DBGID_Key, TEXT(" - VK_HANJA"));
  731. if (pImeCtx->GetCompBufLen())
  732. {
  733. // Keep current composition str
  734. pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
  735. if (GenerateHanjaCandList(pImeCtx))
  736. {
  737. pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
  738. OurImmSetConversionStatus(hIMC,
  739. pImeCtx->GetConversionMode() | IME_CMODE_HANJACONVERT,
  740. pImeCtx->GetSentenceMode());
  741. }
  742. }
  743. else
  744. pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
  745. break;
  746. default :
  747. // if hangul mode
  748. if (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)
  749. ToAsciiExHangulMode(pImeCtx, uVirKey, uScanCode, lpbKeyState);
  750. else
  751. // if junja mode
  752. if ( (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE)
  753. && (bKeyCode = CHangulAutomata::GetEnglishKeyMap(uVirKey,
  754. (IsShiftKeyPushed(lpbKeyState) ? 1 : 0))) )
  755. {
  756. if (uVirKey >= 'A' && uVirKey <= 'Z')
  757. {
  758. bKeyCode = CHangulAutomata::GetEnglishKeyMap(uVirKey,
  759. (IsShiftKeyPushed(lpbKeyState) ? 1 : 0)
  760. ^ ((lpbKeyState[VK_CAPITAL] & 0x01) ? 1: 0));
  761. }
  762. bKeyCode = Banja2Junja(bKeyCode);
  763. pImeCtx->SetResultStr(bKeyCode);
  764. }
  765. // Unknown mode
  766. else
  767. {
  768. DbgAssert(0);
  769. pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
  770. }
  771. } // switch (uVirKey)
  772. }
  773. ToAsciiExExit:
  774. pImeCtx->StoreComposition();
  775. //pImeCtx->StoreCandidate();
  776. pImeCtx->FinalizeMessage(); // final setup for IME Messages
  777. ToAsciiExExit_NoMsg:
  778. uNumMsg = pImeCtx->GetMessageCount();
  779. pImeCtx->ResetMessage(); // reset
  780. pImeCtx->SetTransMessage((LPTRANSMSGLIST)NULL);// start process key
  781. pImeCtx->SetProcessKeyStatus(fFalse);
  782. return (uNumMsg);
  783. }
  784. /*----------------------------------------------------------------------------
  785. ToAsciiExHangulMode
  786. Subroutine used by ImeToAsciiEx.
  787. ----------------------------------------------------------------------------*/
  788. VOID PASCAL ToAsciiExHangulMode(PCIMECtx pImeCtx, UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState)
  789. {
  790. CHangulAutomata* pAutomata;
  791. WCHAR wcCur;
  792. UINT uNumMsg=0;
  793. Dbg(DBGID_API, TEXT("ToAsciiExHangulMode()"));
  794. pAutomata = pImeCtx->GetAutomata();
  795. DbgAssert(pAutomata != NULL);
  796. switch (uVirKey)
  797. {
  798. ///////////////////////////////////////////////////////////
  799. // Back space processing
  800. case VK_BACK :
  801. Dbg(DBGID_Key, TEXT("ImeToAsciiEx : VK_BACK"));
  802. if (pAutomata->BackSpace())
  803. {
  804. wcCur = pAutomata->GetCompositionChar();
  805. if (pImeCtx->GetGData() && pImeCtx->GetGData()->GetJasoDel() == fFalse)
  806. {
  807. pAutomata->InitState();
  808. wcCur = 0;
  809. }
  810. if (wcCur)
  811. {
  812. pImeCtx->SetCompositionStr(wcCur);
  813. break;
  814. }
  815. else
  816. {
  817. Dbg(DBGID_Key, TEXT("ImeToAsciiEx : VK_BACK - Empty char"));
  818. // Send Empty Composition stringto clear message
  819. pImeCtx->AddMessage(WM_IME_COMPOSITION, 0, (GCS_COMPSTR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
  820. // Send Close composition window message
  821. pImeCtx->SetEndComposition(fTrue);
  822. break;
  823. }
  824. }
  825. else
  826. {
  827. // BUG :
  828. DbgAssert(0);
  829. // Put the Backspace message into return buffer.
  830. pImeCtx->AddMessage(WM_CHAR, (WPARAM)VK_BACK, (LPARAM)0x000E0001L); //(uScanCode << 16) | 1UL
  831. }
  832. break;
  833. default :
  834. // Ctrl+xx processing bug #60
  835. if (IsControlKeyPushed(lpbKeyState))
  836. {
  837. pImeCtx->FinalizeCurCompositionChar();
  838. pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
  839. }
  840. else
  841. switch (pAutomata->Machine(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 ))
  842. {
  843. case HAUTO_COMPOSITION:
  844. // Send start composition msg. if no composition exist.
  845. if (pImeCtx->GetCompBufLen() == 0)
  846. pImeCtx->SetStartComposition(fTrue);
  847. // Get Current composition char
  848. wcCur = pAutomata->GetCompositionChar();
  849. // if ISO10646 flag disabled, should permit only KSC5601 chars
  850. if (vpInstData->fISO10646== fFalse)
  851. {
  852. Dbg(DBGID_API, TEXT("ToAsciiExHangulMode - ISO10646 Off"));
  853. if (IsKSC5601(wcCur) == fFalse)
  854. {
  855. Dbg(DBGID_API, TEXT("ToAsciiExHangulMode - Non KSC5601 char"));
  856. // To cancel last Jaso
  857. pAutomata->BackSpace();
  858. // Complete
  859. pAutomata->MakeComplete();
  860. pImeCtx->SetResultStr(pAutomata->GetCompleteChar());
  861. // Run Automata again
  862. pAutomata->Machine(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 );
  863. wcCur = pAutomata->GetCompositionChar();
  864. }
  865. }
  866. pImeCtx->SetCompositionStr(wcCur);
  867. break;
  868. case HAUTO_COMPLETE:
  869. pImeCtx->SetResultStr(pAutomata->GetCompleteChar());
  870. pImeCtx->SetCompositionStr(pAutomata->GetCompositionChar());
  871. break;
  872. ////////////////////////////////////////////////////////
  873. // User pressed Alphanumeric key.
  874. // When user type alphanumeric char in interim state.
  875. // ImeProcessKey should guarantee return fTrue only if
  876. // hangul key pressed or alphanumeric key(including special keys)
  877. // pressed in interim state or Fullshape mode.
  878. case HAUTO_NONHANGULKEY:
  879. wcCur = pAutomata->GetKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0);
  880. if (wcCur && (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
  881. wcCur = Banja2Junja(wcCur);
  882. // if interim state
  883. if (pImeCtx->GetCompBufLen())
  884. {
  885. //DbgAssert(lpImcP->fdwImeMsg & MSG_ALREADY_START);
  886. pImeCtx->FinalizeCurCompositionChar();
  887. if (wcCur)
  888. pImeCtx->AppendResultStr(wcCur);
  889. else
  890. pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
  891. }
  892. else // Not interim state
  893. {
  894. if (wcCur)
  895. pImeCtx->SetResultStr(wcCur);
  896. else
  897. // if not alphanumeric key(special key), just send it to App
  898. pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
  899. }
  900. break;
  901. default :
  902. DbgAssert(0);
  903. } // switch (pAutomata->Machine(uVirKey, (lpbKeyState[VK_SHIFT] & 0x80) ? 1 : 0 ) )
  904. } // switch (uVirKey)
  905. return;
  906. }
  907. /*----------------------------------------------------------------------------
  908. ToAsciiExHanja
  909. Subroutine used by ImeToAsciiEx. Handle key code in Hanja conversion mode on
  910. Returns True only if there is message need to generated.
  911. ----------------------------------------------------------------------------*/
  912. BOOL PASCAL ToAsciiExHanja(PCIMECtx pImeCtx, UINT uVirKey, CONST LPBYTE lpbKeyState)
  913. {
  914. UINT uNumMsg = 0;
  915. DWORD iStart;
  916. WORD bKeyCode;
  917. LPCANDIDATELIST lpCandList;
  918. WCHAR wcHanja, wchInject;
  919. Dbg(DBGID_Hanja, TEXT("ToAsciiExHanja(): IME_CMODE_HANJACONVERT"));
  920. // if Left Alt key or Ctrl+xx down or no cand info.
  921. if (pImeCtx->GetPCandInfo() == NULL || pImeCtx->GetPCandInfo()->dwCount == 0)
  922. {
  923. Dbg(DBGID_Hanja, TEXT("ToAsciiExHanja(): WARNING no cand info. send MSG_CLOSE_CANDIDATE"));
  924. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
  925. // Cancel Hanja conversion mode
  926. OurImmSetConversionStatus(pImeCtx->GetHIMC(),
  927. pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT,
  928. pImeCtx->GetSentenceMode());
  929. return fTrue;
  930. }
  931. wchInject = HIWORD(uVirKey);
  932. uVirKey = LOWORD(uVirKey);
  933. lpCandList = (LPCANDIDATELIST)((LPBYTE)pImeCtx->GetPCandInfo() + sizeof(CANDIDATEINFO));
  934. iStart = (lpCandList->dwSelection / lpCandList->dwPageSize) * lpCandList->dwPageSize;
  935. // FIXED : In Hanja conversion mode, for selection candidate, use english keymap
  936. bKeyCode = CHangulAutomata::GetEnglishKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 );
  937. if (bKeyCode && (uVirKey != VK_PACKET))
  938. {
  939. if (bKeyCode >= '1' && bKeyCode <= '9'
  940. && iStart + bKeyCode - '1' < lpCandList->dwCount)
  941. {
  942. wcHanja = pImeCtx->GetCandidateStr(iStart + bKeyCode - '1');
  943. Dbg(DBGID_Hanja, TEXT("ImeToAsciiEx-HANJACONVERT : wcHanja = 0x%04X"), wcHanja);
  944. pImeCtx->SetEndComposition(fTrue);
  945. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
  946. pImeCtx->SetResultStr(wcHanja);
  947. OurImmSetConversionStatus(pImeCtx->GetHIMC(),
  948. pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT,
  949. pImeCtx->GetSentenceMode());
  950. // pImeCtx->ClearCompositionStrBuffer();
  951. }
  952. else
  953. goto Exit_NoHandledKey;
  954. }
  955. else
  956. {
  957. switch (uVirKey)
  958. {
  959. case VK_HANJA :
  960. case VK_ESCAPE :
  961. case VK_PROCESSKEY :
  962. case VK_HANGUL :
  963. // Added for left and right Window buttons
  964. case VK_LWIN : case VK_RWIN :
  965. case VK_APPS :
  966. case VK_MENU :
  967. case VK_PACKET :
  968. // FIXED : Bug #27
  969. // Word notify CPS_COMPLETE when user ALT down in hanja conv mode
  970. // then send double finalize char
  971. // check if composition char exist
  972. DbgAssert(pImeCtx->GetCompBufLen()); // Comp string should be exist in Hanja conv mode.
  973. if (pImeCtx->GetCompBufLen())
  974. {
  975. // FIXED : if ESC_HANJA called, MSG_ALREADY_START is not set
  976. // This prevent MSG_END_COMPOSITION.
  977. pImeCtx->SetEndComposition(fTrue);
  978. pImeCtx->SetResultStr(pImeCtx->GetCompBufStr());
  979. // Unicode injection
  980. if (uVirKey == VK_PACKET)
  981. {
  982. Dbg(DBGID_Key|DBGID_Hanja, TEXT("ImeToAsciiEx: VK_PACKET arrived(Hanja conv mode Comp char exist) - Append 0x%x"), wchInject);
  983. pImeCtx->AppendResultStr(wchInject);
  984. }
  985. }
  986. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
  987. // Cancel Hanja conversion mode
  988. OurImmSetConversionStatus(pImeCtx->GetHIMC(),
  989. pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT,
  990. pImeCtx->GetSentenceMode());
  991. break;
  992. case VK_LEFT :
  993. if (iStart)
  994. {
  995. lpCandList->dwPageStart -= CAND_PAGE_SIZE;
  996. lpCandList->dwSelection -= CAND_PAGE_SIZE;
  997. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CHANGECAND);
  998. }
  999. else
  1000. goto Exit_NoHandledKey;
  1001. // Keep current composition str
  1002. pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
  1003. break;
  1004. case VK_RIGHT :
  1005. if (iStart + CAND_PAGE_SIZE < lpCandList->dwCount)
  1006. {
  1007. lpCandList->dwPageStart += CAND_PAGE_SIZE;
  1008. lpCandList->dwSelection += CAND_PAGE_SIZE;
  1009. pImeCtx->SetCandidateMsg(CIMECtx::MSG_CHANGECAND);
  1010. }
  1011. else
  1012. goto Exit_NoHandledKey;
  1013. // Keep current composition str
  1014. pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
  1015. break;
  1016. default :
  1017. // Keep current composition str
  1018. // pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
  1019. goto Exit_NoHandledKey;
  1020. }
  1021. }
  1022. return fTrue;
  1023. Exit_NoHandledKey:
  1024. MessageBeep(MB_ICONEXCLAMATION);
  1025. return fFalse;
  1026. }
  1027. /*----------------------------------------------------------------------------
  1028. ImeRegisterWord
  1029. NOT USED
  1030. ----------------------------------------------------------------------------*/
  1031. BOOL WINAPI ImeRegisterWord(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString)
  1032. {
  1033. Dbg(DBGID_API, TEXT("ImeRegisterWord() : NOT IMPLEMENTED"));
  1034. return fFalse;
  1035. }
  1036. /*----------------------------------------------------------------------------
  1037. ImeUnregisterWord
  1038. NOT USED
  1039. ----------------------------------------------------------------------------*/
  1040. BOOL WINAPI ImeUnregisterWord(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString)
  1041. {
  1042. Dbg(DBGID_API, TEXT("ImeUnregisterWord() : NOT IMPLEMENTED"));
  1043. return fFalse;
  1044. }
  1045. /*----------------------------------------------------------------------------
  1046. ImeGetRegisterWordStyle
  1047. NOT USED
  1048. ----------------------------------------------------------------------------*/
  1049. UINT WINAPI ImeGetRegisterWordStyle(UINT nItem, LPSTYLEBUF lpStyleBuf)
  1050. {
  1051. Dbg(DBGID_API, TEXT("ImeGetRegisterWordStyle() : NOT IMPLEMENTED"));
  1052. return (0);
  1053. }
  1054. /*----------------------------------------------------------------------------
  1055. ImeEnumRegisterWord
  1056. NOT USED
  1057. ----------------------------------------------------------------------------*/
  1058. UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROC lpfnRegisterWordEnumProc,
  1059. LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData)
  1060. {
  1061. Dbg(DBGID_API, TEXT("ImeEnumRegisterWord() : NOT IMPLEMENTED"));
  1062. return (0);
  1063. }
  1064. /*----------------------------------------------------------------------------
  1065. ImeGetImeMenuItems
  1066. ----------------------------------------------------------------------------*/
  1067. DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType,
  1068. LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
  1069. DWORD dwSize)
  1070. {
  1071. PCIMECtx pImeCtx;
  1072. DWORD dwNumOfItems=0;
  1073. Dbg(DBGID_API, TEXT("ImeGetImeMenuItems() : "));
  1074. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  1075. return 0;
  1076. if (!lpImeMenu)
  1077. {
  1078. if (!lpImeParentMenu)
  1079. {
  1080. if (dwFlags & IGIMIF_RIGHTMENU)
  1081. dwNumOfItems = NUM_ROOT_MENU_R;
  1082. else
  1083. dwNumOfItems = NUM_ROOT_MENU_L;
  1084. goto ImeGetImeMenuItemsExit;
  1085. }
  1086. else
  1087. {
  1088. if (dwFlags & IGIMIF_RIGHTMENU)
  1089. dwNumOfItems = NUM_SUB_MENU_R;
  1090. else
  1091. dwNumOfItems = NUM_SUB_MENU_L;
  1092. goto ImeGetImeMenuItemsExit;
  1093. }
  1094. return 0;
  1095. }
  1096. if (!lpImeParentMenu)
  1097. {
  1098. if (dwFlags & IGIMIF_RIGHTMENU)
  1099. {
  1100. lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
  1101. lpImeMenu->fType = 0;
  1102. lpImeMenu->fState = 0;
  1103. lpImeMenu->wID = IDIM_ROOT_MR_1;
  1104. lpImeMenu->hbmpChecked = 0;
  1105. lpImeMenu->hbmpUnchecked = 0;
  1106. OurLoadStringW(vpInstData->hInst, IDS_CONFIG, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
  1107. lpImeMenu->hbmpItem = 0;
  1108. dwNumOfItems = NUM_ROOT_MENU_R;
  1109. }
  1110. else // Left Menu
  1111. {
  1112. // 1. Hangul Halfshape menu
  1113. lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
  1114. lpImeMenu->fType = IMFT_RADIOCHECK;
  1115. if ((pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
  1116. !(pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
  1117. lpImeMenu->fState = IMFS_CHECKED;
  1118. else
  1119. lpImeMenu->fState = 0;
  1120. lpImeMenu->wID = IDIM_ROOT_ML_1;
  1121. lpImeMenu->hbmpChecked = 0;
  1122. lpImeMenu->hbmpUnchecked = 0;
  1123. OurLoadStringW(vpInstData->hInst, IDS_IME_HANGUL_HALF, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
  1124. lpImeMenu->hbmpItem = 0;
  1125. // 2. Hangul Fullshape menu
  1126. lpImeMenu++;
  1127. lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
  1128. lpImeMenu->fType = IMFT_RADIOCHECK;
  1129. if ((pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
  1130. (pImeCtx->GetConversionMode()& IME_CMODE_FULLSHAPE))
  1131. lpImeMenu->fState = IMFS_CHECKED;
  1132. else
  1133. lpImeMenu->fState = 0;
  1134. lpImeMenu->wID = IDIM_ROOT_ML_2;
  1135. lpImeMenu->hbmpChecked = 0;
  1136. lpImeMenu->hbmpUnchecked = 0;
  1137. OurLoadStringW(vpInstData->hInst, IDS_IME_HANGUL_FULL, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
  1138. lpImeMenu->hbmpItem = 0;
  1139. // 3. English Halfshape menu
  1140. lpImeMenu++;
  1141. lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
  1142. lpImeMenu->fType = IMFT_RADIOCHECK;
  1143. if (!(pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
  1144. !(pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
  1145. lpImeMenu->fState = IMFS_CHECKED;
  1146. else
  1147. lpImeMenu->fState = 0;
  1148. lpImeMenu->wID = IDIM_ROOT_ML_3;
  1149. lpImeMenu->hbmpChecked = 0;
  1150. lpImeMenu->hbmpUnchecked = 0;
  1151. OurLoadStringW(vpInstData->hInst, IDS_IME_ENG_HALF, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
  1152. lpImeMenu->hbmpItem = 0;
  1153. // 4. English Fullshape menu
  1154. lpImeMenu++;
  1155. lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
  1156. lpImeMenu->fType = IMFT_RADIOCHECK;
  1157. if ( !(pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
  1158. (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
  1159. lpImeMenu->fState = IMFS_CHECKED;
  1160. else
  1161. lpImeMenu->fState = 0;
  1162. lpImeMenu->wID = IDIM_ROOT_ML_4;
  1163. lpImeMenu->hbmpChecked = 0;
  1164. lpImeMenu->hbmpUnchecked = 0;
  1165. OurLoadStringW(vpInstData->hInst, IDS_IME_ENG_FULL, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
  1166. lpImeMenu->hbmpItem = 0;
  1167. // return total number of menu list
  1168. dwNumOfItems = NUM_ROOT_MENU_L;
  1169. }
  1170. }
  1171. ImeGetImeMenuItemsExit:
  1172. return dwNumOfItems;
  1173. }
  1174. ///////////////////////////////////////////////////////////////////////////////
  1175. ///////////////////////////////////////////////////////////////////////////////
  1176. // Private Helper Functions
  1177. //
  1178. //
  1179. // OS setup (Whistler,Win2K) sets this flag
  1180. //
  1181. BOOL IsInSystemSetupMode()
  1182. {
  1183. LPCSTR szKeyName = "SYSTEM\\Setup";
  1184. DWORD dwType, dwSize;
  1185. HKEY hKeySetup;
  1186. DWORD dwSystemSetupInProgress = 0;
  1187. DWORD dwUpgradeInProcess = 0;
  1188. DWORD dwOOBEInProcess = 0;
  1189. LONG lResult;
  1190. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKeySetup) == ERROR_SUCCESS)
  1191. {
  1192. dwSize = sizeof(DWORD);
  1193. lResult = RegQueryValueEx(hKeySetup, TEXT("SystemSetupInProgress"), NULL, &dwType, (LPBYTE) &dwSystemSetupInProgress, &dwSize);
  1194. dwSize = sizeof(DWORD);
  1195. lResult = RegQueryValueEx(hKeySetup, TEXT("UpgradeInProgress"), NULL, &dwType, (LPBYTE) &dwUpgradeInProcess, &dwSize);
  1196. dwSize = sizeof(DWORD);
  1197. lResult = RegQueryValueEx(hKeySetup, TEXT("OobeInProgress"), NULL, &dwType, (LPBYTE) &dwOOBEInProcess, &dwSize);
  1198. if (dwSystemSetupInProgress == 1 || dwUpgradeInProcess == 1 || dwOOBEInProcess == 1)
  1199. {
  1200. RegCloseKey (hKeySetup);
  1201. return TRUE;
  1202. }
  1203. RegCloseKey (hKeySetup);
  1204. }
  1205. if (IsWinNT5orUpper() && (IsRunningAsLocalSystem() || IsRunningInOOBE()))
  1206. return TRUE;
  1207. return FALSE ;
  1208. }
  1209. //+----------------------------------------------------------------------------
  1210. //
  1211. // Function: RunningAsLocalSystem
  1212. //
  1213. // Synopsis: Detects whether we're running in the System account.
  1214. //
  1215. // Arguments: None
  1216. //
  1217. // Returns: TRUE if the service is running as LocalSystem
  1218. // FALSE if it is not or if any errors were encountered
  1219. //
  1220. //-----------------------------------------------------------------------------
  1221. BOOL IsRunningAsLocalSystem()
  1222. {
  1223. SID LocalSystemSid = { SID_REVISION,
  1224. 1,
  1225. SECURITY_NT_AUTHORITY,
  1226. SECURITY_LOCAL_SYSTEM_RID };
  1227. BOOL fCheckSucceeded;
  1228. BOOL fIsLocalSystem = FALSE;
  1229. fCheckSucceeded = CheckTokenMembership(NULL,
  1230. &LocalSystemSid,
  1231. &fIsLocalSystem);
  1232. return (fCheckSucceeded && fIsLocalSystem);
  1233. }
  1234. /*----------------------------------------------------------------------------
  1235. IsRunningInOOBE
  1236. Bug #401732:IME Status window does not come up on the registration page of WPA in the windows starting mode
  1237. ----------------------------------------------------------------------------*/
  1238. BOOL IsRunningInOOBE()
  1239. {
  1240. TCHAR achModule[MAX_PATH];
  1241. TCHAR ch;
  1242. LPTSTR pch;
  1243. LPTSTR pchFileName;
  1244. if (GetModuleFileName(NULL, achModule, ARRAYSIZE(achModule)) == 0)
  1245. return FALSE;
  1246. pch = pchFileName = achModule;
  1247. while ((ch = *pch) != 0)
  1248. {
  1249. pch = CharNext(pch);
  1250. if (ch == '\\')
  1251. pchFileName = pch;
  1252. }
  1253. if (lstrcmpi(pchFileName, TEXT("msoobe.exe")) == 0)
  1254. return TRUE;
  1255. return FALSE;
  1256. }
  1257. BOOL PASCAL Select(HIMC hIMC, BOOL fSelect)
  1258. {
  1259. PCIMECtx pImeCtx = NULL;
  1260. BOOL fRet = fTrue;
  1261. // If IME select On
  1262. if (fSelect)
  1263. {
  1264. IMCPRIVATE imcPriv;
  1265. IImeIPoint1* pIP = NULL;
  1266. LPCImeIPoint pCIImeIPoint = NULL;
  1267. DWORD dwInitStatus = 0;
  1268. // Clear all private buffer
  1269. ZeroMemory(&imcPriv, sizeof(IMCPRIVATE));
  1270. //////////////////////////////////////////////////////////////////////
  1271. // Create IImeIPoint1 instance
  1272. //////////////////////////////////////////////////////////////////////
  1273. if ((pCIImeIPoint = new CIImeIPoint)==NULL)
  1274. return fFalse;
  1275. // This increments the reference count
  1276. if (FAILED(pCIImeIPoint->QueryInterface(IID_IImeIPoint1, (VOID **)&pIP)))
  1277. return fFalse;
  1278. AST(pIP != NULL);
  1279. imcPriv.pIPoint = pIP;
  1280. // initialize IImeIPoint interface. This will create CImeCtx object
  1281. Dbg(DBGID_API, "ImeSelect - init IP");
  1282. pCIImeIPoint->Initialize(hIMC);
  1283. //////////////////////////////////////////////////////////////////////
  1284. // Get CImeCtx object from IImeIPoint1
  1285. //////////////////////////////////////////////////////////////////////
  1286. pCIImeIPoint->GetImeCtx((VOID**)&pImeCtx);
  1287. AST(pImeCtx != NULL);
  1288. if (pImeCtx == NULL)
  1289. {
  1290. Dbg( DBGID_API, "ImeSelect - pImeCtx == NULL" );
  1291. return fFalse;
  1292. }
  1293. // Set pImeCtx
  1294. imcPriv.pImeCtx = pImeCtx;
  1295. // Set hIMC for compare
  1296. imcPriv.hIMC = hIMC;
  1297. //////////////////////////////////////////////////////////////////////
  1298. // Set IMC private buffer
  1299. //////////////////////////////////////////////////////////////////////
  1300. Dbg(DBGID_API, TEXT("ImeSelect - set priv buf"));
  1301. SetPrivateBuffer(hIMC, &imcPriv, sizeof(IMCPRIVATE));
  1302. // Set Unicode flag
  1303. pImeCtx->SetUnicode(vfUnicode);
  1304. //////////////////////////////////////////////////////////////////////
  1305. // Set initial IMC states if not already set
  1306. //////////////////////////////////////////////////////////////////////
  1307. pImeCtx->GetInitStatus(&dwInitStatus);
  1308. // if INPUTCONTEXT member are not initialized, initialize it.
  1309. if (!(dwInitStatus & INIT_CONVERSION))
  1310. {
  1311. pImeCtx->SetOpen(fFalse); // Initial IME close status == Alphanumeric mode
  1312. pImeCtx->SetConversionMode(IME_CMODE_ALPHANUMERIC); // Set initial conversion mode.
  1313. dwInitStatus |= INIT_CONVERSION;
  1314. }
  1315. #if 0
  1316. // !!! We don't need this code NT5 IMM does it !!!
  1317. else
  1318. {
  1319. // When IME switched from other IME, for example KKIME,
  1320. // status window sometimes not updated to correct info because KKIME maintains
  1321. // conversion mode independetly from Open/Close status and they uses non-Korean
  1322. // conversion mode like IME_CMODE_KATAKANA or IME_CMODE_ROMAN.
  1323. // So need to adjust conversion mode according to Open/Clos Status and current
  1324. // conversion mode.
  1325. if (pImeCtx->IsOpen() == fFalse && pImeCtx->GetConversionMode() != IME_CMODE_ALPHANUMERIC)
  1326. pImeCtx->SetConversionMode(IME_CMODE_ALPHANUMERIC);
  1327. else
  1328. if (pImeCtx->IsOpen() && (pImeCtx->GetConversionMode() & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE)) == fFalse)
  1329. pImeCtx->SetConversionMode(IME_CMODE_HANGUL);
  1330. }
  1331. #endif
  1332. if (!(dwInitStatus & INIT_LOGFONT))
  1333. {
  1334. LOGFONT* pLf = pImeCtx->GetLogFont();
  1335. //////////////////////////////////////////////////////////////////
  1336. // Note: Win98 does not support CreateFontW().
  1337. // But, imc->logfont->lfFaceName is UNICODE!
  1338. if (IsMemphis() || IsWinNT())
  1339. StrCopyW((LPWSTR)pLf->lfFaceName, wzIMECompFont);
  1340. else
  1341. lstrcpyA(pLf->lfFaceName, szIMECompFont);
  1342. // Gulim 9pt
  1343. pLf->lfHeight = 16;
  1344. pLf->lfEscapement = 0;
  1345. pLf->lfOrientation = 0;
  1346. pLf->lfWeight = FW_NORMAL;
  1347. pLf->lfItalic = fFalse;
  1348. pLf->lfUnderline = fFalse;
  1349. pLf->lfStrikeOut = fFalse;
  1350. pLf->lfCharSet = HANGUL_CHARSET;
  1351. pLf->lfOutPrecision = OUT_DEFAULT_PRECIS;
  1352. pLf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
  1353. pLf->lfQuality = DEFAULT_QUALITY;
  1354. pLf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
  1355. dwInitStatus |= INIT_LOGFONT;
  1356. }
  1357. if (!(dwInitStatus & INIT_STATUSWNDPOS))
  1358. {
  1359. if (pImeCtx->GetGDataRaw())
  1360. {
  1361. pImeCtx->SetStatusWndPos((pImeCtx->GetGDataRaw())->ptStatusPos);
  1362. }
  1363. dwInitStatus |= INIT_STATUSWNDPOS;
  1364. }
  1365. if (!(dwInitStatus & INIT_COMPFORM))
  1366. {
  1367. pImeCtx->SetCompositionFormStyle(CFS_DEFAULT);
  1368. dwInitStatus |= INIT_COMPFORM;
  1369. }
  1370. // Set New initialization status
  1371. pImeCtx->SetInitStatus(dwInitStatus);
  1372. }
  1373. else // fSelect
  1374. {
  1375. IImeIPoint1* pIP = GetImeIPoint(hIMC);
  1376. LPCImePadSvr lpCImePadSvr;
  1377. CIMCPriv ImcPriv;
  1378. LPIMCPRIVATE pImcPriv;
  1379. // Cleanup Private buffer and release IImeIPoint1
  1380. // Always OnImeSelect already cleanup.
  1381. if (pIP)
  1382. pIP->Release();
  1383. lpCImePadSvr = CImePadSvr::GetCImePadSvr();
  1384. if(lpCImePadSvr)
  1385. lpCImePadSvr->SetIUnkIImeIPoint((IUnknown *)NULL);
  1386. if (ImcPriv.LockIMC(hIMC))
  1387. {
  1388. ImcPriv->pIPoint = (IImeIPoint1*)NULL;
  1389. ImcPriv->pImeCtx = NULL;
  1390. ImcPriv.ResetPrivateBuffer();
  1391. }
  1392. }
  1393. Dbg(DBGID_API, "Select() exit hIMC=%x, fSelect=%d", hIMC, fSelect);
  1394. return (fTrue);
  1395. }
  1396. //////////////////////////////////////////////////////////////////////////////
  1397. // Conversion mode and Open/Close Helper functions
  1398. // In Kor IME, Open status equal to Han mode and Close status equal to Eng mode
  1399. // So, we change pair open status with conversion mode, and vice versa.
  1400. //////////////////////////////////////////////////////////////////////////////
  1401. // UpdateOpenCloseState()
  1402. // Purpose :
  1403. // Set Open/Close state according to conversion mode
  1404. // if Eng mode - set Close
  1405. // if Han mode - Set Open
  1406. VOID PASCAL UpdateOpenCloseState(PCIMECtx pImeCtx)
  1407. {
  1408. if ( (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)
  1409. || (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE)
  1410. || (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT) )
  1411. {
  1412. if (pImeCtx->IsOpen() == fFalse)
  1413. OurImmSetOpenStatus(pImeCtx->GetHIMC(), fTrue);
  1414. }
  1415. else
  1416. {
  1417. if (pImeCtx->IsOpen())
  1418. OurImmSetOpenStatus(pImeCtx->GetHIMC(), fFalse);
  1419. }
  1420. }
  1421. #if NOTUSED
  1422. //////////////////////////////////////////////////////////////////////////////
  1423. // UpdateConversionState()
  1424. // Purpose :
  1425. // Set Conversion state according to Open/Close status
  1426. // if Open - Set Han mode
  1427. // if Close - Set Eng mode
  1428. VOID PASCAL UpdateConversionState(HIMC hIMC)
  1429. {
  1430. LPINPUTCONTEXT lpIMC;
  1431. if (lpIMC = OurImmLockIMC(hIMC))
  1432. {
  1433. if (OurImmGetOpenStatus(hIMC))
  1434. {
  1435. if ( !(lpIMC->fdwConversion & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE)) )
  1436. {
  1437. OurImmSetConversionStatus(hIMC, lpIMC->fdwConversion | IME_CMODE_HANGUL,
  1438. lpIMC->fdwSentence);
  1439. }
  1440. DbgAssert(lpIMC->fdwConversion & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE));
  1441. }
  1442. else
  1443. {
  1444. // BUG: IME_CMODE_HANJACONVERT ????
  1445. if (lpIMC->fdwConversion & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE))
  1446. OurImmSetConversionStatus(hIMC, lpIMC->fdwConversion & ~(IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE),
  1447. lpIMC->fdwSentence);
  1448. DbgAssert(!(lpIMC->fdwConversion & IME_CMODE_HANGUL));
  1449. }
  1450. OurImmUnlockIMC(hIMC);
  1451. }
  1452. }
  1453. #endif
  1454. /*----------------------------------------------------------------------------
  1455. Banja2Junja
  1456. Convert Ascii Half shape to Full shape character
  1457. ----------------------------------------------------------------------------*/
  1458. WCHAR PASCAL Banja2Junja(WCHAR bChar) //, LPDWORD lpTransBuf, LPCOMPOSITIONSTRING lpCompStr)
  1459. {
  1460. WCHAR wcJunja;
  1461. if (bChar == L' ')
  1462. wcJunja = 0x3000; // FullWidth space
  1463. else
  1464. if (bChar == L'~')
  1465. wcJunja = 0xFF5E;
  1466. else
  1467. if (bChar == L'\\')
  1468. wcJunja = 0xFFE6; // FullWidth WON sign
  1469. else
  1470. wcJunja = 0xFF00 + (WORD)(bChar - (BYTE)0x20);
  1471. Dbg(DBGID_Misc, TEXT("Banja2Junja: wcJunja = 0x%04X"), wcJunja);
  1472. return wcJunja;
  1473. }
  1474. /*----------------------------------------------------------------------------
  1475. IsKSC5601
  1476. Test if character within the KSC 5601
  1477. Return True if input Unicode chracter has correspoding KSC 5601 code
  1478. ----------------------------------------------------------------------------*/
  1479. BOOL PASCAL IsKSC5601(WCHAR wcCur)
  1480. {
  1481. WCHAR wcUni[2];
  1482. BYTE szWansung[4];
  1483. wcUni[0] = wcCur;
  1484. wcUni[1] = 0;
  1485. // check if compatibility Hangul jamo
  1486. if (wcCur >= 0x3131 && wcCur <= 0x3163)
  1487. return fTrue;
  1488. // Convert to ANSI
  1489. if (WideCharToMultiByte(CP_KOREA, 0, wcUni, 1, (LPSTR)szWansung, sizeof(szWansung), NULL, NULL)==0)
  1490. {
  1491. DbgAssert(0);
  1492. return fFalse;
  1493. }
  1494. else
  1495. {
  1496. // KSC 5601 Area in 949 cp
  1497. if ( (szWansung[0]>=0xB0 && szWansung[0]<=0xC8)
  1498. && (szWansung[1]>=0xA1 && szWansung[1]<=0xFE) )
  1499. return fTrue;
  1500. else
  1501. return fFalse;
  1502. }
  1503. }