WindowsXP-SP1/windows/feime/cht/config.c
2020-09-30 16:53:49 +02:00

1427 lines
40 KiB
C

/*++
Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
Module Name:
CONFIG.c
++*/
/**********************************************************************/
#include <windows.h>
#include <commdlg.h>
#include <immdev.h>
#include <shlobj.h>
#include "imeattr.h"
#include "imedefs.h"
#include "imerc.h"
#if defined(UNIIME)
#include "uniime.h"
#endif
#if !defined(ROMANIME)
/**********************************************************************/
/* ReverseConversionList() */
/**********************************************************************/
void PASCAL ReverseConversionList(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hLayoutListBox)
{
TCHAR szImeName[16];
HKL FAR *lpKLMem;
int nLayouts, i, nIMEs;
LoadString(hInst, IDS_NONE, szImeName, sizeof(szImeName)/sizeof(TCHAR));
SendMessage(hLayoutListBox, LB_INSERTSTRING,
0, (LPARAM)szImeName);
SendMessage(hLayoutListBox, LB_SELECTSTRING,
0, (LPARAM)szImeName);
SendMessage(hLayoutListBox, LB_SETITEMDATA,
0, (LPARAM)(HKL)NULL);
nLayouts = GetKeyboardLayoutList(0, NULL);
lpKLMem = GlobalAlloc(GPTR, sizeof(HKL) * nLayouts);
if (!lpKLMem) {
return;
}
GetKeyboardLayoutList(nLayouts, lpKLMem);
for (i = 0, nIMEs = 0; i < nLayouts; i++) {
HKL hKL;
hKL = *(lpKLMem + i);
if (LOWORD(hKL) != NATIVE_LANGUAGE) {
// not support other language
continue;
}
// NULL hIMC ???????
if (!ImmGetConversionList(hKL, (HIMC)NULL, NULL,
NULL, 0, GCL_REVERSECONVERSION)) {
// this IME not support reverse conversion
continue;
}
if (!ImmEscape(hKL, (HIMC)NULL, IME_ESC_IME_NAME,
szImeName)) {
// this IME does not report the IME name
continue;
}
nIMEs++;
SendMessage(hLayoutListBox, LB_INSERTSTRING,
nIMEs, (LPARAM)szImeName);
if (hKL == lpImeL->hRevKL) {
SendMessage(hLayoutListBox, LB_SELECTSTRING, nIMEs,
(LPARAM)szImeName);
}
SendMessage(hLayoutListBox, LB_SETITEMDATA,
nIMEs, (LPARAM)hKL);
}
GlobalFree((HGLOBAL)lpKLMem);
return;
}
#endif
/**********************************************************************/
/* ChangeConfiguration() */
/**********************************************************************/
void PASCAL ChangeConfiguration(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hDlg)
{
#if !defined(ROMANIME)
DWORD fdwModeConfig;
DWORD fdwImeMsg;
#if defined(PHON)
int i;
#endif
fdwModeConfig = 0;
fdwImeMsg = 0;
if (IsDlgButtonChecked(hDlg, IDD_OFF_CARET_UI)) {
fdwModeConfig |= MODE_CONFIG_OFF_CARET_UI;
}
if ((lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) ^
(fdwModeConfig & MODE_CONFIG_OFF_CARET_UI)) {
fdwImeMsg |= MSG_IMN_TOGGLE_UI;
}
#if defined(WINAR30)
if (IsDlgButtonChecked(hDlg, IDD_QUICK_KEY)) {
fdwModeConfig |= MODE_CONFIG_QUICK_KEY;
}
if ((lpImeL->fdwModeConfig & MODE_CONFIG_QUICK_KEY) ^
(fdwModeConfig & MODE_CONFIG_QUICK_KEY)) {
fdwImeMsg |= MSG_IMN_UPDATE_QUICK_KEY;
}
#endif
if (IsDlgButtonChecked(hDlg, IDD_PREDICT)) {
fdwModeConfig |= MODE_CONFIG_PREDICT;
}
if ((lpImeL->fdwModeConfig & MODE_CONFIG_PREDICT) ^
(fdwModeConfig & MODE_CONFIG_PREDICT)) {
fdwImeMsg |= MSG_IMN_UPDATE_PREDICT;
}
// check BIG5ONLY
if (IsDlgButtonChecked(hDlg, IDD_BIG5ONLY)) {
fdwModeConfig |= MODE_CONFIG_BIG5ONLY;
}
if (lpImeL->fdwModeConfig != fdwModeConfig) {
SetUserSetting(
#if defined(UNIIME)
lpImeL,
#endif
szRegModeConfig, REG_DWORD, (LPBYTE)&fdwModeConfig,
sizeof(fdwModeConfig));
lpImeL->fdwModeConfig = fdwModeConfig;
if (fdwImeMsg & MSG_IMN_TOGGLE_UI) {
InitImeUIData(lpImeL);
}
}
#if defined(PHON)
// get the reading layout
for (i = IDD_DEFAULT_KB; i < IDD_DEFAULT_KB + READ_LAYOUTS; i++) {
if (IsDlgButtonChecked(hDlg, i)) {
break;
}
}
if (i >= IDD_DEFAULT_KB + READ_LAYOUTS) {
i = READ_LAYOUT_DEFAULT;
} else {
i -= IDD_DEFAULT_KB;
}
if ((int)lpImeL->nReadLayout != i) {
SetUserSetting(
#if defined(UNIIME)
lpImeL,
#endif
szRegReadLayout, REG_DWORD, (LPBYTE)&i, sizeof(i));
lpImeL->nReadLayout = (WORD)i;
fdwImeMsg |= MSG_IMN_UPDATE_SOFTKBD;
}
#endif
{
HWND hLayoutListBox;
int iCurSel;
HKL hKL;
hLayoutListBox = GetDlgItem(hDlg, IDD_LAYOUT_LIST);
iCurSel = (int)SendMessage(hLayoutListBox, LB_GETCURSEL, 0, 0);
hKL = (HKL)SendMessage(hLayoutListBox, LB_GETITEMDATA,
iCurSel, 0);
if (lpImeL->hRevKL != hKL) {
WORD nRevMaxKey;
lpImeL->hRevKL = hKL;
SetUserSetting(
#if defined(UNIIME)
lpImeL,
#endif
szRegRevKL, REG_DWORD, (LPBYTE)&hKL, sizeof(hKL));
// get the new size
nRevMaxKey = (WORD)ImmEscape(hKL, (HIMC)NULL, IME_ESC_MAX_KEY,
NULL);
if (nRevMaxKey < lpImeL->nMaxKey) {
nRevMaxKey = lpImeL->nMaxKey;
}
if (lpImeL->nRevMaxKey != nRevMaxKey) {
lpImeL->nRevMaxKey = nRevMaxKey;
SetCompLocalData(lpImeL);
fdwImeMsg |= MSG_IMN_COMPOSITIONSIZE;
}
}
}
if (fdwImeMsg) {
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
LPPRIVCONTEXT lpImcP;
hIMC = (HIMC)ImmGetContext(hDlg);
if (!hIMC) {
return;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return;
}
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (!lpImcP) {
goto ChgConfigUnlockIMC;
}
lpImcP->fdwImeMsg |= fdwImeMsg;
GenerateMessage(hIMC, lpIMC, lpImcP);
ImmUnlockIMCC(lpIMC->hPrivate);
ChgConfigUnlockIMC:
ImmUnlockIMC(hIMC);
}
#endif
return;
}
#if !defined(ROMANIME) && !defined(WINIME) && !defined(UNICDIME)
/**********************************************************************/
/* BinaryMatched() */
/**********************************************************************/
BOOL PASCAL BinaryMatched(
LPBYTE lpData1,
LPBYTE lpData2,
UINT uLen)
{
UINT i;
for (i = 0; i < uLen; i++) {
if (*lpData1++ != *lpData2++) {
return (FALSE);
}
}
return (TRUE);
}
/**********************************************************************/
/* VerifyEudcDic() */
/**********************************************************************/
#define TITLE_BUF_SIZE 32
#define MESSAGE_BUF_SIZE 256
BOOL PASCAL VerifyEudcDic(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hWnd,
LPTSTR szTitle, // this buffer size must >= TITLE_BUF_SIZE
LPTSTR szMessage) // this buffer size must >= MESSAGE_BUF_SIZE
{
HANDLE hUsrDicFile, hUsrDic;
LPUSRDICIMHDR lpUsrDic;
BOOL fRet;
int i;
DWORD dwSize, dwFileSize;
PSECURITY_ATTRIBUTES psa;
psa = CreateSecurityAttributes();
hUsrDicFile = CreateFile(szMessage, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hUsrDicFile == INVALID_HANDLE_VALUE) {
FreeSecurityAttributes(psa);
if (!hWnd) {
return (FALSE);
}
LoadString(hInst, IDS_NOTOPEN_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_NOTOPEN_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
return (FALSE);
}
fRet = FALSE;
// we do not need to care about DBCS here, even no problem for DBCS
for (i = 0; i < MAX_PATH; i++) {
if (szMessage[i] == '\\') {
szMessage[i] = '!';
}
}
hUsrDic = CreateFileMapping((HANDLE)hUsrDicFile, psa,
PAGE_READONLY, 0, 0, szMessage);
if (!hUsrDic) {
if (!hWnd) {
goto VerifyCloseEudcDic;
}
LoadString(hInst, IDS_NOTOPEN_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_NOTOPEN_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
goto VerifyCloseEudcDicFile;
}
lpUsrDic = MapViewOfFile(hUsrDic, FILE_MAP_READ, 0, 0, 0);
if (!lpUsrDic) {
if (!hWnd) {
goto VerifyCloseEudcDic;
}
LoadString(hInst, IDS_NOTOPEN_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_NOTOPEN_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
goto VerifyCloseEudcDic;
}
dwSize = lpUsrDic->ulTableCount * (sizeof(WORD) + sizeof(WORD) +
lpUsrDic->cMethodKeySize) + 256;
dwFileSize = GetFileSize(hUsrDicFile, (LPDWORD)NULL);
if (dwSize != dwFileSize) {
if (!hWnd) {
goto VerifyUnmapEudcDic;
}
LoadString(hInst, IDS_FILESIZE_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_FILESIZE_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
} else if (lpUsrDic->uHeaderSize != 256) {
if (!hWnd) {
goto VerifyUnmapEudcDic;
}
LoadString(hInst, IDS_HEADERSIZE_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_HEADERSIZE_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
} else if (lpUsrDic->uInfoSize != 13) {
if (!hWnd) {
goto VerifyUnmapEudcDic;
}
LoadString(hInst, IDS_INFOSIZE_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_INFOSIZE_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
} else if (lpUsrDic->idCP != NATIVE_CP && lpUsrDic->idCP != ALT_NATIVE_CP) {
if (!hWnd) {
goto VerifyUnmapEudcDic;
}
LoadString(hInst, IDS_CODEPAGE_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_CODEPAGE_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
} else if (*(LPUNADWORD)lpUsrDic->idUserCharInfoSign != SIGN_CWIN) {
// != CWIN
if (!hWnd) {
goto VerifyUnmapEudcDic;
}
LoadString(hInst, IDS_CWINSIGN_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_CWINSIGN_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
} else if (*(LPUNADWORD)((LPBYTE)lpUsrDic->idUserCharInfoSign +
sizeof(DWORD)) != SIGN__TBL) {
// != _TBL
if (!hWnd) {
goto VerifyUnmapEudcDic;
}
LoadString(hInst, IDS_CWINSIGN_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_CWINSIGN_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
} else if (!BinaryMatched((LPBYTE)lpImeL->szIMEName,
(LPBYTE)lpUsrDic->achMethodName, sizeof(lpUsrDic->achMethodName))) {
if (!hWnd) {
goto VerifyUnmapEudcDic;
}
// The IME Name is not match with this file
LoadString(hInst, IDS_UNMATCHED_TITLE, szTitle, TITLE_BUF_SIZE);
LoadString(hInst, IDS_UNMATCHED_MSG, szMessage, MESSAGE_BUF_SIZE);
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
} else {
fRet = TRUE;
}
VerifyUnmapEudcDic:
UnmapViewOfFile(lpUsrDic);
VerifyCloseEudcDic:
CloseHandle(hUsrDic);
VerifyCloseEudcDicFile:
CloseHandle(hUsrDicFile);
FreeSecurityAttributes(psa);
return (fRet);
}
#if 0
/**********************************************************************/
/* GetEudcDic() */
/**********************************************************************/
void PASCAL GetEudcDic(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hWnd)
{
TCHAR chReplace;
int i, cbString;
OPENFILENAME ofn;
TCHAR szFilter[64];
TCHAR szFileName[MAX_PATH];
TCHAR szDirName[MAX_PATH];
cbString = LoadString(hInst, IDS_USRDIC_FILTER,
szFilter, sizeof(szFilter)/sizeof(TCHAR));
chReplace = szFilter[cbString - 1];
for (i = 0; szFilter[i]; i++) {
if (szFilter[i] == chReplace) {
szFilter[i] = '\0';
}
}
GetWindowsDirectory(szDirName, sizeof(szDirName));
lstrcpy(szFileName, TEXT("*.TBL"));
// prompt a dialog
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = (HWND)NULL;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = sizeof(szFileName) / sizeof(TCHAR);
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = szDirName;
ofn.lpstrTitle = lpImeL->szIMEName;
ofn.Flags = OFN_NOCHANGEDIR|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|
OFN_FILEMUSTEXIST;
ofn.lpstrDefExt = NULL;
if (!GetOpenFileName(&ofn)) {
return;
}
lstrcpy( szDirName, szFileName );
if (!VerifyEudcDic(
#if defined(UNIIME)
lpImeL,
#endif
hWnd, szFilter, szDirName)) {
return;
}
SetWindowText(hWnd, szFileName);
return;
}
/**********************************************************************/
/* ChangeEudcDic() */
/**********************************************************************/
BOOL PASCAL ChangeEudcDic(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
HWND hWnd)
{
BOOL fRet;
TCHAR szFileName[MAX_PATH];
TCHAR szTitle[32];
TCHAR szMessage[MAX_PATH];
#if defined(DEBUG)
// internal error, the data structure need byte alignment
// it should not use WORD or DWORD alignment
if (sizeof(USRDICIMHDR) != 256) {
LoadString(hInst, IDS_INTERNAL_TITLE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
LoadString(hInst, IDS_INTERNAL_MSG, szMessage, sizeof(szMessage)/sizeof(TCHAR));
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
return (FALSE);
}
#endif
GetWindowText(hWnd, szFileName, sizeof(szFileName) / sizeof(TCHAR));
if (!lstrcmp(szFileName, lpImeL->szUsrDic)) {
return (TRUE);
}
if (szFileName[0] == '\0') {
LRESULT lRet;
#if defined(UNIIME)
lRet = UniImeEscape(lpInstL, lpImeL, (HIMC)NULL,
IME_ESC_SET_EUDC_DICTIONARY, szFileName);
#else
lRet = ImeEscape((HIMC)NULL, IME_ESC_SET_EUDC_DICTIONARY, szFileName);
#endif
if (lRet) {
return (TRUE);
} else {
LoadString(hInst, IDS_EUDCDICFAIL_TITLE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
LoadString(hInst, IDS_EUDCDICFAIL_MSG, szMessage, sizeof(szMessage)/sizeof(TCHAR));
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
return (FALSE);
}
}
lstrcpy( szMessage, szFileName );
if (fRet = VerifyEudcDic(
#if defined(UNIIME)
lpImeL,
#endif
hWnd, szTitle, szMessage)) {
LRESULT lRet;
#if defined(UNIIME)
lRet = UniImeEscape(lpInstL, lpImeL, (HIMC)NULL,
IME_ESC_SET_EUDC_DICTIONARY, szFileName);
#else
lRet = ImeEscape((HIMC)NULL, IME_ESC_SET_EUDC_DICTIONARY, szFileName);
#endif
if (lRet) {
fRet = TRUE;
} else {
LoadString(hInst, IDS_EUDCDICFAIL_TITLE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
LoadString(hInst, IDS_EUDCDICFAIL_MSG, szMessage, sizeof(szMessage)/sizeof(TCHAR));
MessageBox(hWnd, szMessage, szTitle,
MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
}
}
return (fRet);
}
#endif
#endif
/**********************************************************************/
/* ConfigureDlgProc() */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
INT_PTR CALLBACK ConfigDlgProc( // dialog procedure of configuration
HWND hDlg,
UINT uMessage,
WPARAM wParam,
LPARAM lParam)
{
#if !defined(ROMANIME)
HWND hLayoutListBox;
HIMC hIMC;
static HIMC hOldIMC;
#endif
#if defined(UNIIME)
static LPINSTDATAL lpInstL;
static LPIMEL lpImeL;
#endif
switch (uMessage) {
case WM_INITDIALOG:
#if defined(UNIIME)
lpInstL = (LPINSTDATAL)lParam;
lpImeL = lpInstL->lpImeL;
#endif
if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
CheckDlgButton(hDlg, IDD_OFF_CARET_UI, BST_CHECKED);
}
#if !defined(ROMANIME)
#if defined(PHON)
CheckRadioButton(hDlg, IDD_DEFAULT_KB,
IDD_DEFAULT_KB + READ_LAYOUTS - 1,
lpImeL->nReadLayout + IDD_DEFAULT_KB);
#endif
hLayoutListBox = GetDlgItem(hDlg, IDD_LAYOUT_LIST);
hIMC = ImmCreateContext();
if (hIMC) {
ImmSetOpenStatus(hIMC, FALSE);
hOldIMC = ImmAssociateContext(hLayoutListBox, hIMC);
}
if (!hOldIMC) {
} else if (!hIMC) {
} else {
LPINPUTCONTEXT lpIMC;
POINT ptPos;
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hOldIMC);
if (!lpIMC) {
goto ConfigDlgStatusPosOvr;
}
ptPos = lpIMC->ptStatusWndPos;
ImmUnlockIMC(hOldIMC);
ImmSetStatusWindowPos(hIMC, &ptPos);
}
ConfigDlgStatusPosOvr:
// put all reverse conversion hKL into this list
ReverseConversionList(
#if defined(UNIIME)
lpImeL,
#endif
hLayoutListBox);
if (lpImeL->fdwModeConfig & MODE_CONFIG_PREDICT) {
CheckDlgButton(hDlg, IDD_PREDICT, BST_CHECKED);
}
if ( lpImeL->fdwModeConfig & MODE_CONFIG_BIG5ONLY ) {
CheckDlgButton(hDlg, IDD_BIG5ONLY, BST_CHECKED);
}
#if defined(WINAR30)
if (lpImeL->fdwModeConfig & MODE_CONFIG_QUICK_KEY) {
CheckDlgButton(hDlg, IDD_QUICK_KEY, BST_CHECKED);
}
#endif
#endif
SetWindowText(hDlg, lpImeL->szIMEName);
return (TRUE); // don't want to set focus to special control
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
ChangeConfiguration(
#if defined(UNIIME)
lpImeL,
#endif
hDlg);
// falling throgh ....
case IDCANCEL:
#if !defined(ROMANIME)
hLayoutListBox = GetDlgItem(hDlg, IDD_LAYOUT_LIST);
hIMC = ImmGetContext(hLayoutListBox);
ImmAssociateContext(hLayoutListBox, hOldIMC);
ImmDestroyContext(hIMC);
#endif
EndDialog(hDlg, FALSE);
break;
default:
return (FALSE);
break;
}
return (TRUE);
default:
return (FALSE);
}
return (TRUE);
}
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
/**********************************************************************/
/* SetUsrDic */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
BOOL PASCAL SetUsrDic(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
HWND hWnd,
LPCTSTR szEudcDic,
LPTSTR szTitle, // this buffer size must >= TITLE_BUF_SIZE
LPTSTR szMessage) // this buffer size must >= MESSAGE_BUF_SIZE
{
HANDLE hUsrDicFile, hUsrDicMem, hReadUsrDicMem;
BOOL fRet;
DWORD dwUsrDicSize;
UINT uRecLen, uReadLen, uWriteLen;
UINT uUsrDicSize;
PSECURITY_ATTRIBUTES psa;
psa = CreateSecurityAttributes();
hUsrDicFile = CreateFile(szEudcDic, GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
psa, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hUsrDicFile == INVALID_HANDLE_VALUE) {
FreeSecurityAttributes(psa);
return (FALSE);
}
fRet = TRUE;
if (GetLastError() == ERROR_ALREADY_EXISTS) {
lstrcpy( szMessage, szEudcDic );
fRet = VerifyEudcDic(
#if defined(UNIIME)
lpImeL,
#endif
hWnd, szTitle, szMessage);
} else {
LPUSRDICIMHDR lpUsrDicImHdr;
DWORD dwWriteBytes;
lpUsrDicImHdr = (LPUSRDICIMHDR)GlobalAlloc(GPTR, sizeof(USRDICIMHDR));
if (!lpUsrDicImHdr) {
fRet = FALSE;
goto SetUsrDicClose;
}
// write the header
lpUsrDicImHdr->uHeaderSize = sizeof(USRDICIMHDR);
lpUsrDicImHdr->idMajor = 1;
lpUsrDicImHdr->ulTableCount = 0;
lpUsrDicImHdr->cMethodKeySize = lpImeL->nMaxKey;
lpUsrDicImHdr->uInfoSize = 13;
lpUsrDicImHdr->idCP = NATIVE_CP;
*(LPUNADWORD)lpUsrDicImHdr->idUserCharInfoSign = SIGN_CWIN;
*(LPUNADWORD)((LPBYTE)lpUsrDicImHdr->idUserCharInfoSign +
sizeof(DWORD)) = SIGN__TBL;
*(LPMETHODNAME)lpUsrDicImHdr->achMethodName =
*(LPMETHODNAME)lpImeL->szIMEName;
WriteFile(hUsrDicFile, lpUsrDicImHdr, sizeof(USRDICIMHDR),
&dwWriteBytes, NULL);
GlobalFree((HANDLE)lpUsrDicImHdr);
}
SetUsrDicClose:
CloseHandle(hUsrDicFile);
if (!fRet) {
FreeSecurityAttributes(psa);
return (fRet);
}
lstrcpy( lpImeL->szUsrDic, szEudcDic );
SetUserSetting(
#if defined(UNIIME)
lpImeL,
#endif
szRegUserDic, REG_SZ, (LPBYTE)lpImeL->szUsrDic,
lstrlen(lpImeL->szUsrDic) * sizeof(TCHAR));
if (!lpImeL->szUsrDicMap[0]) {
UINT i;
TCHAR szDirName[MAX_PATH];
GetTempPath(sizeof(szDirName) / sizeof(TCHAR), szDirName);
// we do not want to create a real file so we GetTickCount()
i = (UINT)GetTickCount();
if (!i) {
i++;
}
GetTempFileName(szDirName, lpImeL->szUIClassName, i, szMessage);
GetFileTitle(szMessage, lpImeL->szUsrDicMap,
sizeof(lpImeL->szUsrDicMap) / sizeof(TCHAR));
}
hUsrDicFile = CreateFile(szEudcDic, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
psa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
if (hUsrDicFile == INVALID_HANDLE_VALUE) {
FreeSecurityAttributes(psa);
return (FALSE);
}
uRecLen = lpImeL->nMaxKey + 4;
uReadLen = lpImeL->nMaxKey + 2;
uWriteLen = lpImeL->nSeqBytes + 2;
dwUsrDicSize = GetFileSize(hUsrDicFile, (LPDWORD)NULL);
uUsrDicSize = (UINT)(dwUsrDicSize - 256) / uRecLen * uWriteLen;
// max EUDC chars
hUsrDicMem = CreateFileMapping(INVALID_HANDLE_VALUE,
psa, PAGE_READWRITE, 0, MAX_EUDC_CHARS * uWriteLen + 20,
lpImeL->szUsrDicMap);
if (!hUsrDicMem) {
fRet = FALSE;
goto SetUsrDicCloseRead;
}
if (lpInstL->hUsrDicMem) {
CloseHandle(lpInstL->hUsrDicMem);
lpInstL->hUsrDicMem = NULL;
}
lpInstL->hUsrDicMem = hUsrDicMem;
fRet = ReadUsrDicToMem(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
hUsrDicFile, dwUsrDicSize, uUsrDicSize, uRecLen, uReadLen, uWriteLen);
if (fRet) {
hReadUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
lpImeL->szUsrDicMap);
} else {
hReadUsrDicMem = NULL;
uUsrDicSize = 0;
}
CloseHandle(lpInstL->hUsrDicMem);
lpInstL->hUsrDicMem = hReadUsrDicMem;
lpImeL->uUsrDicSize = uUsrDicSize;
SetUsrDicCloseRead:
CloseHandle(hUsrDicFile);
FreeSecurityAttributes(psa);
return (fRet);
}
/**********************************************************************/
/* UsrDicFileName */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
BOOL PASCAL UsrDicFileName(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
HWND hWnd)
{
#if !defined(ROMANIME) && !defined(UNICDIME) && !defined(WINIME)
TCHAR szFileName[MAX_PATH];
TCHAR szTitle[TITLE_BUF_SIZE+1];
TCHAR szMessage[MESSAGE_BUF_SIZE+1];
TCHAR szIMEUserPath[MAX_PATH];
PSECURITY_ATTRIBUTES psa = NULL;
if ( lpImeL->szUsrDic[0] == TEXT('\0') ) {
// psa = CreateSecurityAttributes();
SHGetSpecialFolderPath(NULL, szIMEUserPath, CSIDL_APPDATA , FALSE);
if ( szIMEUserPath[lstrlen(szIMEUserPath) - 1] == TEXT('\\') )
szIMEUserPath[lstrlen(szIMEUserPath) - 1] = TEXT('\0');
lstrcat(szIMEUserPath, TEXT("\\Microsoft") );
// Because CreateDirectory( ) cannot create directory like \AA\BB,
// if AA and BB both do not exist. It can create only one layer of
// directory each time. so we must call twice CreateDirectory( ) for
// \AA\BB
if ( GetFileAttributes(szIMEUserPath) != FILE_ATTRIBUTE_DIRECTORY)
CreateDirectory(szIMEUserPath, psa);
lstrcat(szIMEUserPath, TEXT("\\IME") );
if ( GetFileAttributes(szIMEUserPath) != FILE_ATTRIBUTE_DIRECTORY)
CreateDirectory(szIMEUserPath, psa);
lstrcat(szIMEUserPath, TEXT("\\") );
lstrcat(szIMEUserPath, lpImeL->szUIClassName);
//
// Create the directory, so that CreateFile( ) can work fine later.
// ortherwise, if the directory does not exist, and you try to create a
// file under that dir, CreateFile will return error.
//
if ( GetFileAttributes(szIMEUserPath) != FILE_ATTRIBUTE_DIRECTORY)
CreateDirectory(szIMEUserPath, psa);
// FreeSecurityAttributes(psa);
lstrcpy(szFileName, szIMEUserPath);
lstrcat(szFileName, TEXT("\\"));
lstrcat(szFileName, lpImeL->szUIClassName);
lstrcat(szFileName, TEXT(".TBL") );
}
return SetUsrDic(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
hWnd, szFileName, szTitle, szMessage);
#endif //!defined(ROMANIME) && !defined(UNICDIME) && !defined(WINIME)
}
#endif
/**********************************************************************/
/* ImeConfigure() / UniImeConfigure() */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
// configurate the IME setting
#if defined(UNIIME)
BOOL WINAPI UniImeConfigure(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
BOOL WINAPI ImeConfigure(
#endif
HKL hKL, // hKL of this IME
HWND hAppWnd, // the owner window
DWORD dwMode, // mode of dialog
LPVOID lpData) // the data depend on each mode
{
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
BOOL fRet;
#endif
switch (dwMode) {
case IME_CONFIG_GENERAL:
if (lpImeL->lConfigGeneral) {
ResourceLocked(
#if defined(UNIIME)
lpImeL,
#endif
hAppWnd);
return (FALSE);
}
InterlockedIncrement(&lpImeL->lConfigGeneral);
if (lpImeL->lConfigGeneral > 1) {
InterlockedDecrement(&lpImeL->lConfigGeneral);
ResourceLocked(
#if defined(UNIIME)
lpImeL,
#endif
hAppWnd);
return (FALSE);
}
DialogBoxParam(hInst, MAKEINTRESOURCE(IDDG_IME_CONFIG), hAppWnd,
ConfigDlgProc, (LPARAM)lpInstL);
InterlockedDecrement(&lpImeL->lConfigGeneral);
break;
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
case IME_CONFIG_SELECTDICTIONARY:
if (lpImeL->lConfigSelectDic) {
ResourceLocked(
#if defined(UNIIME)
lpImeL,
#endif
hAppWnd);
return (FALSE);
}
InterlockedIncrement(&lpImeL->lConfigSelectDic);
if (lpImeL->lConfigSelectDic != 1) {
InterlockedDecrement(&lpImeL->lConfigSelectDic);
ResourceLocked(
#if defined(UNIIME)
lpImeL,
#endif
hAppWnd);
return (FALSE);
}
// currently, we can only select end user dictionary
// because we do not multiple phrase prediction dictionary or
// multiple phrase box.
fRet = UsrDicFileName(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
hAppWnd);
InterlockedDecrement(&lpImeL->lConfigSelectDic);
return (fRet);
break;
#endif
default:
return (FALSE);
break;
}
return (TRUE);
}
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
/**********************************************************************/
/* Input2Sequence */
/* Return Value: */
/* LOWORD - Internal Code, HIWORD - sequence code */
/**********************************************************************/
LRESULT PASCAL Input2Sequence(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
DWORD uVirtKey,
LPBYTE lpSeqCode)
{
UINT uCharCode;
UINT uSeqCode;
UINT uInternalCode;
char cIndex;
uVirtKey = LOWORD(uVirtKey);
uCharCode = MapVirtualKey(uVirtKey, 2);
if (uCharCode < ' ') {
return (FALSE);
} else if (uCharCode > 'z') {
return (FALSE);
} else {
}
uCharCode = bUpper[uCharCode - ' '];
#if defined(PHON)
uCharCode = bStandardLayout[lpImeL->nReadLayout][uCharCode - ' '];
#endif
if (lpImeL->fCompChar[(uCharCode - ' ') >> 4] &
fMask[uCharCode & 0x000F]) {
} else {
return (FALSE);
}
uSeqCode = lpImeL->wChar2SeqTbl[uCharCode - ' '];
#if defined(PHON)
cIndex = cIndexTable[uCharCode - ' '];
if (*(lpSeqCode + cIndex)) {
uSeqCode |= 0x4000;
}
{
int i;
for (i = 0; i < cIndex; i++) {
if (*(lpSeqCode + i) == 0) {
*(lpSeqCode + i) = 0xFF;
}
}
}
#else
for (cIndex = 0; cIndex < lpImeL->nMaxKey; cIndex++) {
if (*(lpSeqCode + cIndex) == 0) {
break;
}
}
#endif
if (cIndex >= lpImeL->nMaxKey) {
return (FALSE);
} else if (cIndex == lpImeL->nMaxKey - 1) {
uSeqCode |= 0x8000;
} else if (uCharCode == ' ') {
uSeqCode |= 0x8000;
} else {
}
*(lpSeqCode + cIndex) = (BYTE)uSeqCode;
uInternalCode = lpImeL->wSeq2CompTbl[(BYTE)uSeqCode];
#ifndef UNICODE
uInternalCode = HIBYTE(uInternalCode) | (LOBYTE(uInternalCode) << 8);
#endif
return MAKELRESULT(uInternalCode, uSeqCode);
}
#endif
/**********************************************************************/
/* ImeEscape() / UniImeEscape() */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
#define IME_INPUTKEYTOSEQUENCE 0x22
// escape function of IMEs
#if defined(UNIIME)
LRESULT WINAPI UniImeEscape(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
LRESULT WINAPI ImeEscape(
#endif
HIMC hIMC,
UINT uSubFunc,
LPVOID lpData)
{
LRESULT lRet;
switch (uSubFunc) {
case IME_ESC_QUERY_SUPPORT:
if (!lpData) {
return (FALSE);
}
switch (*(LPUINT)lpData) {
case IME_ESC_QUERY_SUPPORT:
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
case IME_ESC_SEQUENCE_TO_INTERNAL:
case IME_ESC_GET_EUDC_DICTIONARY:
case IME_ESC_SET_EUDC_DICTIONARY:
case IME_INPUTKEYTOSEQUENCE: // will not supported in next version
// and not support 32 bit applications
#endif
case IME_ESC_MAX_KEY:
case IME_ESC_IME_NAME:
case IME_ESC_SYNC_HOTKEY:
#ifndef HANDLE_PRIVATE_HOTKEY
case IME_ESC_PRIVATE_HOTKEY:
#endif
return (TRUE);
default:
return (FALSE);
}
break;
#if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
case IME_ESC_SEQUENCE_TO_INTERNAL:
if (!lpData) {
return (FALSE);
}
if (*(LPDWORD)lpData > lpImeL->nSeqCode) {
return (FALSE);
}
lRet = lpImeL->wSeq2CompTbl[*(LPDWORD)lpData];
#ifndef UNICODE
lRet = HIBYTE(lRet) | (LOBYTE(lRet) << 8);
#endif
return (lRet);
case IME_ESC_GET_EUDC_DICTIONARY:
if (!lpData) {
return (FALSE);
}
if (lpImeL->szUsrDic[0] == '\0') {
*(LPTSTR)lpData = '\0';
return (TRUE);
}
lstrcpy(lpData, lpImeL->szUsrDic);
return (TRUE);
case IME_ESC_SET_EUDC_DICTIONARY:
{
TCHAR szTitle[TITLE_BUF_SIZE];
TCHAR szMessage[MESSAGE_BUF_SIZE];
return SetUsrDic(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
NULL, lpData, szTitle, szMessage);
}
case IME_INPUTKEYTOSEQUENCE:
return Input2Sequence(
#if defined(UNIIME)
lpImeL,
#endif
*(LPDWORD)lpData, *(LPBYTE FAR *)((LPBYTE)lpData + sizeof(DWORD)));
#endif
case IME_ESC_MAX_KEY:
return (lpImeL->nMaxKey);
case IME_ESC_IME_NAME:
if (!lpData) {
return (FALSE);
}
*(LPMETHODNAME)lpData = *(LPMETHODNAME)lpImeL->szIMEName;
// append a NULL terminator
*(LPTSTR)((LPBYTE)lpData + sizeof(METHODNAME)) = '\0';
return (TRUE);
case IME_ESC_SYNC_HOTKEY:
#ifdef HANDLE_PRIVATE_HOTKEY
{
UINT i;
for (i = 0; i < NUM_OF_IME_HOTKEYS; i++) {
BOOL fRet;
fRet = ImmGetHotKey(IME_ITHOTKEY_RESEND_RESULTSTR + i,
&sImeG.uModifiers[i], &sImeG.uVKey[i], NULL);
if (!fRet) {
sImeG.uVKey[i] = 0;
sImeG.uModifiers[i] = 0;
}
}
}
#endif
return (TRUE);
#ifndef HANDLE_PRIVATE_HOTKEY
case IME_ESC_PRIVATE_HOTKEY: {
LPINPUTCONTEXT lpIMC;
lRet = FALSE;
//
// early return for invalid input context
//
if ( (lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC)) == NULL ) {
return (FALSE);
}
//
// those private hotkeys are effective only in NATIVE mode
//
if ((lpIMC->fdwConversion & (IME_CMODE_NATIVE|IME_CMODE_EUDC|
IME_CMODE_NOCONVERSION|IME_CMODE_CHARCODE)) == IME_CMODE_NATIVE) {
LPPRIVCONTEXT lpImcP;
LPCOMPOSITIONSTRING lpCompStr;
if ( (lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate)) == NULL ) {
ImmUnlockIMC(hIMC);
return (FALSE);
}
switch (*(LPUINT)lpData) {
case IME_ITHOTKEY_RESEND_RESULTSTR: // 0x200
lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
if ( lpCompStr != NULL ) {
if (lpCompStr->dwResultStrLen) {
lpImcP->fdwImeMsg |= MSG_COMPOSITION;
lpImcP->dwCompChar = 0;
lpImcP->fdwGcsFlag |= GCS_RESULTREAD|GCS_RESULT;
GenerateMessage(hIMC, lpIMC, lpImcP);
lRet = TRUE;
}
ImmUnlockIMCC(lpIMC->hCompStr);
}
break;
case IME_ITHOTKEY_PREVIOUS_COMPOSITION: // 0x201
lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
if ( lpCompStr == NULL ) {
break;
}
if (lpCompStr->dwResultReadStrLen) {
DWORD dwResultReadStrLen;
TCHAR szReading[16];
dwResultReadStrLen = lpCompStr->dwResultReadStrLen;
if (dwResultReadStrLen > lpImeL->nMaxKey*sizeof(WCHAR)/sizeof(TCHAR)) {
dwResultReadStrLen = lpImeL->nMaxKey*sizeof(WCHAR)/sizeof(TCHAR);
}
CopyMemory(szReading, (LPBYTE)lpCompStr +
lpCompStr->dwResultReadStrOffset,
dwResultReadStrLen * sizeof(TCHAR));
// NULL termainator
szReading[dwResultReadStrLen] = TEXT('\0');
#if defined(UNIIME)
UniImeSetCompositionString(lpInstL, lpImeL, hIMC, SCS_SETSTR,
NULL, 0, szReading, dwResultReadStrLen * sizeof(TCHAR));
#else
ImeSetCompositionString(hIMC, SCS_SETSTR, NULL, 0, szReading,
dwResultReadStrLen * sizeof(TCHAR));
#endif
GenerateMessage(hIMC, lpIMC, lpImcP);
lRet = TRUE;
}
ImmUnlockIMCC(lpIMC->hCompStr);
break;
case IME_ITHOTKEY_UISTYLE_TOGGLE: // 0x202
lpImeL->fdwModeConfig ^= MODE_CONFIG_OFF_CARET_UI;
SetUserSetting(
#if defined(UNIIME)
lpImeL,
#endif
szRegModeConfig, REG_DWORD, (LPBYTE)&lpImeL->fdwModeConfig,
sizeof(lpImeL->fdwModeConfig));
InitImeUIData(lpImeL);
lpImcP->fdwImeMsg |= MSG_IMN_TOGGLE_UI;
GenerateMessage(hIMC, lpIMC, lpImcP);
lRet = TRUE;
break;
default:
break;
}
ImmUnlockIMCC(lpIMC->hPrivate);
if ( ! lRet ) {
MessageBeep((UINT)-1);
}
}
ImmUnlockIMC(hIMC);
return (lRet);
}
#endif // HANDLE_PRIVATE_HOTKEY
default:
return (FALSE);
}
return (lRet);
}