Source code of Windows XP (NT5)
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.

2007 lines
57 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. IMEEUDC.c
  5. ++*/
  6. #include <windows.h>
  7. #include <commdlg.h>
  8. #include <imm.h>
  9. #include "imeeudc.h"
  10. //
  11. // J. J. Lee 9-29-1994
  12. //
  13. // UI of this program
  14. // +--------------------------------------------------+
  15. // +--------------------------------------------------+
  16. // | |
  17. // | +------------+ |
  18. // | | FA40 | |
  19. // | +------------+ |
  20. // | |
  21. // | +------------+ +-----+ |
  22. // | (IMEName iStartIME + 0) | GOLD | | ^ | |
  23. // | +------------+ | | | |
  24. // | | | |
  25. // | +------------+ |scrol| |
  26. // | (IMEName iStartIME + 1) | WOOD | | bar | |
  27. // | +------------+ | | |
  28. // | | | |
  29. // | +------------+ | | | |
  30. // | (IMEName iStartIME + 2) | WATER | | V | |
  31. // | +------------+ +-----+ |
  32. // | |
  33. // | +----------+ +-----------+ |
  34. // | | Register | | Abort | |
  35. // | +----------+ +-----------+ |
  36. // | |
  37. // +--------------------------------------------------+
  38. //
  39. // The scroll bar only appear when there are more than 3 IMEs
  40. //
  41. // This is a sample code for EUDC regsiter a new created word into IMEs
  42. typedef struct _tagREGWORDSTRUCT {
  43. HKL hKL;
  44. BOOL bUpdate;
  45. TCHAR szIMEName[16];
  46. UINT uIMENameLen;
  47. TCHAR szReading[14];
  48. DWORD dwReadingLen;
  49. } REGWORDSTRUCT;
  50. typedef REGWORDSTRUCT FAR *LPREGWORDSTRUCT;
  51. typedef struct _tagIMELINKREGWORD {
  52. HIMC hOldIMC;
  53. HIMC hRegWordIMC;
  54. BOOL fCompMsg;
  55. UINT nEudcIMEs;
  56. UINT nCurrIME;
  57. TCHAR szEudcCodeString[4];
  58. REGWORDSTRUCT sRegWordStruct[1];
  59. } IMELINKREGWORD;
  60. typedef IMELINKREGWORD FAR *LPIMELINKREGWORD;
  61. typedef struct _tagIMERADICALRECT {
  62. UINT nStartIME;
  63. UINT nPerPageIMEs;
  64. SIZE lTextSize;
  65. SIZE lCurrReadingExtent;
  66. HWND hRegWordButton;
  67. HWND hScrollWnd;
  68. RECT rcRadical[1];
  69. } IMERADICALRECT;
  70. typedef IMERADICALRECT FAR *LPIMERADICALRECT;
  71. static const TCHAR szAppName[] = TEXT("EUDC");
  72. static const TCHAR szMenuName[] = TEXT("ImeEudcMenu");
  73. static const TCHAR szRegWordCls[] = TEXT("Radical");
  74. static const TCHAR szImeLinkDlg[] = TEXT("ImeLinkDlg");
  75. typedef struct _tagCOUNTRYSETTING {
  76. UINT uCodePage;
  77. LPCTSTR szCodePage;
  78. } COUNTRYSETTING;
  79. static const COUNTRYSETTING sCountry[] = {
  80. {
  81. BIG5_CP, TEXT("BIG5")
  82. }
  83. , {
  84. ALT_BIG5_CP, TEXT("BIG5")
  85. }
  86. #if defined(UNICODE)
  87. , {
  88. UNICODE_CP, TEXT("UNICODE")
  89. }
  90. #endif
  91. , {
  92. GB2312_CP, TEXT("GB2312")
  93. }
  94. };
  95. static HINSTANCE hAppInst;
  96. /************************************************************/
  97. /* SwitchToThisIME */
  98. /************************************************************/
  99. void SwitchToThisIME(
  100. HWND hWnd,
  101. UINT uIndex)
  102. {
  103. LPIMELINKREGWORD lpImeLinkRegWord;
  104. LPREGWORDSTRUCT lpRegWordStructTmp;
  105. LPIMERADICALRECT lpImeLinkRadical;
  106. DWORD fdwConversionMode, fdwSentenceMode;
  107. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  108. GWL_IMELINKREGWORD);
  109. if (lpImeLinkRegWord->nCurrIME == uIndex) {
  110. return;
  111. }
  112. if (uIndex >= lpImeLinkRegWord->nEudcIMEs) {
  113. MessageBeep((UINT)-1);
  114. return;
  115. }
  116. lpImeLinkRadical = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  117. GWL_RADICALRECT);
  118. if (uIndex < lpImeLinkRadical->nStartIME) {
  119. lpImeLinkRadical->nStartIME = uIndex;
  120. } else if ((uIndex - lpImeLinkRadical->nStartIME) >=
  121. lpImeLinkRadical->nPerPageIMEs) {
  122. lpImeLinkRadical->nStartIME = uIndex -
  123. (lpImeLinkRadical->nPerPageIMEs - 1);
  124. } else {
  125. }
  126. // avoid clear composition string
  127. SendMessage(hWnd, WM_EUDC_COMPMSG, 0, FALSE);
  128. lpRegWordStructTmp = &lpImeLinkRegWord->sRegWordStruct[uIndex];
  129. // switch to this IME
  130. ActivateKeyboardLayout(lpRegWordStructTmp->hKL, 0);
  131. ImmGetConversionStatus(lpImeLinkRegWord->hRegWordIMC,
  132. &fdwConversionMode, &fdwSentenceMode);
  133. fdwConversionMode = (fdwConversionMode | IME_CMODE_EUDC |
  134. IME_CMODE_NATIVE) | (fdwConversionMode & IME_CMODE_SOFTKBD);
  135. ImmSetConversionStatus(lpImeLinkRegWord->hRegWordIMC,
  136. fdwConversionMode, fdwSentenceMode);
  137. SendMessage(hWnd, WM_EUDC_COMPMSG, 0, TRUE);
  138. lpImeLinkRegWord->nCurrIME = uIndex;
  139. if(lpImeLinkRadical->hScrollWnd){
  140. SCROLLINFO scInfo;
  141. scInfo.cbSize = sizeof(SCROLLINFO);
  142. scInfo.fMask = SIF_POS;
  143. scInfo.nPos = lpImeLinkRegWord->nCurrIME;
  144. SetScrollInfo(lpImeLinkRadical->hScrollWnd,
  145. SB_CTL, &scInfo, FALSE);
  146. }
  147. InvalidateRect(hWnd, NULL, TRUE);
  148. *(LPTSTR)&lpRegWordStructTmp->szReading[
  149. lpRegWordStructTmp->dwReadingLen] = '\0';
  150. ImmSetCompositionString(lpImeLinkRegWord->hRegWordIMC, SCS_SETSTR,
  151. NULL, 0, lpRegWordStructTmp->szReading,
  152. lpRegWordStructTmp->dwReadingLen * sizeof(TCHAR));
  153. SetFocus(hWnd);
  154. return;
  155. }
  156. /************************************************************/
  157. /* RegWordCreate */
  158. /************************************************************/
  159. LPIMELINKREGWORD RegWordCreate(
  160. HWND hWnd)
  161. {
  162. HWND hEudcEditWnd;
  163. UINT nLayouts;
  164. HKL FAR *lphKL;
  165. UINT i, nIMEs;
  166. DWORD dwSize;
  167. LPIMELINKREGWORD lpImeLinkRegWord;
  168. LPREGWORDSTRUCT lpRegWordStructTmp;
  169. TCHAR szStrBuf[16];
  170. HDC hDC;
  171. SIZE lTextSize;
  172. RECT rcRect;
  173. LPIMERADICALRECT lpImeLinkRadical;
  174. TCHAR szTitle[32];
  175. TCHAR szMessage[256];
  176. hEudcEditWnd = GetWindow(GetParent(hWnd), GW_OWNER);
  177. nLayouts = GetKeyboardLayoutList(0, NULL);
  178. lphKL = GlobalAlloc(GPTR, sizeof(HKL) * nLayouts);
  179. if (!lphKL) {
  180. return (NULL);
  181. }
  182. lpImeLinkRegWord = NULL;
  183. // get all keyboard layouts, it will include all IMEs
  184. GetKeyboardLayoutList(nLayouts, lphKL);
  185. for (i = 0, nIMEs = 0; i < nLayouts; i++) {
  186. BOOL fRet;
  187. HKL hKL;
  188. TCHAR szImeEudcDic[80];
  189. hKL = *(lphKL + i);
  190. fRet = ImmIsIME(hKL);
  191. if (!fRet) { // this is not an IME
  192. continue;
  193. }
  194. szImeEudcDic[0] = '\0';
  195. fRet = (BOOL) ImmEscape(hKL, (HIMC)NULL, IME_ESC_GET_EUDC_DICTIONARY,
  196. szImeEudcDic);
  197. if (!fRet) {
  198. continue;
  199. } else if (szImeEudcDic[0]) {
  200. } else {
  201. continue;
  202. }
  203. *(lphKL + nIMEs) = hKL; // write back to the same buffer
  204. nIMEs++;
  205. }
  206. if (!nIMEs) {
  207. LoadString(hAppInst, IDS_NOIME_TITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
  208. LoadString(hAppInst, IDS_NOIME_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
  209. MessageBox(hEudcEditWnd, szMessage, szTitle, MB_OK);
  210. goto RegWordCreateFreeHKL;
  211. }
  212. // now there are nIMEs can support IME EUDC dictionary
  213. dwSize = sizeof(IMELINKREGWORD) - sizeof(REGWORDSTRUCT) +
  214. sizeof(REGWORDSTRUCT) * nIMEs;
  215. lpImeLinkRegWord = (LPIMELINKREGWORD)GlobalAlloc(GPTR, dwSize);
  216. if (!lpImeLinkRegWord) {
  217. LoadString(hAppInst, IDS_NOMEM_TITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
  218. LoadString(hAppInst, IDS_NOMEM_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
  219. MessageBox(hEudcEditWnd, szMessage, szTitle, MB_OK);
  220. goto RegWordCreateFreeHKL;
  221. }
  222. lpImeLinkRegWord->nEudcIMEs = nIMEs;
  223. lpRegWordStructTmp = &lpImeLinkRegWord->sRegWordStruct[0];
  224. for (i = 0; i < nIMEs; i++) {
  225. LRESULT lRet;
  226. #ifndef UNICODE
  227. UINT j, uInternal;
  228. #endif
  229. UINT uReadingSize;
  230. lpRegWordStructTmp->hKL = *(lphKL + i);
  231. lRet = ImmEscape(lpRegWordStructTmp->hKL, (HIMC)NULL,
  232. IME_ESC_MAX_KEY, NULL);
  233. if (!lRet) {
  234. // error message - can not support this IME!
  235. lpImeLinkRegWord->nEudcIMEs--;
  236. continue;
  237. }
  238. uReadingSize = sizeof(TCHAR);
  239. #ifndef UNICODE
  240. for (j = 0; j < 256; j++) {
  241. uInternal = ImmEscape(lpRegWordStructTmp->hKL, (HIMC)NULL,
  242. IME_ESC_SEQUENCE_TO_INTERNAL, &j);
  243. if (uInternal > 255) {
  244. uReadingSize = sizeof(WCHAR);
  245. break;
  246. }
  247. }
  248. #endif
  249. if (lRet * uReadingSize > sizeof(lpRegWordStructTmp->szReading) - sizeof(TCHAR)) {
  250. // error case, we can not support this IME
  251. // we should count this into data structure
  252. // error message - the reading of this IME is too long!
  253. lpImeLinkRegWord->nEudcIMEs--;
  254. continue;
  255. }
  256. lRet = ImmEscape(lpRegWordStructTmp->hKL, (HIMC)NULL,
  257. IME_ESC_IME_NAME, lpRegWordStructTmp->szIMEName);
  258. if (!lRet) {
  259. // error message - can not support this IME!
  260. lpImeLinkRegWord->nEudcIMEs--;
  261. continue;
  262. }
  263. // avoid length problem
  264. lpRegWordStructTmp->szIMEName[
  265. sizeof(lpRegWordStructTmp->szIMEName) / sizeof(TCHAR) - 1] = '\0';
  266. lpRegWordStructTmp->uIMENameLen =
  267. lstrlen(lpRegWordStructTmp->szIMEName);
  268. lpRegWordStructTmp++;
  269. }
  270. if (!lpImeLinkRegWord->nEudcIMEs) {
  271. LoadString(hAppInst, IDS_NOIME_TITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
  272. LoadString(hAppInst, IDS_NOIME_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
  273. MessageBox(hEudcEditWnd, szMessage, szTitle, MB_OK);
  274. goto RegWordCreateFreeRegWord;
  275. }
  276. LoadString(hAppInst, IDS_CHINESE_CHAR, szStrBuf, sizeof(szStrBuf) / sizeof(TCHAR));
  277. hDC = GetDC(NULL);
  278. GetTextExtentPoint(hDC, szStrBuf, lstrlen(szStrBuf), &lTextSize);
  279. ReleaseDC(NULL, hDC);
  280. // decide the rectangle of IME radical
  281. GetWindowRect(hWnd, &rcRect);
  282. // we can show how many IME per page
  283. nIMEs = (rcRect.bottom - rcRect.top) / (2 * lTextSize.cy);
  284. if (lpImeLinkRegWord->nEudcIMEs <= nIMEs) {
  285. // all IMEs can fit in one page
  286. nIMEs = lpImeLinkRegWord->nEudcIMEs;
  287. }
  288. dwSize = sizeof(IMERADICALRECT) - sizeof(RECT) + sizeof(RECT) *
  289. RECT_NUMBER * nIMEs;
  290. lpImeLinkRadical = (LPIMERADICALRECT)GlobalAlloc(GPTR, dwSize);
  291. if (!lpImeLinkRadical) {
  292. // we can not handle any IME
  293. lpImeLinkRegWord->nEudcIMEs = 0;
  294. LoadString(hAppInst, IDS_NOMEM_TITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
  295. LoadString(hAppInst, IDS_NOMEM_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
  296. MessageBox(hEudcEditWnd, szMessage, szTitle, MB_OK);
  297. goto RegWordCreateFreeRegWord;
  298. }
  299. lpImeLinkRadical->nStartIME = 0;
  300. lpImeLinkRadical->nPerPageIMEs = nIMEs;
  301. lpImeLinkRadical->lTextSize = lTextSize;
  302. if (lpImeLinkRegWord->nEudcIMEs > nIMEs) {
  303. // IMEs more than one page, add scroll bar
  304. SCROLLINFO scInfo;
  305. // IMEs more than one page, add scroll bar
  306. lpImeLinkRadical->hScrollWnd = CreateWindowEx(0,
  307. TEXT("scrollbar"), NULL,
  308. WS_CHILD|WS_VISIBLE|SBS_VERT,
  309. rcRect.right - rcRect.left - lTextSize.cx, 0,
  310. lTextSize.cx, rcRect.bottom - rcRect.top,
  311. hWnd, 0, hAppInst, NULL);
  312. scInfo.cbSize = sizeof(SCROLLINFO);
  313. scInfo.fMask = SIF_ALL;
  314. scInfo.nMin = 0;
  315. scInfo.nMax = lpImeLinkRegWord->nEudcIMEs - 1 + (nIMEs - 1);
  316. scInfo.nPage = nIMEs;
  317. scInfo.nPos = 0;
  318. scInfo.nTrackPos = 0;
  319. SetScrollInfo(lpImeLinkRadical->hScrollWnd, SB_CTL, &scInfo, FALSE);
  320. }
  321. // decide the UI dimension
  322. for (i = 0; i < nIMEs; i++) {
  323. UINT j, k;
  324. // rectangle for IME name
  325. j = i * RECT_NUMBER + RECT_IMENAME;
  326. lpImeLinkRadical->rcRadical[j].left = lTextSize.cx;
  327. // add UI margin - UI_MARGIN
  328. lpImeLinkRadical->rcRadical[j].top = lTextSize.cy * (i * 4 + 1) / 2 -
  329. UI_MARGIN;
  330. lpImeLinkRadical->rcRadical[j].right =
  331. lpImeLinkRadical->rcRadical[j].left + lTextSize.cx * 4;
  332. // add UI margin - UI_MARGIN * 2
  333. lpImeLinkRadical->rcRadical[j].bottom =
  334. lpImeLinkRadical->rcRadical[j].top + lTextSize.cy +
  335. UI_MARGIN * 2;
  336. // rectangle for radical
  337. k = i * RECT_NUMBER + RECT_RADICAL;
  338. lpImeLinkRadical->rcRadical[k].left =
  339. lpImeLinkRadical->rcRadical[j].right + lTextSize.cx;
  340. // add UI margin - UI_MARGIN
  341. lpImeLinkRadical->rcRadical[k].top =
  342. lpImeLinkRadical->rcRadical[j].top;
  343. lpImeLinkRadical->rcRadical[k].right =
  344. lpImeLinkRadical->rcRadical[k].left + lTextSize.cx *
  345. (sizeof(lpRegWordStructTmp->szReading) / sizeof(TCHAR) / 2 - 1);
  346. // add UI margin - UI_MARGIN * 2
  347. lpImeLinkRadical->rcRadical[k].bottom =
  348. lpImeLinkRadical->rcRadical[k].top + lTextSize.cy +
  349. UI_MARGIN * 2;
  350. }
  351. SetWindowLongPtr(hWnd, GWL_RADICALRECT, (LONG_PTR)lpImeLinkRadical);
  352. RegWordCreateFreeRegWord:
  353. if (!lpImeLinkRegWord->nEudcIMEs) {
  354. GlobalFree((HGLOBAL)lpImeLinkRegWord);
  355. lpImeLinkRegWord = NULL;
  356. }
  357. RegWordCreateFreeHKL:
  358. GlobalFree((HGLOBAL)lphKL);
  359. return (lpImeLinkRegWord);
  360. }
  361. /************************************************************/
  362. /* WmImeComposition */
  363. /************************************************************/
  364. void WmImeComposition(
  365. HWND hWnd,
  366. LPARAM lParam)
  367. {
  368. LPIMELINKREGWORD lpImeLinkRegWord;
  369. LPREGWORDSTRUCT lpRegWordStructTmp;
  370. LONG lRet;
  371. BOOL bUpdate;
  372. TCHAR szReading[sizeof(lpRegWordStructTmp->szReading)];
  373. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  374. GWL_IMELINKREGWORD);
  375. lpRegWordStructTmp = &lpImeLinkRegWord->sRegWordStruct[
  376. lpImeLinkRegWord->nCurrIME];
  377. lRet = ImmGetCompositionString(lpImeLinkRegWord->hRegWordIMC,
  378. GCS_COMPREADSTR, szReading, sizeof(szReading));
  379. if (lRet < 0) {
  380. lpRegWordStructTmp->bUpdate = UPDATE_ERROR;
  381. return;
  382. }
  383. if (lRet > (sizeof(szReading) - sizeof(TCHAR))) {
  384. lRet = sizeof(szReading) - sizeof(TCHAR);
  385. }
  386. szReading[lRet / sizeof(TCHAR)] = '\0';
  387. if (lpRegWordStructTmp->dwReadingLen != (DWORD)lRet / sizeof(TCHAR)) {
  388. bUpdate = TRUE;
  389. } else if (lstrcmp(lpRegWordStructTmp->szReading, szReading)) {
  390. bUpdate = TRUE;
  391. } else {
  392. bUpdate = FALSE;
  393. }
  394. if (bUpdate) {
  395. LPIMERADICALRECT lpImeLinkRadical;
  396. UINT i;
  397. UINT j, k;
  398. lpImeLinkRadical = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  399. GWL_RADICALRECT);
  400. lstrcpy(lpRegWordStructTmp->szReading, szReading);
  401. if (lParam & GCS_RESULTSTR) {
  402. lpRegWordStructTmp->bUpdate = UPDATE_FINISH;
  403. } else {
  404. lpRegWordStructTmp->bUpdate = UPDATE_START;
  405. }
  406. lpRegWordStructTmp->dwReadingLen = (DWORD)lRet / sizeof(TCHAR);
  407. if (!IsWindowEnabled(lpImeLinkRadical->hRegWordButton)) {
  408. EnableWindow(lpImeLinkRadical->hRegWordButton, TRUE);
  409. }
  410. i = lpImeLinkRegWord->nCurrIME - lpImeLinkRadical->nStartIME;
  411. j = i * RECT_NUMBER + RECT_IMENAME;
  412. InvalidateRect(hWnd, &lpImeLinkRadical->rcRadical[j], FALSE);
  413. k = i * RECT_NUMBER + RECT_RADICAL;
  414. InvalidateRect(hWnd, &lpImeLinkRadical->rcRadical[k], FALSE);
  415. } else if (lParam & GCS_RESULTSTR) {
  416. LPIMERADICALRECT lpImeLinkRadical;
  417. UINT i;
  418. UINT j, k;
  419. lpImeLinkRadical = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  420. GWL_RADICALRECT);
  421. if (lpRegWordStructTmp->bUpdate) {
  422. lpRegWordStructTmp->bUpdate = UPDATE_FINISH;
  423. }
  424. i = lpImeLinkRegWord->nCurrIME - lpImeLinkRadical->nStartIME;
  425. j = i * RECT_NUMBER + RECT_IMENAME;
  426. InvalidateRect(hWnd, &lpImeLinkRadical->rcRadical[j], FALSE);
  427. k = i * RECT_NUMBER + RECT_RADICAL;
  428. InvalidateRect(hWnd, &lpImeLinkRadical->rcRadical[k], FALSE);
  429. } else {
  430. }
  431. return;
  432. }
  433. /************************************************************/
  434. /* lstrcmpn */
  435. /************************************************************/
  436. int lstrcmpn(
  437. LPCTSTR lpctszStr1,
  438. LPCTSTR lpctszStr2,
  439. int cCount)
  440. {
  441. int i;
  442. for (i = 0; i < cCount; i++) {
  443. int iCmp = *lpctszStr1++ - *lpctszStr2++;
  444. if (iCmp) { return iCmp; }
  445. }
  446. return 0;
  447. }
  448. /************************************************************/
  449. /* EnumReading */
  450. /************************************************************/
  451. int CALLBACK EnumReading(
  452. LPCTSTR lpszReading,
  453. DWORD dwStyle,
  454. LPCTSTR lpszString,
  455. LPREGWORDSTRUCT lpRegWordStructTmp)
  456. {
  457. int iLen;
  458. DWORD dwZeroSeq;
  459. LRESULT lRet;
  460. TCHAR tszZeroSeq[8];
  461. iLen = lstrlen(lpszReading);
  462. if (iLen * sizeof(TCHAR) > sizeof(lpRegWordStructTmp->szReading) -
  463. sizeof(WORD)) {
  464. return (0);
  465. }
  466. lpRegWordStructTmp->dwReadingLen = (DWORD)iLen;
  467. lstrcpy(lpRegWordStructTmp->szReading, lpszReading);
  468. dwZeroSeq = 0;
  469. lRet = ImmEscape(lpRegWordStructTmp->hKL, (HIMC)NULL,
  470. IME_ESC_SEQUENCE_TO_INTERNAL, &dwZeroSeq);
  471. if (!lRet) { return (1); }
  472. iLen = 0;
  473. if (LOWORD(lRet)) {
  474. #ifdef UNICODE
  475. tszZeroSeq[iLen++] = LOWORD(lRet);
  476. #else
  477. if (LOWORD(lRet) > 0xFF) {
  478. tszZeroSeq[iLen++] = HIBYTE(LOWORD(lRet));
  479. tszZeroSeq[iLen++] = LOBYTE(LOWORD(lRet));
  480. } else {
  481. tszZeroSeq[iLen++] = LOBYTE(LOWORD(lRet));
  482. }
  483. #endif
  484. }
  485. if (HIWORD(lRet) == 0xFFFF) {
  486. // This is caused by sign extent in Win9x in the return value of
  487. // ImmEscape, it causes an invalid internal code.
  488. } else if (HIWORD(lRet)) {
  489. #ifdef UNICODE
  490. tszZeroSeq[iLen++] = HIWORD(lRet);
  491. #else
  492. if (HIWORD(lRet) > 0xFF) {
  493. tszZeroSeq[iLen++] = HIBYTE(HIWORD(lRet));
  494. tszZeroSeq[iLen++] = LOBYTE(HIWORD(lRet));
  495. } else {
  496. tszZeroSeq[iLen++] = LOBYTE(HIWORD(lRet));
  497. }
  498. #endif
  499. } else {
  500. }
  501. for (; lpRegWordStructTmp->dwReadingLen > 0;
  502. lpRegWordStructTmp->dwReadingLen -= iLen) {
  503. if (lstrcmpn(&lpRegWordStructTmp->szReading[
  504. lpRegWordStructTmp->dwReadingLen - iLen], tszZeroSeq, iLen) != 0) {
  505. break;
  506. }
  507. }
  508. lpRegWordStructTmp->szReading[lpRegWordStructTmp->dwReadingLen] = '\0';
  509. return (1);
  510. }
  511. /************************************************************/
  512. /* EudcCode */
  513. /************************************************************/
  514. void EudcCode(
  515. HWND hWnd,
  516. UINT uCode)
  517. {
  518. LPIMELINKREGWORD lpImeLinkRegWord;
  519. LPREGWORDSTRUCT lpRegWordStructTmp;
  520. UINT i;
  521. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  522. GWL_IMELINKREGWORD);
  523. #ifdef UNICODE
  524. lpImeLinkRegWord->szEudcCodeString[0] = (WCHAR)uCode;
  525. #else
  526. lpImeLinkRegWord->szEudcCodeString[0] = HIBYTE(uCode);
  527. lpImeLinkRegWord->szEudcCodeString[1] = LOBYTE(uCode);
  528. #endif
  529. lpImeLinkRegWord->szEudcCodeString[2] =
  530. lpImeLinkRegWord->szEudcCodeString[3] = '\0';
  531. lpRegWordStructTmp = &lpImeLinkRegWord->sRegWordStruct[0];
  532. for (i = 0; i < lpImeLinkRegWord->nEudcIMEs; i++) {
  533. lpRegWordStructTmp->bUpdate = UPDATE_NONE;
  534. lpRegWordStructTmp->szReading[0] = '\0';
  535. lpRegWordStructTmp->dwReadingLen = 0;
  536. ImmEnumRegisterWord(lpRegWordStructTmp->hKL, EnumReading,
  537. NULL, IME_REGWORD_STYLE_EUDC,
  538. lpImeLinkRegWord->szEudcCodeString,
  539. lpRegWordStructTmp);
  540. lpRegWordStructTmp->dwReadingLen = lstrlen(lpRegWordStructTmp->szReading);
  541. lpRegWordStructTmp++;
  542. }
  543. lpRegWordStructTmp = &lpImeLinkRegWord->sRegWordStruct[
  544. lpImeLinkRegWord->nCurrIME];
  545. ImmSetCompositionString(lpImeLinkRegWord->hRegWordIMC, SCS_SETSTR,
  546. NULL, 0, lpRegWordStructTmp->szReading,
  547. lpRegWordStructTmp->dwReadingLen * sizeof(TCHAR));
  548. InvalidateRect(hWnd, NULL, FALSE);
  549. return;
  550. }
  551. /************************************************************/
  552. /* ChangeToOtherIME */
  553. /************************************************************/
  554. void ChangeToOtherIME(
  555. HWND hWnd,
  556. LPARAM lMousePos)
  557. {
  558. POINT ptMouse;
  559. LPIMERADICALRECT lpImeLinkRadical;
  560. UINT i;
  561. BOOL bFound;
  562. ptMouse.x = LOWORD(lMousePos);
  563. ptMouse.y = HIWORD(lMousePos);
  564. lpImeLinkRadical = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  565. GWL_RADICALRECT);
  566. bFound = FALSE;
  567. for (i = 0; i < lpImeLinkRadical->nPerPageIMEs; i++) {
  568. UINT j;
  569. j = i * RECT_NUMBER + RECT_RADICAL;
  570. if (PtInRect(&lpImeLinkRadical->rcRadical[j], ptMouse)) {
  571. bFound = TRUE;
  572. break;
  573. }
  574. }
  575. if (!bFound) {
  576. return;
  577. }
  578. SwitchToThisIME(hWnd, lpImeLinkRadical->nStartIME + i);
  579. return;
  580. }
  581. /************************************************************/
  582. /* ScrollIME */
  583. /************************************************************/
  584. void ScrollIME(
  585. HWND hWnd,
  586. WPARAM wParam)
  587. {
  588. LPIMELINKREGWORD lpImeLinkRegWord;
  589. LPIMERADICALRECT lpImeLinkRadical;
  590. int iLines;
  591. UINT uIndex;
  592. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  593. GWL_IMELINKREGWORD);
  594. lpImeLinkRadical = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  595. GWL_RADICALRECT);
  596. switch (LOWORD(wParam)) {
  597. case SB_PAGEDOWN:
  598. // scroll (page size - 1)
  599. iLines = lpImeLinkRadical->nPerPageIMEs - 1;
  600. break;
  601. case SB_LINEDOWN:
  602. iLines = 1;
  603. break;
  604. case SB_PAGEUP:
  605. // scroll (page size - 1)
  606. iLines = 1 - lpImeLinkRadical->nPerPageIMEs;
  607. break;
  608. case SB_LINEUP:
  609. iLines = -1;
  610. break;
  611. case SB_TOP:
  612. // swicth to the first one
  613. SwitchToThisIME(hWnd, 0);
  614. return;
  615. case SB_BOTTOM:
  616. // swicth to the last one
  617. SwitchToThisIME(hWnd, lpImeLinkRegWord->nEudcIMEs - 1);
  618. return;
  619. case SB_THUMBPOSITION:
  620. SwitchToThisIME(hWnd, HIWORD(wParam));
  621. return;
  622. default:
  623. return;
  624. }
  625. uIndex = lpImeLinkRegWord->nCurrIME;
  626. if (iLines > 0) {
  627. uIndex += (UINT)iLines;
  628. if (uIndex >= lpImeLinkRegWord->nEudcIMEs) {
  629. // should not exceed the total IMEs
  630. uIndex = lpImeLinkRegWord->nEudcIMEs - 1;
  631. }
  632. } else {
  633. UINT uLines;
  634. uLines = -iLines;
  635. if (uLines > uIndex) {
  636. uIndex = 0;
  637. } else {
  638. uIndex -= uLines;
  639. }
  640. }
  641. SwitchToThisIME(hWnd, uIndex);
  642. return;
  643. }
  644. /************************************************************/
  645. /* ScrollIMEByKey */
  646. /************************************************************/
  647. void ScrollIMEByKey(
  648. HWND hWnd,
  649. WPARAM wParam)
  650. {
  651. switch (wParam) {
  652. case VK_NEXT:
  653. ScrollIME(hWnd, SB_PAGEDOWN);
  654. break;
  655. case VK_DOWN: // can not work because dialog do not pass this key to us
  656. ScrollIME(hWnd, SB_LINEDOWN);
  657. break;
  658. case VK_PRIOR:
  659. ScrollIME(hWnd, SB_PAGEUP);
  660. break;
  661. case VK_UP: // can not work because dialog do not pass this key to us
  662. ScrollIME(hWnd, SB_LINEUP);
  663. break;
  664. default:
  665. return;
  666. }
  667. return;
  668. }
  669. /************************************************************/
  670. /* RegWordGetFocus */
  671. /************************************************************/
  672. void RegWordGetFocus(
  673. HWND hWnd)
  674. {
  675. LPIMELINKREGWORD lpImeLinkRegWord;
  676. LPIMERADICALRECT lpImeLinkRadical;
  677. UINT i;
  678. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  679. GWL_IMELINKREGWORD);
  680. lpImeLinkRadical = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  681. GWL_RADICALRECT);
  682. CreateCaret(hWnd, NULL, 2, lpImeLinkRadical->lTextSize.cy +
  683. CARET_MARGIN * 2);
  684. if (lpImeLinkRegWord->nCurrIME < lpImeLinkRadical->nStartIME) {
  685. lpImeLinkRegWord->nCurrIME = lpImeLinkRadical->nStartIME;
  686. } else if ((lpImeLinkRegWord->nCurrIME - lpImeLinkRadical->nStartIME) >=
  687. lpImeLinkRadical->nPerPageIMEs) {
  688. lpImeLinkRegWord->nCurrIME = lpImeLinkRadical->nStartIME +
  689. lpImeLinkRadical->nPerPageIMEs - 1;
  690. } else {
  691. }
  692. i = lpImeLinkRegWord->nCurrIME - lpImeLinkRadical->nStartIME;
  693. i = (i * RECT_NUMBER) + RECT_RADICAL;
  694. SetCaretPos(lpImeLinkRadical->rcRadical[i].left +
  695. lpImeLinkRadical->lCurrReadingExtent.cx + 2,
  696. lpImeLinkRadical->rcRadical[i].top + UI_MARGIN - CARET_MARGIN);
  697. ShowCaret(hWnd);
  698. return;
  699. }
  700. /************************************************************/
  701. /* RegWordPaint */
  702. /************************************************************/
  703. void RegWordPaint(
  704. HWND hWnd)
  705. {
  706. LPIMERADICALRECT lpImeLinkRadical;
  707. LPIMELINKREGWORD lpImeLinkRegWord;
  708. LPREGWORDSTRUCT lpRegWordStructTmp;
  709. HDC hDC;
  710. PAINTSTRUCT ps;
  711. UINT i;
  712. UINT nShowIMEs;
  713. lpImeLinkRadical = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  714. GWL_RADICALRECT);
  715. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  716. GWL_IMELINKREGWORD);
  717. lpRegWordStructTmp = &lpImeLinkRegWord->sRegWordStruct[
  718. lpImeLinkRadical->nStartIME];
  719. HideCaret(hWnd);
  720. hDC = BeginPaint(hWnd, &ps);
  721. // we only can show up to the final one
  722. nShowIMEs = lpImeLinkRegWord->nEudcIMEs - lpImeLinkRadical->nStartIME;
  723. if (nShowIMEs > lpImeLinkRadical->nPerPageIMEs) {
  724. // we only can show one page a time
  725. nShowIMEs = lpImeLinkRadical->nPerPageIMEs;
  726. }
  727. for (i = 0; i < nShowIMEs; i++) {
  728. RECT rcSunken;
  729. UINT j, k;
  730. k = i * RECT_NUMBER + RECT_RADICAL;
  731. rcSunken = lpImeLinkRadical->rcRadical[k];
  732. rcSunken.left -= 2;
  733. rcSunken.top -= 2;
  734. rcSunken.right += 2;
  735. rcSunken.bottom += 2;
  736. DrawEdge(hDC, &rcSunken, BDR_SUNKENOUTER, BF_RECT);
  737. SetBkColor(hDC, GetSysColor(COLOR_BTNFACE));
  738. if (lpRegWordStructTmp->bUpdate == UPDATE_ERROR) {
  739. // red text for error
  740. SetTextColor(hDC, RGB(0xFF, 0x00, 0x00));
  741. } else if (lpRegWordStructTmp->bUpdate == UPDATE_START) {
  742. // yellow text for not finished
  743. SetTextColor(hDC, RGB(0xFF, 0xFF, 0x00));
  744. } else if (lpRegWordStructTmp->bUpdate == UPDATE_REGISTERED) {
  745. // green text for registered
  746. SetTextColor(hDC, RGB(0x00, 0x80, 0x00));
  747. } else {
  748. SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  749. }
  750. j = i * RECT_NUMBER + RECT_IMENAME;
  751. ExtTextOut(hDC, lpImeLinkRadical->rcRadical[j].left,
  752. lpImeLinkRadical->rcRadical[j].top,
  753. ETO_OPAQUE|ETO_CLIPPED, &lpImeLinkRadical->rcRadical[j],
  754. lpRegWordStructTmp->szIMEName,
  755. lpRegWordStructTmp->uIMENameLen, NULL);
  756. if ((lpImeLinkRegWord->nCurrIME - lpImeLinkRadical->nStartIME) == i) {
  757. SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  758. SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  759. GetTextExtentPoint(hDC, lpRegWordStructTmp->szReading,
  760. lpRegWordStructTmp->dwReadingLen,
  761. &lpImeLinkRadical->lCurrReadingExtent);
  762. SetCaretPos(lpImeLinkRadical->rcRadical[k].left +
  763. lpImeLinkRadical->lCurrReadingExtent.cx + 2,
  764. lpImeLinkRadical->rcRadical[k].top + UI_MARGIN - CARET_MARGIN);
  765. } else {
  766. SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  767. }
  768. ExtTextOut(hDC, lpImeLinkRadical->rcRadical[k].left,
  769. lpImeLinkRadical->rcRadical[k].top + UI_MARGIN,
  770. ETO_OPAQUE, &lpImeLinkRadical->rcRadical[k],
  771. lpRegWordStructTmp->szReading,
  772. lpRegWordStructTmp->dwReadingLen, NULL);
  773. lpRegWordStructTmp++;
  774. }
  775. EndPaint(hWnd, &ps);
  776. ShowCaret(hWnd);
  777. return;
  778. }
  779. /************************************************************/
  780. /* RegWordWndProc */
  781. /************************************************************/
  782. LRESULT CALLBACK RegWordWndProc(
  783. HWND hWnd,
  784. UINT uMsg,
  785. WPARAM wParam,
  786. LPARAM lParam)
  787. {
  788. switch (uMsg) {
  789. case WM_CREATE:
  790. {
  791. LPIMELINKREGWORD lpImeLinkRegWord;
  792. UINT uIndex;
  793. // initialize to 0
  794. SetWindowLongPtr(hWnd, GWL_IMELINKREGWORD, 0L);
  795. SetWindowLongPtr(hWnd, GWL_RADICALRECT, 0L);
  796. lpImeLinkRegWord = RegWordCreate(hWnd);
  797. if (!lpImeLinkRegWord) {
  798. return (-1);
  799. }
  800. lpImeLinkRegWord->fCompMsg = TRUE;
  801. lpImeLinkRegWord->nCurrIME = 0xFFFFFFFF;
  802. lpImeLinkRegWord->hRegWordIMC = ImmCreateContext();
  803. if (!lpImeLinkRegWord->hRegWordIMC) {
  804. return (-1);
  805. }
  806. lpImeLinkRegWord->hOldIMC = ImmAssociateContext(hWnd,
  807. lpImeLinkRegWord->hRegWordIMC);
  808. SetWindowLongPtr(hWnd, GWL_IMELINKREGWORD, (LONG_PTR)lpImeLinkRegWord);
  809. uIndex = 0;
  810. SwitchToThisIME(hWnd, 0);
  811. // the switch will fail, if the window is disable, try again
  812. PostMessage(hWnd, WM_EUDC_SWITCHIME, 0, uIndex);
  813. }
  814. break;
  815. case WM_EUDC_COMPMSG:
  816. {
  817. LPIMELINKREGWORD lpImeLinkRegWord;
  818. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  819. GWL_IMELINKREGWORD);
  820. lpImeLinkRegWord->fCompMsg = (BOOL)lParam;
  821. }
  822. break;
  823. case WM_EUDC_SWITCHIME:
  824. {
  825. LPIMELINKREGWORD lpImeLinkRegWord;
  826. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  827. GWL_IMELINKREGWORD);
  828. lpImeLinkRegWord->nCurrIME = 0xFFFFFFFF;
  829. SwitchToThisIME(hWnd, (UINT)lParam);
  830. }
  831. break;
  832. case WM_IME_STARTCOMPOSITION:
  833. case WM_IME_ENDCOMPOSITION:
  834. break;
  835. case WM_IME_COMPOSITION:
  836. {
  837. LPIMELINKREGWORD lpImeLinkRegWord;
  838. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  839. GWL_IMELINKREGWORD);
  840. if (lpImeLinkRegWord->fCompMsg) {
  841. WmImeComposition(hWnd, lParam);
  842. }
  843. }
  844. break;
  845. case WM_IME_NOTIFY:
  846. switch (wParam) {
  847. case IMN_OPENSTATUSWINDOW:
  848. case IMN_CLOSESTATUSWINDOW:
  849. case IMN_OPENCANDIDATE:
  850. case IMN_CHANGECANDIDATE:
  851. case IMN_CLOSECANDIDATE:
  852. break;
  853. default:
  854. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  855. }
  856. break;
  857. case WM_IME_SETCONTEXT:
  858. return DefWindowProc(hWnd, uMsg, wParam, lParam & ~(ISC_SHOWUIALL));
  859. case WM_EUDC_REGISTER_BUTTON:
  860. {
  861. LPIMERADICALRECT lpImeRadicalRect;
  862. lpImeRadicalRect = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  863. GWL_RADICALRECT);
  864. lpImeRadicalRect->hRegWordButton = (HWND)lParam;
  865. }
  866. break;
  867. case WM_EUDC_CODE:
  868. EudcCode(hWnd, (UINT)lParam);
  869. break;
  870. case WM_LBUTTONDOWN:
  871. ChangeToOtherIME(hWnd, lParam);
  872. break;
  873. case WM_VSCROLL:
  874. ScrollIME(hWnd, wParam);
  875. break;
  876. case WM_KEYDOWN:
  877. ScrollIMEByKey(hWnd, wParam);
  878. break;
  879. case WM_SETFOCUS:
  880. RegWordGetFocus(hWnd);
  881. break;
  882. case WM_KILLFOCUS:
  883. DestroyCaret();
  884. break;
  885. case WM_PAINT:
  886. RegWordPaint(hWnd);
  887. break;
  888. case WM_DESTROY:
  889. {
  890. LPIMERADICALRECT lpImeRadicalRect;
  891. LPIMELINKREGWORD lpImeLinkRegWord;
  892. lpImeRadicalRect = (LPIMERADICALRECT)GetWindowLongPtr(hWnd,
  893. GWL_RADICALRECT);
  894. if (lpImeRadicalRect) {
  895. GlobalFree((HGLOBAL)lpImeRadicalRect);
  896. }
  897. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  898. GWL_IMELINKREGWORD);
  899. if (!lpImeLinkRegWord) {
  900. break;
  901. }
  902. ImmAssociateContext(hWnd, lpImeLinkRegWord->hOldIMC);
  903. ImmDestroyContext(lpImeLinkRegWord->hRegWordIMC);
  904. GlobalFree((HGLOBAL)lpImeLinkRegWord);
  905. }
  906. break;
  907. default:
  908. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  909. }
  910. return (0L);
  911. }
  912. /************************************************************/
  913. /* RegisterThisEudc */
  914. /************************************************************/
  915. int RegisterThisEudc(
  916. HWND hWnd)
  917. {
  918. LPIMELINKREGWORD lpImeLinkRegWord;
  919. LPREGWORDSTRUCT lpRegWordStructTmp;
  920. UINT i;
  921. int iRet;
  922. lpImeLinkRegWord = (LPIMELINKREGWORD)GetWindowLongPtr(hWnd,
  923. GWL_IMELINKREGWORD);
  924. lpRegWordStructTmp = &lpImeLinkRegWord->sRegWordStruct[0];
  925. iRet = -1;
  926. for (i = 0; i < lpImeLinkRegWord->nEudcIMEs; i++, lpRegWordStructTmp++) {
  927. if (lpRegWordStructTmp->bUpdate == UPDATE_NONE) {
  928. } else if (lpRegWordStructTmp->bUpdate != UPDATE_FINISH) {
  929. TCHAR szStrBuf[128];
  930. int iYesNo;
  931. if (iRet != -1) {
  932. continue;
  933. }
  934. LoadString(hAppInst, IDS_QUERY_NOTFINISH, szStrBuf,
  935. sizeof(szStrBuf) / sizeof(TCHAR));
  936. iYesNo = MessageBox(hWnd, szStrBuf,
  937. lpRegWordStructTmp->szIMEName,
  938. MB_APPLMODAL|MB_YESNO|MB_DEFBUTTON1);
  939. if (iYesNo == IDYES) {
  940. iRet = i;
  941. }
  942. } else {
  943. BOOL fRet;
  944. TCHAR szStrBuf[128];
  945. int iYesNo;
  946. fRet = ImmRegisterWord(lpRegWordStructTmp->hKL,
  947. lpRegWordStructTmp->szReading, IME_REGWORD_STYLE_EUDC,
  948. lpImeLinkRegWord->szEudcCodeString);
  949. if (fRet) {
  950. lpRegWordStructTmp->bUpdate = UPDATE_REGISTERED;
  951. continue;
  952. } else {
  953. lpRegWordStructTmp->bUpdate = UPDATE_ERROR;
  954. }
  955. if (iRet != -1) {
  956. continue;
  957. }
  958. LoadString(hAppInst, IDS_QUERY_REGISTER, szStrBuf,
  959. sizeof(szStrBuf) / sizeof(TCHAR));
  960. iYesNo = MessageBox(hWnd, szStrBuf,
  961. lpRegWordStructTmp->szIMEName,
  962. MB_APPLMODAL|MB_YESNO|MB_DEFBUTTON1);
  963. if (iYesNo == IDYES) {
  964. iRet = i;
  965. }
  966. }
  967. }
  968. InvalidateRect(hWnd, NULL, FALSE);
  969. return (iRet);
  970. }
  971. /************************************************************/
  972. /* CodePageInfo() */
  973. /************************************************************/
  974. int CodePageInfo(
  975. UINT uCodePage)
  976. {
  977. int i;
  978. for (i = 0; i < sizeof(sCountry) / sizeof(COUNTRYSETTING); i++) {
  979. if (sCountry[i].uCodePage == uCodePage) {
  980. return(i);
  981. }
  982. }
  983. return (-1);
  984. }
  985. /************************************************************/
  986. /* ImeLinkDlgProc */
  987. /************************************************************/
  988. INT_PTR CALLBACK ImeLinkDlgProc(
  989. HWND hDlg,
  990. UINT uMsg,
  991. WPARAM wParam,
  992. LPARAM lParam)
  993. {
  994. switch (uMsg) {
  995. case WM_INITDIALOG:
  996. {
  997. HWND hRadicalWnd, hRegWordButton;
  998. int cbString;
  999. #ifdef UNICODE // this code could not run under non NATIVE platforms
  1000. UINT uCodePage, uNativeCode;
  1001. int i;
  1002. #endif
  1003. TCHAR szTitle[128];
  1004. cbString = GetWindowText(hDlg, szTitle, sizeof(szTitle) /
  1005. sizeof(TCHAR));
  1006. #ifdef UNICODE
  1007. uCodePage = GetACP();
  1008. i = CodePageInfo(uCodePage);
  1009. if (uCodePage == UNICODE_CP || i == -1) {
  1010. wsprintf(&szTitle[cbString], TEXT("%4X"), (UINT)lParam);
  1011. } else {
  1012. uNativeCode = 0;
  1013. WideCharToMultiByte(uCodePage, WC_COMPOSITECHECK,
  1014. (LPCWSTR)&lParam, 1,
  1015. (LPSTR)&uNativeCode, sizeof(uNativeCode),
  1016. NULL, NULL);
  1017. // convert to multi byte string
  1018. uNativeCode = LOBYTE(uNativeCode) << 8 | HIBYTE(uNativeCode);
  1019. wsprintf(&szTitle[cbString], TEXT("%4X (%s - %4X)"),
  1020. (UINT)lParam, sCountry[i].szCodePage, (UINT)uNativeCode);
  1021. }
  1022. #else
  1023. wsprintf(&szTitle[cbString], TEXT("%4X"), (UINT)lParam);
  1024. #endif
  1025. SetWindowText(hDlg, szTitle);
  1026. hRadicalWnd = GetDlgItem(hDlg, IDD_RADICAL);
  1027. SendMessage(hRadicalWnd, WM_EUDC_CODE, 0, lParam);
  1028. hRegWordButton = GetDlgItem(hDlg, IDOK);
  1029. EnableWindow(hRegWordButton, FALSE);
  1030. SendMessage(hRadicalWnd, WM_EUDC_REGISTER_BUTTON, 0,
  1031. (LPARAM)hRegWordButton);
  1032. }
  1033. return (TRUE); // do not want to set focus to special control
  1034. case WM_COMMAND:
  1035. switch (wParam) {
  1036. case IDOK:
  1037. {
  1038. HWND hRadicalWnd;
  1039. hRadicalWnd = GetDlgItem(hDlg, IDD_RADICAL);
  1040. if (RegisterThisEudc(hRadicalWnd) == -1) {
  1041. EndDialog(hDlg, TRUE);
  1042. } else {
  1043. SetFocus(hRadicalWnd);
  1044. }
  1045. }
  1046. break;
  1047. case IDCANCEL:
  1048. EndDialog(hDlg, FALSE);
  1049. break;
  1050. default:
  1051. return (FALSE);
  1052. }
  1053. return (TRUE);
  1054. case WM_IME_NOTIFY:
  1055. // we need to hook these messages from frame window also
  1056. // otherwise sometime the OPENSTATUS will send to the frame
  1057. // window and the child - hRadicalWnd will not get these messages
  1058. switch (wParam) {
  1059. case IMN_OPENSTATUSWINDOW:
  1060. case IMN_CLOSESTATUSWINDOW:
  1061. return (TRUE);
  1062. default:
  1063. return (FALSE);
  1064. }
  1065. default:
  1066. return (FALSE);
  1067. }
  1068. return (TRUE);
  1069. }
  1070. /************************************************************/
  1071. /* ImeLink */
  1072. /************************************************************/
  1073. void ImeLink(
  1074. HWND hWnd,
  1075. UINT uCode)
  1076. {
  1077. static BOOL bFirstTime = TRUE;
  1078. UINT nLayouts;
  1079. HKL FAR *lphKL;
  1080. TCHAR szTitle[32];
  1081. TCHAR szMessage[256];
  1082. UINT i, nIMEs;
  1083. WNDCLASSEX wcClass;
  1084. HKL hOldKL;
  1085. nLayouts = GetKeyboardLayoutList(0, NULL);
  1086. lphKL = GlobalAlloc(GPTR, sizeof(HKL) * nLayouts);
  1087. if (!lphKL) {
  1088. LoadString(hAppInst, IDS_NOMEM_TITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
  1089. LoadString(hAppInst, IDS_NOMEM_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
  1090. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1091. return;
  1092. }
  1093. // MSVC may have problem for recusive modal dialog box,
  1094. // I mean create a modal dialog box within a modal dialog box.
  1095. // so we need to move the code from RegWordCreate() to here to
  1096. // prevent creating a modal dialog form a modal dialog.
  1097. // The ImmConfigureIME API call is possible to create a modal dialog.
  1098. // get all keyboard layouts, it will include all IMEs
  1099. GetKeyboardLayoutList(nLayouts, lphKL);
  1100. for (i = 0, nIMEs = 0; i < nLayouts; i++) {
  1101. BOOL fRet;
  1102. HKL hKL;
  1103. TCHAR szImeEudcDic[80];
  1104. hKL = *(lphKL + i);
  1105. fRet = ImmIsIME(hKL);
  1106. if (!fRet) { // this is not an IME
  1107. continue;
  1108. }
  1109. szImeEudcDic[0] = '\0';
  1110. fRet = (BOOL) ImmEscape(hKL, (HIMC)NULL, IME_ESC_GET_EUDC_DICTIONARY,
  1111. szImeEudcDic);
  1112. if (!fRet) {
  1113. continue;
  1114. }
  1115. if (szImeEudcDic[0]) {
  1116. fRet = TRUE;
  1117. } else if (!bFirstTime) {
  1118. } else {
  1119. fRet = ImmConfigureIME(hKL, hWnd, IME_CONFIG_SELECTDICTIONARY, NULL);
  1120. }
  1121. if (!fRet) {
  1122. // this IME do not have an IME EUDC dictionary
  1123. continue;
  1124. }
  1125. if (szImeEudcDic[0] == '\0') {
  1126. // check whether we really get a dictionary
  1127. fRet = (BOOL) ImmEscape(hKL, (HIMC)NULL, IME_ESC_GET_EUDC_DICTIONARY,
  1128. szImeEudcDic);
  1129. if (!fRet) {
  1130. continue;
  1131. } else if (szImeEudcDic[0] == '\0') {
  1132. continue;
  1133. } else {
  1134. }
  1135. } else {
  1136. }
  1137. nIMEs++;
  1138. }
  1139. GlobalFree((HGLOBAL)lphKL);
  1140. if (bFirstTime) {
  1141. bFirstTime = FALSE;
  1142. }
  1143. if (!nIMEs) {
  1144. LoadString(hAppInst, IDS_NOIME_TITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
  1145. LoadString(hAppInst, IDS_NOIME_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
  1146. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1147. return;
  1148. }
  1149. if (!GetClassInfoEx(hAppInst, szRegWordCls, &wcClass)) {
  1150. wcClass.cbSize = sizeof(WNDCLASSEX);
  1151. wcClass.style = CS_HREDRAW|CS_VREDRAW;
  1152. wcClass.lpfnWndProc = RegWordWndProc;
  1153. wcClass.cbClsExtra = 0;
  1154. wcClass.cbWndExtra = GWL_SIZE;
  1155. wcClass.hInstance = hAppInst;
  1156. wcClass.hIcon = NULL;
  1157. wcClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  1158. wcClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  1159. wcClass.lpszMenuName = NULL;
  1160. wcClass.lpszClassName = szRegWordCls;
  1161. wcClass.hIconSm = NULL;
  1162. RegisterClassEx(&wcClass);
  1163. }
  1164. hOldKL = GetKeyboardLayout(0);
  1165. DialogBoxParam(hAppInst, szImeLinkDlg, hWnd, ImeLinkDlgProc,
  1166. (LPARAM)uCode);
  1167. ActivateKeyboardLayout(hOldKL, 0);
  1168. return;
  1169. }
  1170. /************************************************************/
  1171. /* MatchImeName() */
  1172. /************************************************************/
  1173. HKL MatchImeName(
  1174. LPCTSTR szStr)
  1175. {
  1176. TCHAR szImeName[16];
  1177. int nLayout;
  1178. HKL hKL;
  1179. HGLOBAL hMem;
  1180. HKL FAR * lpMem;
  1181. int i;
  1182. nLayout = GetKeyboardLayoutList(0, NULL);
  1183. // alloc temp buffer
  1184. hMem = GlobalAlloc(GHND, sizeof(HKL) * nLayout);
  1185. if (!hMem) {
  1186. return (NULL);
  1187. }
  1188. lpMem = (HKL FAR *)GlobalLock(hMem);
  1189. if (!lpMem) {
  1190. GlobalFree(hMem);
  1191. return (NULL);
  1192. }
  1193. // get all keyboard layouts, it includes all IMEs
  1194. GetKeyboardLayoutList(nLayout, lpMem);
  1195. for (i = 0; i < nLayout; i++) {
  1196. BOOL fRet;
  1197. hKL = *(lpMem + i);
  1198. fRet = (BOOL) ImmEscape(hKL, (HIMC)NULL, IME_ESC_IME_NAME, szImeName);
  1199. if (!fRet) { // this hKL can not ask name
  1200. continue;
  1201. }
  1202. if (lstrcmp(szStr, szImeName) == 0) {
  1203. goto MatchOvr;
  1204. }
  1205. }
  1206. hKL = NULL;
  1207. MatchOvr:
  1208. GlobalUnlock(hMem);
  1209. GlobalFree(hMem);
  1210. return (hKL);
  1211. }
  1212. /************************************************************/
  1213. /* RegisterTable() */
  1214. /************************************************************/
  1215. HKL RegisterTable(
  1216. HWND hWnd,
  1217. LPUSRDICIMHDR lpIsvUsrDic,
  1218. DWORD dwFileSize,
  1219. UINT uCodePage)
  1220. {
  1221. HKL hKL;
  1222. HDC hDC;
  1223. SIZE lTextSize;
  1224. RECT rcProcess;
  1225. DWORD i;
  1226. LPBYTE lpCurr, lpEnd;
  1227. BOOL fRet;
  1228. TCHAR szStr[16];
  1229. TCHAR szProcessFmt[32];
  1230. TCHAR szResult[2][32];
  1231. TCHAR szProcessInfo[48];
  1232. WORD wInternalCode[256];
  1233. WORD wAltInternalCode[256];
  1234. #ifdef UNICODE
  1235. if (uCodePage == UNICODE_CP) {
  1236. LPUNATSTR lpszMethodName;
  1237. lpszMethodName = (LPUNATSTR)lpIsvUsrDic->achMethodName;
  1238. for (i = 0; i < sizeof(lpIsvUsrDic->achMethodName) / sizeof(TCHAR); i++) {
  1239. szStr[i] = *lpszMethodName++;
  1240. }
  1241. szStr[i] = '\0';
  1242. } else {
  1243. UINT uLen;
  1244. uLen = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED,
  1245. (LPCSTR)lpIsvUsrDic->achMethodName,
  1246. sizeof(lpIsvUsrDic->achMethodName),
  1247. szStr,
  1248. sizeof(szStr) / sizeof(TCHAR));
  1249. szStr[uLen] = '\0';
  1250. }
  1251. #else
  1252. for (i = 0; i < sizeof(lpIsvUsrDic->achMethodName); i++) {
  1253. szStr[i] = lpIsvUsrDic->achMethodName[i];
  1254. }
  1255. szStr[i] = '\0';
  1256. #endif
  1257. hKL = MatchImeName(szStr);
  1258. if (!hKL) {
  1259. return (hKL);
  1260. }
  1261. LoadString(hAppInst, IDS_PROCESS_FMT, szProcessFmt, sizeof(szProcessFmt) / sizeof(TCHAR));
  1262. LoadString(hAppInst, IDS_RESULT_FAIL, szResult[0], sizeof(szResult[0]) / sizeof(TCHAR));
  1263. LoadString(hAppInst, IDS_RESULT_SUCCESS, szResult[1], sizeof(szResult[1]) / sizeof(TCHAR));
  1264. LoadString(hAppInst, IDS_CHINESE_CHAR, szStr, sizeof(szStr) / sizeof(TCHAR));
  1265. hDC = GetDC(NULL);
  1266. GetTextExtentPoint(hDC, szStr, sizeof(WORD)/sizeof(TCHAR),
  1267. &lTextSize);
  1268. ReleaseDC(NULL, hDC);
  1269. // show the processing in somewhere, don't need to be same as this
  1270. rcProcess.left = 1;
  1271. rcProcess.top = 1;
  1272. rcProcess.right = rcProcess.left + lTextSize.cx *
  1273. sizeof(szProcessInfo) / sizeof(WORD);
  1274. rcProcess.bottom = rcProcess.top + lTextSize.cy;
  1275. // convert sequence code to internal code
  1276. for (i = 0; i < sizeof(wInternalCode) / sizeof(WORD); i++) {
  1277. LRESULT lRet;
  1278. lRet = ImmEscape(hKL, (HIMC)NULL,
  1279. IME_ESC_SEQUENCE_TO_INTERNAL, &i);
  1280. if (HIWORD(lRet) == 0xFFFF) {
  1281. // This is caused by sign extent in Win9x in the return value of
  1282. // ImmEscape, it causes an invalid internal code.
  1283. wAltInternalCode[i] = 0;
  1284. } else {
  1285. wAltInternalCode[i] = HIWORD(lRet);
  1286. }
  1287. wInternalCode[i] = LOWORD(lRet);
  1288. #ifndef UNICODE
  1289. if (wAltInternalCode[i] > 0xFF) {
  1290. // convert to multi byte string
  1291. wAltInternalCode[i] = LOBYTE(wAltInternalCode[i]) << 8 |
  1292. HIBYTE(wAltInternalCode[i]);
  1293. }
  1294. if (wInternalCode[i] > 0xFF) {
  1295. // convert to multi byte string
  1296. wInternalCode[i] = LOBYTE(wInternalCode[i]) << 8 |
  1297. HIBYTE(wInternalCode[i]);
  1298. }
  1299. #endif
  1300. }
  1301. // check for each record and register it
  1302. // get to the first record and skip the Bank ID
  1303. lpCurr = (LPBYTE)(lpIsvUsrDic + 1) + sizeof(WORD);
  1304. lpEnd = (LPBYTE)lpIsvUsrDic + dwFileSize;
  1305. for (; lpCurr < lpEnd;
  1306. // internal code + sequence code + Bank ID of next record
  1307. lpCurr += sizeof(WORD) + lpIsvUsrDic->cMethodKeySize + sizeof(WORD)) {
  1308. int j;
  1309. // quick way to init \0 for the register string
  1310. *(LPDWORD)szStr = 0;
  1311. #ifdef UNICODE
  1312. if (uCodePage == UNICODE_CP) {
  1313. szStr[0] = *(LPUNATSTR)lpCurr;
  1314. } else {
  1315. CHAR szMultiByte[4];
  1316. szMultiByte[0] = HIBYTE(*(LPUNATSTR)lpCurr);
  1317. szMultiByte[1] = LOBYTE(*(LPUNATSTR)lpCurr);
  1318. MultiByteToWideChar(uCodePage, MB_PRECOMPOSED,
  1319. szMultiByte, 2, szStr, 2);
  1320. }
  1321. #else
  1322. szStr[1] = *lpCurr;
  1323. szStr[0] = *(lpCurr + 1);
  1324. #endif
  1325. for (i = 0, j = 0; i < lpIsvUsrDic->cMethodKeySize; i++) {
  1326. if (!wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)]) {
  1327. } else if (wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)] < 0xFF) {
  1328. *(LPTSTR)&szStr[4 + j] = (TCHAR)
  1329. wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  1330. j += sizeof(TCHAR) / sizeof(TCHAR);
  1331. } else {
  1332. *(LPWSTR)&szStr[4 + j] = (WCHAR)
  1333. wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  1334. j += sizeof(WCHAR) / sizeof(TCHAR);
  1335. }
  1336. if (wInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)] < 0xFF) {
  1337. *(LPTSTR)&szStr[4 + j] = (TCHAR)
  1338. wInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  1339. j += sizeof(TCHAR) / sizeof(TCHAR);
  1340. } else {
  1341. *(LPWSTR)&szStr[4 + j] = (WCHAR)
  1342. wInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  1343. j += sizeof(WCHAR) / sizeof(TCHAR);
  1344. }
  1345. }
  1346. szStr[4 + j] = szStr[4 + j + 1] = szStr[4 + j + 2] = '\0';
  1347. fRet = ImmRegisterWord(hKL, &szStr[4], IME_REGWORD_STYLE_EUDC,
  1348. szStr);
  1349. wsprintf(szProcessInfo, szProcessFmt, (LPTSTR)szStr,
  1350. (LPTSTR)&szStr[4], szResult[fRet]);
  1351. hDC = GetDC(hWnd);
  1352. // show the process information
  1353. ExtTextOut(hDC, rcProcess.left, rcProcess.top, ETO_OPAQUE,
  1354. &rcProcess, szProcessInfo, lstrlen(szProcessInfo),
  1355. NULL);
  1356. ReleaseDC(NULL, hDC);
  1357. if (!fRet) {
  1358. // wait 3 seconds for fail case
  1359. Sleep(3000);
  1360. }
  1361. }
  1362. return (hKL);
  1363. }
  1364. /************************************************************/
  1365. /* BatchImeLink() */
  1366. /************************************************************/
  1367. void BatchImeLink(
  1368. HWND hWnd)
  1369. {
  1370. HANDLE hIsvUsrDicFile, hIsvUsrDic;
  1371. LPUSRDICIMHDR lpIsvUsrDic;
  1372. TCHAR chReplace;
  1373. int i, cbString;
  1374. DWORD dwSize, dwFileSize;
  1375. LPTSTR szTitle, szMessage;
  1376. int iTitle, iMessage;
  1377. OPENFILENAME ofn;
  1378. TCHAR szFilter[64];
  1379. TCHAR szFileName[MAX_PATH];
  1380. TCHAR szDirName[MAX_PATH];
  1381. // try to share the buffer
  1382. szTitle = szFilter;
  1383. iTitle = sizeof(szFilter) / sizeof(TCHAR);
  1384. szMessage = szDirName;
  1385. iMessage = sizeof(szDirName) / sizeof(TCHAR);
  1386. // internal error, the data structure need byte alignment
  1387. // it should not use WORD or DWORD alignment
  1388. if (sizeof(USRDICIMHDR) != 256) {
  1389. LoadString(hAppInst, IDS_INTERNAL_TITLE, szTitle, iTitle);
  1390. LoadString(hAppInst, IDS_INTERNAL_MSG, szMessage, iMessage);
  1391. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1392. return;
  1393. }
  1394. // do we need to set a new file name
  1395. cbString = LoadString(hAppInst, IDS_ISV_FILE_FILTER, szFilter,
  1396. sizeof(szFilter) / sizeof(TCHAR));
  1397. chReplace = szFilter[cbString - 1];
  1398. for (i = 0; szFilter[i]; i++) {
  1399. if (szFilter[i] == chReplace) {
  1400. szFilter[i] = '\0';
  1401. }
  1402. }
  1403. GetWindowsDirectory(szDirName, sizeof(szDirName) / sizeof(TCHAR));
  1404. lstrcpy(szFileName, TEXT("*.TBL"));
  1405. // prompt a open file dialog
  1406. ofn.lStructSize = sizeof(OPENFILENAME);
  1407. ofn.hwndOwner = hWnd;
  1408. ofn.lpstrFilter = szFilter;
  1409. ofn.lpstrCustomFilter = NULL;
  1410. ofn.nMaxCustFilter = 0;
  1411. ofn.nFilterIndex = 1;
  1412. ofn.lpstrFile = szFileName;
  1413. ofn.nMaxFile = sizeof(szFileName) / sizeof(TCHAR);
  1414. ofn.lpstrFileTitle = NULL;
  1415. ofn.nMaxFileTitle = 0;
  1416. ofn.lpstrInitialDir = szDirName;
  1417. ofn.lpstrTitle = NULL;;
  1418. ofn.Flags = OFN_NOCHANGEDIR|OFN_HIDEREADONLY|OFN_CREATEPROMPT|
  1419. OFN_PATHMUSTEXIST;
  1420. ofn.lpstrDefExt = NULL;
  1421. if (!GetOpenFileName(&ofn)) {
  1422. return;
  1423. }
  1424. hIsvUsrDicFile = CreateFile(ofn.lpstrFile, GENERIC_READ, 0, NULL,
  1425. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1426. if (hIsvUsrDicFile == INVALID_HANDLE_VALUE) {
  1427. LoadString(hAppInst, IDS_NOTOPEN_TITLE, szTitle, iTitle);
  1428. LoadString(hAppInst, IDS_NOTOPEN_MSG, szMessage, iMessage);
  1429. MessageBox(hWnd, szMessage, szTitle,
  1430. MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
  1431. return;
  1432. }
  1433. #if 0
  1434. for (i = 0; i < sizeof(szFileName); i++) {
  1435. if (szFileName[i] == '\\') {
  1436. szFileName[i] = ' ';
  1437. }
  1438. }
  1439. #endif
  1440. hIsvUsrDic = CreateFileMapping((HANDLE)hIsvUsrDicFile, NULL,
  1441. PAGE_READONLY, 0, 0, NULL);
  1442. if (!hIsvUsrDic) {
  1443. LoadString(hAppInst, IDS_NOTOPEN_TITLE, szTitle, iTitle);
  1444. LoadString(hAppInst, IDS_NOTOPEN_MSG, szMessage, iMessage);
  1445. MessageBox(hWnd, szMessage, szTitle,
  1446. MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
  1447. goto BatchCloseUsrDicFile;
  1448. }
  1449. lpIsvUsrDic = MapViewOfFile(hIsvUsrDic, FILE_MAP_READ, 0, 0, 0);
  1450. if (!lpIsvUsrDic) {
  1451. LoadString(hAppInst, IDS_NOTOPEN_TITLE, szTitle, iTitle);
  1452. LoadString(hAppInst, IDS_NOTOPEN_MSG, szMessage, iMessage);
  1453. MessageBox(hWnd, szMessage, szTitle,
  1454. MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
  1455. goto BatchCloseUsrDic;
  1456. }
  1457. dwSize = lpIsvUsrDic->ulTableCount * (sizeof(WORD) + sizeof(WORD) +
  1458. lpIsvUsrDic->cMethodKeySize) + 256;
  1459. dwFileSize = GetFileSize(hIsvUsrDicFile, (LPDWORD)NULL);
  1460. #if 0 // temp code
  1461. dwSize = dwFileSize;
  1462. #endif
  1463. if (dwSize != dwFileSize) {
  1464. LoadString(hAppInst, IDS_FILESIZE_TITLE, szTitle, iTitle);
  1465. LoadString(hAppInst, IDS_FILESIZE_MSG, szMessage, iMessage);
  1466. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1467. } else if (lpIsvUsrDic->uHeaderSize != 256) {
  1468. LoadString(hAppInst, IDS_HEADERSIZE_TITLE, szTitle, iTitle);
  1469. LoadString(hAppInst, IDS_HEADERSIZE_MSG, szMessage, iMessage);
  1470. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1471. } else if (lpIsvUsrDic->uInfoSize != 13) {
  1472. LoadString(hAppInst, IDS_INFOSIZE_TITLE, szTitle, iTitle);
  1473. LoadString(hAppInst, IDS_INFOSIZE_MSG, szMessage, iMessage);
  1474. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1475. } else if (CodePageInfo(lpIsvUsrDic->idCP) == -1) {
  1476. LoadString(hAppInst, IDS_CODEPAGE_TITLE, szTitle, iTitle);
  1477. LoadString(hAppInst, IDS_CODEPAGE_MSG, szMessage, iMessage);
  1478. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1479. } else if (*(LPUNADWORD)lpIsvUsrDic->idUserCharInfoSign != SIGN_CWIN) {
  1480. // != CWIN
  1481. LoadString(hAppInst, IDS_CWINSIGN_TITLE, szTitle, iTitle);
  1482. LoadString(hAppInst, IDS_CWINSIGN_MSG, szMessage, iMessage);
  1483. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1484. } else if (*(LPUNADWORD)((LPBYTE)lpIsvUsrDic->idUserCharInfoSign +
  1485. sizeof(DWORD)) != SIGN__TBL) {
  1486. // != _TBL
  1487. LoadString(hAppInst, IDS_CWINSIGN_TITLE, szTitle, iTitle);
  1488. LoadString(hAppInst, IDS_CWINSIGN_MSG, szMessage, iMessage);
  1489. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1490. } else if (!RegisterTable(hWnd, lpIsvUsrDic, dwFileSize, lpIsvUsrDic->idCP)) {
  1491. LoadString(hAppInst, IDS_UNMATCHED_TITLE, szTitle, iTitle);
  1492. LoadString(hAppInst, IDS_UNMATCHED_MSG, szMessage, iMessage);
  1493. MessageBox(hWnd, szMessage, szTitle, MB_OK);
  1494. } else {
  1495. // OK
  1496. }
  1497. UnmapViewOfFile(lpIsvUsrDic);
  1498. BatchCloseUsrDic:
  1499. CloseHandle(hIsvUsrDic);
  1500. BatchCloseUsrDicFile:
  1501. CloseHandle(hIsvUsrDicFile);
  1502. return;
  1503. }
  1504. /************************************************************/
  1505. /* WndProc() */
  1506. /************************************************************/
  1507. LRESULT CALLBACK WndProc( // this is the window procedure of
  1508. // EUDC editor
  1509. HWND hWnd,
  1510. UINT uMsg,
  1511. WPARAM wParam,
  1512. LPARAM lParam)
  1513. {
  1514. #ifdef UNICODE
  1515. static UINT uCode = 0xE000;
  1516. #else
  1517. static UINT uCode = 0xFA40;
  1518. #endif
  1519. switch (uMsg) {
  1520. case WM_COMMAND:
  1521. switch (wParam) {
  1522. case IDM_NEW_EUDC:
  1523. uCode++;
  1524. break;
  1525. case IDM_IME_LINK:
  1526. ImeLink(hWnd, uCode);
  1527. break;
  1528. case IDM_BATCH_IME_LINK:
  1529. BatchImeLink(hWnd);
  1530. break;
  1531. default:
  1532. break;
  1533. }
  1534. break;
  1535. case WM_DESTROY:
  1536. PostQuitMessage(0);
  1537. return (0L);
  1538. default:
  1539. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  1540. }
  1541. return (0L);
  1542. }
  1543. /************************************************************/
  1544. /* WinMain() */
  1545. /************************************************************/
  1546. int WINAPI WinMain(
  1547. HINSTANCE hInst,
  1548. HINSTANCE hPrevInst,
  1549. LPSTR lpszCmdLine,
  1550. int nCmdShow)
  1551. {
  1552. WNDCLASS wcClass;
  1553. HWND hWnd;
  1554. MSG sMsg;
  1555. hAppInst = hInst;
  1556. wcClass.style = CS_HREDRAW|CS_VREDRAW;
  1557. wcClass.lpfnWndProc = WndProc;
  1558. wcClass.cbClsExtra = 0;
  1559. wcClass.cbWndExtra = 0;
  1560. wcClass.hInstance = hAppInst;
  1561. wcClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  1562. wcClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  1563. wcClass.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  1564. wcClass.lpszMenuName = szMenuName;
  1565. wcClass.lpszClassName = szAppName;
  1566. RegisterClass(&wcClass);
  1567. hWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
  1568. szAppName,
  1569. TEXT("Fake EUDC Editor"),
  1570. WS_OVERLAPPEDWINDOW,
  1571. CW_USEDEFAULT, CW_USEDEFAULT,
  1572. CW_USEDEFAULT, CW_USEDEFAULT,
  1573. NULL, NULL, hAppInst, NULL);
  1574. ShowWindow(hWnd, SW_SHOWDEFAULT);
  1575. UpdateWindow(hWnd);
  1576. if (!hWnd) {
  1577. return (0);
  1578. }
  1579. while (GetMessage(&sMsg, NULL, 0, 0)) {
  1580. TranslateMessage(&sMsg);
  1581. DispatchMessage(&sMsg);
  1582. }
  1583. return ((int) sMsg.wParam);
  1584. }