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.

549 lines
15 KiB

  1. /**************************************************/
  2. /* */
  3. /* */
  4. /* Chinese IME Batch Mode */
  5. /* (Dialogbox) */
  6. /* */
  7. /* */
  8. /* Copyright (c) 1997-1999 Microsoft Corporation. */
  9. /**************************************************/
  10. #include "stdafx.h"
  11. #include "eudcedit.h"
  12. #if 1 // use function in imeblink.c!
  13. #include "imeblink.h"
  14. #endif
  15. #include "blinkdlg.h"
  16. #include "util.h"
  17. #define SIGN_CWIN 0x4E495743 /* Sign of CWin */
  18. #define SIGN__TBL 0x4C42545F /* Sign of IME Table */
  19. #if 0 // move to imeblink.c!
  20. #define UNICODE_CP 1200
  21. #define BIG5_CP 950
  22. #define ALT_BIG5_CP 938
  23. #define GB2312_CP 936
  24. typedef struct _tagCOUNTRYSETTING {
  25. UINT uCodePage;
  26. LPCTSTR szCodePage;
  27. } COUNTRYSETTING;
  28. static const COUNTRYSETTING sCountry[] = {
  29. {
  30. BIG5_CP, TEXT("BIG5")
  31. }
  32. , {
  33. ALT_BIG5_CP, TEXT("BIG5")
  34. }
  35. #if defined(UNICODE)
  36. , {
  37. UNICODE_CP, TEXT("UNICODE")
  38. }
  39. #endif
  40. , {
  41. GB2312_CP, TEXT("GB2312")
  42. }
  43. };
  44. #endif // move to imeblink.c!
  45. #ifdef _DEBUG
  46. #undef THIS_FILE
  47. static char BASED_CODE THIS_FILE[] = __FILE__;
  48. #endif
  49. /****************************************/
  50. /* */
  51. /* Constructor */
  52. /* */
  53. /****************************************/
  54. CBLinkDlg::CBLinkDlg( CWnd *pParent)
  55. : CDialog( CBLinkDlg::IDD, pParent)
  56. {
  57. //{{AFX_DATA_INIT(CBLinkDlg)
  58. //}}AFX_DATA_INIT
  59. }
  60. /****************************************/
  61. /* */
  62. /* MESSAGE "WM_INITDIALOG" */
  63. /* */
  64. /****************************************/
  65. BOOL
  66. CBLinkDlg::OnInitDialog()
  67. {
  68. CString DlgTtl;
  69. CDialog::OnInitDialog();
  70. // Increment contexthelp mark "?" in dialog caption.
  71. // LONG WindowStyle = GetWindowLong( this->GetSafeHwnd(), GWL_EXSTYLE);
  72. // WindowStyle |= WS_EX_CONTEXTHELP;
  73. // SetWindowLong( this->GetSafeHwnd(), GWL_EXSTYLE, WindowStyle);
  74. // Set dialog title name.
  75. DlgTtl.LoadString( IDS_BATCHLNK_DLGTITLE);
  76. this->SetWindowText( DlgTtl);
  77. return TRUE;
  78. }
  79. /****************************************/
  80. /* */
  81. /* COMMAND "BROWSE" */
  82. /* */
  83. /****************************************/
  84. void
  85. CBLinkDlg::OnBrowsetable()
  86. {
  87. OPENFILENAME ofn;
  88. CString DlgTtl, DlgMsg;
  89. CString sFilter;
  90. TCHAR chReplace;
  91. TCHAR szFilter[64];
  92. TCHAR szFileName[MAX_PATH];
  93. TCHAR szDirName[MAX_PATH];
  94. TCHAR szTitleName[MAX_PATH];
  95. // Check size of IME batch table structure
  96. if( sizeof( USRDICIMHDR) != 256){
  97. OutputMessageBox( this->GetSafeHwnd(),
  98. IDS_INTERNAL_TITLE,
  99. IDS_INTERNAL_MSG, TRUE);
  100. return;
  101. }
  102. // Set filter of file( from string table)
  103. GetStringRes(szFilter, IDS_BATCHIME_FILTER);
  104. int StringLength = lstrlen( szFilter);
  105. chReplace = szFilter[StringLength-1];
  106. for( int i = 0; szFilter[i]; i++){
  107. if( szFilter[i] == chReplace)
  108. szFilter[i] = '\0';
  109. }
  110. GetSystemWindowsDirectory( szDirName, sizeof(szDirName)/sizeof(TCHAR));
  111. lstrcpy( szFileName, TEXT("*.TBL"));
  112. DlgTtl.LoadString( IDS_BROWSETABLE_DLGTITLE);
  113. // Set data in structure of OPENFILENAME
  114. ofn.lStructSize = sizeof( OPENFILENAME);
  115. ofn.hwndOwner = this->GetSafeHwnd();
  116. ofn.lpstrFilter = szFilter;
  117. ofn.lpstrCustomFilter = NULL;
  118. ofn.nMaxCustFilter = 0;
  119. ofn.nFilterIndex = 0;
  120. ofn.lpstrFileTitle = szTitleName;
  121. ofn.nMaxFileTitle = sizeof( szTitleName) / sizeof(TCHAR);
  122. ofn.lpstrFile = szFileName;
  123. ofn.nMaxFile = sizeof( szFileName) / sizeof(TCHAR);
  124. ofn.lpstrInitialDir = szDirName;
  125. ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR
  126. | OFN_CREATEPROMPT | OFN_PATHMUSTEXIST;
  127. ofn.lpstrDefExt = NULL;
  128. ofn.lpstrTitle = DlgTtl;
  129. if( !GetOpenFileName( &ofn))
  130. return;
  131. this->SetDlgItemText( IDC_IMETABLE, ofn.lpstrFile);
  132. CWnd *cWnd = GetDlgItem( IDOK);
  133. GotoDlgCtrl( cWnd);
  134. }
  135. /****************************************/
  136. /* */
  137. /* COMMAND "IDOK" */
  138. /* */
  139. /****************************************/
  140. void
  141. CBLinkDlg::OnOK()
  142. {
  143. if( !RegistStringTable())
  144. return;
  145. CDialog::OnOK();
  146. }
  147. /****************************************/
  148. /* */
  149. /* Register reading string */
  150. /* */
  151. /****************************************/
  152. BOOL
  153. CBLinkDlg::RegistStringTable()
  154. {
  155. LPUSRDICIMHDR lpIsvUsrDic;
  156. HANDLE hIsvUsrDicFile, hIsvUsrDic;
  157. DWORD dwSize, dwFileSize;
  158. BOOL stFunc;
  159. TCHAR szTableFile[MAX_PATH];
  160. TCHAR szFileName[MAX_PATH];
  161. CString DlgMsg, DlgTtl;
  162. this->GetDlgItemText( IDC_IMETABLE, szTableFile, sizeof( szTableFile)/sizeof(TCHAR));
  163. lstrcpy( szFileName, TEXT("*.TBL"));
  164. // Create file( to read)
  165. hIsvUsrDicFile = CreateFile( szTableFile, GENERIC_READ, 0, NULL,
  166. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  167. if( hIsvUsrDicFile == INVALID_HANDLE_VALUE){
  168. DlgTtl.LoadString( IDS_NOTOPEN_TITLE);
  169. DlgMsg.LoadString( IDS_NOTOPEN_MSG);
  170. this->MessageBox( DlgMsg, DlgTtl, MB_OK | MB_ICONHAND |
  171. MB_TASKMODAL | MB_TOPMOST);
  172. return FALSE;
  173. }
  174. #if 0
  175. for( i = 0; i < sizeof( szFileName); i++){
  176. if( szFileName[i] == '\\'){
  177. szFileName[i] = ' ';
  178. }
  179. }
  180. #endif
  181. // Create file mapping( read only)
  182. hIsvUsrDic = CreateFileMapping((HANDLE)hIsvUsrDicFile, NULL,
  183. PAGE_READONLY, 0, 0, NULL);
  184. if( !hIsvUsrDic){
  185. stFunc = FALSE;
  186. DlgTtl.LoadString( IDS_NOTOPEN_TITLE);
  187. DlgMsg.LoadString( IDS_NOTOPEN_MSG);
  188. this->MessageBox( DlgMsg, DlgTtl, MB_OK | MB_ICONHAND |
  189. MB_TASKMODAL | MB_TOPMOST);
  190. goto BatchCloseUsrDicFile;
  191. }
  192. // Set view file
  193. lpIsvUsrDic = (LPUSRDICIMHDR)MapViewOfFile( hIsvUsrDic,
  194. FILE_MAP_READ, 0, 0, 0);
  195. if( !lpIsvUsrDic){
  196. stFunc = FALSE;
  197. DlgTtl.LoadString( IDS_NOTOPEN_TITLE);
  198. DlgMsg.LoadString( IDS_NOTOPEN_MSG);
  199. this->MessageBox( DlgMsg, DlgTtl, MB_OK | MB_ICONHAND |
  200. MB_TASKMODAL | MB_TOPMOST);
  201. goto BatchCloseUsrDic;
  202. }
  203. dwSize = lpIsvUsrDic->ulTableCount * ( sizeof(WORD) + sizeof(WORD)
  204. + lpIsvUsrDic->cMethodKeySize) + 256;
  205. dwFileSize = GetFileSize( hIsvUsrDicFile, (LPDWORD)NULL);
  206. #if 0
  207. dwSize = dwFileSize;
  208. #endif
  209. // Check table file data
  210. if( dwSize != dwFileSize){
  211. stFunc = FALSE;
  212. OutputMessageBox( this->GetSafeHwnd(),
  213. IDS_FILESIZE_MSGTITLE,
  214. IDS_FILESIZE_MSG, TRUE);
  215. }else if( lpIsvUsrDic->uHeaderSize != 256){
  216. stFunc = FALSE;
  217. OutputMessageBox( this->GetSafeHwnd(),
  218. IDS_FILEHEADER_MSGTITLE,
  219. IDS_FILEHEADER_MSG, TRUE);
  220. }else if( lpIsvUsrDic->uInfoSize != 13){
  221. stFunc = FALSE;
  222. OutputMessageBox( this->GetSafeHwnd(),
  223. IDS_INMETHOD_MSGTITLE,
  224. IDS_INMETHOD_MSG, TRUE);
  225. }else if( CodePageInfo( lpIsvUsrDic->idCP) == -1){
  226. stFunc = FALSE;
  227. OutputMessageBox( this->GetSafeHwnd(),
  228. IDS_CODEPAGE_MSGTITLE,
  229. IDS_CODEPAGE_MSG, TRUE);
  230. }else if( *(DWORD UNALIGNED *)lpIsvUsrDic->idUserCharInfoSign != SIGN_CWIN){
  231. stFunc = FALSE;
  232. OutputMessageBox( this->GetSafeHwnd(),
  233. IDS_SIGN_MSGTITLE,
  234. IDS_SIGN_MSG, TRUE);
  235. }else if( *(DWORD UNALIGNED *)((LPBYTE)lpIsvUsrDic->idUserCharInfoSign +
  236. sizeof(DWORD)) != SIGN__TBL){
  237. stFunc = FALSE;
  238. OutputMessageBox( this->GetSafeHwnd(),
  239. IDS_SIGN_MSGTITLE,
  240. IDS_SIGN_MSG, TRUE);
  241. }else{
  242. stFunc = TRUE;
  243. if( !RegisterTable( this->GetSafeHwnd(),
  244. lpIsvUsrDic, dwFileSize, lpIsvUsrDic->idCP)){
  245. OutputMessageBox( this->GetSafeHwnd(),
  246. IDS_UNMATCHED_TITLE,
  247. IDS_UNMATCHED_MSG, TRUE);
  248. stFunc = FALSE;
  249. }
  250. }
  251. UnmapViewOfFile( lpIsvUsrDic);
  252. BatchCloseUsrDic:
  253. CloseHandle( hIsvUsrDic);
  254. BatchCloseUsrDicFile:
  255. CloseHandle( hIsvUsrDicFile);
  256. return stFunc;
  257. }
  258. #if 0 // move to imeblink.c!
  259. /****************************************/
  260. /* */
  261. /* Register reading string */
  262. /* */
  263. /****************************************/
  264. HKL
  265. CBLinkDlg::RegisterTable(
  266. HWND hWnd,
  267. LPUSRDICIMHDR lpIsvUsrDic,
  268. DWORD dwFileSize,
  269. UINT uCodePage)
  270. {
  271. HKL hKL;
  272. DWORD i;
  273. LPBYTE lpCurr, lpEnd;
  274. BOOL fRet;
  275. TCHAR szStr[16];
  276. WORD wInternalCode[256];
  277. WORD wAltInternalCode[256];
  278. #ifdef UNICODE
  279. if (uCodePage == UNICODE_CP) {
  280. LPUNATSTR lpszMethodName;
  281. lpszMethodName = (LPUNATSTR)lpIsvUsrDic->achMethodName;
  282. for (i = 0; i < sizeof(lpIsvUsrDic->achMethodName) / sizeof(TCHAR); i++) {
  283. szStr[i] = *lpszMethodName++;
  284. }
  285. szStr[i] = '\0';
  286. } else {
  287. UINT uLen;
  288. uLen = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED,
  289. (LPCSTR)lpIsvUsrDic->achMethodName,
  290. sizeof(lpIsvUsrDic->achMethodName),
  291. szStr,
  292. sizeof(szStr) / sizeof(TCHAR));
  293. szStr[uLen] = '\0';
  294. }
  295. #else
  296. for( i = 0; i < sizeof( lpIsvUsrDic->achMethodName); i++){
  297. szStr[i] = lpIsvUsrDic->achMethodName[i];
  298. }
  299. szStr[i] = '\0';
  300. #endif
  301. hKL = MatchImeName( szStr);
  302. if( !hKL) return (hKL);
  303. for( i = 0; i < sizeof(wInternalCode) / sizeof(WORD); i++) {
  304. LRESULT lRet;
  305. lRet = ImmEscape(hKL, (HIMC)NULL,
  306. IME_ESC_SEQUENCE_TO_INTERNAL, &i);
  307. if (HIWORD(lRet) == 0xFFFF) {
  308. // This is caused by sign extent in Win9x in the return value of
  309. // ImmEscape, it causes an invalid internal code.
  310. wAltInternalCode[i] = 0;
  311. } else {
  312. wAltInternalCode[i] = HIWORD(lRet);
  313. }
  314. #ifndef UNICODE
  315. if( wAltInternalCode[i] > 0xFF) {
  316. wAltInternalCode[i] = LOBYTE(wAltInternalCode[i]) << 8 |
  317. HIBYTE(wAltInternalCode[i]);
  318. }
  319. if( wInternalCode[i] > 0xFF) {
  320. wInternalCode[i] = LOBYTE(wInternalCode[i]) << 8 |
  321. HIBYTE(wInternalCode[i]);
  322. }
  323. #endif
  324. }
  325. lpCurr = (LPBYTE)(lpIsvUsrDic + 1) + sizeof(WORD);
  326. lpEnd = (LPBYTE)lpIsvUsrDic + dwFileSize;
  327. for (; lpCurr < lpEnd; lpCurr += sizeof(WORD) + lpIsvUsrDic->cMethodKeySize + sizeof(WORD)) {
  328. int j;
  329. *(LPDWORD)szStr = 0;
  330. #ifdef UNICODE
  331. if (uCodePage == UNICODE_CP) {
  332. szStr[0] = *(LPUNATSTR)lpCurr;
  333. } else {
  334. CHAR szMultiByte[4];
  335. szMultiByte[0] = HIBYTE(*(LPUNASTR)lpCurr);
  336. szMultiByte[1] = LOBYTE(*(LPUNASTR)lpCurr);
  337. MultiByteToWideChar(uCodePage, MB_PRECOMPOSED,
  338. szMultiByte, 2, szStr, 2);
  339. }
  340. #else
  341. szStr[1] = *lpCurr;
  342. szStr[0] = *(lpCurr + 1);
  343. #endif
  344. for (i = 0, j = 0; i < lpIsvUsrDic->cMethodKeySize; i++) {
  345. if (!wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)]) {
  346. } else if (wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)] < 0xFF) {
  347. *(LPTSTR)&szStr[4 + j] = (TCHAR)
  348. wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  349. j += sizeof(TCHAR) / sizeof(TCHAR);
  350. } else {
  351. *(LPWSTR)&szStr[4 + j] = (WCHAR)
  352. wAltInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  353. j += sizeof(WCHAR) / sizeof(TCHAR);
  354. }
  355. if (wInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)] < 0xFF) {
  356. *(LPTSTR)&szStr[4 + j] = (TCHAR)
  357. wInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  358. j += sizeof(TCHAR) / sizeof(TCHAR);
  359. } else {
  360. *(LPWSTR)&szStr[4 + j] = (WCHAR)
  361. wInternalCode[*(LPBYTE)(lpCurr + sizeof(WORD) + i)];
  362. j += sizeof(WCHAR) / sizeof(TCHAR);
  363. }
  364. }
  365. szStr[4 + j] = szStr[4 + j + 1] = szStr[4 + j + 2] = '\0';
  366. fRet = ImmRegisterWord(hKL, &szStr[4], IME_REGWORD_STYLE_EUDC,
  367. szStr);
  368. }
  369. return (hKL);
  370. }
  371. /****************************************/
  372. /* */
  373. /* Get keyboard layout handle */
  374. /* */
  375. /****************************************/
  376. HKL
  377. CBLinkDlg::MatchImeName(
  378. LPCTSTR szStr)
  379. {
  380. TCHAR szImeName[16];
  381. int nLayout;
  382. HKL hKL;
  383. HGLOBAL hMem;
  384. HKL FAR *lpMem;
  385. int i;
  386. nLayout = GetKeyboardLayoutList( 0, NULL);
  387. hMem = GlobalAlloc( GHND, sizeof(HKL) * nLayout);
  388. if( !hMem) return NULL;
  389. lpMem = (HKL FAR *)GlobalLock( hMem);
  390. if( !lpMem){
  391. GlobalFree( hMem);
  392. return NULL;
  393. }
  394. GetKeyboardLayoutList( nLayout, lpMem);
  395. for( i = 0; i < nLayout; i++){
  396. BOOL fRet;
  397. hKL = *(lpMem + i);
  398. for( j = 0; j < uLen; j++){
  399. szImeName[j] = '\0';
  400. }
  401. fRet = ImmEscape(hKL, (HIMC)NULL, IME_ESC_IME_NAME, szImeName);
  402. if( !fRet) continue;
  403. if(lstrcmp(szStr, szImeName) == 0){
  404. goto MatchOvr;
  405. }
  406. }
  407. hKL = NULL;
  408. MatchOvr:
  409. GlobalUnlock( hMem);
  410. GlobalFree( hMem);
  411. return( hKL);
  412. }
  413. /****************************************/
  414. /* */
  415. /* CodePage Info */
  416. /* */
  417. /****************************************/
  418. int
  419. CBLinkDlg::CodePageInfo(
  420. UINT uCodePage)
  421. {
  422. int i;
  423. for (i = 0; i < sizeof(sCountry) / sizeof(COUNTRYSETTING); i++) {
  424. if (sCountry[i].uCodePage == uCodePage) {
  425. return(i);
  426. }
  427. }
  428. return (-1);
  429. }
  430. #endif // move to imeblink.c!
  431. static DWORD aIds[] =
  432. {
  433. IDC_STATICIMETBL, IDH_EUDC_BLINK_EDITTBL,
  434. IDC_IMETABLE, IDH_EUDC_BLINK_EDITTBL,
  435. IDC_BROWSETABLE, IDH_EUDC_BROWSE,
  436. 0, 0
  437. };
  438. /****************************************/
  439. /* */
  440. /* Window Procedure */
  441. /* */
  442. /****************************************/
  443. LRESULT
  444. CBLinkDlg::WindowProc(
  445. UINT message,
  446. WPARAM wParam,
  447. LPARAM lParam)
  448. {/*
  449. if( message == WM_HELP){
  450. ::WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  451. HelpPath, HELP_WM_HELP, (DWORD_PTR)(LPDWORD)aIds);
  452. return(0);
  453. }
  454. if( message == WM_CONTEXTMENU){
  455. ::WinHelp((HWND)wParam, HelpPath,
  456. HELP_CONTEXTMENU, (DWORD_PTR)(LPDWORD)aIds);
  457. return(0);
  458. }
  459. */
  460. return CDialog::WindowProc(message, wParam, lParam);
  461. }
  462. BEGIN_MESSAGE_MAP(CBLinkDlg, CDialog)
  463. //{{AFX_MSG_MAP(CBLinkDlg)
  464. ON_BN_CLICKED(IDC_BROWSETABLE, OnBrowsetable)
  465. //}}AFX_MSG_MAP
  466. END_MESSAGE_MAP()