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.

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