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.
11536 lines
354 KiB
11536 lines
354 KiB
//
|
|
// Include Files.
|
|
//
|
|
|
|
#include "input.h"
|
|
#include <shlobj.h>
|
|
#include <regstr.h>
|
|
#include <setupapi.h>
|
|
#include <immp.h>
|
|
#include <winuserp.h>
|
|
#include <winbasep.h>
|
|
#include <oleauto.h>
|
|
|
|
#include "inputdlg.h"
|
|
#include "msctf.h"
|
|
#include "msctfp.h"
|
|
#include "ctffunc.h"
|
|
#include "util.h"
|
|
#include "inputhlp.h"
|
|
|
|
#include "external.h"
|
|
|
|
#define IMAGEID_KEYBOARD 0
|
|
#define IMAGEID_SPEECH 1
|
|
#define IMAGEID_PEN 2
|
|
#define IMAGEID_TIPITEMS 3
|
|
#define IMAGEID_EXTERNAL 4
|
|
#define IMAGEID_SMARTTAG 5
|
|
|
|
#define TV_ITEM_TYPE_LANG 0x0001
|
|
#define TV_ITEM_TYPE_GROUP 0x0002
|
|
#define TV_ITEM_TYPE_KBD 0x0010
|
|
#define TV_ITEM_TYPE_SPEECH 0x0020
|
|
#define TV_ITEM_TYPE_PEN 0x0040
|
|
#define TV_ITEM_TYPE_TIP 0x0100
|
|
#define TV_ITEM_TYPE_EXTERNAL 0x0200
|
|
#define TV_ITEM_TYPE_SMARTTAG 0x0400
|
|
|
|
#define INPUT_TYPE_KBD TV_ITEM_TYPE_KBD
|
|
#define INPUT_TYPE_PEN TV_ITEM_TYPE_PEN
|
|
#define INPUT_TYPE_SPEECH TV_ITEM_TYPE_SPEECH
|
|
#define INPUT_TYPE_TIP TV_ITEM_TYPE_TIP
|
|
#define INPUT_TYPE_EXTERNAL TV_ITEM_TYPE_EXTERNAL
|
|
#define INPUT_TYPE_SMARTTAG TV_ITEM_TYPE_SMARTTAG
|
|
|
|
#define MAX_DUPLICATED_HKL 64
|
|
|
|
//
|
|
// Context Help Ids.
|
|
//
|
|
|
|
static int aInputHelpIds[] =
|
|
{
|
|
IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
|
|
IDC_LOCALE_DEFAULT_TEXT, IDH_INPUT_DEFAULT_LOCALE,
|
|
IDC_LOCALE_DEFAULT, IDH_INPUT_DEFAULT_LOCALE,
|
|
IDC_GROUPBOX2, IDH_COMM_GROUPBOX,
|
|
IDC_INPUT_LIST_TEXT, IDH_INPUT_LIST,
|
|
IDC_INPUT_LIST, IDH_INPUT_LIST,
|
|
IDC_KBDL_ADD, IDH_INPUT_ADD,
|
|
IDC_KBDL_DELETE, IDH_INPUT_DELETE,
|
|
IDC_KBDL_EDIT, IDH_INPUT_EDIT,
|
|
IDC_GROUPBOX3, IDH_COMM_GROUPBOX,
|
|
IDC_TB_SETTING, IDH_INPUT_TOOLBAR_SETTINGS,
|
|
IDC_HOTKEY_SETTING, IDH_INPUT_KEY_SETTINGS,
|
|
0, 0
|
|
};
|
|
|
|
static int aToolbarSettingsHelpIds[] =
|
|
{
|
|
IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
|
|
IDC_TB_SHOWLANGBAR, IDH_INPUT_SHOWLANGBAR,
|
|
IDC_TB_HIGHTRANS, IDH_INPUT_HIGH_TRANS,
|
|
IDC_TB_EXTRAICON, IDH_INPUT_EXTRAICON,
|
|
IDC_TB_TEXTLABELS, IDH_INPUT_TEXT_LABELS,
|
|
0, 0
|
|
};
|
|
|
|
static int aLocaleKeysSettingsHelpIds[] =
|
|
{
|
|
IDC_KBDL_CAPSLOCK_FRAME, IDH_COMM_GROUPBOX,
|
|
IDC_KBDL_CAPSLOCK, IDH_INPUT_SETTINGS_CAPSLOCK,
|
|
IDC_KBDL_SHIFTLOCK, IDH_INPUT_SETTINGS_CAPSLOCK,
|
|
IDC_KBDL_HOTKEY_FRAME, IDH_COMM_GROUPBOX,
|
|
IDC_KBDL_HOTKEY, IDH_INPUT_SETTINGS_HOTKEY,
|
|
IDC_KBDL_HOTKEY_SEQUENCE, IDH_INPUT_SETTINGS_HOTKEY,
|
|
IDC_KBDL_HOTKEY_LIST, IDH_INPUT_SETTINGS_HOTKEY_LIST,
|
|
IDC_KBDL_CHANGE_HOTKEY, IDH_INPUT_SETTINGS_HOTKEY,
|
|
0, 0
|
|
};
|
|
|
|
static int aLocaleAddHelpIds[] =
|
|
{
|
|
IDC_KBDLA_LOCALE_TEXT, IDH_INPUT_ADD_LOCALE,
|
|
IDC_KBDLA_LOCALE, IDH_INPUT_ADD_LOCALE,
|
|
IDC_KBDLA_LAYOUT_TEXT, IDH_INPUT_ADD_LAYOUT,
|
|
IDC_KBDLA_LAYOUT, IDH_INPUT_ADD_LAYOUT,
|
|
IDC_PEN_TEXT, IDH_INPUT_ADD_PEN,
|
|
IDC_PEN_TIP, IDH_INPUT_ADD_PEN,
|
|
IDC_SPEECH_TEXT, IDH_INPUT_ADD_SPEECH,
|
|
IDC_SPEECH_TIP, IDH_INPUT_ADD_SPEECH,
|
|
0, 0
|
|
};
|
|
|
|
static int aLocaleHotkeyHelpIds[] =
|
|
{
|
|
IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
|
|
IDC_KBDLH_LANGHOTKEY, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_SHIFT, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_PLUS, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_CTRL, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_L_ALT, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_LAYOUTHOTKEY, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_SHIFT2, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_PLUS2, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_CTRL2, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_L_ALT2, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
IDC_KBDLH_GRAVE, IDH_INPUT_LANG_HOTKEY_CHANGE,
|
|
0, 0
|
|
};
|
|
|
|
static int aLayoutHotkeyHelpIds[] =
|
|
{
|
|
IDC_KBDLH_LAYOUT_TEXT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
|
|
IDC_KBDLH_LANGHOTKEY, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
|
|
IDC_KBDLH_SHIFT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
|
|
IDC_KBDLH_CTRL, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
|
|
IDC_KBDLH_L_ALT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
|
|
IDC_KBDLH_KEY_COMBO, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
|
|
0, 0
|
|
};
|
|
|
|
|
|
//
|
|
// Global Variables.
|
|
//
|
|
|
|
HWND g_hDlg;
|
|
HWND g_hwndTV;
|
|
|
|
HTREEITEM g_hTVRoot;
|
|
HIMAGELIST g_hImageList;
|
|
|
|
UINT g_cTVItemSize = 0;
|
|
|
|
BOOL g_OSNT4 = FALSE;
|
|
BOOL g_OSNT5 = FALSE;
|
|
BOOL g_OSWIN95 = FALSE;
|
|
|
|
BOOL g_bAdvChanged = FALSE;
|
|
|
|
static BOOL g_bGetSwitchLangHotKey = TRUE;
|
|
static BOOL g_bCoInit = FALSE;
|
|
|
|
static DWORD g_dwPrimLangID = 0;
|
|
static UINT g_iThaiLayout = 0;
|
|
static BOOL g_bPenOrSapiTip = FALSE;
|
|
static BOOL g_bExtraTip = FALSE;
|
|
|
|
UINT g_iInputs = 0;
|
|
UINT g_iOrgInputs = 0;
|
|
|
|
WNDPROC g_lpfnTVWndProc = NULL;
|
|
|
|
TCHAR szPropHwnd[] = TEXT("PROP_HWND");
|
|
TCHAR szPropIdx[] = TEXT("PROP_IDX");
|
|
|
|
TCHAR szDefault[DESC_MAX];
|
|
TCHAR szInputTypeKbd[DESC_MAX];
|
|
TCHAR szInputTypePen[DESC_MAX];
|
|
TCHAR szInputTypeSpeech[DESC_MAX];
|
|
TCHAR szInputTypeExternal[DESC_MAX];
|
|
|
|
HINSTANCE g_hShlwapi = NULL;
|
|
|
|
FARPROC pfnSHLoadRegUIString = NULL;
|
|
|
|
//
|
|
// External Routines.
|
|
//
|
|
|
|
extern HWND g_hwndAdvanced;
|
|
|
|
extern void Region_RebootTheSystem();
|
|
|
|
extern BOOL Region_OpenIntlInfFile(HINF *phInf);
|
|
|
|
extern BOOL Region_CloseInfFile(HINF *phInf);
|
|
|
|
extern BOOL Region_ReadDefaultLayoutFromInf(
|
|
LPTSTR pszLocale,
|
|
LPDWORD pdwLocale,
|
|
LPDWORD pdwLayout,
|
|
LPDWORD pdwLocale2,
|
|
LPDWORD pdwLayout2,
|
|
HINF hIntlInf);
|
|
|
|
// For (_WIN32_WINNT >= 0x0500 from winuser.h
|
|
#define KLF_SHIFTLOCK 0x00010000
|
|
#define KLF_RESET 0x40000000
|
|
#define SM_IMMENABLED 82
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MarkSptipRemoved
|
|
//
|
|
// TRUE - mark the reg value as "removed", FALSE - delete the reg value
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL MarkSptipRemoved(BOOL bRemoved)
|
|
{
|
|
//
|
|
// SPTIP's private regentries for the use of detecting
|
|
// whether user has removed profile
|
|
//
|
|
const TCHAR c_szProfileRemoved[] = TEXT("ProfileRemoved");
|
|
const TCHAR c_szSapilayrKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Sapilayr\\");
|
|
HKEY hkey;
|
|
long lRet = ERROR_SUCCESS;
|
|
DWORD dw = bRemoved ? 1 : 0;
|
|
|
|
if (ERROR_SUCCESS ==
|
|
RegCreateKey(HKEY_CURRENT_USER, c_szSapilayrKey, &hkey))
|
|
{
|
|
lRet = RegSetValueEx(hkey, c_szProfileRemoved, 0,
|
|
REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CompareStringTIP
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
int CompareStringTIP(LPTSTR lpStr1, LPTSTR lpStr2)
|
|
{
|
|
if (g_bCHSystem)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
UINT uSize1 = lstrlen(lpStr1);
|
|
UINT uSize2 = lstrlen(lpStr2);
|
|
UINT uSizeDef = lstrlen(szDefault);
|
|
|
|
if (uSize1 == uSize2)
|
|
return lstrcmp(lpStr1, lpStr2);
|
|
|
|
if (uSize1 > uSizeDef)
|
|
{
|
|
if (lstrcmp(lpStr1 + uSize1 - uSizeDef, szDefault) == 0)
|
|
{
|
|
StringCchCopy(szTemp, ARRAYSIZE(szTemp), lpStr1);
|
|
*(szTemp + uSize1 - uSizeDef) = TEXT('\0');
|
|
|
|
return lstrcmp(szTemp, lpStr2);
|
|
}
|
|
}
|
|
|
|
if (uSize2 > uSizeDef)
|
|
{
|
|
if (lstrcmp(lpStr2 + uSize2 - uSizeDef, szDefault) == 0)
|
|
{
|
|
StringCchCopy(szTemp, ARRAYSIZE(szTemp), lpStr2);
|
|
*(szTemp + uSize2 - uSizeDef) = TEXT('\0');
|
|
|
|
return lstrcmp(szTemp, lpStr1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return lstrcmp(lpStr1, lpStr2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_ErrorMsg
|
|
//
|
|
// Sound a beep and put up the given error message.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_ErrorMsg(
|
|
HWND hwnd,
|
|
UINT iErr,
|
|
LPTSTR lpValue)
|
|
{
|
|
TCHAR sz[DESC_MAX];
|
|
TCHAR szString[DESC_MAX];
|
|
|
|
//
|
|
// Sound a beep.
|
|
//
|
|
MessageBeep(MB_OK);
|
|
|
|
//
|
|
// Put up the appropriate error message box.
|
|
//
|
|
if (LoadString(hInstance, iErr, sz, ARRAYSIZE(sz)))
|
|
{
|
|
//
|
|
// If the caller wants to display a message with a caller supplied
|
|
// value string, do it.
|
|
//
|
|
if (lpValue)
|
|
{
|
|
StringCchPrintf(szString, ARRAYSIZE(szString), sz, lpValue);
|
|
MessageBox(hwnd, szString, NULL, MB_OK_OOPS);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(hwnd, sz, NULL, MB_OK_OOPS);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsFELangID
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsFELangID(DWORD dwLangID)
|
|
{
|
|
if ((dwLangID == 0x0404) || (dwLangID == 0x0411) ||
|
|
(dwLangID == 0x0412) || (dwLangID == 0x0804))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsUnregisteredFEDummyHKL
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsUnregisteredFEDummyHKL(HKL hkl)
|
|
{
|
|
HKEY hKey;
|
|
BOOL bRet = FALSE;
|
|
TCHAR szFEDummyHKL[10];
|
|
|
|
switch (LANGIDFROMLCID(hkl))
|
|
{
|
|
case 0x411: break;
|
|
case 0x412: break;
|
|
case 0x404: break;
|
|
case 0x804: break;
|
|
default:
|
|
goto Exit;
|
|
}
|
|
|
|
if (HIWORD((DWORD)(UINT_PTR)hkl) != LOWORD((DWORD)(UINT_PTR)hkl))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
StringCchPrintf(szFEDummyHKL, ARRAYSIZE(szFEDummyHKL), TEXT("%08x"), LOWORD((DWORD)(UINT_PTR)hkl));
|
|
|
|
//
|
|
// Now read all of preload hkl from the registry.
|
|
//
|
|
if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdPreloadKey, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwIndex;
|
|
DWORD cchValue, cbData;
|
|
LONG dwRetVal;
|
|
TCHAR szValue[MAX_PATH]; // language id (number)
|
|
TCHAR szData[MAX_PATH]; // language name
|
|
|
|
dwIndex = 0;
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
cbData = sizeof(szData);
|
|
dwRetVal = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
|
|
if (dwRetVal != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
// There is FE dummy hkl. we will skip this hkl if it is not loaded
|
|
// from Preload registry section.
|
|
//
|
|
bRet = TRUE;
|
|
|
|
do
|
|
{
|
|
if (!lstrcmp(szFEDummyHKL, szData))
|
|
{
|
|
HKEY hSubKey;
|
|
BOOL bSubHKL = FALSE;
|
|
|
|
//
|
|
// Check substitute hkl.
|
|
//
|
|
if (RegOpenKey(HKEY_CURRENT_USER,
|
|
c_szKbdSubstKey,
|
|
&hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx(hSubKey, szData,
|
|
NULL, NULL,
|
|
NULL, NULL)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
bSubHKL = TRUE;
|
|
}
|
|
RegCloseKey(hSubKey);
|
|
|
|
if (bSubHKL)
|
|
goto Next;
|
|
}
|
|
|
|
//
|
|
// Found dummy hkl from preload section, so we need to display
|
|
// this dummy hkl
|
|
//
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
Next:
|
|
dwIndex++;
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
szValue[0] = TEXT('\0');
|
|
cbData = sizeof(szData);
|
|
szData[0] = TEXT('\0');
|
|
dwRetVal = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
|
|
} while (dwRetVal == ERROR_SUCCESS);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
Exit:
|
|
return bRet;
|
|
}
|
|
|
|
|
|
#ifdef _WIN64
|
|
//
|
|
// Issue optimization for IA64 retail version case - related bug#361062
|
|
//
|
|
#pragma optimize("", off)
|
|
#endif // _WIN64
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetSubstituteHKL
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HKL GetSubstituteHKL(REFCLSID rclsid, LANGID langid, REFGUID guidProfile)
|
|
{
|
|
HKEY hkey;
|
|
DWORD cb;
|
|
HKL hkl = NULL;
|
|
TCHAR szSubKeyPath[MAX_PATH];
|
|
TCHAR szSubHKL[MAX_PATH];
|
|
|
|
StringCchCopy(szSubKeyPath, ARRAYSIZE(szSubKeyPath), c_szCTFTipPath);
|
|
|
|
StringFromGUID2(rclsid, (LPOLESTR) szSubKeyPath + lstrlen(szSubKeyPath), 100);
|
|
|
|
StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\"));
|
|
StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), c_szLangProfileKey);
|
|
StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\"));
|
|
StringCchPrintf(szSubKeyPath + lstrlen(szSubKeyPath),
|
|
ARRAYSIZE(szSubKeyPath) - lstrlen(szSubKeyPath),
|
|
TEXT("0x%08x"),
|
|
langid);
|
|
StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\"));
|
|
|
|
StringFromGUID2(guidProfile, (LPOLESTR) szSubKeyPath + lstrlen(szSubKeyPath), 50);
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, szSubKeyPath, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(szSubHKL);
|
|
RegQueryValueEx(hkey, c_szSubstituteLayout, NULL, NULL, (LPBYTE)szSubHKL, &cb);
|
|
RegCloseKey(hkey);
|
|
|
|
if ((szSubHKL[0] == '0') && ((szSubHKL[1] == 'X') || (szSubHKL[1] == 'x')))
|
|
{
|
|
hkl = (HKL) IntToPtr(TransNum(szSubHKL+2));
|
|
|
|
if (LOWORD(hkl) != langid)
|
|
hkl = 0;
|
|
}
|
|
}
|
|
return hkl;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
#pragma optimize("", on)
|
|
#endif // _WIN64
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsTipSubstituteHKL
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsTipSubstituteHKL(HKL hkl)
|
|
{
|
|
UINT ctr;
|
|
|
|
//
|
|
// Search substitute HKL of Tips.
|
|
//
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if (hkl == g_lpTips[ctr].hklSub)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsEnabledTipOrMultiLayouts()
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsEnabledTipOrMultiLayouts()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (g_iInputs < 2 && !g_iEnabledTips)
|
|
{
|
|
// No Tip and one layout, so diable turn off ctfmon UI.
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// AddKbdLayoutOnKbdTip
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void AddKbdLayoutOnKbdTip(HKL hkl, UINT iLayout)
|
|
{
|
|
UINT ctr;
|
|
|
|
//
|
|
// Search substitute HKL of Tips.
|
|
//
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
|
|
if (hkl == g_lpTips[ctr].hklSub)
|
|
{
|
|
if (iLayout)
|
|
g_lpTips[ctr].iLayout = iLayout;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsAvailableTip
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
BOOL IsTipAvailableForAdd(DWORD dwLangID)
|
|
{
|
|
UINT ctr;
|
|
|
|
//
|
|
// Search substitute HKL of Tips.
|
|
//
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if ((dwLangID == g_lpTips[ctr].dwLangID) &&
|
|
!(g_lpTips[ctr].bEnabled))
|
|
{
|
|
if (g_lpTips[ctr].uInputType & INPUT_TYPE_SPEECH)
|
|
{
|
|
if (!(g_lpTips[ctr].fEngineAvailable))
|
|
continue;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CreateImageIcons
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CreateImageIcons()
|
|
{
|
|
HBITMAP hBmp;
|
|
UINT flags = ILC_COLOR | ILC_MASK;
|
|
HIMAGELIST hIml, hImlTmp;
|
|
HICON hIcon = NULL;
|
|
|
|
//
|
|
// Create the image list
|
|
//
|
|
g_hImageList = ImageList_Create( GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CYSMICON),
|
|
ILC_COLOR32 | ILC_MASK,
|
|
0,
|
|
0 );
|
|
|
|
//
|
|
// Load the group icons of input type.
|
|
//
|
|
hIcon = LoadImage(hInstOrig,
|
|
MAKEINTRESOURCE(IDI_KEYBOARD),
|
|
IMAGE_ICON,
|
|
0,
|
|
0,
|
|
LR_DEFAULTCOLOR);
|
|
|
|
ImageList_AddIcon(g_hImageList, hIcon);
|
|
|
|
hIcon = LoadImage(hInstOrig,
|
|
MAKEINTRESOURCE(IDI_SPEECH),
|
|
IMAGE_ICON,
|
|
0,
|
|
0,
|
|
LR_DEFAULTCOLOR);
|
|
|
|
ImageList_AddIcon(g_hImageList, hIcon);
|
|
|
|
hIcon = LoadImage(hInstOrig,
|
|
MAKEINTRESOURCE(IDI_PEN),
|
|
IMAGE_ICON,
|
|
0,
|
|
0,
|
|
LR_DEFAULTCOLOR);
|
|
|
|
ImageList_AddIcon(g_hImageList, hIcon);
|
|
|
|
hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_TIPITEM),
|
|
MAKEINTRESOURCE(IDI_TIPITEM),
|
|
IMAGE_ICON,
|
|
0,
|
|
0,
|
|
LR_DEFAULTCOLOR);
|
|
|
|
ImageList_AddIcon(g_hImageList, hIcon);
|
|
|
|
hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_ICON),
|
|
MAKEINTRESOURCE(IDI_ICON),
|
|
IMAGE_ICON,
|
|
0,
|
|
0,
|
|
LR_DEFAULTCOLOR);
|
|
|
|
ImageList_AddIcon(g_hImageList, hIcon);
|
|
|
|
hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_SMARTTAG),
|
|
MAKEINTRESOURCE(IDI_SMARTTAG),
|
|
IMAGE_ICON,
|
|
0,
|
|
0,
|
|
LR_DEFAULTCOLOR);
|
|
|
|
ImageList_AddIcon(g_hImageList, hIcon);
|
|
|
|
// Associate the image list with the tree.
|
|
hImlTmp = TreeView_SetImageList(g_hwndTV, g_hImageList, TVSIL_NORMAL);
|
|
if (hImlTmp)
|
|
ImageList_Destroy(hImlTmp);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CreateLangIcon
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HICON CreateLangIcon( HWND hwnd, UINT langID )
|
|
{
|
|
HBITMAP hbmColour;
|
|
HBITMAP hbmMono;
|
|
HBITMAP hbmOld;
|
|
HICON hicon = NULL;
|
|
ICONINFO ii;
|
|
RECT rc;
|
|
DWORD rgbText;
|
|
DWORD rgbBk = 0;
|
|
UINT i;
|
|
HDC hdc;
|
|
HDC hdcScreen;
|
|
//HBRUSH hbr;
|
|
LOGFONT lf;
|
|
HFONT hfont;
|
|
HFONT hfontOld;
|
|
TCHAR szData[20];
|
|
|
|
//
|
|
// Get the indicator by using the first 2 characters of the
|
|
// abbreviated language name.
|
|
//
|
|
if (GetLocaleInfo(MAKELCID(langID, SORT_DEFAULT),
|
|
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
|
|
szData,
|
|
ARRAYSIZE(szData)))
|
|
|
|
{
|
|
//
|
|
// Make Uppercase
|
|
//
|
|
if (g_OSWIN95)
|
|
{
|
|
szData[0] -= 0x20;
|
|
szData[1] -= 0x20;
|
|
}
|
|
//
|
|
// Only use the first two characters.
|
|
//
|
|
szData[2] = TEXT('\0');
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Id wasn't found. Use question marks.
|
|
//
|
|
szData[0] = TEXT('?');
|
|
szData[1] = TEXT('?');
|
|
szData[2] = TEXT('\0');
|
|
}
|
|
|
|
if(SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0))
|
|
{
|
|
if( (hfont = CreateFontIndirect(&lf)) )
|
|
{
|
|
UINT cxSmIcon = GetSystemMetrics( SM_CXSMICON );
|
|
UINT cySmIcon = GetSystemMetrics( SM_CYSMICON );
|
|
|
|
hdcScreen = GetDC(NULL);
|
|
hdc = CreateCompatibleDC(hdcScreen);
|
|
hbmColour = CreateCompatibleBitmap(hdcScreen, cxSmIcon, cySmIcon);
|
|
ReleaseDC( NULL, hdcScreen);
|
|
if (hbmColour && hdc)
|
|
{
|
|
hbmMono = CreateBitmap(cxSmIcon, cySmIcon, 1, 1, NULL);
|
|
if (hbmMono)
|
|
{
|
|
hbmOld = SelectObject( hdc, hbmColour);
|
|
rc.left = 0;
|
|
rc.top = 0;
|
|
rc.right = cxSmIcon;
|
|
rc.bottom = cySmIcon;
|
|
|
|
rgbBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
|
|
rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
|
|
ExtTextOut(hdc,
|
|
rc.left,
|
|
rc.top,
|
|
ETO_OPAQUE,
|
|
&rc,
|
|
TEXT(""),
|
|
0,
|
|
NULL);
|
|
|
|
|
|
SelectObject( hdc, GetStockObject(DEFAULT_GUI_FONT));
|
|
hfontOld = SelectObject( hdc, hfont);
|
|
DrawText(hdc,
|
|
szData,
|
|
2,
|
|
&rc,
|
|
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
|
|
|
if (g_bShowRtL)
|
|
MirrorBitmapInDC(hdc, hbmColour);
|
|
|
|
SelectObject( hdc, hbmMono);
|
|
PatBlt(hdc, 0, 0, cxSmIcon, cySmIcon, BLACKNESS);
|
|
|
|
ii.fIcon = TRUE;
|
|
ii.xHotspot = 0;
|
|
ii.yHotspot = 0;
|
|
ii.hbmColor = hbmColour;
|
|
ii.hbmMask = hbmMono;
|
|
hicon = CreateIconIndirect(&ii);
|
|
|
|
SelectObject(hdc, hbmOld);
|
|
DeleteObject(hbmMono);
|
|
SelectObject(hdc, hfontOld);
|
|
}
|
|
DeleteObject(hbmColour);
|
|
DeleteDC(hdc);
|
|
}
|
|
DeleteObject(hfont);
|
|
}
|
|
}
|
|
|
|
return hicon;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetLanguageName
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL GetLanguageName(
|
|
LCID lcid,
|
|
LPTSTR lpLangName,
|
|
UINT cchLangName)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (g_OSWIN95)
|
|
{
|
|
if (!GetLocaleInfo(lcid,
|
|
LOCALE_SLANGUAGE,
|
|
lpLangName,
|
|
cchLangName))
|
|
{
|
|
LoadString(hInstance, IDS_LOCALE_UNKNOWN, lpLangName, cchLangName);
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WCHAR wszLangName[MAX_PATH];
|
|
|
|
if (!GetLocaleInfoW(lcid,
|
|
LOCALE_SLANGUAGE,
|
|
wszLangName,
|
|
ARRAYSIZE(wszLangName)))
|
|
{
|
|
LoadString(hInstance, IDS_LOCALE_UNKNOWN, lpLangName, cchLangName);
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
StringCchCopy(lpLangName, cchLangName, wszLangName);
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CreateTVItemNode
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPTVITEMNODE CreateTVItemNode(DWORD dwLangID)
|
|
{
|
|
LPTVITEMNODE pTVItemNode;
|
|
HANDLE hItemNode;
|
|
|
|
//
|
|
// Create the new node.
|
|
//
|
|
if (!(pTVItemNode = (LPTVITEMNODE) LocalAlloc(LPTR, sizeof(TVITEMNODE))))
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
g_cTVItemSize++;
|
|
|
|
//
|
|
// Fill in the new node with the appropriate info.
|
|
//
|
|
pTVItemNode->dwLangID = dwLangID;
|
|
pTVItemNode->bDefLang = FALSE;
|
|
pTVItemNode->iIdxTips = -1;
|
|
pTVItemNode->atmDefTipName = 0;
|
|
pTVItemNode->atmTVItemName = 0;
|
|
pTVItemNode->lParam = 0;
|
|
|
|
//
|
|
// Return the pointer to the new node.
|
|
//
|
|
return (pTVItemNode);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RemoveTVItemNode
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void RemoveTVItemNode(
|
|
LPTVITEMNODE pTVItemNode)
|
|
{
|
|
if (pTVItemNode)
|
|
{
|
|
if (pTVItemNode->uInputType & INPUT_TYPE_KBD)
|
|
{
|
|
int idxSel = -1;
|
|
TCHAR szItemName[MAX_PATH * 2];
|
|
HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
|
|
|
|
GetLanguageName(MAKELCID(pTVItemNode->dwLangID, SORT_DEFAULT),
|
|
szItemName,
|
|
ARRAYSIZE(szItemName));
|
|
|
|
StringCchCat(szItemName, ARRAYSIZE(szItemName), TEXT(" - "));
|
|
|
|
GetAtomName(pTVItemNode->atmTVItemName,
|
|
szItemName + lstrlen(szItemName), MAX_PATH);
|
|
|
|
idxSel = ComboBox_FindString(hwndDefList, 0, szItemName);
|
|
|
|
if (idxSel != CB_ERR)
|
|
{
|
|
ComboBox_DeleteString(hwndDefList, idxSel);
|
|
}
|
|
}
|
|
|
|
if (pTVItemNode->atmTVItemName)
|
|
DeleteAtom(pTVItemNode->atmTVItemName);
|
|
|
|
if (pTVItemNode->atmDefTipName)
|
|
DeleteAtom(pTVItemNode->atmDefTipName);
|
|
|
|
LocalFree(pTVItemNode);
|
|
g_cTVItemSize--;
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_AddToLinkedList
|
|
//
|
|
// Adds an Input Locale to the main g_lpLang array.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPLANGNODE Locale_AddToLinkedList(
|
|
UINT idx,
|
|
HKL hkl)
|
|
{
|
|
LPINPUTLANG pInpLang = &g_lpLang[idx];
|
|
LPLANGNODE pLangNode;
|
|
LPLANGNODE pTemp;
|
|
HANDLE hLangNode;
|
|
|
|
//
|
|
// Create the new node.
|
|
//
|
|
if (!(hLangNode = LocalAlloc(LHND, sizeof(LANGNODE))))
|
|
{
|
|
return (NULL);
|
|
}
|
|
pLangNode = LocalLock(hLangNode);
|
|
|
|
//
|
|
// Fill in the new node with the appropriate info.
|
|
//
|
|
pLangNode->wStatus = 0;
|
|
pLangNode->iLayout = (UINT)(-1);
|
|
pLangNode->hkl = hkl;
|
|
pLangNode->hklUnload = hkl;
|
|
pLangNode->iLang = idx;
|
|
pLangNode->hLangNode = hLangNode;
|
|
pLangNode->pNext = NULL;
|
|
pLangNode->nIconIME = -1;
|
|
|
|
//
|
|
// If an hkl is given, see if it's an IME. If so, mark the status bit.
|
|
//
|
|
if ((hkl) && ((HIWORD(hkl) & 0xf000) == 0xe000))
|
|
{
|
|
pLangNode->wStatus |= LANG_IME;
|
|
}
|
|
|
|
//
|
|
// Put the new node in the list.
|
|
//
|
|
pTemp = pInpLang->pNext;
|
|
if (pTemp == NULL)
|
|
{
|
|
pInpLang->pNext = pLangNode;
|
|
}
|
|
else
|
|
{
|
|
while (pTemp->pNext != NULL)
|
|
{
|
|
pTemp = pTemp->pNext;
|
|
}
|
|
pTemp->pNext = pLangNode;
|
|
}
|
|
|
|
//
|
|
// Increment the count.
|
|
//
|
|
pInpLang->iNumCount++;
|
|
|
|
//
|
|
// Return the pointer to the new node.
|
|
//
|
|
return (pLangNode);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_RemoveFromLinkedList
|
|
//
|
|
// Removes a link from the linked list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_RemoveFromLinkedList(
|
|
LPLANGNODE pLangNode)
|
|
{
|
|
LPINPUTLANG pInpLang;
|
|
LPLANGNODE pPrev;
|
|
LPLANGNODE pCur;
|
|
HANDLE hCur;
|
|
|
|
pInpLang = &g_lpLang[pLangNode->iLang];
|
|
|
|
//
|
|
// Find the node in the list.
|
|
//
|
|
pPrev = NULL;
|
|
pCur = pInpLang->pNext;
|
|
|
|
while (pCur && (pCur != pLangNode))
|
|
{
|
|
pPrev = pCur;
|
|
pCur = pCur->pNext;
|
|
}
|
|
|
|
if (pPrev == NULL)
|
|
{
|
|
if (pCur == pLangNode)
|
|
{
|
|
pInpLang->pNext = pCur->pNext;
|
|
}
|
|
else
|
|
{
|
|
pInpLang->pNext = NULL;
|
|
}
|
|
}
|
|
else if (pCur)
|
|
{
|
|
pPrev->pNext = pCur->pNext;
|
|
}
|
|
|
|
//
|
|
// Remove the node from the list.
|
|
//
|
|
if (pCur)
|
|
{
|
|
hCur = pCur->hLangNode;
|
|
LocalUnlock(hCur);
|
|
LocalFree(hCur);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_GetImeHotKeyInfo
|
|
//
|
|
// Initializes array for CHS/CHT specific IME related hotkey items.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int Locale_GetImeHotKeyInfo(
|
|
HWND hwnd,
|
|
LPHOTKEYINFO *aImeHotKey)
|
|
{
|
|
|
|
HWND hwndTV = g_hwndTV;
|
|
LPLANGNODE pLangNode;
|
|
LANGID LangID;
|
|
int ctr;
|
|
BOOL fCHS, fCHT;
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
|
|
fCHS = fCHT = FALSE;
|
|
ctr = 0;
|
|
|
|
//
|
|
// Check if the CHS or CHT layouts are loaded.
|
|
//
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
|
|
if (pLangNode == NULL)
|
|
continue;
|
|
}
|
|
else
|
|
continue;
|
|
|
|
LangID = LOWORD(g_lpLayout[pLangNode->iLayout].dwID);
|
|
|
|
if ( PRIMARYLANGID(LangID) == LANG_CHINESE )
|
|
{
|
|
if ( SUBLANGID(LangID) == SUBLANG_CHINESE_SIMPLIFIED)
|
|
fCHS = TRUE;
|
|
else if ( SUBLANGID(LangID) == SUBLANG_CHINESE_TRADITIONAL )
|
|
fCHT = TRUE;
|
|
}
|
|
|
|
if (fCHS && fCHT)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( (fCHS == TRUE) && (fCHT == TRUE) )
|
|
{
|
|
// Both CHS and CHT IMEs are Loaded
|
|
|
|
*aImeHotKey = g_aImeHotKeyCHxBoth;
|
|
return(sizeof(g_aImeHotKeyCHxBoth) / sizeof(HOTKEYINFO) );
|
|
}
|
|
else
|
|
{
|
|
if ( fCHS == TRUE )
|
|
{
|
|
// only CHS IMEs are loaded
|
|
|
|
*aImeHotKey = g_aImeHotKey0804;
|
|
return (sizeof(g_aImeHotKey0804) / sizeof(HOTKEYINFO));
|
|
}
|
|
|
|
if ( fCHT == TRUE )
|
|
{
|
|
|
|
// Only CHT IMEs are loaded.
|
|
|
|
*aImeHotKey = g_aImeHotKey0404;
|
|
return (sizeof(g_aImeHotKey0404) / sizeof(HOTKEYINFO));
|
|
}
|
|
|
|
}
|
|
|
|
// all other cases, No Chinese IME is loaded.
|
|
|
|
*aImeHotKey=NULL;
|
|
return (0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_EnumChildWndProc
|
|
//
|
|
// disable all controls.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CALLBACK Locale_EnumChildWndProc(HWND hwnd, LPARAM lParam)
|
|
{
|
|
|
|
EnableWindow(hwnd, FALSE);
|
|
ShowWindow(hwnd, SW_HIDE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_EnablePane
|
|
//
|
|
// The controls in "iControl" are the controls that get disabled if the
|
|
// pane can't come up.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_EnablePane(
|
|
HWND hwnd,
|
|
BOOL bEnable,
|
|
UINT DisableId)
|
|
{
|
|
|
|
if (!bEnable)
|
|
{
|
|
if (DisableId == IDC_KBDL_DISABLED_2)
|
|
{
|
|
//
|
|
// Disable all controls.
|
|
//
|
|
EnumChildWindows(hwnd, (WNDENUMPROC)Locale_EnumChildWndProc, 0);
|
|
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED_2), SW_SHOW);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED_2), TRUE);
|
|
}
|
|
else
|
|
{
|
|
if (!g_iEnabledTips)
|
|
{
|
|
//
|
|
// Disable all controls.
|
|
//
|
|
EnumChildWindows(hwnd, (WNDENUMPROC)Locale_EnumChildWndProc, 0);
|
|
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED), SW_SHOW);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED), TRUE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable Add, Property, Hotkey and default language setting controls.
|
|
//
|
|
EnableWindow(GetDlgItem(hwnd, IDC_LOCALE_DEFAULT), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_ADD), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_HOTKEY_SETTING), FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_KillPaneDialog
|
|
//
|
|
// Processing for a WM_DESTROY message.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_KillPaneDialog(
|
|
HWND hwnd)
|
|
{
|
|
UINT ctr, iCount;
|
|
HANDLE hCur;
|
|
LPLANGNODE pCur;
|
|
LPHOTKEYINFO aImeHotKey;
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
HTREEITEM hItem;
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
if (g_bCoInit)
|
|
CoUninitialize();
|
|
|
|
//
|
|
// Delete all hot key atoms and free up the hotkey arrays.
|
|
//
|
|
if (g_SwitchLangHotKey.atmHotKeyName)
|
|
{
|
|
DeleteAtom(g_SwitchLangHotKey.atmHotKeyName);
|
|
}
|
|
|
|
iCount = Locale_GetImeHotKeyInfo(hwnd, &aImeHotKey);
|
|
for (ctr = 0; ctr < iCount; ctr++)
|
|
{
|
|
if (aImeHotKey[ctr].atmHotKeyName)
|
|
{
|
|
DeleteAtom(aImeHotKey[ctr].atmHotKeyName);
|
|
}
|
|
}
|
|
|
|
for (ctr = 0; ctr < DSWITCH_HOTKEY_SIZE; ctr++)
|
|
{
|
|
if (g_aDirectSwitchHotKey[ctr].atmHotKeyName)
|
|
{
|
|
DeleteAtom(g_aDirectSwitchHotKey[ctr].atmHotKeyName);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete all TreeView node.
|
|
//
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
RemoveTVItemNode(pTVItemNode);
|
|
}
|
|
}
|
|
|
|
tvItem.hItem = hGroupItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
RemoveTVItemNode(pTVItemNode);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
}
|
|
tvItem.hItem = hLangItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
RemoveTVItemNode(pTVItemNode);
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (g_cTVItemSize)
|
|
{
|
|
MessageBox(NULL, TEXT("Error is occurred during terminate window"), NULL, MB_OK);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Delete all Language Name atoms and free the g_lpLang array.
|
|
//
|
|
for (ctr = 0; ctr < g_iLangBuff; ctr++)
|
|
{
|
|
if (g_lpLang[ctr].atmLanguageName)
|
|
{
|
|
DeleteAtom(g_lpLang[ctr].atmLanguageName);
|
|
}
|
|
|
|
pCur = g_lpLang[ctr].pNext;
|
|
g_lpLang[ctr].pNext = NULL;
|
|
while (pCur)
|
|
{
|
|
hCur = pCur->hLangNode;
|
|
pCur = pCur->pNext;
|
|
LocalUnlock(hCur);
|
|
LocalFree(hCur);
|
|
}
|
|
}
|
|
|
|
if (g_hImageList != NULL)
|
|
{
|
|
TreeView_SetImageList(hwndTV, NULL, TVSIL_NORMAL);
|
|
ImageList_Destroy(g_hImageList);
|
|
}
|
|
LocalUnlock(g_hLang);
|
|
LocalFree(g_hLang);
|
|
|
|
//
|
|
// Delete all layout text and layout file atoms and free the
|
|
// g_lpLayout array.
|
|
//
|
|
for (ctr = 0; ctr < g_iLayoutBuff; ctr++)
|
|
{
|
|
if (g_lpLayout[ctr].atmLayoutText)
|
|
{
|
|
DeleteAtom(g_lpLayout[ctr].atmLayoutText);
|
|
}
|
|
if (g_lpLayout[ctr].atmLayoutFile)
|
|
{
|
|
DeleteAtom(g_lpLayout[ctr].atmLayoutFile);
|
|
}
|
|
if (g_lpLayout[ctr].atmIMEFile)
|
|
{
|
|
DeleteAtom(g_lpLayout[ctr].atmIMEFile);
|
|
}
|
|
}
|
|
|
|
LocalUnlock(g_hLayout);
|
|
LocalFree(g_hLayout);
|
|
|
|
//
|
|
// Make sure the mutex is released.
|
|
//
|
|
if (g_hMutex)
|
|
{
|
|
ReleaseMutex(g_hMutex);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SelectDefaultKbdLayoutAsBold
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SelectDefaultKbdLayoutAsBold(
|
|
HWND hwndTV,
|
|
HTREEITEM hTVItem)
|
|
{
|
|
TV_ITEM tvItem;
|
|
TCHAR szItemName[MAX_PATH];
|
|
TCHAR szLayoutName[MAX_PATH];
|
|
|
|
TreeView_SelectItem(hwndTV, hTVItem);
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE;
|
|
tvItem.hItem = hTVItem;
|
|
tvItem.state = 0;
|
|
tvItem.stateMask = TVIS_BOLD;
|
|
tvItem.pszText = szItemName;
|
|
tvItem.cchTextMax = sizeof(szItemName) / sizeof(TCHAR);
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVItemNode)
|
|
return;
|
|
|
|
if (g_bCHSystem)
|
|
{
|
|
GetAtomName(pTVItemNode->atmTVItemName, szLayoutName, ARRAYSIZE(szLayoutName));
|
|
StringCchCat(szLayoutName, ARRAYSIZE(szLayoutName), szDefault);
|
|
tvItem.pszText = szLayoutName;
|
|
}
|
|
|
|
tvItem.state |= TVIS_BOLD;
|
|
|
|
SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FindTVLangItem
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HTREEITEM
|
|
FindTVLangItem(DWORD dwLangID, LPTSTR lpLangText)
|
|
{
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hLangItem;
|
|
LPTVITEMNODE pTVLangNode;
|
|
|
|
TCHAR szLangName[MAX_PATH];
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.pszText = szLangName;
|
|
tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hLangItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
int iSize = lstrlen(lpLangText);
|
|
|
|
pTVLangNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVLangNode)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
*(szLangName + min(iSize, tvItem.cchTextMax)) = TEXT('\0');
|
|
|
|
if (!CompareStringTIP(szLangName, lpLangText) ||
|
|
(dwLangID && (pTVLangNode->dwLangID == dwLangID)))
|
|
{
|
|
return hLangItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// AddTreeViewItems
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HTREEITEM AddTreeViewItems(
|
|
UINT uItemType,
|
|
LPTSTR lpLangText,
|
|
LPTSTR lpGroupText,
|
|
LPTSTR lpTipText,
|
|
LPTVITEMNODE *ppTVItemNode)
|
|
{
|
|
HTREEITEM hTVItem;
|
|
HTREEITEM hTVItem2;
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem = NULL;
|
|
HTREEITEM hGroupItem;
|
|
TV_ITEM tvItem;
|
|
TV_INSERTSTRUCT tvIns;
|
|
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
|
|
|
|
TCHAR szDefItem[MAX_PATH];
|
|
TCHAR szLangName[ MAX_PATH ];
|
|
LPTVITEMNODE pTVLangNode;
|
|
LPTVITEMNODE pTVItemNode;
|
|
BOOL bFoundLang = FALSE;
|
|
BOOL bFindGroup = FALSE;
|
|
|
|
LPLANGNODE pLangNode;
|
|
|
|
pTVItemNode = *ppTVItemNode;
|
|
|
|
if (!pTVItemNode)
|
|
return NULL;
|
|
|
|
|
|
// We only want to add an lang item if it is not already there.
|
|
//
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM;
|
|
tvItem.state = 0;
|
|
tvItem.stateMask = 0;
|
|
tvItem.pszText = szLangName;
|
|
tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
|
|
|
|
for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hItem != NULL ;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
pTVLangNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVLangNode)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (pTVLangNode->dwLangID == pTVItemNode->dwLangID)
|
|
{
|
|
// We found a match!
|
|
//
|
|
hLangItem = hItem;
|
|
bFoundLang = TRUE;
|
|
|
|
if (!pTVLangNode->atmDefTipName && pTVItemNode->atmDefTipName)
|
|
{
|
|
TCHAR szDefTip[DESC_MAX];
|
|
|
|
GetAtomName(pTVItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
|
|
pTVLangNode->atmDefTipName = AddAtom(szDefTip);
|
|
}
|
|
|
|
if (!(pTVLangNode->hklSub) && pTVItemNode->hklSub)
|
|
pTVLangNode->hklSub = pTVItemNode->hklSub;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (bFoundLang && (uItemType & TV_ITEM_TYPE_LANG))
|
|
{
|
|
RemoveTVItemNode(pTVItemNode);
|
|
*ppTVItemNode = NULL;
|
|
return hItem;
|
|
}
|
|
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
|
|
|
|
tvItem.lParam = (LPARAM) pTVItemNode;
|
|
|
|
if (uItemType & TV_ITEM_TYPE_LANG)
|
|
{
|
|
HICON hIcon = NULL;
|
|
int iImage;
|
|
|
|
hIcon = CreateLangIcon(hwndTV, LOWORD(pTVItemNode->dwLangID));
|
|
if (hIcon)
|
|
{
|
|
iImage = ImageList_AddIcon(g_hImageList, hIcon);
|
|
tvItem.iImage = iImage;
|
|
tvItem.iSelectedImage = iImage;
|
|
}
|
|
|
|
pTVItemNode->atmTVItemName = AddAtom(lpLangText);
|
|
pTVItemNode->uInputType |= TV_ITEM_TYPE_LANG;
|
|
|
|
tvItem.pszText = lpLangText;
|
|
tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
|
|
|
|
tvIns.item = tvItem;
|
|
tvIns.hInsertAfter = TVI_SORT;
|
|
tvIns.hParent = g_hTVRoot;
|
|
|
|
hTVItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns);
|
|
|
|
return hTVItem;
|
|
}
|
|
|
|
if (hLangItem == NULL)
|
|
return NULL;
|
|
|
|
// Find the group node of input type
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem) ;
|
|
hGroupItem != NULL ;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hGroupItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
if (!lstrcmp(tvItem.pszText, lpGroupText))
|
|
{
|
|
bFindGroup = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
tvItem.lParam = (LPARAM) pTVItemNode;
|
|
pTVItemNode->uInputType |= uItemType;
|
|
g_iInputs++;
|
|
|
|
if (!bFindGroup)
|
|
{
|
|
LPTVITEMNODE pTVGroupNode;
|
|
|
|
if (pTVItemNode->bNoAddCat)
|
|
{
|
|
pTVGroupNode = pTVItemNode;
|
|
}
|
|
else
|
|
{
|
|
if (!(pTVGroupNode = CreateTVItemNode(pTVItemNode->dwLangID)))
|
|
return NULL;
|
|
|
|
pTVGroupNode->dwLangID = pTVItemNode->dwLangID;
|
|
pTVGroupNode->uInputType = pTVItemNode->uInputType | TV_ITEM_TYPE_GROUP;
|
|
pTVGroupNode->atmTVItemName = AddAtom(lpTipText);
|
|
tvItem.lParam = (LPARAM) pTVGroupNode;
|
|
}
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
|
|
|
|
tvItem.state = 0;
|
|
|
|
if (pTVItemNode->uInputType & TV_ITEM_TYPE_KBD)
|
|
{
|
|
tvItem.iImage = IMAGEID_KEYBOARD;
|
|
tvItem.iSelectedImage = IMAGEID_KEYBOARD;
|
|
}
|
|
else if (pTVItemNode->uInputType & TV_ITEM_TYPE_PEN)
|
|
{
|
|
tvItem.iImage = IMAGEID_PEN;
|
|
tvItem.iSelectedImage = IMAGEID_PEN;
|
|
}
|
|
else if (pTVItemNode->uInputType & TV_ITEM_TYPE_SPEECH)
|
|
{
|
|
tvItem.iImage = IMAGEID_SPEECH;
|
|
tvItem.iSelectedImage = IMAGEID_SPEECH;
|
|
}
|
|
else if (pTVItemNode->uInputType & TV_ITEM_TYPE_SMARTTAG)
|
|
{
|
|
tvItem.iImage = IMAGEID_SMARTTAG;
|
|
tvItem.iSelectedImage = IMAGEID_SMARTTAG;
|
|
}
|
|
else
|
|
{
|
|
tvItem.iImage = IMAGEID_EXTERNAL;
|
|
tvItem.iSelectedImage = IMAGEID_EXTERNAL;
|
|
}
|
|
|
|
if (pTVItemNode->bNoAddCat)
|
|
tvItem.pszText = lpTipText;
|
|
else
|
|
tvItem.pszText = lpGroupText;
|
|
tvItem.cchTextMax = MAX_PATH;
|
|
|
|
tvIns.item = tvItem;
|
|
|
|
tvIns.hInsertAfter = TVI_SORT;
|
|
tvIns.hParent = hLangItem;
|
|
|
|
|
|
hGroupItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns);
|
|
|
|
hTVItem = TreeView_GetParent(hwndTV, hGroupItem);
|
|
TreeView_Expand(hwndTV, hTVItem, TVE_EXPAND);
|
|
|
|
}
|
|
|
|
if (pTVItemNode->bNoAddCat)
|
|
return hGroupItem;
|
|
|
|
//
|
|
// Check layout name whether it is already added on the treeview.
|
|
//
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
if (!CompareStringTIP(tvItem.pszText, lpTipText))
|
|
{
|
|
if (pTVItemNode->lParam)
|
|
Locale_RemoveFromLinkedList((LPLANGNODE)pTVItemNode->lParam);
|
|
RemoveTVItemNode(pTVItemNode);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
pTVItemNode->atmTVItemName = AddAtom(lpTipText);
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
|
|
|
|
tvItem.state = 0;
|
|
tvItem.stateMask = TVIS_BOLD;
|
|
|
|
tvItem.iImage = IMAGEID_TIPITEMS;
|
|
tvItem.iSelectedImage = IMAGEID_TIPITEMS;
|
|
tvItem.lParam = (LPARAM) pTVItemNode;
|
|
|
|
tvItem.pszText = lpTipText;
|
|
tvItem.cchTextMax = MAX_PATH;
|
|
|
|
tvIns.item = tvItem;
|
|
|
|
tvIns.hInsertAfter = TVI_SORT;
|
|
tvIns.hParent = hGroupItem;
|
|
|
|
|
|
hTVItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns);
|
|
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
|
|
//
|
|
// Adding the available default setting languages
|
|
//
|
|
if ((pTVItemNode->uInputType == TV_ITEM_TYPE_KBD) ||
|
|
(pTVItemNode->uInputType & (TV_ITEM_TYPE_KBD|TV_ITEM_TYPE_TIP) && pTVItemNode->hklSub))
|
|
{
|
|
StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), lpLangText);
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), lpTipText);
|
|
|
|
if (ComboBox_FindStringExact(hwndDefList, 0, szDefItem) == CB_ERR)
|
|
ComboBox_AddString(hwndDefList, szDefItem);
|
|
}
|
|
|
|
#if 0
|
|
if (pTVItemNode->hklSub)
|
|
{
|
|
TV_ITEM tvItem2;
|
|
|
|
tvItem2.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
if (tvItem2.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
|
|
{
|
|
if (TreeView_GetItem(hwndTV, &tvItem2) && tvItem2.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem2.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (pLangNode && (pLangNode->wStatus & LANG_DEFAULT))
|
|
{
|
|
//
|
|
// Select the default layout item as bold
|
|
//
|
|
SelectDefaultKbdLayoutAsBold(hwndTV, hTVItem);
|
|
|
|
TreeView_Expand(hwndTV, hTVItem, TVE_EXPAND);
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
|
|
tvItem.hItem = hLangItem;
|
|
tvItem.pszText = szLangName;
|
|
tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
LPTVITEMNODE pTVLangItemNode;
|
|
int idxSel = -1;
|
|
|
|
StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), lpLangText);
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), lpTipText);
|
|
|
|
//
|
|
// Set the default locale selection.
|
|
//
|
|
//
|
|
if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) == CB_ERR)
|
|
{
|
|
// Simply set the current selection to be the first entry
|
|
// in the list.
|
|
//
|
|
ComboBox_SetCurSel(hwndDefList, 0);
|
|
}
|
|
else
|
|
ComboBox_SetCurSel(hwndDefList, idxSel);
|
|
|
|
if (pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam)
|
|
{
|
|
pTVLangItemNode->bDefLang = TRUE;
|
|
pTVLangItemNode->atmDefTipName = AddAtom(lpTipText);
|
|
tvItem.state |= TVIS_BOLD;
|
|
}
|
|
|
|
StringCchCopy(tvItem.pszText, tvItem.cchTextMax, lpLangText);
|
|
|
|
//
|
|
// No more adding default description
|
|
//
|
|
//StringCchCat(tvItem.pszText, ARRAYSIZE(tvItem.cchTextMax), szDefault);
|
|
|
|
SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
|
|
|
|
TreeView_SelectSetFirstVisible(hwndTV, hLangItem);
|
|
}
|
|
}
|
|
|
|
if (hTVItem2 = TreeView_GetParent(hwndTV, hTVItem))
|
|
TreeView_Expand(hwndTV, hTVItem2, TVE_EXPAND);
|
|
|
|
return hTVItem;
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateDefaultTVLangItem
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL UpdateDefaultTVLangItem(
|
|
DWORD dwLangID,
|
|
LPTSTR lpDefTip,
|
|
BOOL bDefLang,
|
|
BOOL bSubhkl)
|
|
{
|
|
HTREEITEM hItem;
|
|
TV_ITEM tvItem;
|
|
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
TCHAR szLangName[ MAX_PATH ];
|
|
LPTVITEMNODE pTVLangItemNode;
|
|
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
|
|
tvItem.pszText = szLangName;
|
|
tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
|
|
|
|
for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hItem != NULL ;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVLangItemNode)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (pTVLangItemNode->dwLangID == dwLangID)
|
|
{
|
|
// We found a match!
|
|
//
|
|
GetAtomName(pTVLangItemNode->atmTVItemName, szLangName, ARRAYSIZE(szLangName));
|
|
|
|
if (pTVLangItemNode->atmDefTipName)
|
|
DeleteAtom(pTVLangItemNode->atmDefTipName);
|
|
pTVLangItemNode->atmDefTipName = AddAtom(lpDefTip);
|
|
|
|
if (bSubhkl &&
|
|
(pTVLangItemNode->lParam && pTVLangItemNode->hklSub))
|
|
|
|
{
|
|
LPLANGNODE pLangNode = NULL;
|
|
|
|
if (pLangNode = (LPLANGNODE)pTVLangItemNode->lParam)
|
|
{
|
|
if (bDefLang)
|
|
pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
|
|
else if (pLangNode->wStatus & LANG_DEFAULT)
|
|
pLangNode->wStatus &= ~(LANG_DEFAULT | LANG_DEF_CHANGE);
|
|
}
|
|
}
|
|
|
|
tvItem.stateMask |= TVIS_BOLD;
|
|
|
|
if (bDefLang)
|
|
{
|
|
TreeView_SelectSetFirstVisible(hwndTV, hItem);
|
|
|
|
pTVLangItemNode->bDefLang = TRUE;
|
|
//
|
|
// No more adding default description
|
|
//
|
|
//StringCchCat(szLangName, ARRAYSIZE(szLangName), szDefault);
|
|
tvItem.state |= TVIS_BOLD;
|
|
}
|
|
else
|
|
{
|
|
pTVLangItemNode->bDefLang = FALSE;
|
|
tvItem.state &= ~TVIS_BOLD;
|
|
}
|
|
|
|
tvItem.pszText = szLangName;
|
|
|
|
SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateLangKBDItemNode
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL UpdateLangKBDItemNode(
|
|
HTREEITEM hLangItem,
|
|
LPTSTR lpDefTip,
|
|
BOOL bDefault)
|
|
{
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
BOOL fRet = FALSE;
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hGroupItem;
|
|
HTREEITEM hItem;
|
|
|
|
LPTVITEMNODE pTVItemNode;
|
|
LPLANGNODE pLangNode;
|
|
|
|
|
|
TCHAR szItemName[ MAX_PATH ];
|
|
TCHAR szLayoutName[ MAX_PATH ];
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE | TVIF_STATE;
|
|
tvItem.pszText = szItemName;
|
|
tvItem.cchTextMax = sizeof(szItemName) / sizeof(TCHAR);
|
|
|
|
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
|
|
if (!CompareStringTIP(tvItem.pszText, lpDefTip) &&
|
|
(pTVItemNode = (LPTVITEMNODE) tvItem.lParam))
|
|
{
|
|
GetAtomName(pTVItemNode->atmTVItemName, szLayoutName, ARRAYSIZE(szLayoutName));
|
|
|
|
tvItem.stateMask |= TVIS_BOLD;
|
|
|
|
if (bDefault)
|
|
{
|
|
pTVItemNode->bDefLang = TRUE;
|
|
tvItem.state |= TVIS_BOLD;
|
|
|
|
if (g_bCHSystem)
|
|
StringCchCat(szLayoutName, ARRAYSIZE(szLayoutName), szDefault);
|
|
}
|
|
else
|
|
{
|
|
pTVItemNode->bDefLang = FALSE;
|
|
tvItem.state &= ~TVIS_BOLD;
|
|
}
|
|
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
|
|
if (pLangNode != NULL)
|
|
{
|
|
if (bDefault)
|
|
pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
|
|
else if (pLangNode->wStatus & LANG_DEFAULT)
|
|
pLangNode->wStatus &= ~(LANG_DEFAULT | LANG_DEF_CHANGE);
|
|
}
|
|
|
|
tvItem.pszText = szLayoutName;
|
|
SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
|
|
|
|
fRet = TRUE;
|
|
return fRet;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FindDefaultTipItem
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HTREEITEM FindDefaultTipItem(
|
|
DWORD dwLangID,
|
|
LPTSTR lpDefTip)
|
|
{
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
HTREEITEM hItem;
|
|
LPTVITEMNODE pTVLangItemNode;
|
|
|
|
TCHAR szLangName[MAX_PATH];
|
|
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.pszText = szLangName;
|
|
tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
|
|
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
|
|
pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVLangItemNode)
|
|
continue;
|
|
|
|
if ((pTVLangItemNode->uInputType & INPUT_TYPE_KBD) &&
|
|
(pTVLangItemNode->dwLangID == dwLangID))
|
|
{
|
|
if (!CompareStringTIP(tvItem.pszText, lpDefTip) || lpDefTip == NULL)
|
|
return hItem;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetNextDefaultLayout
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SetNextDefaultLayout(
|
|
DWORD dwLangID,
|
|
BOOL bDefLang,
|
|
LPTSTR lpNextTip,
|
|
UINT cchNextTip)
|
|
{
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hItem;
|
|
LPLANGNODE pLangNode = NULL;
|
|
LPTVITEMNODE pTVDefItemNode = NULL;
|
|
|
|
hItem = FindDefaultTipItem(dwLangID, NULL);
|
|
|
|
tvItem.hItem = hItem;
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVDefItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
pLangNode = (LPLANGNODE)pTVDefItemNode->lParam;
|
|
|
|
GetAtomName(pTVDefItemNode->atmTVItemName, lpNextTip, cchNextTip);
|
|
|
|
if (bDefLang)
|
|
{
|
|
//
|
|
// Select the default layout item as bold
|
|
//
|
|
SelectDefaultKbdLayoutAsBold(g_hwndTV, hItem);
|
|
}
|
|
|
|
if (pLangNode && bDefLang)
|
|
pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// EnsureDefaultKbdLayout
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void EnsureDefaultKbdLayout(UINT *nLocales)
|
|
{
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
HTREEITEM hItem;
|
|
LPTVITEMNODE pTVItemNode;
|
|
LPLANGNODE pLangNode = NULL;
|
|
BOOL bDefLayout = FALSE;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
(*nLocales)++;
|
|
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVItemNode)
|
|
continue;
|
|
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
|
|
if (pLangNode == NULL &&
|
|
(pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
|
|
pTVItemNode->hklSub)
|
|
{
|
|
if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
|
|
{
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pLangNode == NULL)
|
|
continue;
|
|
|
|
if (!(pLangNode->wStatus & LANG_UNLOAD) &&
|
|
(pLangNode->wStatus & LANG_DEFAULT))
|
|
{
|
|
bDefLayout = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bDefLayout)
|
|
{
|
|
LPTVITEMNODE pTVLangItemNode;
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
|
|
{
|
|
tvItem.hItem = hLangItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
|
|
pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVLangItemNode)
|
|
continue;
|
|
|
|
if (pTVLangItemNode->bDefLang)
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVItemNode)
|
|
continue;
|
|
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
|
|
if (pLangNode == NULL &&
|
|
(pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
|
|
pTVItemNode->hklSub)
|
|
{
|
|
if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
|
|
{
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pLangNode == NULL)
|
|
continue;
|
|
|
|
if (!(pLangNode->wStatus & LANG_UNLOAD))
|
|
{
|
|
pLangNode->wStatus |= LANG_DEFAULT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FindTVItem
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HTREEITEM FindTVItem(DWORD dwLangID, LPTSTR lpTipText)
|
|
{
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem = NULL;
|
|
HTREEITEM hGroupItem = NULL;
|
|
LPTVITEMNODE pTVLangNode;
|
|
TCHAR szLangName[ MAX_PATH ];
|
|
|
|
|
|
tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.pszText = szLangName;
|
|
tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
|
|
|
|
|
|
for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hItem != NULL ;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
pTVLangNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVLangNode)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (pTVLangNode->dwLangID == dwLangID)
|
|
{
|
|
hLangItem = hItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (hLangItem && lpTipText)
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
|
|
if (!CompareStringTIP(tvItem.pszText, lpTipText))
|
|
{
|
|
return hItem;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CheckButtons
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CheckButtons(
|
|
HWND hwnd)
|
|
{
|
|
TV_ITEM tvItem;
|
|
UINT uInputType;
|
|
HTREEITEM hTVItem;
|
|
LPTVITEMNODE pTVItemNode;
|
|
LPLANGNODE pLangNode = NULL;
|
|
|
|
hTVItem = TreeView_GetSelection(g_hwndTV);
|
|
|
|
if (!hTVItem)
|
|
return;
|
|
|
|
tvItem.hItem = hTVItem;
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
if (!(pTVItemNode = (LPTVITEMNODE) tvItem.lParam))
|
|
return;
|
|
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
uInputType = pTVItemNode->uInputType;
|
|
|
|
if ((uInputType & INPUT_TYPE_KBD) &&
|
|
(g_iInputs >= 2))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), TRUE);
|
|
}
|
|
else
|
|
{
|
|
BOOL bKbdGroup = FALSE;
|
|
|
|
if (uInputType & TV_ITEM_TYPE_LANG)
|
|
{
|
|
HTREEITEM hGroupItem;
|
|
|
|
for (hGroupItem = TreeView_GetChild(g_hwndTV, hTVItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(g_hwndTV, hGroupItem))
|
|
{
|
|
tvItem.hItem = hGroupItem;
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem))
|
|
{
|
|
LPTVITEMNODE pTVItemNode2;
|
|
|
|
if (!(pTVItemNode2 = (LPTVITEMNODE) tvItem.lParam))
|
|
return;
|
|
|
|
if (pTVItemNode2->uInputType & INPUT_TYPE_KBD)
|
|
{
|
|
bKbdGroup = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bKbdGroup && (g_iInputs >= 2))
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), TRUE);
|
|
else
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), FALSE);
|
|
}
|
|
|
|
if ((!g_bSetupCase) &&
|
|
((pLangNode &&
|
|
(pLangNode->wStatus & LANG_IME) &&
|
|
(pLangNode->wStatus & LANG_ORIGACTIVE) &&
|
|
(uInputType == INPUT_TYPE_KBD) &&
|
|
(GetSystemMetrics(SM_IMMENABLED))) ||
|
|
((uInputType & INPUT_TYPE_TIP) && !(uInputType & TV_ITEM_TYPE_GROUP))))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), TRUE);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), FALSE);
|
|
}
|
|
|
|
if (g_iInputs == 1)
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), TRUE);
|
|
}
|
|
|
|
if (uInputType & TV_ITEM_TYPE_LANG)
|
|
{
|
|
if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(g_hwndTV, hTVItem))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
else if (uInputType & TV_ITEM_TYPE_GROUP)
|
|
{
|
|
if (uInputType & TV_ITEM_TYPE_KBD)
|
|
{
|
|
if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(g_hwndTV, hTVItem))
|
|
{
|
|
hTVItem = TreeView_GetParent(g_hwndTV, hTVItem);
|
|
|
|
if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(g_hwndTV, hTVItem))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
else if (uInputType & TV_ITEM_TYPE_KBD)
|
|
{
|
|
if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(g_hwndTV, hTVItem))
|
|
{
|
|
hTVItem = TreeView_GetParent(g_hwndTV, hTVItem);
|
|
|
|
if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(g_hwndTV, hTVItem))
|
|
{
|
|
hTVItem = TreeView_GetParent(g_hwndTV, hTVItem);
|
|
|
|
if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(g_hwndTV, hTVItem))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// EnumCiceroTips
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL EnumCiceroTips()
|
|
{
|
|
|
|
ULONG ul;
|
|
ULONG ulCnt;
|
|
HRESULT hr;
|
|
LPTIPS pTips;
|
|
LANGID *plangid;
|
|
UINT uInputType;
|
|
BOOL bReturn = TRUE;
|
|
BOOL bEnabledTip = FALSE;
|
|
TCHAR szTipName[MAX_PATH];
|
|
TCHAR szTipTypeName[MAX_PATH];
|
|
IEnumTfLanguageProfiles *pEnum;
|
|
ITfInputProcessorProfiles *pProfiles = NULL;
|
|
ITfFnLangProfileUtil *pLangUtil = NULL;
|
|
ITfCategoryMgr *pCategory = NULL;
|
|
|
|
//
|
|
// initialize COM
|
|
//
|
|
if (CoInitialize(NULL) == S_OK)
|
|
g_bCoInit = TRUE;
|
|
else
|
|
g_bCoInit = FALSE;
|
|
|
|
//
|
|
// Check-up SAPI TIP registration.
|
|
//
|
|
hr = CoCreateInstance(&CLSID_SapiLayr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfFnLangProfileUtil,
|
|
(LPVOID *) &pLangUtil);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pLangUtil->lpVtbl->RegisterActiveProfiles(pLangUtil);
|
|
}
|
|
|
|
//
|
|
// load Assembly list
|
|
//
|
|
hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfInputProcessorProfiles,
|
|
(LPVOID *) &pProfiles);
|
|
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
|
|
//
|
|
// Create the new node.
|
|
//
|
|
if (!(g_hTips = (LPTIPS) LocalAlloc(LHND, ALLOCBLOCK * sizeof(TIPS))))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
g_nTipsBuffSize = ALLOCBLOCK;
|
|
g_iTipsBuff = 0;
|
|
g_lpTips = LocalLock(g_hTips);
|
|
|
|
|
|
//
|
|
// Enum all available languages
|
|
//
|
|
if (SUCCEEDED(pProfiles->lpVtbl->EnumLanguageProfiles(pProfiles, 0, &pEnum)))
|
|
{
|
|
TF_LANGUAGEPROFILE tflp;
|
|
CLSID clsid;
|
|
GUID guidProfile;
|
|
|
|
while (pEnum->lpVtbl->Next(pEnum, 1, &tflp, NULL) == S_OK)
|
|
{
|
|
BSTR bstr = NULL;
|
|
BSTR bstr2 = NULL;
|
|
LANGID langid = tflp.langid;
|
|
BOOL bNoCategory = FALSE;
|
|
|
|
hr = pProfiles->lpVtbl->GetLanguageProfileDescription(
|
|
pProfiles,
|
|
&tflp.clsid,
|
|
tflp.langid,
|
|
&tflp.guidProfile,
|
|
&bstr);
|
|
|
|
if (FAILED(hr))
|
|
continue;
|
|
|
|
StringCchCopy(szTipName, ARRAYSIZE(szTipName), bstr);
|
|
|
|
if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_KEYBOARD))
|
|
{
|
|
StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeKbd);
|
|
uInputType = INPUT_TYPE_KBD;
|
|
}
|
|
else if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_HANDWRITING))
|
|
{
|
|
StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypePen);
|
|
uInputType = INPUT_TYPE_PEN;
|
|
}
|
|
else if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_SPEECH))
|
|
{
|
|
StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeSpeech);
|
|
uInputType = INPUT_TYPE_SPEECH;
|
|
bNoCategory = TRUE;
|
|
}
|
|
else
|
|
{
|
|
g_bExtraTip = TRUE;
|
|
uInputType = INPUT_TYPE_EXTERNAL;
|
|
|
|
if (pCategory == NULL)
|
|
{
|
|
hr = CoCreateInstance(&CLSID_TF_CategoryMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfCategoryMgr,
|
|
(LPVOID *) &pCategory);
|
|
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
}
|
|
|
|
if (pCategory->lpVtbl->GetGUIDDescription(pCategory,
|
|
&tflp.catid,
|
|
&bstr2) == S_OK)
|
|
{
|
|
StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), bstr2);
|
|
}
|
|
else
|
|
{
|
|
StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeExternal);
|
|
}
|
|
|
|
if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_SMARTTAG))
|
|
{
|
|
bNoCategory = TRUE;
|
|
uInputType |= INPUT_TYPE_SMARTTAG;
|
|
}
|
|
}
|
|
|
|
uInputType |= INPUT_TYPE_TIP;
|
|
|
|
if (g_iTipsBuff + 1 == g_nTipsBuffSize)
|
|
{
|
|
HANDLE hTemp;
|
|
|
|
LocalUnlock(g_hTips);
|
|
g_nTipsBuffSize += ALLOCBLOCK;
|
|
hTemp = LocalReAlloc(g_hTips,
|
|
g_nTipsBuffSize * sizeof(TIPS),
|
|
LHND);
|
|
if (hTemp == NULL)
|
|
return FALSE;
|
|
g_hTips = hTemp;
|
|
g_lpTips = LocalLock(g_hTips);
|
|
}
|
|
|
|
g_lpTips[g_iTipsBuff].dwLangID = (DWORD) langid;
|
|
g_lpTips[g_iTipsBuff].uInputType = uInputType;
|
|
g_lpTips[g_iTipsBuff].atmTipText = AddAtom(szTipName);
|
|
g_lpTips[g_iTipsBuff].clsid = tflp.clsid;
|
|
g_lpTips[g_iTipsBuff].guidProfile = tflp.guidProfile;
|
|
g_lpTips[g_iTipsBuff].bNoAddCat = bNoCategory;
|
|
|
|
if (pProfiles->lpVtbl->GetDefaultLanguageProfile(pProfiles,
|
|
langid,
|
|
&tflp.catid,
|
|
&clsid,
|
|
&guidProfile) == S_OK)
|
|
{
|
|
if (IsEqualGUID(&tflp.guidProfile, &guidProfile))
|
|
g_lpTips[g_iTipsBuff].bDefault = TRUE;
|
|
}
|
|
|
|
if (uInputType & INPUT_TYPE_KBD)
|
|
{
|
|
g_lpTips[g_iTipsBuff].hklSub = GetSubstituteHKL(&tflp.clsid,
|
|
tflp.langid,
|
|
&tflp.guidProfile);
|
|
}
|
|
|
|
pProfiles->lpVtbl->IsEnabledLanguageProfile(pProfiles,
|
|
&tflp.clsid,
|
|
tflp.langid,
|
|
&tflp.guidProfile,
|
|
&bEnabledTip);
|
|
|
|
// we need a special care for speech here, because:
|
|
//
|
|
// - speech TIP uses -1 profile with disabled status
|
|
//
|
|
// - when a user start a session, either this control
|
|
// panel or first Cicero app, it'll fire off setting up
|
|
// per user profiles based on SR engines currently
|
|
// installed and available on the machine
|
|
//
|
|
// - speech TIP also fires off the logic when any SR
|
|
// engines are added or removed
|
|
//
|
|
// to make this senario work, we have to check with
|
|
// speech TIP's ITfFnProfileUtil interface each time
|
|
// we invoke "Add Input Language" dialog box.
|
|
//
|
|
if (pLangUtil && (uInputType & INPUT_TYPE_SPEECH))
|
|
|
|
{
|
|
BOOL fSpeechAvailable = FALSE;
|
|
pLangUtil->lpVtbl->IsProfileAvailableForLang( pLangUtil,
|
|
langid,
|
|
&fSpeechAvailable
|
|
);
|
|
g_lpTips[g_iTipsBuff].fEngineAvailable = fSpeechAvailable;
|
|
}
|
|
|
|
//
|
|
// Enable pen and speech category adding options if user has the
|
|
// installed pen or speech items.
|
|
//
|
|
if ((!g_bPenOrSapiTip) &&
|
|
((uInputType & INPUT_TYPE_PEN) || g_lpTips[g_iTipsBuff].fEngineAvailable))
|
|
g_bPenOrSapiTip = TRUE;
|
|
|
|
if (bEnabledTip && langid)
|
|
{
|
|
TCHAR szLangName[MAX_PATH];
|
|
LPTVITEMNODE pTVItemNode;
|
|
LPTVITEMNODE pTVLangItemNode;
|
|
|
|
GetLanguageName(MAKELCID(langid, SORT_DEFAULT),
|
|
szLangName,
|
|
ARRAYSIZE(szLangName));
|
|
|
|
if (!(pTVLangItemNode = CreateTVItemNode(langid)))
|
|
{
|
|
bReturn = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (pTVLangItemNode->hklSub)
|
|
pTVLangItemNode->atmDefTipName = AddAtom(szTipName);
|
|
|
|
AddTreeViewItems(TV_ITEM_TYPE_LANG,
|
|
szLangName,
|
|
NULL,
|
|
NULL,
|
|
&pTVLangItemNode);
|
|
|
|
if (!(pTVItemNode = CreateTVItemNode(langid)))
|
|
{
|
|
bReturn = FALSE;
|
|
break;
|
|
}
|
|
|
|
pTVItemNode->uInputType = uInputType;
|
|
pTVItemNode->iIdxTips = g_iTipsBuff;
|
|
pTVItemNode->clsid = tflp.clsid;
|
|
pTVItemNode->guidProfile = tflp.guidProfile;
|
|
pTVItemNode->hklSub = g_lpTips[g_iTipsBuff].hklSub;
|
|
pTVItemNode->bNoAddCat = g_lpTips[g_iTipsBuff].bNoAddCat;
|
|
|
|
//
|
|
// Make sure the loading TIP substitute hkl
|
|
//
|
|
if (pTVItemNode->hklSub)
|
|
{
|
|
TCHAR szSubhkl[10];
|
|
HKL hklNew;
|
|
|
|
StringCchPrintf(szSubhkl, ARRAYSIZE(szSubhkl), TEXT("%08x"), (DWORD)(UINT_PTR)pTVItemNode->hklSub);
|
|
hklNew = LoadKeyboardLayout(szSubhkl,
|
|
KLF_SUBSTITUTE_OK |
|
|
KLF_REPLACELANG |
|
|
KLF_NOTELLSHELL);
|
|
if (hklNew != pTVItemNode->hklSub)
|
|
{
|
|
pTVItemNode->hklSub = 0;
|
|
g_lpTips[g_iTipsBuff].hklSub = 0;
|
|
}
|
|
}
|
|
|
|
AddTreeViewItems(uInputType,
|
|
szLangName,
|
|
szTipTypeName,
|
|
szTipName,
|
|
&pTVItemNode);
|
|
|
|
g_lpTips[g_iTipsBuff].bEnabled = TRUE;
|
|
g_iEnabledTips++;
|
|
|
|
if (uInputType & INPUT_TYPE_KBD)
|
|
g_iEnabledKbdTips++;
|
|
}
|
|
|
|
g_iTipsBuff++;
|
|
|
|
if (bstr)
|
|
SysFreeString(bstr);
|
|
|
|
if (bstr2)
|
|
SysFreeString(bstr2);
|
|
}
|
|
pEnum->lpVtbl->Release(pEnum);
|
|
}
|
|
|
|
if (pCategory)
|
|
pCategory->lpVtbl->Release(pCategory);
|
|
|
|
if (pLangUtil)
|
|
pLangUtil->lpVtbl->Release(pLangUtil);
|
|
|
|
if (pProfiles)
|
|
pProfiles->lpVtbl->Release(pProfiles);
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SaveLanguageProfileStatus
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LRESULT SaveLanguageProfileStatus(
|
|
BOOL bSave,
|
|
int iIdxTip,
|
|
HKL hklSub)
|
|
{
|
|
HRESULT hr;
|
|
UINT idx;
|
|
int iIdxDef = -1;
|
|
int iIdxDefTip = -1;
|
|
ITfInputProcessorProfiles *pProfiles = NULL;
|
|
|
|
//
|
|
// load Assembly list
|
|
//
|
|
hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfInputProcessorProfiles,
|
|
(LPVOID *) &pProfiles);
|
|
|
|
if (FAILED(hr))
|
|
return S_FALSE;
|
|
|
|
if (bSave)
|
|
{
|
|
ITfFnLangProfileUtil *pLangUtil = NULL;
|
|
|
|
for (idx = 0; idx < g_iTipsBuff; idx++)
|
|
{
|
|
|
|
hr = pProfiles->lpVtbl->EnableLanguageProfile(
|
|
pProfiles,
|
|
&(g_lpTips[idx].clsid),
|
|
(LANGID)g_lpTips[idx].dwLangID,
|
|
&(g_lpTips[idx].guidProfile),
|
|
g_lpTips[idx].bEnabled);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
|
|
hr = CoCreateInstance(&CLSID_SapiLayr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfFnLangProfileUtil,
|
|
(LPVOID *) &pLangUtil);
|
|
if (S_OK == hr)
|
|
{
|
|
pLangUtil->lpVtbl->RegisterActiveProfiles(pLangUtil);
|
|
pLangUtil->lpVtbl->Release(pLangUtil);
|
|
}
|
|
}
|
|
|
|
if (hklSub && iIdxTip != -1 && iIdxTip < (int)g_iTipsBuff)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
TCHAR szItem[MAX_PATH];
|
|
TCHAR szDefLayout[MAX_PATH];
|
|
HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
|
|
|
|
szDefLayout[0] = L'\0';
|
|
|
|
//
|
|
// Get the current selection in the input locale list.
|
|
//
|
|
if ((iIdxDef = ComboBox_GetCurSel(hwndDefList)) != CB_ERR)
|
|
{
|
|
WCHAR *pwchar;
|
|
|
|
SendMessage(hwndDefList, CB_GETLBTEXT, iIdxDef, (LPARAM)szItem);
|
|
|
|
pwchar = wcschr(szItem, L'-');
|
|
|
|
if (pwchar != NULL)
|
|
StringCchCopy(szDefLayout, ARRAYSIZE(szDefLayout), pwchar + 2);
|
|
}
|
|
|
|
GetAtomName(g_lpTips[iIdxTip].atmTipText, szItem, ARRAYSIZE(szItem));
|
|
|
|
if (lstrcmp(szItem, szDefLayout) == 0)
|
|
{
|
|
iIdxDefTip = iIdxTip;
|
|
bFound = TRUE;
|
|
}
|
|
else
|
|
{
|
|
for (idx = 0; idx < g_iTipsBuff; idx++)
|
|
{
|
|
if (hklSub == g_lpTips[idx].hklSub)
|
|
{
|
|
GetAtomName(g_lpTips[idx].atmTipText,
|
|
szItem,
|
|
ARRAYSIZE(szItem));
|
|
|
|
if (lstrcmp(szItem, szDefLayout) == 0)
|
|
{
|
|
iIdxDefTip = idx;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bFound && iIdxDefTip != -1)
|
|
{
|
|
pProfiles->lpVtbl->SetDefaultLanguageProfile(
|
|
pProfiles,
|
|
(LANGID)g_lpTips[iIdxDefTip].dwLangID,
|
|
&(g_lpTips[iIdxDefTip].clsid),
|
|
&(g_lpTips[iIdxDefTip].guidProfile));
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (pProfiles)
|
|
pProfiles->lpVtbl->Release(pProfiles);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateToolBarSetting
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void UpdateToolBarSetting()
|
|
{
|
|
HRESULT hr;
|
|
|
|
ITfLangBarMgr *pLangBar = NULL;
|
|
|
|
//
|
|
// load LangBar manager
|
|
//
|
|
hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfLangBarMgr,
|
|
(LPVOID *) &pLangBar);
|
|
|
|
if (SUCCEEDED(hr))
|
|
pLangBar->lpVtbl->ShowFloating(pLangBar, g_dwToolBar);
|
|
|
|
if (pLangBar)
|
|
pLangBar->lpVtbl->Release(pLangBar);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_ApplyError
|
|
//
|
|
// Put up the given error message with the language name in it.
|
|
//
|
|
// NOTE: This error is NOT fatal - as we could be half way through the
|
|
// list before an error occurs. The registry will already have
|
|
// some information and we should let them have what comes next
|
|
// as well.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int Locale_ApplyError(
|
|
HWND hwnd,
|
|
LPLANGNODE pLangNode,
|
|
UINT iErr,
|
|
UINT iStyle)
|
|
{
|
|
UINT idxLang, idxLayout;
|
|
TCHAR sz[MAX_PATH];
|
|
TCHAR szTemp[MAX_PATH];
|
|
TCHAR szLangName[MAX_PATH * 2];
|
|
LPTSTR pszLang;
|
|
|
|
//
|
|
// Load in the string for the given string id.
|
|
//
|
|
LoadString(hInstance, iErr, sz, ARRAYSIZE(sz));
|
|
|
|
//
|
|
// Get the language name to fill into the above string.
|
|
//
|
|
if (pLangNode)
|
|
{
|
|
idxLang = pLangNode->iLang;
|
|
idxLayout = pLangNode->iLayout;
|
|
GetAtomName(g_lpLang[idxLang].atmLanguageName, szLangName, ARRAYSIZE(szLangName));
|
|
if (g_lpLang[idxLang].dwID != g_lpLayout[idxLayout].dwID)
|
|
{
|
|
pszLang = szLangName + lstrlen(szLangName);
|
|
pszLang[0] = TEXT(' ');
|
|
pszLang[1] = TEXT('-');
|
|
pszLang[2] = TEXT(' ');
|
|
GetAtomName(g_lpLayout[idxLayout].atmLayoutText,
|
|
pszLang + 3,
|
|
ARRAYSIZE(szLangName) - (lstrlen(szLangName) + 3));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LoadString(hInstance, IDS_UNKNOWN, szLangName, ARRAYSIZE(szLangName));
|
|
}
|
|
|
|
//
|
|
// Put up the error message box.
|
|
//
|
|
StringCchPrintf(szTemp, ARRAYSIZE(szTemp), sz, szLangName);
|
|
return (MessageBox(hwnd, szTemp, NULL, iStyle));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_FetchIndicator
|
|
//
|
|
// Saves the two letter indicator symbol for the given language in the
|
|
// g_lpLang array.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_FetchIndicator(
|
|
LPLANGNODE pLangNode)
|
|
{
|
|
TCHAR szData[MAX_PATH];
|
|
LPINPUTLANG pInpLang = &g_lpLang[pLangNode->iLang];
|
|
|
|
//
|
|
// Get the indicator by using the first 2 characters of the
|
|
// abbreviated language name.
|
|
//
|
|
if (GetLocaleInfo(LOWORD(pInpLang->dwID),
|
|
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
|
|
szData,
|
|
ARRAYSIZE(szData)))
|
|
{
|
|
//
|
|
// Save the first two characters.
|
|
//
|
|
pInpLang->szSymbol[0] = szData[0];
|
|
pInpLang->szSymbol[1] = szData[1];
|
|
pInpLang->szSymbol[2] = TEXT('\0');
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Id wasn't found. Return question marks.
|
|
//
|
|
pInpLang->szSymbol[0] = TEXT('?');
|
|
pInpLang->szSymbol[1] = TEXT('?');
|
|
pInpLang->szSymbol[2] = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_SetSecondaryControls
|
|
//
|
|
// Sets the secondary controls to either be enabled or disabled.
|
|
// When there is only 1 active TIP, then this function will be called to
|
|
// disable these controls.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_SetSecondaryControls(
|
|
HWND hwndMain)
|
|
{
|
|
if (g_iInputs >= 2)
|
|
{
|
|
EnableWindow(GetDlgItem(hwndMain, IDC_HOTKEY_SETTING), TRUE);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwndMain, IDC_HOTKEY_SETTING), FALSE);
|
|
}
|
|
|
|
CheckButtons(hwndMain);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_CommandSetDefault
|
|
//
|
|
// Sets the new default when the Set as Default button is pressed.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_CommandSetDefault(
|
|
HWND hwnd)
|
|
{
|
|
int iIdxDef;
|
|
int idxList;
|
|
LPLANGNODE pLangNode = NULL;
|
|
HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT);
|
|
TCHAR sz[DESC_MAX];
|
|
|
|
HTREEITEM hTVCurLangItem = NULL;
|
|
HTREEITEM hTVCurItem = NULL;
|
|
TV_ITEM tvItem;
|
|
TV_ITEM tvItem2;
|
|
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
|
|
LPTVITEMNODE pCurItemNode;
|
|
LPTVITEMNODE pPrevDefItemNode;
|
|
|
|
TCHAR szLangText[DESC_MAX];
|
|
TCHAR szLayoutName[DESC_MAX];
|
|
TCHAR szDefItem[MAX_PATH];
|
|
LPINPUTLANG pInpLang;
|
|
WCHAR *pwchar;
|
|
|
|
TCHAR szDefTip[DESC_MAX];
|
|
|
|
szLayoutName[0] = L'\0';
|
|
|
|
//
|
|
// Get the current selection in the input locale list.
|
|
//
|
|
iIdxDef = (int) SendMessage(hwndDefList, CB_GETCURSEL, 0, 0);
|
|
|
|
if (iIdxDef == CB_ERR)
|
|
{
|
|
//iIdxDef = 0;
|
|
DWORD dwLangID;
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hLangItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) &&
|
|
(pCurItemNode = (LPTVITEMNODE) tvItem.lParam))
|
|
{
|
|
if (pCurItemNode->bDefLang)
|
|
{
|
|
dwLangID = pCurItemNode->dwLangID;
|
|
GetAtomName(pCurItemNode->atmTVItemName,
|
|
szLangText,
|
|
ARRAYSIZE(szLangText));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SendMessage(hwndDefList, CB_GETLBTEXT, iIdxDef, (LPARAM)szDefItem);
|
|
|
|
pwchar = wcschr(szDefItem, L'-');
|
|
|
|
if ((pwchar != NULL) && (szDefItem < (pwchar - 1)))
|
|
{
|
|
*(pwchar - 1) = TEXT('\0');
|
|
StringCchCopy(szLayoutName, ARRAYSIZE(szLayoutName), pwchar + 2);
|
|
}
|
|
|
|
StringCchCopy(szLangText, ARRAYSIZE(szLangText), szDefItem);
|
|
}
|
|
|
|
hTVCurLangItem = FindTVLangItem(0, szLangText);
|
|
|
|
if (hTVCurLangItem == NULL)
|
|
{
|
|
//
|
|
// There is no default keyboard layout on the system, so try to set
|
|
// the default keyboard layout with the first available item.
|
|
//
|
|
if (SendMessage(hwndDefList, CB_GETLBTEXT, 0, (LPARAM)szDefItem) != CB_ERR)
|
|
{
|
|
pwchar = wcschr(szDefItem, L'-');
|
|
|
|
if ((pwchar != NULL) && (szDefItem < (pwchar - 1)))
|
|
{
|
|
*(pwchar - 1) = TEXT('\0');
|
|
StringCchCopy(szLayoutName, ARRAYSIZE(szLayoutName), pwchar + 2);
|
|
}
|
|
|
|
StringCchCopy(szLangText, ARRAYSIZE(szLangText), szDefItem);
|
|
ComboBox_SetCurSel(hwndDefList, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVCurLangItem;
|
|
}
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
//
|
|
// Get the pointer to the lang node from the list box
|
|
// item data.
|
|
//
|
|
pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (hTVCurItem = FindTVItem(pCurItemNode->dwLangID, szLayoutName))
|
|
{
|
|
tvItem.hItem = hTVCurItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
TreeView_SelectItem(hwndTV, hTVCurItem);
|
|
pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure we're not removing the only entry in the list.
|
|
//
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Find the previous default Tip.
|
|
//
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hLangItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) &&
|
|
(pPrevDefItemNode = (LPTVITEMNODE) tvItem.lParam))
|
|
{
|
|
if (pPrevDefItemNode->bDefLang)
|
|
{
|
|
GetAtomName(pPrevDefItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
|
|
UpdateDefaultTVLangItem(pPrevDefItemNode->dwLangID, szDefTip, FALSE, TRUE);
|
|
UpdateLangKBDItemNode(hLangItem, szDefTip, FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pCurItemNode->bDefLang = TRUE;
|
|
|
|
if (pCurItemNode->atmDefTipName)
|
|
GetAtomName(pCurItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
|
|
else
|
|
GetAtomName(pCurItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip));
|
|
|
|
UpdateDefaultTVLangItem(pCurItemNode->dwLangID,
|
|
szDefTip,
|
|
TRUE,
|
|
pCurItemNode->hklSub ? TRUE : FALSE);
|
|
|
|
if (!UpdateLangKBDItemNode(hTVCurLangItem, szDefTip, TRUE))
|
|
{
|
|
SetNextDefaultLayout(pCurItemNode->dwLangID,
|
|
pCurItemNode->bDefLang,
|
|
szDefTip,
|
|
ARRAYSIZE(szDefTip));
|
|
}
|
|
|
|
if (pCurItemNode->uInputType & TV_ITEM_TYPE_LANG)
|
|
{
|
|
hItem = FindDefaultTipItem(pCurItemNode->dwLangID, szDefTip);
|
|
tvItem.hItem = hItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
//
|
|
// Select the default layout item as bold
|
|
//
|
|
SelectDefaultKbdLayoutAsBold(hwndTV, hItem);
|
|
|
|
pLangNode = (LPLANGNODE)pCurItemNode->lParam;
|
|
if (pLangNode)
|
|
pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
|
|
}
|
|
|
|
//
|
|
// Enable the Apply button.
|
|
//
|
|
g_dwChanges |= CHANGE_DEFAULT;
|
|
PropSheet_Changed(GetParent(hwnd), hwnd);
|
|
}
|
|
|
|
void Locale_CommandSetDefaultLayout(
|
|
HWND hwnd)
|
|
{
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hTVItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hTVCurItem;
|
|
TCHAR szDefTip[DESC_MAX];
|
|
TCHAR szLangText[DESC_MAX];
|
|
LPLANGNODE pLangNode = NULL;
|
|
LPTVITEMNODE pCurItemNode;
|
|
LPTVITEMNODE pPrevDefItemNode;
|
|
HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
|
|
//
|
|
// Get the current selection layout in the input layout lists.
|
|
//
|
|
hTVCurItem = TreeView_GetSelection(hwndTV);
|
|
|
|
if (!hTVCurItem)
|
|
return;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVCurItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
//
|
|
// Get the pointer to the lang node from the list box
|
|
// item data.
|
|
//
|
|
pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure we're not removing the only entry in the list.
|
|
//
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Find the previous default Tip.
|
|
//
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
tvItem.hItem = hLangItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) &&
|
|
(pPrevDefItemNode = (LPTVITEMNODE) tvItem.lParam))
|
|
{
|
|
if (pPrevDefItemNode->bDefLang)
|
|
{
|
|
if (pPrevDefItemNode->atmDefTipName)
|
|
GetAtomName(pPrevDefItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
|
|
else
|
|
GetAtomName(pPrevDefItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip));
|
|
UpdateDefaultTVLangItem(pPrevDefItemNode->dwLangID, szDefTip, FALSE, TRUE);
|
|
UpdateLangKBDItemNode(hLangItem, szDefTip, FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pCurItemNode->atmDefTipName)
|
|
GetAtomName(pCurItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
|
|
else
|
|
GetAtomName(pCurItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip));
|
|
|
|
UpdateDefaultTVLangItem(pCurItemNode->dwLangID,
|
|
szDefTip,
|
|
TRUE,
|
|
pCurItemNode->hklSub ? TRUE : FALSE);
|
|
|
|
pCurItemNode->bDefLang = TRUE;
|
|
|
|
pLangNode = (LPLANGNODE)pCurItemNode->lParam;
|
|
|
|
if (pLangNode)
|
|
pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
|
|
|
|
if (hTVItem = FindTVLangItem(pCurItemNode->dwLangID, NULL))
|
|
{
|
|
int idxSel = -1;
|
|
TCHAR szDefItem[MAX_PATH];
|
|
HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVItem;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
GetAtomName(pTVItemNode->atmTVItemName, szLangText, ARRAYSIZE(szLangText));
|
|
}
|
|
|
|
StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), szLangText);
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), szDefTip);
|
|
|
|
//
|
|
// Set the default locale selection.
|
|
//
|
|
if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) != CB_ERR)
|
|
ComboBox_SetCurSel(hwndDefList, idxSel);
|
|
}
|
|
|
|
SelectDefaultKbdLayoutAsBold(hwndTV, FindDefaultTipItem(pCurItemNode->dwLangID, szDefTip));
|
|
|
|
//
|
|
// Enable the Apply button.
|
|
//
|
|
g_dwChanges |= CHANGE_DEFAULT;
|
|
PropSheet_Changed(GetParent(hwnd), hwnd);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetLanguageHotkeyFromRegistry()
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL GetLanguageHotkeyFromRegistry(
|
|
LPTSTR lpLangKey,
|
|
UINT cchLangKey,
|
|
LPTSTR lpLayoutKey,
|
|
UINT cchLayoutKey)
|
|
{
|
|
DWORD cb;
|
|
HKEY hkey;
|
|
|
|
lpLangKey[0] = 0;
|
|
StringCchCopy(lpLayoutKey, cchLayoutKey, TEXT("3"));
|
|
|
|
if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdToggleKey, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(lpLangKey);
|
|
|
|
RegQueryValueEx(hkey, g_OSWIN95? NULL : c_szToggleHotKey, NULL, NULL, (LPBYTE)lpLangKey, &cb);
|
|
|
|
if (g_iEnabledKbdTips)
|
|
{
|
|
StringCchCopy(lpLangKey, cchLangKey, TEXT("1"));
|
|
RegQueryValueEx(hkey, c_szToggleLang, NULL, NULL, (LPBYTE)lpLangKey, &cb);
|
|
}
|
|
|
|
if (RegQueryValueEx(hkey, c_szToggleLayout, NULL, NULL, (LPBYTE)lpLayoutKey, &cb) != ERROR_SUCCESS)
|
|
{
|
|
if (lstrcmp(lpLangKey, TEXT("1")) == 0)
|
|
{
|
|
lpLayoutKey[0] = TEXT('2');
|
|
lpLayoutKey[1] = TEXT('\0');
|
|
}
|
|
if (lstrcmp(lpLangKey, TEXT("2")) == 0)
|
|
{
|
|
lpLayoutKey[0] = TEXT('1');
|
|
lpLayoutKey[1] = TEXT('\0');
|
|
}
|
|
else
|
|
{
|
|
lpLayoutKey[0] = TEXT('3');
|
|
lpLayoutKey[1] = TEXT('\0');
|
|
}
|
|
|
|
if (GetSystemMetrics(SM_MIDEASTENABLED))
|
|
{
|
|
lpLayoutKey[0] = TEXT('3');
|
|
lpLayoutKey[1] = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
if (lstrcmp(lpLangKey, lpLayoutKey) == 0)
|
|
StringCchCopy(lpLayoutKey, cchLayoutKey, TEXT("3"));
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_SetDefaultHotKey
|
|
//
|
|
// Set the default hotkey for a locale switch.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_SetDefaultHotKey(
|
|
HWND hwnd,
|
|
BOOL bAdd)
|
|
{
|
|
LPHOTKEYINFO pHotKeyNode;
|
|
BOOL bReset = FALSE;
|
|
|
|
//
|
|
// Initialize lang hotkey value to switch between lnaguages.
|
|
//
|
|
if (g_bGetSwitchLangHotKey)
|
|
{
|
|
TCHAR szItem[DESC_MAX];
|
|
TCHAR sz[10];
|
|
TCHAR sz2[10];
|
|
|
|
g_SwitchLangHotKey.dwHotKeyID = HOTKEY_SWITCH_LANG;
|
|
g_SwitchLangHotKey.fdwEnable = MOD_CONTROL | MOD_ALT | MOD_SHIFT;
|
|
|
|
LoadString( hInstance,
|
|
IDS_KBD_SWITCH_LOCALE,
|
|
szItem,
|
|
sizeof(szItem) / sizeof(TCHAR) );
|
|
|
|
g_SwitchLangHotKey.atmHotKeyName = AddAtom(szItem);
|
|
|
|
if (!GetLanguageHotkeyFromRegistry(sz, ARRAYSIZE(sz), sz2, ARRAYSIZE(sz2)))
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = 0;
|
|
g_SwitchLangHotKey.uLayoutHotKey = 0;
|
|
g_SwitchLangHotKey.uVKey = 0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set the modifiers.
|
|
//
|
|
if (sz[1] == 0)
|
|
{
|
|
switch (sz[0])
|
|
{
|
|
case ( TEXT('1') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = MOD_ALT | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('2') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = MOD_CONTROL | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('3') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = 0;
|
|
break;
|
|
}
|
|
case ( TEXT('4') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = 0;
|
|
g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Get the layout hotkey from the registry
|
|
//
|
|
if (sz2[1] == 0)
|
|
{
|
|
switch (sz2[0])
|
|
{
|
|
case ( TEXT('1') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = MOD_ALT | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('2') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = MOD_CONTROL | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('3') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = 0;
|
|
break;
|
|
}
|
|
case ( TEXT('4') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = 0;
|
|
g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
g_bGetSwitchLangHotKey = FALSE;
|
|
}
|
|
|
|
//
|
|
// Get language switch hotkey
|
|
//
|
|
pHotKeyNode = (LPHOTKEYINFO) &g_SwitchLangHotKey;
|
|
|
|
//
|
|
// Check the current hotkey setting
|
|
//
|
|
if ((bAdd && g_iInputs >= 2) &&
|
|
(g_SwitchLangHotKey.uModifiers == 0 &&
|
|
g_SwitchLangHotKey.uLayoutHotKey == 0 &&
|
|
g_SwitchLangHotKey.uVKey == 0))
|
|
{
|
|
bReset = TRUE;
|
|
}
|
|
|
|
if (bAdd && (g_iInputs == 2 || bReset))
|
|
{
|
|
if (g_dwPrimLangID == LANG_THAI && g_iThaiLayout)
|
|
{
|
|
pHotKeyNode->uVKey = CHAR_GRAVE;
|
|
pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
|
|
}
|
|
else
|
|
pHotKeyNode->uModifiers = MOD_ALT | MOD_SHIFT;
|
|
|
|
if (g_bMESystem)
|
|
{
|
|
pHotKeyNode->uVKey = CHAR_GRAVE;
|
|
pHotKeyNode->uLayoutHotKey &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
|
|
}
|
|
else if (pHotKeyNode->uModifiers & MOD_CONTROL)
|
|
pHotKeyNode->uLayoutHotKey = MOD_ALT;
|
|
else
|
|
pHotKeyNode->uLayoutHotKey = MOD_CONTROL;
|
|
|
|
g_dwChanges |= CHANGE_LANGSWITCH;
|
|
}
|
|
|
|
if (!bAdd)
|
|
{
|
|
if (g_iInputs == 1)
|
|
{
|
|
//
|
|
// Remove the locale hotkey, since it's no longer required.
|
|
//
|
|
pHotKeyNode->uVKey = 0;
|
|
pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
|
|
pHotKeyNode->uLayoutHotKey &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
|
|
|
|
g_dwChanges |= CHANGE_LANGSWITCH;
|
|
}
|
|
else if ((g_dwPrimLangID == LANG_THAI && !g_iThaiLayout) &&
|
|
(pHotKeyNode->uVKey == CHAR_GRAVE))
|
|
{
|
|
//
|
|
// Reset the locale switch hotkey from Grave accent to
|
|
// Left-Alt + Shift.
|
|
//
|
|
pHotKeyNode->uVKey = 0;
|
|
if (pHotKeyNode->uLayoutHotKey & MOD_ALT)
|
|
pHotKeyNode->uModifiers = MOD_CONTROL | MOD_SHIFT;
|
|
else
|
|
pHotKeyNode->uModifiers = MOD_ALT | MOD_SHIFT;
|
|
|
|
g_dwChanges |= CHANGE_LANGSWITCH;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_SetLanguageHotkey
|
|
//
|
|
// Set the language switch hotkey on the registry.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_SetLanguageHotkey()
|
|
{
|
|
UINT idx, idx2;
|
|
HKEY hkeyToggle;
|
|
TCHAR szTemp[10], szTemp2[10];
|
|
LPHOTKEYINFO pHotKeyNode;
|
|
|
|
//
|
|
// Get language switch hotkey
|
|
//
|
|
pHotKeyNode = (LPHOTKEYINFO) &g_SwitchLangHotKey;
|
|
|
|
idx = 3;
|
|
idx2 = 3;
|
|
|
|
if (pHotKeyNode->uModifiers & MOD_ALT)
|
|
{
|
|
idx = 1;
|
|
}
|
|
else if (pHotKeyNode->uModifiers & MOD_CONTROL)
|
|
{
|
|
idx = 2;
|
|
}
|
|
else if (g_iThaiLayout && pHotKeyNode->uVKey == CHAR_GRAVE)
|
|
{
|
|
idx = 4;
|
|
}
|
|
|
|
if (pHotKeyNode->uLayoutHotKey & MOD_ALT)
|
|
{
|
|
idx2 = 1;
|
|
}
|
|
else if (pHotKeyNode->uLayoutHotKey & MOD_CONTROL)
|
|
{
|
|
idx2 = 2;
|
|
}
|
|
else if (g_bMESystem && pHotKeyNode->uVKey == CHAR_GRAVE)
|
|
{
|
|
idx2 = 4;
|
|
}
|
|
|
|
//
|
|
// Get the toggle hotkey as a string so that it can be written
|
|
// into the registry (as data).
|
|
//
|
|
StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), idx);
|
|
StringCchPrintf(szTemp2, ARRAYSIZE(szTemp2), TEXT("%d"), idx2);
|
|
|
|
//
|
|
// Set the new entry in the registry. It is of the form:
|
|
//
|
|
// HKCU\Keyboard Layout
|
|
// Toggle: Hotkey = <hotkey number>
|
|
//
|
|
if (RegCreateKey(HKEY_CURRENT_USER,
|
|
c_szKbdToggleKey,
|
|
&hkeyToggle ) == ERROR_SUCCESS)
|
|
{
|
|
RegSetValueEx(hkeyToggle,
|
|
g_OSWIN95? NULL : c_szToggleHotKey,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szTemp,
|
|
(DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
|
|
|
|
RegSetValueEx(hkeyToggle,
|
|
c_szToggleLang,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szTemp,
|
|
(DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
|
|
|
|
RegSetValueEx(hkeyToggle,
|
|
c_szToggleLayout,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szTemp2,
|
|
(DWORD)(lstrlen(szTemp2) + 1) * sizeof(TCHAR) );
|
|
|
|
RegCloseKey(hkeyToggle);
|
|
}
|
|
|
|
//
|
|
// Since we updated the registry, we should reread this next time.
|
|
//
|
|
g_bGetSwitchLangHotKey = TRUE;
|
|
|
|
//
|
|
// Call SystemParametersInfo to enable the toggle.
|
|
//
|
|
SystemParametersInfo(SPI_SETLANGTOGGLE, 0, NULL, 0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_FileExists
|
|
//
|
|
// Determines if the file exists and is accessible.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_FileExists(
|
|
LPTSTR pFileName)
|
|
{
|
|
WIN32_FIND_DATA FindData;
|
|
HANDLE FindHandle;
|
|
BOOL bRet;
|
|
UINT OldMode;
|
|
|
|
OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
|
|
FindHandle = FindFirstFile(pFileName, &FindData);
|
|
if (FindHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
FindClose(FindHandle);
|
|
bRet = TRUE;
|
|
}
|
|
|
|
SetErrorMode(OldMode);
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_GetHotkeys
|
|
//
|
|
// Gets the hotkey keyboard switch value from the registry and then
|
|
// sets the appropriate radio button in the dialog.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_GetHotkeys(
|
|
HWND hwnd,
|
|
BOOL *bHasIme)
|
|
{
|
|
TCHAR sz[10];
|
|
TCHAR sz2[10];
|
|
int ctr1, iLangCount, iCount;
|
|
UINT iIndex;
|
|
TCHAR szLanguage[DESC_MAX];
|
|
TCHAR szLayout[DESC_MAX];
|
|
TCHAR szItem[DESC_MAX];
|
|
TCHAR szAction[DESC_MAX];
|
|
LPLANGNODE pLangNode;
|
|
HWND hwndTV = g_hwndTV;
|
|
HWND hwndHotkey = GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST);
|
|
LPHOTKEYINFO aImeHotKey;
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
|
|
//
|
|
// Clear out the hot keys list box.
|
|
//
|
|
ListBox_ResetContent(hwndHotkey);
|
|
|
|
//
|
|
// Get the hotkey value to switch between locales from the registry.
|
|
//
|
|
if (g_bGetSwitchLangHotKey)
|
|
{
|
|
g_SwitchLangHotKey.dwHotKeyID = HOTKEY_SWITCH_LANG;
|
|
g_SwitchLangHotKey.fdwEnable = MOD_CONTROL | MOD_ALT | MOD_SHIFT;
|
|
|
|
LoadString( hInstance,
|
|
IDS_KBD_SWITCH_LOCALE,
|
|
szItem,
|
|
sizeof(szItem) / sizeof(TCHAR) );
|
|
|
|
g_SwitchLangHotKey.atmHotKeyName = AddAtom(szItem);
|
|
|
|
if (!GetLanguageHotkeyFromRegistry(sz, ARRAYSIZE(sz), sz2, ARRAYSIZE(sz2)))
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = 0;
|
|
g_SwitchLangHotKey.uLayoutHotKey = 0;
|
|
g_SwitchLangHotKey.uVKey = 0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set the modifiers.
|
|
//
|
|
if (sz[1] == 0)
|
|
{
|
|
switch (sz[0])
|
|
{
|
|
case ( TEXT('1') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = MOD_ALT | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('2') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = MOD_CONTROL | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('3') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = 0;
|
|
break;
|
|
}
|
|
case ( TEXT('4') ) :
|
|
{
|
|
g_SwitchLangHotKey.uModifiers = 0;
|
|
g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Get the layout hotkey from the registry
|
|
//
|
|
if (sz2[1] == 0)
|
|
{
|
|
switch (sz2[0])
|
|
{
|
|
case ( TEXT('1') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = MOD_ALT | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('2') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = MOD_CONTROL | MOD_SHIFT;
|
|
break;
|
|
}
|
|
case ( TEXT('3') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = 0;
|
|
break;
|
|
}
|
|
case ( TEXT('4') ) :
|
|
{
|
|
g_SwitchLangHotKey.uLayoutHotKey = 0;
|
|
g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
g_bGetSwitchLangHotKey = FALSE;
|
|
}
|
|
}
|
|
|
|
iIndex = ListBox_InsertString(hwndHotkey, -1, szItem);
|
|
ListBox_SetItemData(hwndHotkey, iIndex, (LONG_PTR)&g_SwitchLangHotKey);
|
|
|
|
//
|
|
// Determine the hotkey value for direct locale switch.
|
|
//
|
|
// Query all available direct switch hotkey IDs and put the
|
|
// corresponding hkl, key, and modifiers information into the array.
|
|
//
|
|
for (ctr1 = 0; ctr1 < DSWITCH_HOTKEY_SIZE; ctr1++)
|
|
{
|
|
BOOL fRet;
|
|
|
|
g_aDirectSwitchHotKey[ctr1].dwHotKeyID = IME_HOTKEY_DSWITCH_FIRST + ctr1;
|
|
g_aDirectSwitchHotKey[ctr1].fdwEnable = MOD_VIRTKEY | MOD_CONTROL |
|
|
MOD_ALT | MOD_SHIFT |
|
|
MOD_LEFT | MOD_RIGHT;
|
|
g_aDirectSwitchHotKey[ctr1].idxLayout = -1;
|
|
|
|
fRet = ImmGetHotKey( g_aDirectSwitchHotKey[ctr1].dwHotKeyID,
|
|
&g_aDirectSwitchHotKey[ctr1].uModifiers,
|
|
&g_aDirectSwitchHotKey[ctr1].uVKey,
|
|
&g_aDirectSwitchHotKey[ctr1].hkl );
|
|
if (!fRet)
|
|
{
|
|
g_aDirectSwitchHotKey[ctr1].uModifiers = 0;
|
|
|
|
if ((g_aDirectSwitchHotKey[ctr1].fdwEnable & (MOD_LEFT | MOD_RIGHT)) ==
|
|
(MOD_LEFT | MOD_RIGHT))
|
|
{
|
|
g_aDirectSwitchHotKey[ctr1].uModifiers |= MOD_LEFT | MOD_RIGHT;
|
|
}
|
|
g_aDirectSwitchHotKey[ctr1].uVKey = 0;
|
|
g_aDirectSwitchHotKey[ctr1].hkl = (HKL)NULL;
|
|
}
|
|
}
|
|
|
|
LoadString( hInstance,
|
|
IDS_KBD_SWITCH_TO,
|
|
szAction,
|
|
sizeof(szAction) / sizeof(TCHAR) );
|
|
|
|
//
|
|
// Try to find either a matching hkl or empty spot in the array
|
|
// for each of the hkls in the locale list.
|
|
//
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
int ctr2;
|
|
int iEmpty = -1;
|
|
int iMatch = -1;
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
tvItem.hItem = hItem;
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
else
|
|
break;
|
|
|
|
if (pLangNode == NULL &&
|
|
(pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
|
|
pTVItemNode->hklSub)
|
|
{
|
|
if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
|
|
{
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pLangNode == NULL)
|
|
continue;
|
|
|
|
for (ctr2 = 0; ctr2 < DSWITCH_HOTKEY_SIZE; ctr2++)
|
|
{
|
|
if (!g_aDirectSwitchHotKey[ctr2].hkl)
|
|
{
|
|
if ((iEmpty == -1) &&
|
|
(g_aDirectSwitchHotKey[ctr2].idxLayout == -1))
|
|
{
|
|
//
|
|
// Remember the first empty spot.
|
|
//
|
|
iEmpty = ctr2;
|
|
}
|
|
}
|
|
else if (g_aDirectSwitchHotKey[ctr2].hkl == pLangNode->hkl)
|
|
{
|
|
//
|
|
// We found a match. Remember it.
|
|
//
|
|
iMatch = ctr2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (iMatch == -1)
|
|
{
|
|
if (iEmpty == -1)
|
|
{
|
|
//
|
|
// We don't have any spots left.
|
|
//
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// New item.
|
|
//
|
|
iMatch = iEmpty;
|
|
if (pLangNode->hkl)
|
|
{
|
|
g_aDirectSwitchHotKey[iMatch].hkl = pLangNode->hkl;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This must be a newly added layout. We don't have
|
|
// the hkl yet. Remember the index position of this
|
|
// layout - we can get the real hkl when the user
|
|
// chooses to apply.
|
|
//
|
|
g_aDirectSwitchHotKey[iMatch].idxLayout = ctr1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pLangNode->wStatus & LANG_IME)
|
|
{
|
|
*bHasIme = TRUE;
|
|
}
|
|
|
|
if (pLangNode->wStatus & LANG_HOTKEY)
|
|
{
|
|
g_aDirectSwitchHotKey[iMatch].uModifiers = pLangNode->uModifiers;
|
|
g_aDirectSwitchHotKey[iMatch].uVKey = pLangNode->uVKey;
|
|
}
|
|
|
|
GetAtomName(g_lpLang[pLangNode->iLang].atmLanguageName,
|
|
szLanguage,
|
|
ARRAYSIZE(szLanguage));
|
|
|
|
GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
|
|
szLayout,
|
|
ARRAYSIZE(szLayout));
|
|
|
|
StringCchCat(szLanguage, ARRAYSIZE(szLanguage), TEXT(" - "));
|
|
StringCchCat(szLanguage, ARRAYSIZE(szLanguage), szLayout);
|
|
|
|
StringCchPrintf(szItem, ARRAYSIZE(szItem), szAction, szLanguage);
|
|
|
|
if (ListBox_FindStringExact(hwndHotkey, 0, szItem) != CB_ERR)
|
|
continue;
|
|
|
|
g_aDirectSwitchHotKey[iMatch].atmHotKeyName = AddAtom(szItem);
|
|
iIndex = ListBox_InsertString(hwndHotkey, -1, szItem);
|
|
|
|
ListBox_SetItemData(hwndHotkey, iIndex, &g_aDirectSwitchHotKey[iMatch]);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine IME specific hotkeys for CHS and CHT locales.
|
|
//
|
|
iCount = *bHasIme ? Locale_GetImeHotKeyInfo(hwnd,&aImeHotKey) : 0;
|
|
|
|
for (ctr1 = 0; ctr1 < iCount; ctr1++)
|
|
{
|
|
BOOL bRet;
|
|
|
|
LoadString( hInstance,
|
|
aImeHotKey[ctr1].idHotKeyName,
|
|
szItem,
|
|
sizeof(szItem) / sizeof(TCHAR) );
|
|
|
|
aImeHotKey[ctr1].atmHotKeyName = AddAtom(szItem);
|
|
|
|
iIndex = ListBox_InsertString(hwndHotkey, -1,szItem);
|
|
|
|
ListBox_SetItemData(hwndHotkey, iIndex, &aImeHotKey[ctr1]);
|
|
|
|
//
|
|
// Get the hot key value.
|
|
//
|
|
bRet = ImmGetHotKey( aImeHotKey[ctr1].dwHotKeyID,
|
|
&aImeHotKey[ctr1].uModifiers,
|
|
&aImeHotKey[ctr1].uVKey,
|
|
NULL );
|
|
if (!bRet)
|
|
{
|
|
aImeHotKey[ctr1].uModifiers = 0;
|
|
if ((aImeHotKey[ctr1].fdwEnable & (MOD_LEFT | MOD_RIGHT)) ==
|
|
(MOD_LEFT | MOD_RIGHT))
|
|
{
|
|
aImeHotKey[ctr1].uModifiers |= MOD_LEFT | MOD_RIGHT;
|
|
}
|
|
aImeHotKey[ctr1].uVKey = 0;
|
|
aImeHotKey[ctr1].hkl = (HKL)NULL;
|
|
}
|
|
}
|
|
ListBox_SetCurSel(hwndHotkey, 0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_SetImmHotkey
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_SetImmHotkey(
|
|
HWND hwnd,
|
|
LPLANGNODE pLangNode,
|
|
UINT nLangs,
|
|
HKL * pLangs,
|
|
BOOL *bDirectSwitch)
|
|
{
|
|
int ctr1;
|
|
HKL hkl;
|
|
BOOL bRet;
|
|
UINT uVKey;
|
|
UINT uModifiers;
|
|
int iEmpty = -1;
|
|
int iMatch = -1;
|
|
LPHOTKEYINFO pHotKeyNode;
|
|
|
|
|
|
if (pLangNode == NULL)
|
|
return;
|
|
|
|
for (ctr1 = 0; ctr1 < DSWITCH_HOTKEY_SIZE; ctr1++)
|
|
{
|
|
if (!g_aDirectSwitchHotKey[ctr1].hkl)
|
|
{
|
|
if ((iEmpty == -1) &&
|
|
(g_aDirectSwitchHotKey[ctr1].idxLayout == -1))
|
|
{
|
|
//
|
|
// Remember the first empty spot.
|
|
//
|
|
iEmpty = ctr1;
|
|
}
|
|
}
|
|
else if (g_aDirectSwitchHotKey[ctr1].hkl == pLangNode->hkl)
|
|
{
|
|
//
|
|
// We found a match. Remember it.
|
|
//
|
|
iMatch = ctr1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (iMatch == -1)
|
|
{
|
|
if (iEmpty == -1)
|
|
{
|
|
//
|
|
// We don't have any spots left.
|
|
//
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// New item.
|
|
//
|
|
iMatch = iEmpty;
|
|
if (pLangNode->hkl)
|
|
{
|
|
g_aDirectSwitchHotKey[iMatch].hkl = pLangNode->hkl;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This must be a newly added layout. We don't have
|
|
// the hkl yet. Remember the index position of this
|
|
// layout - we can get the real hkl when the user
|
|
// chooses to apply.
|
|
//
|
|
g_aDirectSwitchHotKey[iMatch].idxLayout = ctr1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iMatch == -1)
|
|
return;
|
|
|
|
//
|
|
// Get Hotkey information for current layout.
|
|
//
|
|
pHotKeyNode = (LPHOTKEYINFO) &g_aDirectSwitchHotKey[iMatch];
|
|
|
|
bRet = ImmGetHotKey(pHotKeyNode->dwHotKeyID, &uModifiers, &uVKey, &hkl);
|
|
|
|
if (!bRet &&
|
|
(!pHotKeyNode->uVKey) &&
|
|
((pHotKeyNode->uModifiers & (MOD_ALT | MOD_CONTROL | MOD_SHIFT))
|
|
!= (MOD_ALT | MOD_CONTROL | MOD_SHIFT)))
|
|
{
|
|
//
|
|
// No such hotkey exists. User does not specify key and modifier
|
|
// information either. We can skip this one.
|
|
//
|
|
return;
|
|
}
|
|
|
|
if ((pHotKeyNode->uModifiers == uModifiers) &&
|
|
(pHotKeyNode->uVKey == uVKey))
|
|
{
|
|
//
|
|
// No change.
|
|
//
|
|
if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
|
|
{
|
|
*bDirectSwitch = TRUE;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (pHotKeyNode->idxLayout != -1)
|
|
{
|
|
//
|
|
// We had this layout index remembered because at that time
|
|
// we did not have a real hkl to work with. Now it is
|
|
// time to get the real hkl.
|
|
//
|
|
pHotKeyNode->hkl = pLangNode->hkl;
|
|
}
|
|
|
|
if (!bRet && IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
|
|
{
|
|
//
|
|
// New direct switch hotkey ID. We need to see if the same
|
|
// hkl is set at another ID. If so, set the other ID instead
|
|
// of the one requested.
|
|
//
|
|
DWORD dwHotKeyID;
|
|
|
|
//
|
|
// Loop through all direct switch hotkeys.
|
|
//
|
|
for (dwHotKeyID = IME_HOTKEY_DSWITCH_FIRST;
|
|
(dwHotKeyID <= IME_HOTKEY_DSWITCH_LAST);
|
|
dwHotKeyID++)
|
|
{
|
|
if (dwHotKeyID == pHotKeyNode->dwHotKeyID)
|
|
{
|
|
//
|
|
// Skip itself.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
bRet = ImmGetHotKey(dwHotKeyID, &uModifiers, &uVKey, &hkl);
|
|
if (!bRet)
|
|
{
|
|
//
|
|
// Did not find the hotkey id. Skip.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
if (hkl == pHotKeyNode->hkl)
|
|
{
|
|
//
|
|
// We found the same hkl already with hotkey
|
|
// settings at another ID. Set hotkey
|
|
// ID equal to the one with the same hkl. So later
|
|
// we will modify hotkey for the correct hkl.
|
|
//
|
|
pHotKeyNode->dwHotKeyID = dwHotKeyID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the hotkey value.
|
|
//
|
|
bRet = ImmSetHotKey( pHotKeyNode->dwHotKeyID,
|
|
pHotKeyNode->uModifiers,
|
|
pHotKeyNode->uVKey,
|
|
pHotKeyNode->hkl );
|
|
|
|
if (bRet)
|
|
{
|
|
//
|
|
// Hotkey set successfully. See if user used any direct
|
|
// switch hot key. We may have to load imm later.
|
|
//
|
|
if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
|
|
{
|
|
if (pHotKeyNode->uVKey != 0)
|
|
{
|
|
*bDirectSwitch = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Must be IME related hotkey. We need to sync up the
|
|
// imes so that the new hotkey is effective to all
|
|
// of them.
|
|
//
|
|
UINT ctr2;
|
|
|
|
for (ctr2 = 0; ctr2 < nLangs; ctr2++)
|
|
{
|
|
if (!ImmIsIME(pLangs[ctr2]))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ImmEscape( pLangs[ctr2],
|
|
NULL,
|
|
IME_ESC_SYNC_HOTKEY,
|
|
&pHotKeyNode->dwHotKeyID );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failed to set hotkey. Maybe a duplicate. Warn user.
|
|
//
|
|
TCHAR szString[DESC_MAX];
|
|
|
|
GetAtomName( pHotKeyNode->atmHotKeyName,
|
|
szString,
|
|
sizeof(szString) / sizeof(TCHAR) );
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_SET_HOTKEY_ERR, szString);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_SetImmCHxHotkey
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_SetImmCHxHotkey(
|
|
HWND hwnd,
|
|
UINT nLangs,
|
|
HKL * pLangs)
|
|
{
|
|
HKL hkl;
|
|
UINT ctr1;
|
|
UINT uVKey;
|
|
UINT iCount;
|
|
UINT uModifiers;
|
|
LPHOTKEYINFO aImeHotKey;
|
|
LPHOTKEYINFO pHotKeyNode;
|
|
|
|
//
|
|
// Determine IME specific hotkeys for CHS and CHT locales.
|
|
//
|
|
iCount = Locale_GetImeHotKeyInfo(hwnd, &aImeHotKey);
|
|
|
|
for (ctr1 = 0; ctr1 < iCount; ctr1++)
|
|
{
|
|
UINT iIndex;
|
|
BOOL bRet;
|
|
|
|
//
|
|
// Get Hotkey information for current layout.
|
|
//
|
|
pHotKeyNode = (LPHOTKEYINFO) &aImeHotKey[ctr1];
|
|
|
|
bRet = ImmGetHotKey(pHotKeyNode->dwHotKeyID, &uModifiers, &uVKey, &hkl);
|
|
|
|
if (!bRet &&
|
|
(!pHotKeyNode->uVKey) &&
|
|
((pHotKeyNode->uModifiers & (MOD_ALT | MOD_CONTROL | MOD_SHIFT))
|
|
!= (MOD_ALT | MOD_CONTROL | MOD_SHIFT)))
|
|
{
|
|
//
|
|
// No such hotkey exists. User does not specify key and modifier
|
|
// information either. We can skip this one.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
if ((pHotKeyNode->uModifiers == uModifiers) &&
|
|
(pHotKeyNode->uVKey == uVKey))
|
|
{
|
|
//
|
|
// No change.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Set the hotkey value.
|
|
//
|
|
bRet = ImmSetHotKey( pHotKeyNode->dwHotKeyID,
|
|
pHotKeyNode->uModifiers,
|
|
pHotKeyNode->uVKey,
|
|
pHotKeyNode->hkl );
|
|
|
|
if (bRet)
|
|
{
|
|
//
|
|
// Must be IME related hotkey. We need to sync up the
|
|
// imes so that the new hotkey is effective to all
|
|
// of them.
|
|
//
|
|
UINT ctr2;
|
|
|
|
for (ctr2 = 0; ctr2 < nLangs; ctr2++)
|
|
{
|
|
if (!ImmIsIME(pLangs[ctr2]))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ImmEscape( pLangs[ctr2],
|
|
NULL,
|
|
IME_ESC_SYNC_HOTKEY,
|
|
&pHotKeyNode->dwHotKeyID );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failed to set hotkey. Maybe a duplicate. Warn user.
|
|
//
|
|
TCHAR szString[DESC_MAX];
|
|
|
|
GetAtomName( pHotKeyNode->atmHotKeyName,
|
|
szString,
|
|
sizeof(szString) / sizeof(TCHAR) );
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_SET_HOTKEY_ERR, szString);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_GetAttributes
|
|
//
|
|
// Gets the global layout attributes (eg: CapsLock/ShiftLock value) from
|
|
// the registry and then sets the appropriate radio button in the dialog.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_GetAttributes(
|
|
HWND hwnd)
|
|
{
|
|
DWORD cb;
|
|
HKEY hkey;
|
|
|
|
//
|
|
// Initialize the global.
|
|
//
|
|
g_dwAttributes = 0; // KLF_SHIFTLOCK = 0x00010000
|
|
|
|
//
|
|
// Get the Atributes value from the registry.
|
|
//
|
|
if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdLayouts, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
RegQueryValueEx( hkey,
|
|
c_szAttributes,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&g_dwAttributes,
|
|
&cb );
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
//
|
|
// Set the radio buttons appropriately.
|
|
//
|
|
CheckDlgButton( hwnd,
|
|
IDC_KBDL_SHIFTLOCK,
|
|
(g_dwAttributes & KLF_SHIFTLOCK)
|
|
? BST_CHECKED
|
|
: BST_UNCHECKED );
|
|
CheckDlgButton( hwnd,
|
|
IDC_KBDL_CAPSLOCK,
|
|
(g_dwAttributes & KLF_SHIFTLOCK)
|
|
? BST_UNCHECKED
|
|
: BST_CHECKED);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_LoadLayouts
|
|
//
|
|
// Loads the layouts from the registry.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_LoadLayouts(
|
|
HWND hwnd)
|
|
{
|
|
HKEY hKey;
|
|
HKEY hkey1;
|
|
DWORD cb;
|
|
DWORD dwIndex;
|
|
LONG dwRetVal;
|
|
DWORD dwValue;
|
|
DWORD dwType;
|
|
TCHAR szValue[MAX_PATH]; // language id (number)
|
|
TCHAR szData[MAX_PATH]; // language name
|
|
TCHAR szSystemDir[MAX_PATH * 2];
|
|
UINT SysDirLen;
|
|
DWORD dwLayoutID;
|
|
BOOL bLoadedLayout;
|
|
|
|
//
|
|
// Load shlwapi module to get the localized layout name
|
|
//
|
|
g_hShlwapi = LoadSystemLibrary(TEXT("shlwapi.dll"));
|
|
|
|
if (g_hShlwapi)
|
|
{
|
|
//
|
|
// Get address SHLoadRegUIStringW
|
|
//
|
|
pfnSHLoadRegUIString = GetProcAddress(g_hShlwapi, (LPVOID)439);
|
|
}
|
|
|
|
//
|
|
// Now read all of the layouts from the registry.
|
|
//
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLayoutPath, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
return (FALSE);
|
|
}
|
|
|
|
dwIndex = 0;
|
|
dwRetVal = RegEnumKey( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
sizeof(szValue) / sizeof(TCHAR) );
|
|
|
|
if (dwRetVal != ERROR_SUCCESS)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
RegCloseKey(hKey);
|
|
return (FALSE);
|
|
}
|
|
|
|
g_hLayout = LocalAlloc(LHND, ALLOCBLOCK * sizeof(LAYOUT));
|
|
g_nLayoutBuffSize = ALLOCBLOCK;
|
|
g_iLayoutBuff = 0;
|
|
g_iLayoutIME = 0; // number of IME layouts.
|
|
g_lpLayout = LocalLock(g_hLayout);
|
|
|
|
if (!g_hLayout)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
RegCloseKey(hKey);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Save the system directory string.
|
|
//
|
|
szSystemDir[0] = 0;
|
|
if (SysDirLen = GetSystemDirectory(szSystemDir, MAX_PATH))
|
|
{
|
|
if (SysDirLen > MAX_PATH)
|
|
{
|
|
SysDirLen = 0;
|
|
szSystemDir[0] = 0;
|
|
}
|
|
else if (szSystemDir[SysDirLen - 1] != TEXT('\\'))
|
|
{
|
|
szSystemDir[SysDirLen] = TEXT('\\');
|
|
szSystemDir[SysDirLen + 1] = 0;
|
|
SysDirLen++;
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
//
|
|
// New layout - get the layout id, the layout file name, and
|
|
// the layout description string.
|
|
//
|
|
if (g_iLayoutBuff + 1 == g_nLayoutBuffSize)
|
|
{
|
|
HANDLE hTemp;
|
|
|
|
LocalUnlock(g_hLayout);
|
|
|
|
g_nLayoutBuffSize += ALLOCBLOCK;
|
|
hTemp = LocalReAlloc( g_hLayout,
|
|
g_nLayoutBuffSize * sizeof(LAYOUT),
|
|
LHND );
|
|
if (hTemp == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
g_hLayout = hTemp;
|
|
g_lpLayout = LocalLock(g_hLayout);
|
|
}
|
|
|
|
//
|
|
// Get the layout id
|
|
//
|
|
dwLayoutID = TransNum(szValue);
|
|
|
|
//
|
|
// Save the layout id.
|
|
//
|
|
g_lpLayout[g_iLayoutBuff].dwID = dwLayoutID;
|
|
|
|
StringCchCopy(szData, ARRAYSIZE(szData), c_szLayoutPath);
|
|
StringCchCat(szData, ARRAYSIZE(szData), TEXT("\\"));
|
|
StringCchCat(szData, ARRAYSIZE(szData), szValue);
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, szData, &hkey1) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Get the name of the layout file.
|
|
//
|
|
szValue[0] = TEXT('\0');
|
|
cb = sizeof(szValue);
|
|
if ((RegQueryValueEx( hkey1,
|
|
c_szLayoutFile,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szValue,
|
|
&cb ) == ERROR_SUCCESS) &&
|
|
(cb > sizeof(TCHAR)))
|
|
{
|
|
g_lpLayout[g_iLayoutBuff].atmLayoutFile = AddAtom(szValue);
|
|
|
|
//
|
|
// See if the layout file exists already.
|
|
//
|
|
StringCchCopy(szSystemDir + SysDirLen,
|
|
ARRAYSIZE(szSystemDir) - SysDirLen,
|
|
szValue);
|
|
g_lpLayout[g_iLayoutBuff].bInstalled = (Locale_FileExists(szSystemDir));
|
|
|
|
//
|
|
// Get the name of the layout.
|
|
//
|
|
szValue[0] = TEXT('\0');
|
|
cb = sizeof(szValue);
|
|
g_lpLayout[g_iLayoutBuff].iSpecialID = 0;
|
|
bLoadedLayout = FALSE;
|
|
|
|
if (pfnSHLoadRegUIString &&
|
|
pfnSHLoadRegUIString(hkey1,
|
|
c_szDisplayLayoutText,
|
|
szValue,
|
|
ARRAYSIZE(szValue)) == S_OK)
|
|
{
|
|
g_lpLayout[g_iLayoutBuff].atmLayoutText = AddAtom(szValue);
|
|
bLoadedLayout = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get the name of the layout.
|
|
//
|
|
szValue[0] = TEXT('\0');
|
|
cb = sizeof(szValue);
|
|
if (RegQueryValueEx( hkey1,
|
|
c_szLayoutText,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szValue,
|
|
&cb ) == ERROR_SUCCESS)
|
|
{
|
|
g_lpLayout[g_iLayoutBuff].atmLayoutText = AddAtom(szValue);
|
|
bLoadedLayout = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bLoadedLayout)
|
|
{
|
|
|
|
//
|
|
// See if it's an IME or a special id.
|
|
//
|
|
szValue[0] = TEXT('\0');
|
|
cb = sizeof(szValue);
|
|
if ((HIWORD(g_lpLayout[g_iLayoutBuff].dwID) & 0xf000) == 0xe000)
|
|
{
|
|
//
|
|
// Get the name of the IME file.
|
|
//
|
|
if (RegQueryValueEx( hkey1,
|
|
c_szIMEFile,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szValue,
|
|
&cb ) == ERROR_SUCCESS)
|
|
{
|
|
g_lpLayout[g_iLayoutBuff].atmIMEFile = AddAtom(szValue);
|
|
szValue[0] = TEXT('\0');
|
|
cb = sizeof(szValue);
|
|
g_iLayoutBuff++;
|
|
g_iLayoutIME++; // increment number of IME layouts.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// See if this is a special id.
|
|
//
|
|
if (RegQueryValueEx( hkey1,
|
|
c_szLayoutID,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szValue,
|
|
&cb ) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// This may not exist.
|
|
//
|
|
g_lpLayout[g_iLayoutBuff].iSpecialID =
|
|
(UINT)TransNum(szValue);
|
|
}
|
|
g_iLayoutBuff++;
|
|
}
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkey1);
|
|
}
|
|
|
|
dwIndex++;
|
|
szValue[0] = TEXT('\0');
|
|
dwRetVal = RegEnumKey( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
sizeof(szValue) / sizeof(TCHAR) );
|
|
|
|
} while (dwRetVal == ERROR_SUCCESS);
|
|
|
|
cb = sizeof(DWORD);
|
|
g_dwAttributes = 0;
|
|
if (RegQueryValueEx( hKey,
|
|
c_szAttributes,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&g_dwAttributes,
|
|
&cb ) != ERROR_SUCCESS)
|
|
{
|
|
g_dwAttributes &= 0x00FF0000;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
if (g_hShlwapi)
|
|
{
|
|
FreeLibrary(g_hShlwapi);
|
|
g_hShlwapi = NULL;
|
|
pfnSHLoadRegUIString = NULL;
|
|
}
|
|
return (g_iLayoutBuff);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_LoadLocales
|
|
//
|
|
// Loads the locales from the registry.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_LoadLocales(
|
|
HWND hwnd)
|
|
{
|
|
HKEY hKey;
|
|
DWORD cchValue, cbData;
|
|
DWORD dwIndex;
|
|
DWORD dwLocale, dwLayout;
|
|
DWORD dwLocale2, dwLayout2;
|
|
LONG dwRetVal;
|
|
UINT ctr1, ctr2 = 0;
|
|
TCHAR szValue[MAX_PATH]; // language id (number)
|
|
TCHAR szData[MAX_PATH]; // language name
|
|
HINF hIntlInf;
|
|
BOOL bRet;
|
|
|
|
if (!(g_hLang = LocalAlloc(LHND, ALLOCBLOCK * sizeof(INPUTLANG))))
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
return (FALSE);
|
|
}
|
|
|
|
g_nLangBuffSize = ALLOCBLOCK;
|
|
g_iLangBuff = 0;
|
|
g_lpLang = LocalLock(g_hLang);
|
|
|
|
//
|
|
// Now read all of the locales from the registry.
|
|
//
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLocaleInfo, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
return (FALSE);
|
|
}
|
|
|
|
dwIndex = 0;
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
cbData = sizeof(szData);
|
|
dwRetVal = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
|
|
|
|
if (dwRetVal != ERROR_SUCCESS)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
RegCloseKey(hKey);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Open the INF file.
|
|
//
|
|
bRet = Region_OpenIntlInfFile(&hIntlInf);
|
|
|
|
do
|
|
{
|
|
//
|
|
// Check for cchValue > 1 - an empty string will be enumerated,
|
|
// and will come back with cchValue == 1 for the null terminator.
|
|
// Also, check for cbData > 2 - an empty string will be 2, since
|
|
// this is the count of bytes.
|
|
//
|
|
if ((cchValue > 1) && (cchValue < HKL_LEN) && (cbData > 2))
|
|
{
|
|
//
|
|
// New language - get the language name and the language id.
|
|
//
|
|
if ((g_iLangBuff + 1) == g_nLangBuffSize)
|
|
{
|
|
HANDLE hTemp;
|
|
|
|
LocalUnlock(g_hLang);
|
|
|
|
g_nLangBuffSize += ALLOCBLOCK;
|
|
hTemp = LocalReAlloc( g_hLang,
|
|
g_nLangBuffSize * sizeof(INPUTLANG),
|
|
LHND );
|
|
if (hTemp == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
g_hLang = hTemp;
|
|
g_lpLang = LocalLock(g_hLang);
|
|
}
|
|
|
|
g_lpLang[g_iLangBuff].dwID = TransNum(szValue);
|
|
g_lpLang[g_iLangBuff].iUseCount = 0;
|
|
g_lpLang[g_iLangBuff].iNumCount = 0;
|
|
g_lpLang[g_iLangBuff].pNext = NULL;
|
|
|
|
//
|
|
// Get the default keyboard layout for the language.
|
|
//
|
|
if (bRet && Region_ReadDefaultLayoutFromInf( szValue,
|
|
&dwLocale,
|
|
&dwLayout,
|
|
&dwLocale2,
|
|
&dwLayout2,
|
|
hIntlInf ) == TRUE)
|
|
{
|
|
//
|
|
// The default layout is either the first layout in the inf file line
|
|
// or it's the first layout in the line that has the same language
|
|
// is the locale.
|
|
g_lpLang[g_iLangBuff].dwDefaultLayout = dwLayout2?dwLayout2:dwLayout;
|
|
}
|
|
|
|
//
|
|
// Get the full localized name of the language.
|
|
//
|
|
if (GetLanguageName(LOWORD(g_lpLang[g_iLangBuff].dwID), szData, ARRAYSIZE(szData)))
|
|
{
|
|
g_lpLang[g_iLangBuff].atmLanguageName = AddAtom(szData);
|
|
g_iLangBuff++;
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
szValue[0] = TEXT('\0');
|
|
cbData = sizeof(szData);
|
|
szData[0] = TEXT('\0');
|
|
dwRetVal = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
|
|
} while (dwRetVal == ERROR_SUCCESS);
|
|
|
|
//
|
|
// If we succeeded in opening the INF file, close it.
|
|
//
|
|
if (bRet)
|
|
{
|
|
Region_CloseInfFile(&hIntlInf);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
return (TRUE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_LoadLocalesNT4
|
|
//
|
|
// Loads the locales from the registry.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_LoadLocalesNT4(
|
|
HWND hwnd)
|
|
{
|
|
HKEY hKey;
|
|
DWORD cch;
|
|
DWORD dwIndex;
|
|
LONG dwRetVal;
|
|
UINT i, j = 0;
|
|
|
|
TCHAR szValue[MAX_PATH]; // language id (number)
|
|
TCHAR szData[MAX_PATH]; // language name
|
|
|
|
if (!(g_hLang = LocalAlloc(LHND, ALLOCBLOCK * sizeof(INPUTLANG))))
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
return (FALSE);
|
|
}
|
|
|
|
g_nLangBuffSize = ALLOCBLOCK;
|
|
g_iLangBuff = 0;
|
|
g_lpLang = LocalLock(g_hLang);
|
|
|
|
//
|
|
// Now read all of the locales from the registry.
|
|
//
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLocaleInfoNT4, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
return (FALSE);
|
|
}
|
|
|
|
dwIndex = 0;
|
|
cch = sizeof(szValue) / sizeof(TCHAR);
|
|
dwRetVal = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cch,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if (dwRetVal != ERROR_SUCCESS)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
RegCloseKey(hKey);
|
|
return (FALSE);
|
|
}
|
|
|
|
do
|
|
{
|
|
if ((cch > 1) && (cch < HKL_LEN))
|
|
{
|
|
//
|
|
// Check for cch > 1: an empty string will be enumerated,
|
|
// and will come back with cch == 1 for the null terminator.
|
|
//
|
|
// New language - get the language name, the language
|
|
// description, and the language id.
|
|
//
|
|
if ((g_iLangBuff + 1) == g_nLangBuffSize)
|
|
{
|
|
HANDLE hTemp;
|
|
|
|
LocalUnlock(g_hLang);
|
|
|
|
g_nLangBuffSize += ALLOCBLOCK;
|
|
hTemp = LocalReAlloc( g_hLang,
|
|
g_nLangBuffSize * sizeof(INPUTLANG),
|
|
LHND );
|
|
if (hTemp == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
g_hLang = hTemp;
|
|
g_lpLang = LocalLock(g_hLang);
|
|
}
|
|
|
|
g_lpLang[g_iLangBuff].dwID = TransNum(szValue);
|
|
g_lpLang[g_iLangBuff].iUseCount = 0;
|
|
g_lpLang[g_iLangBuff].iNumCount = 0;
|
|
g_lpLang[g_iLangBuff].pNext = NULL;
|
|
|
|
//
|
|
// Get the full localized name of the language.
|
|
//
|
|
if (GetLanguageName(LOWORD(g_lpLang[g_iLangBuff].dwID), szData, ARRAYSIZE(szData)))
|
|
{
|
|
g_lpLang[g_iLangBuff].atmLanguageName = AddAtom(szData);
|
|
|
|
g_iLangBuff++;
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
cch = sizeof(szValue) / sizeof(TCHAR);
|
|
szValue[0] = TEXT('\0');
|
|
dwRetVal = RegEnumValue( hKey,
|
|
dwIndex,
|
|
szValue,
|
|
&cch,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
} while (dwRetVal == ERROR_SUCCESS);
|
|
|
|
RegCloseKey(hKey);
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_GetActiveLocales
|
|
//
|
|
// Gets the active locales.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_GetActiveLocales(
|
|
HWND hwnd)
|
|
{
|
|
HKL *pLangs;
|
|
UINT nLangs, ctr1, ctr2, ctr3, id;
|
|
HWND hwndList = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
HKL hklSystem = 0;
|
|
int idxListBox;
|
|
BOOL bReturn = FALSE;
|
|
BOOL bTipSubhkl = FALSE;
|
|
DWORD langLay;
|
|
HANDLE hLangNode;
|
|
LPLANGNODE pLangNode;
|
|
HICON hIcon = NULL;
|
|
|
|
TCHAR szLangText[DESC_MAX];
|
|
TCHAR szLayoutName[DESC_MAX];
|
|
LPINPUTLANG pInpLang;
|
|
HTREEITEM hTVItem;
|
|
TV_ITEM tvItem;
|
|
|
|
|
|
//
|
|
// Initialize US layout option.
|
|
//
|
|
g_iUsLayout = -1;
|
|
|
|
//
|
|
// Get the active keyboard layout list from the system.
|
|
//
|
|
if (!SystemParametersInfo( SPI_GETDEFAULTINPUTLANG,
|
|
0,
|
|
&hklSystem,
|
|
0 ))
|
|
{
|
|
hklSystem = GetKeyboardLayout(0);
|
|
}
|
|
|
|
nLangs = GetKeyboardLayoutList(0, NULL);
|
|
if (nLangs == 0)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
return bReturn;
|
|
}
|
|
pLangs = (HKL *)LocalAlloc(LPTR, sizeof(DWORD_PTR) * nLangs);
|
|
|
|
if (pLangs == NULL)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
return bReturn;
|
|
}
|
|
|
|
GetKeyboardLayoutList(nLangs, (HKL *)pLangs);
|
|
|
|
//
|
|
// Find the position of the US layout to use as a default.
|
|
//
|
|
for (ctr1 = 0; ctr1 < g_iLayoutBuff; ctr1++)
|
|
{
|
|
if (g_lpLayout[ctr1].dwID == US_LOCALE)
|
|
{
|
|
g_iUsLayout = ctr1;
|
|
break;
|
|
}
|
|
}
|
|
if (ctr1 == g_iLayoutBuff)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Get the active keyboard information and put it in the internal
|
|
// language structure.
|
|
//
|
|
for (ctr2 = 0; ctr2 < nLangs; ctr2++)
|
|
{
|
|
//
|
|
// Filter out TIP substitute HKL from TreeView.
|
|
//
|
|
bTipSubhkl = IsTipSubstituteHKL(pLangs[ctr2]);
|
|
|
|
if (hklSystem != pLangs[ctr2] &&
|
|
IsUnregisteredFEDummyHKL(pLangs[ctr2]))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (ctr1 = 0; ctr1 < g_iLangBuff; ctr1++)
|
|
{
|
|
//
|
|
// See if there's a match.
|
|
//
|
|
if (LOWORD(pLangs[ctr2]) == LOWORD(g_lpLang[ctr1].dwID))
|
|
{
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
//
|
|
// Found a match.
|
|
// Create a node for this language.
|
|
//
|
|
pLangNode = Locale_AddToLinkedList(ctr1, pLangs[ctr2]);
|
|
if (!pLangNode)
|
|
{
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Get language name to add it to treeview
|
|
//
|
|
pInpLang = &g_lpLang[pLangNode->iLang];
|
|
GetAtomName(pInpLang->atmLanguageName, szLangText, ARRAYSIZE(szLangText));
|
|
|
|
if ((HIWORD(pLangs[ctr2]) & 0xf000) == 0xe000)
|
|
{
|
|
pLangNode->wStatus |= LANG_IME;
|
|
}
|
|
pLangNode->wStatus |= (LANG_ORIGACTIVE | LANG_ACTIVE);
|
|
pLangNode->hkl = pLangs[ctr2];
|
|
pLangNode->hklUnload = pLangs[ctr2];
|
|
Locale_FetchIndicator(pLangNode);
|
|
|
|
//
|
|
// Match the language to the layout.
|
|
//
|
|
pLangNode->iLayout = 0;
|
|
langLay = (DWORD)HIWORD(pLangs[ctr2]);
|
|
|
|
if ((HIWORD(pLangs[ctr2]) == 0xffff) ||
|
|
(HIWORD(pLangs[ctr2]) == 0xfffe))
|
|
{
|
|
//
|
|
// Mark default or previous error as US - this
|
|
// means that the layout will be that of the basic
|
|
// keyboard driver (the US one).
|
|
//
|
|
pLangNode->wStatus |= LANG_CHANGED;
|
|
pLangNode->iLayout = g_iUsLayout;
|
|
langLay = 0;
|
|
}
|
|
else if ((HIWORD(pLangs[ctr2]) & 0xf000) == 0xf000)
|
|
{
|
|
//
|
|
// Layout is special, need to search for the ID
|
|
// number.
|
|
//
|
|
id = HIWORD(pLangs[ctr2]) & 0x0fff;
|
|
for (ctr3 = 0; ctr3 < g_iLayoutBuff; ctr3++)
|
|
{
|
|
if (id == g_lpLayout[ctr3].iSpecialID)
|
|
{
|
|
pLangNode->iLayout = ctr3;
|
|
langLay = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (langLay)
|
|
{
|
|
//
|
|
// Didn't find the id, so reset to basic for
|
|
// the language.
|
|
//
|
|
langLay = (DWORD)LOWORD(pLangs[ctr2]);
|
|
}
|
|
}
|
|
|
|
if (langLay)
|
|
{
|
|
//
|
|
// Search for the id.
|
|
//
|
|
for (ctr3 = 0; ctr3 < g_iLayoutBuff; ctr3++)
|
|
{
|
|
if (((LOWORD(langLay) & 0xf000) == 0xe000) &&
|
|
(g_lpLayout[ctr3].dwID) == (DWORD)((DWORD_PTR)(pLangs[ctr2])))
|
|
{
|
|
pLangNode->iLayout = ctr3;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (langLay == (DWORD)LOWORD(g_lpLayout[ctr3].dwID))
|
|
{
|
|
pLangNode->iLayout = ctr3;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ctr3 == g_iLayoutBuff)
|
|
{
|
|
//
|
|
// Something went wrong or didn't load from
|
|
// the registry correctly.
|
|
//
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
pLangNode->wStatus |= LANG_CHANGED;
|
|
pLangNode->iLayout = g_iUsLayout;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this is the current language, then it's the default
|
|
// one.
|
|
//
|
|
if ((DWORD)((DWORD_PTR)pLangNode->hkl) == (DWORD)((DWORD_PTR)hklSystem))
|
|
{
|
|
TCHAR sz[DESC_MAX];
|
|
|
|
pInpLang = &g_lpLang[ctr1];
|
|
|
|
//
|
|
// Found the default. Set the Default input locale
|
|
// text in the property sheet.
|
|
//
|
|
if (pLangNode->wStatus & LANG_IME)
|
|
{
|
|
GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
|
|
sz,
|
|
ARRAYSIZE(sz));
|
|
}
|
|
else
|
|
{
|
|
GetAtomName(pInpLang->atmLanguageName, sz, ARRAYSIZE(sz));
|
|
}
|
|
pLangNode->wStatus |= LANG_DEFAULT;
|
|
}
|
|
|
|
// Get layout name and add it to treeview
|
|
GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
|
|
szLayoutName,
|
|
ARRAYSIZE(szLayoutName));
|
|
|
|
if (bTipSubhkl)
|
|
{
|
|
AddKbdLayoutOnKbdTip((HKL) ((DWORD_PTR)(pLangs[ctr2])), pLangNode->iLayout);
|
|
}
|
|
|
|
if (bTipSubhkl &&
|
|
(hTVItem = FindTVLangItem(pInpLang->dwID, NULL)))
|
|
{
|
|
TV_ITEM tvTipItem;
|
|
HTREEITEM hGroupItem;
|
|
HTREEITEM hTipItem;
|
|
LPTVITEMNODE pTVTipItemNode;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVItem;
|
|
|
|
//GetAtomName(pTVItemNode->atmDefTipName, szLayoutName, ARRAYSIZE(szLayoutName));
|
|
|
|
tvTipItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvTipItem.hItem = hTVItem;
|
|
|
|
//
|
|
// Adding the default keyboard layout info into each TIPs.
|
|
//
|
|
for (hGroupItem = TreeView_GetChild(g_hwndTV, hTVItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(g_hwndTV, hGroupItem))
|
|
{
|
|
for (hTipItem = TreeView_GetChild(g_hwndTV, hGroupItem);
|
|
hTipItem != NULL;
|
|
hTipItem = TreeView_GetNextSibling(g_hwndTV, hTipItem))
|
|
{
|
|
tvTipItem.hItem = hTipItem;
|
|
if (TreeView_GetItem(g_hwndTV, &tvTipItem) && tvTipItem.lParam)
|
|
{
|
|
pTVTipItemNode = (LPTVITEMNODE) tvTipItem.lParam;
|
|
|
|
if (pTVTipItemNode->hklSub == pLangNode->hkl)
|
|
{
|
|
pTVTipItemNode->lParam = (LPARAM) pLangNode;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (pLangNode->wStatus & LANG_DEFAULT)
|
|
{
|
|
UINT ctr;
|
|
TCHAR szDefItem[MAX_PATH];
|
|
|
|
//
|
|
// Set the default locale selection.
|
|
//
|
|
HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
|
|
int idxSel = -1;
|
|
|
|
|
|
//
|
|
// Search substitute HKL of Tips.
|
|
//
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if (pLangs[ctr2] == g_lpTips[ctr].hklSub &&
|
|
g_lpTips[ctr].bDefault)
|
|
{
|
|
GetAtomName(g_lpTips[ctr].atmTipText,
|
|
szLayoutName,
|
|
ARRAYSIZE(szLayoutName));
|
|
break;
|
|
}
|
|
}
|
|
|
|
StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), szLangText);
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
|
|
StringCchCat(szDefItem, ARRAYSIZE(szDefItem), szLayoutName);
|
|
|
|
if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) != CB_ERR)
|
|
ComboBox_SetCurSel(hwndDefList, idxSel);
|
|
|
|
Locale_CommandSetDefault(hwnd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//
|
|
//
|
|
if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
|
|
goto Error;
|
|
|
|
pTVItemNode->lParam = (LPARAM)pLangNode;
|
|
|
|
if (!pTVItemNode->atmDefTipName)
|
|
pTVItemNode->atmDefTipName = AddAtom(szLayoutName);
|
|
|
|
//
|
|
// Add language node into treeview
|
|
//
|
|
AddTreeViewItems(TV_ITEM_TYPE_LANG,
|
|
szLangText, NULL, NULL, &pTVItemNode);
|
|
|
|
if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
|
|
goto Error;
|
|
|
|
pTVItemNode->lParam = (LPARAM)pLangNode;
|
|
|
|
//
|
|
// Add keyboard layout item into treeview
|
|
//
|
|
hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
|
|
szLangText,
|
|
szInputTypeKbd,
|
|
szLayoutName,
|
|
&pTVItemNode);
|
|
}
|
|
|
|
//
|
|
// Check Thai layout.
|
|
//
|
|
if (g_dwPrimLangID == LANG_THAI && hTVItem)
|
|
{
|
|
if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
|
|
g_iThaiLayout++;
|
|
}
|
|
|
|
//
|
|
// Break out of inner loop - we've found it.
|
|
//
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
bReturn = TRUE;
|
|
|
|
Error:
|
|
if (pLangs)
|
|
LocalFree((HANDLE)pLangs);
|
|
return (bReturn);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetInstalledInput
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL GetInstalledInput(HWND hwnd)
|
|
{
|
|
DWORD dwLayout = 0;
|
|
LANGID langID;
|
|
|
|
//
|
|
// Reset the installed input
|
|
//
|
|
g_iInputs = 0;
|
|
|
|
|
|
//
|
|
// Need to check language id for Thai, Chinese and Arabic.
|
|
//
|
|
g_dwPrimLangID = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID()));
|
|
|
|
if (g_dwPrimLangID == LANG_ARABIC || g_dwPrimLangID == LANG_HEBREW)
|
|
{
|
|
g_bMESystem = TRUE;
|
|
}
|
|
#if 0
|
|
else if (g_dwPrimLangID == LANG_CHINESE)
|
|
{
|
|
g_bCHSystem = TRUE;
|
|
}
|
|
#endif
|
|
|
|
langID = GetUserDefaultUILanguage();
|
|
if (PRIMARYLANGID(langID) == LANG_ARABIC || PRIMARYLANGID(langID) == LANG_HEBREW)
|
|
{
|
|
g_bShowRtL = TRUE;
|
|
}
|
|
|
|
//
|
|
// Enum new tips(speech, pen and keyboard).
|
|
// If there are new tips in the system, read tip category enabling status
|
|
// and add them into tree view control.
|
|
//
|
|
EnumCiceroTips();
|
|
|
|
//
|
|
// Read all availabe keyboard layouts from system
|
|
//
|
|
if (g_OSNT4)
|
|
{
|
|
if (!Locale_LoadLocalesNT4(hwnd))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (!Locale_LoadLocales(hwnd))
|
|
return FALSE;
|
|
}
|
|
|
|
if ((!Locale_LoadLayouts(hwnd)) ||
|
|
(!Locale_GetActiveLocales(hwnd)))
|
|
return FALSE;
|
|
|
|
//
|
|
// Only 1 TIP, so disable the secondary controls.
|
|
//
|
|
Locale_SetSecondaryControls(hwnd);
|
|
|
|
//
|
|
// Save the originial input layouts
|
|
//
|
|
g_iOrgInputs = g_iInputs;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InitPropSheet
|
|
//
|
|
// Processing for a WM_INITDIALOG message for the Input Locales
|
|
// property sheet.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void InitPropSheet(
|
|
HWND hwnd,
|
|
LPPROPSHEETPAGE psp)
|
|
{
|
|
HKEY hKey;
|
|
HANDLE hlib;
|
|
HWND hwndList;
|
|
LPLANGNODE pLangNode;
|
|
LANGID LangID;
|
|
UINT iNumLangs, ctr;
|
|
TCHAR szItem[DESC_MAX];
|
|
BOOL bImeSetting = FALSE;
|
|
|
|
//
|
|
// See if there are any other instances of this property page.
|
|
// If so, disable this page.
|
|
//
|
|
if (g_hMutex && (WaitForSingleObject(g_hMutex, 0) != WAIT_OBJECT_0))
|
|
{
|
|
// Need to disable controls ...
|
|
Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED_2);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// See if we're in setup mode.
|
|
//
|
|
if (IsSetupMode())
|
|
{
|
|
//
|
|
// Set the setup special case flag.
|
|
//
|
|
g_bSetupCase = TRUE;
|
|
}
|
|
|
|
//
|
|
// Make sure the event is clear.
|
|
//
|
|
if (g_hEvent)
|
|
{
|
|
SetEvent(g_hEvent);
|
|
}
|
|
|
|
g_OSNT4 = IsOSPlatform(OS_NT4);
|
|
g_OSNT5 = IsOSPlatform(OS_NT5);
|
|
#ifndef _WIN64
|
|
g_OSWIN95 = IsOSPlatform(OS_WIN95);
|
|
#endif // _WIN64
|
|
|
|
//
|
|
// Check the Administrative privileges by the token group SID.
|
|
//
|
|
if (IsAdminPrivilegeUser())
|
|
{
|
|
g_bAdmin_Privileges = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The user does not have admin privileges.
|
|
//
|
|
g_bAdmin_Privileges = FALSE;
|
|
}
|
|
|
|
//
|
|
// Load the strings
|
|
//
|
|
LoadString(hInstance, IDS_LOCALE_DEFAULT, szDefault, ARRAYSIZE(szDefault));
|
|
LoadString(hInstance, IDS_INPUT_KEYBOARD, szInputTypeKbd, ARRAYSIZE(szInputTypeKbd));
|
|
LoadString(hInstance, IDS_INPUT_PEN, szInputTypePen, ARRAYSIZE(szInputTypePen));
|
|
LoadString(hInstance, IDS_INPUT_SPEECH, szInputTypeSpeech, ARRAYSIZE(szInputTypeSpeech));
|
|
LoadString(hInstance, IDS_INPUT_EXTERNAL, szInputTypeExternal, ARRAYSIZE(szInputTypeExternal));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_CommandAdd
|
|
//
|
|
// Invokes the Add dialog.
|
|
//
|
|
// Returns 1 if a dialog box was invoked and the dialog returned IDOK.
|
|
// Otherwise, it returns 0.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int Locale_CommandAdd(
|
|
HWND hwnd)
|
|
{
|
|
HWND hwndList;
|
|
HWND hwndTV;
|
|
int idxList;
|
|
UINT nList;
|
|
int rc = 0;
|
|
INITINFO InitInfo;
|
|
LPCTSTR lpTemplateName;
|
|
HINSTANCE hInstRes;
|
|
|
|
HTREEITEM hTVItem;
|
|
|
|
hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
hTVItem = TreeView_GetSelection(hwndTV);
|
|
|
|
if (!hTVItem)
|
|
return 0;
|
|
|
|
InitInfo.hwndMain = hwnd;
|
|
InitInfo.pLangNode = NULL;
|
|
|
|
if (g_bExtraTip)
|
|
{
|
|
hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_ADD_EXTRA);
|
|
lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_ADD_EXTRA);
|
|
}
|
|
else if (g_bPenOrSapiTip)
|
|
{
|
|
hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_ADD);
|
|
lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_ADD);
|
|
}
|
|
else
|
|
{
|
|
hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_SIMPLE_ADD);
|
|
lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_SIMPLE_ADD);
|
|
}
|
|
|
|
//
|
|
// Bring up the appropriate dialog box. And check return value for added
|
|
// items.
|
|
//
|
|
if ((rc = (int)DialogBoxParam(hInstRes,
|
|
lpTemplateName,
|
|
hwnd,
|
|
KbdLocaleAddDlg,
|
|
(LPARAM)(&InitInfo) )) == IDOK)
|
|
{
|
|
//
|
|
// Turn on ApplyNow button.
|
|
//
|
|
PropSheet_Changed(GetParent(hwnd), hwnd);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failure, so need to return 0.
|
|
//
|
|
TreeView_SelectItem(hwndTV, hTVItem);
|
|
rc = 0;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_CommandEdit
|
|
//
|
|
// Invokes the Properties dialog.
|
|
//
|
|
// Returns 1 if a dialog box was invoked and the dialog returned IDOK.
|
|
// Otherwise, it returns 0.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_CommandEdit(
|
|
HWND hwnd,
|
|
LPLANGNODE pLangNode)
|
|
{
|
|
HWND hwndList;
|
|
HWND hwndTV;
|
|
int idxList;
|
|
UINT nList;
|
|
int rc = 0;
|
|
INITINFO InitInfo;
|
|
|
|
HTREEITEM hTVItem;
|
|
TV_ITEM tvItem;
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
hTVItem = TreeView_GetSelection(g_hwndTV);
|
|
|
|
if (!hTVItem)
|
|
return;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVItem;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (pTVItemNode->uInputType & INPUT_TYPE_TIP)
|
|
{
|
|
HRESULT hr;
|
|
|
|
ITfFnConfigure *pConfig = NULL;
|
|
|
|
//
|
|
// Load LangBar manager to bring the property window
|
|
//
|
|
hr = CoCreateInstance(&pTVItemNode->clsid,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfFnConfigure,
|
|
(LPVOID *) &pConfig);
|
|
|
|
//
|
|
// Call property dialog from TIP.
|
|
//
|
|
if (SUCCEEDED(hr))
|
|
pConfig->lpVtbl->Show(pConfig,
|
|
hwnd,
|
|
(LANGID)pTVItemNode->dwLangID,
|
|
&pTVItemNode->guidProfile);
|
|
|
|
if (pConfig)
|
|
pConfig->lpVtbl->Release(pConfig);
|
|
|
|
}
|
|
else
|
|
{
|
|
if ((pLangNode = (LPLANGNODE)pTVItemNode->lParam) && (pLangNode->wStatus & LANG_IME))
|
|
ImmConfigureIME(pLangNode->hkl, hwnd, IME_CONFIG_GENERAL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RemoveTVSubItems
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL RemoveTVSubItems(
|
|
HWND hwnd,
|
|
HTREEITEM hTVItem,
|
|
LPTVITEMNODE pTVItemNode)
|
|
{
|
|
TV_ITEM tvItem;
|
|
BOOL bRemoveAll = TRUE;
|
|
HTREEITEM hGroupItem, hItem;
|
|
HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
|
|
|
|
//
|
|
// Delete all TreeView node.
|
|
//
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
if (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG)
|
|
{
|
|
hGroupItem = TreeView_GetChild(hwndTV, hTVItem);
|
|
}
|
|
else
|
|
{
|
|
hGroupItem = hTVItem;
|
|
bRemoveAll = FALSE;
|
|
}
|
|
|
|
while (hGroupItem != NULL)
|
|
{
|
|
BOOL bNextGroup = FALSE;
|
|
LPTVITEMNODE pTVTempNode = NULL;
|
|
HTREEITEM hDeletedItem = NULL;
|
|
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
if (hDeletedItem)
|
|
{
|
|
TreeView_DeleteItem(hwndTV, hDeletedItem);
|
|
hDeletedItem = NULL;
|
|
}
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
LPLANGNODE pLangNode = NULL;
|
|
|
|
if (pTVTempNode = (LPTVITEMNODE) tvItem.lParam)
|
|
pLangNode = (LPLANGNODE)pTVTempNode->lParam;
|
|
else
|
|
continue;
|
|
|
|
if (pTVTempNode->uInputType & INPUT_TYPE_TIP)
|
|
{
|
|
g_lpTips[pTVTempNode->iIdxTips].bEnabled = FALSE;
|
|
g_iEnabledTips--;
|
|
|
|
if (pTVTempNode->uInputType & INPUT_TYPE_KBD)
|
|
g_iEnabledKbdTips--;
|
|
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
|
|
if ((pTVTempNode->uInputType & INPUT_TYPE_KBD) && pTVTempNode->hklSub)
|
|
{
|
|
UINT ctr;
|
|
UINT uNumSubhkl = 0;
|
|
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if (pTVTempNode->hklSub == g_lpTips[ctr].hklSub &&
|
|
g_lpTips[ctr].bEnabled)
|
|
{
|
|
uNumSubhkl++;
|
|
}
|
|
}
|
|
|
|
if (!uNumSubhkl)
|
|
{
|
|
pLangNode = (LPLANGNODE)pTVTempNode->lParam;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Someone still use this substitute HKL.
|
|
//
|
|
pLangNode = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((pTVTempNode->uInputType & TV_ITEM_TYPE_KBD) && pLangNode)
|
|
{
|
|
if (!(pTVTempNode->uInputType & INPUT_TYPE_TIP))
|
|
pLangNode = (LPLANGNODE)pTVTempNode->lParam;
|
|
|
|
if (!pLangNode)
|
|
return FALSE;
|
|
|
|
//
|
|
// Check Thai layout.
|
|
//
|
|
if (g_dwPrimLangID == LANG_THAI)
|
|
{
|
|
if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
|
|
g_iThaiLayout--;
|
|
}
|
|
|
|
pLangNode->wStatus &= ~(LANG_ACTIVE|LANG_DEFAULT);
|
|
pLangNode->wStatus |= LANG_CHANGED;
|
|
|
|
g_lpLang[pLangNode->iLang].iNumCount--;
|
|
|
|
if (!(pLangNode->wStatus & LANG_ORIGACTIVE))
|
|
{
|
|
Locale_RemoveFromLinkedList(pLangNode);
|
|
}
|
|
}
|
|
|
|
RemoveTVItemNode(pTVTempNode);
|
|
hDeletedItem = hItem;
|
|
g_iInputs--;
|
|
}
|
|
}
|
|
|
|
tvItem.hItem = hGroupItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVTempNode = (LPTVITEMNODE)tvItem.lParam;
|
|
|
|
if (!pTVTempNode)
|
|
continue;
|
|
|
|
if (pTVTempNode->uInputType & INPUT_TYPE_SPEECH ||
|
|
pTVTempNode->uInputType & INPUT_TYPE_SMARTTAG)
|
|
{
|
|
|
|
g_lpTips[pTVTempNode->iIdxTips].bEnabled = FALSE;
|
|
g_iEnabledTips--;
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
|
|
if (pTVTempNode->uInputType & INPUT_TYPE_SPEECH)
|
|
MarkSptipRemoved(TRUE);
|
|
}
|
|
|
|
if (pTVTempNode->uInputType & ~TV_ITEM_TYPE_LANG)
|
|
{
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem);
|
|
bNextGroup = TRUE;
|
|
TreeView_DeleteItem(hwndTV, tvItem.hItem );
|
|
}
|
|
|
|
RemoveTVItemNode(pTVTempNode);
|
|
|
|
if (pTVTempNode == pTVItemNode)
|
|
pTVItemNode = NULL;
|
|
}
|
|
|
|
if (!bNextGroup)
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem);
|
|
|
|
if (!bRemoveAll)
|
|
hGroupItem = NULL;
|
|
}
|
|
|
|
if (pTVItemNode && (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG))
|
|
{
|
|
int idxSel = -1;
|
|
TCHAR szItemName[DESC_MAX];
|
|
HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT);
|
|
|
|
GetAtomName(pTVItemNode->atmTVItemName, szItemName, ARRAYSIZE(szItemName));
|
|
|
|
idxSel = ComboBox_FindString(hwndDefList, 0, szItemName);
|
|
|
|
for (; idxSel != CB_ERR; )
|
|
{
|
|
ComboBox_DeleteString(hwndDefList, idxSel);
|
|
idxSel = ComboBox_FindString(hwndDefList, 0, szItemName);
|
|
}
|
|
|
|
if (pTVItemNode->bDefLang)
|
|
{
|
|
ComboBox_SetCurSel(hwndDefList, 0);
|
|
Locale_CommandSetDefault(hwnd);
|
|
}
|
|
|
|
RemoveTVItemNode(pTVItemNode);
|
|
TreeView_DeleteItem(hwndTV, hTVItem );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetNewRemoveItem
|
|
//
|
|
// Removes the currently selected input locale from the list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
HTREEITEM GetNewRemoveItem(
|
|
HWND hwnd,
|
|
HTREEITEM hTVItem,
|
|
BOOL *bDelSameSubhkl,
|
|
LPTSTR lpDelItems,
|
|
UINT cchDelItems)
|
|
{
|
|
TV_ITEM tvItem;
|
|
LPTVITEMNODE pTVItemNode;
|
|
HTREEITEM hTVNewItem = hTVItem;
|
|
HTREEITEM hTVLangItem = NULL;
|
|
HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
//
|
|
// Get the pointer to the lang node from the list box
|
|
// item data.
|
|
//
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVItemNode)
|
|
goto Error;
|
|
|
|
if (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG)
|
|
return hTVItem;
|
|
|
|
if (pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP)
|
|
{
|
|
if (!TreeView_GetNextSibling(hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(hwndTV, hTVItem))
|
|
{
|
|
if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVItem)) &&
|
|
(TreeView_GetNextSibling(hwndTV, hTVLangItem) ||
|
|
TreeView_GetPrevSibling(hwndTV, hTVLangItem)))
|
|
{
|
|
hTVNewItem = TreeView_GetParent(hwndTV, hTVItem);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!TreeView_GetNextSibling(hwndTV, hTVItem) &&
|
|
!TreeView_GetPrevSibling(hwndTV, hTVItem))
|
|
{
|
|
if (hTVNewItem = TreeView_GetParent(hwndTV, hTVItem))
|
|
{
|
|
if (!TreeView_GetNextSibling(hwndTV, hTVNewItem) &&
|
|
!TreeView_GetPrevSibling(hwndTV, hTVNewItem))
|
|
|
|
{
|
|
if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVNewItem)) &&
|
|
(TreeView_GetNextSibling(hwndTV, hTVLangItem) ||
|
|
TreeView_GetPrevSibling(hwndTV, hTVLangItem)))
|
|
{
|
|
hTVNewItem = TreeView_GetParent(hwndTV, hTVNewItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pTVItemNode->hklSub)
|
|
{
|
|
HTREEITEM hItem;
|
|
HTREEITEM hTVKbdGrpItem;
|
|
LPTVITEMNODE pTVTempItem;
|
|
UINT uSubhklItems = 0;
|
|
BOOL bFoundOther = FALSE;
|
|
|
|
if (hTVKbdGrpItem = TreeView_GetParent(hwndTV, hTVItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hTVKbdGrpItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
tvItem.hItem = hItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVTempItem = (LPTVITEMNODE) tvItem.lParam;
|
|
}
|
|
else
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
if (pTVItemNode->hklSub != pTVTempItem->hklSub)
|
|
{
|
|
bFoundOther = TRUE;
|
|
}
|
|
else
|
|
{
|
|
TCHAR szItemName[MAX_PATH];
|
|
|
|
GetAtomName(pTVTempItem->atmTVItemName,
|
|
szItemName,
|
|
ARRAYSIZE(szItemName));
|
|
|
|
if (lstrlen(lpDelItems) < MAX_PATH / 2)
|
|
{
|
|
StringCchCat(lpDelItems, cchDelItems, TEXT("\r\n\t"));
|
|
StringCchCat(lpDelItems, cchDelItems, szItemName);
|
|
}
|
|
else
|
|
{
|
|
StringCchCat(lpDelItems, cchDelItems, TEXT("..."));
|
|
}
|
|
|
|
uSubhklItems++;
|
|
}
|
|
}
|
|
|
|
if (uSubhklItems >= 2)
|
|
*bDelSameSubhkl = TRUE;
|
|
|
|
if (!bFoundOther)
|
|
{
|
|
if (!TreeView_GetNextSibling(hwndTV, hTVKbdGrpItem) &&
|
|
!TreeView_GetPrevSibling(hwndTV, hTVKbdGrpItem))
|
|
{
|
|
if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVKbdGrpItem)) &&
|
|
(TreeView_GetNextSibling(hwndTV, hTVLangItem) ||
|
|
TreeView_GetPrevSibling(hwndTV, hTVLangItem)))
|
|
{
|
|
hTVNewItem = TreeView_GetParent(hwndTV, hTVKbdGrpItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Error:
|
|
return hTVNewItem;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_CommandDelete
|
|
//
|
|
// Removes the currently selected input locale from the list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_CommandDelete(
|
|
HWND hwnd)
|
|
{
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hTVItem;
|
|
LPTVITEMNODE pTVItemNode;
|
|
TCHAR szDelItems[MAX_PATH];
|
|
LPLANGNODE pLangNode = NULL;
|
|
BOOL bDelSameSubhkl = FALSE;
|
|
BOOL bRemovedDefLayout = FALSE;
|
|
DWORD dwNextLangId;
|
|
HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
|
|
|
|
//
|
|
// Get the current selection in the input locale list.
|
|
//
|
|
hTVItem = TreeView_GetSelection(hwndTV);
|
|
|
|
if (!hTVItem)
|
|
return;
|
|
|
|
szDelItems[0] = TEXT('\0');
|
|
|
|
hTVItem = GetNewRemoveItem(hwnd, hTVItem, &bDelSameSubhkl, szDelItems, ARRAYSIZE(szDelItems));
|
|
|
|
if (bDelSameSubhkl)
|
|
{
|
|
TCHAR szTitle[MAX_PATH];
|
|
TCHAR szMsg[MAX_PATH];
|
|
TCHAR szMsg2[MAX_PATH*2];
|
|
|
|
CicLoadString(hInstance, IDS_DELETE_CONFIRMTITLE, szTitle, ARRAYSIZE(szTitle));
|
|
CicLoadString(hInstance, IDS_DELETE_TIP, szMsg, ARRAYSIZE(szMsg));
|
|
StringCchPrintf(szMsg2, ARRAYSIZE(szMsg2), szMsg, szDelItems);
|
|
|
|
if (MessageBox(hwnd, szMsg2, szTitle, MB_YESNO|MB_ICONQUESTION ) == IDNO)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVItem;
|
|
|
|
if (TreeView_GetItem(hwndTV, &tvItem))
|
|
{
|
|
//
|
|
// Get the pointer to the lang node from the list box
|
|
// item data.
|
|
//
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (!pTVItemNode)
|
|
return;
|
|
|
|
if ((pTVItemNode->uInputType & TV_ITEM_TYPE_LANG) ||
|
|
(pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP))
|
|
{
|
|
if (RemoveTVSubItems(hwnd, hTVItem, pTVItemNode))
|
|
goto ItemChanged;
|
|
|
|
return;
|
|
}
|
|
|
|
if (pTVItemNode->uInputType & INPUT_TYPE_KBD)
|
|
{
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure we're not removing the only entry in the list.
|
|
//
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
|
|
if (pTVItemNode->uInputType & INPUT_TYPE_TIP)
|
|
{
|
|
g_lpTips[pTVItemNode->iIdxTips].bEnabled = FALSE;
|
|
g_iEnabledTips--;
|
|
|
|
if (pTVItemNode->uInputType & INPUT_TYPE_KBD)
|
|
g_iEnabledKbdTips--;
|
|
|
|
if (pTVItemNode->uInputType & INPUT_TYPE_SPEECH)
|
|
{
|
|
// mark SPTIP's hack entry
|
|
MarkSptipRemoved(TRUE);
|
|
}
|
|
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
|
|
if ((pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub)
|
|
{
|
|
UINT ctr;
|
|
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if (pTVItemNode->hklSub == g_lpTips[ctr].hklSub &&
|
|
g_lpTips[ctr].bEnabled)
|
|
{
|
|
HTREEITEM hDelItem;
|
|
TCHAR szTipText[MAX_PATH];
|
|
|
|
g_iEnabledTips--;
|
|
g_iEnabledKbdTips--;
|
|
g_lpTips[ctr].bEnabled = FALSE;
|
|
|
|
GetAtomName(g_lpTips[ctr].atmTipText,
|
|
szTipText,
|
|
ARRAYSIZE(szTipText));
|
|
|
|
//
|
|
// Find the installed same keyboard TIP layout to delete it
|
|
// together.
|
|
//
|
|
if (hDelItem = FindTVItem(g_lpTips[ctr].dwLangID,
|
|
szTipText))
|
|
{
|
|
tvItem.hItem = hDelItem;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
RemoveTVItemNode((LPTVITEMNODE)tvItem.lParam);
|
|
TreeView_DeleteItem(g_hwndTV, tvItem.hItem );
|
|
}
|
|
|
|
g_iInputs--;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (pTVItemNode->uInputType & INPUT_TYPE_KBD && pLangNode)
|
|
{
|
|
//
|
|
// Check Thai layout.
|
|
//
|
|
if (g_dwPrimLangID == LANG_THAI)
|
|
{
|
|
if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
|
|
g_iThaiLayout--;
|
|
}
|
|
|
|
if (pLangNode->wStatus & LANG_DEFAULT)
|
|
{
|
|
bRemovedDefLayout = TRUE;
|
|
dwNextLangId = pTVItemNode->dwLangID;
|
|
}
|
|
|
|
//
|
|
// Set the input locale to be not active and show that its state
|
|
// has changed. Also, delete the string from the input locale list
|
|
// in the property sheet.
|
|
//
|
|
// Decrement the number of nodes for this input locale.
|
|
//
|
|
pLangNode->wStatus &= ~(LANG_ACTIVE|LANG_DEFAULT);
|
|
pLangNode->wStatus |= LANG_CHANGED;
|
|
|
|
g_lpLang[pLangNode->iLang].iNumCount--;
|
|
|
|
//
|
|
// If it wasn't originally active, then remove it from the list.
|
|
// There's nothing more to do with this node.
|
|
//
|
|
if (!(pLangNode->wStatus & LANG_ORIGACTIVE))
|
|
{
|
|
Locale_RemoveFromLinkedList(pLangNode);
|
|
}
|
|
}
|
|
|
|
g_iInputs--;
|
|
RemoveTVItemNode(pTVItemNode);
|
|
TreeView_DeleteItem(hwndTV, hTVItem);
|
|
|
|
//
|
|
// Set the next available default layout
|
|
//
|
|
if (bRemovedDefLayout)
|
|
{
|
|
int idxSel = -1;
|
|
TCHAR szNextDefTip[MAX_PATH];
|
|
TCHAR szDefLayout[MAX_PATH * 2];
|
|
LPTVITEMNODE pTVLangItemNode = NULL;
|
|
HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT);
|
|
|
|
SetNextDefaultLayout(dwNextLangId,
|
|
TRUE,
|
|
szNextDefTip,
|
|
ARRAYSIZE(szNextDefTip));
|
|
|
|
if (tvItem.hItem = FindTVLangItem(dwNextLangId, NULL))
|
|
{
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
|
|
if (pTVLangItemNode->atmDefTipName)
|
|
DeleteAtom(pTVLangItemNode->atmDefTipName);
|
|
pTVLangItemNode->atmDefTipName = AddAtom(szNextDefTip);
|
|
|
|
GetAtomName(pTVLangItemNode->atmTVItemName,
|
|
szDefLayout,
|
|
MAX_PATH);
|
|
|
|
StringCchCat(szDefLayout, ARRAYSIZE(szDefLayout), TEXT(" - "));
|
|
StringCchCat(szDefLayout, ARRAYSIZE(szDefLayout), szNextDefTip);
|
|
}
|
|
}
|
|
|
|
idxSel = ComboBox_FindString(hwndDefList, 0, szDefLayout);
|
|
|
|
if (idxSel == CB_ERR)
|
|
idxSel = 0;
|
|
|
|
ComboBox_SetCurSel(hwndDefList, idxSel);
|
|
}
|
|
|
|
//
|
|
// Find keyboard group dangling node that doesn't has child keyboard
|
|
// layout item.
|
|
//
|
|
hTVItem = TreeView_GetSelection(hwndTV);
|
|
|
|
if (!hTVItem)
|
|
return;
|
|
|
|
tvItem.hItem = hTVItem;
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
if ((pTVItemNode = (LPTVITEMNODE) tvItem.lParam))
|
|
{
|
|
if ((pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
|
|
(pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP))
|
|
{
|
|
if (TreeView_GetChild(hwndTV, hTVItem) == NULL)
|
|
{
|
|
//
|
|
// Delete keyboard group dangling node
|
|
//
|
|
RemoveTVItemNode(pTVItemNode);
|
|
TreeView_DeleteItem(hwndTV, hTVItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ItemChanged:
|
|
//
|
|
// Only 1 active tip, so disable the secondary controls.
|
|
//
|
|
Locale_SetSecondaryControls(hwnd);
|
|
|
|
//
|
|
// Update the default locale switch hotkey.
|
|
//
|
|
Locale_SetDefaultHotKey(hwnd, FALSE);
|
|
|
|
//
|
|
// Move the focus to the Add button if the Remove button
|
|
// is now disabled (so that we don't lose input focus)
|
|
//
|
|
if (!IsWindowEnabled(GetDlgItem(hwnd, IDC_KBDL_DELETE)))
|
|
{
|
|
SetFocus(GetDlgItem(hwnd, IDC_KBDL_ADD));
|
|
}
|
|
|
|
//
|
|
// Enable the Apply button.
|
|
//
|
|
PropSheet_Changed(GetParent(hwnd), hwnd);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_CommandHotKeySetting
|
|
//
|
|
// Invokes the Change HotKey dialog.
|
|
//
|
|
// Returns 1 if a dialog box was invoked and the dialog returned IDOK.
|
|
// Otherwise, it returns 0.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_CommandHotKeySetting(
|
|
HWND hwnd)
|
|
{
|
|
int rc = 0;
|
|
INITINFO InitInfo;
|
|
|
|
InitInfo.hwndMain = hwnd;
|
|
|
|
if (g_OSNT5)
|
|
{
|
|
rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_HOTKEY),
|
|
MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_HOTKEY),
|
|
hwnd,
|
|
KbdLocaleHotKeyDlg,
|
|
(LPARAM)(&InitInfo));
|
|
}
|
|
else
|
|
{
|
|
rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
|
|
MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
|
|
hwnd,
|
|
KbdLocaleSimpleHotkey,
|
|
(LPARAM)&InitInfo);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_CommandToolBarSetting
|
|
//
|
|
// Invokes the ToolBar setting dialog.
|
|
//
|
|
// Returns 1 if a dialog box was invoked and the dialog returned IDOK.
|
|
// Otherwise, it returns 0.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_CommandToolBarSetting(
|
|
HWND hwnd)
|
|
{
|
|
int rc = 0;
|
|
|
|
if ((rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_TOOLBAR_SETTING),
|
|
MAKEINTRESOURCE(DLG_TOOLBAR_SETTING),
|
|
hwnd,
|
|
ToolBarSettingDlg,
|
|
(LPARAM)NULL)) == IDOK)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_AddLanguage
|
|
//
|
|
// Adds the new input locale to the list in the property page.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_AddLanguage(
|
|
HWND hwndMain,
|
|
LPLANGNODE pLangNode,
|
|
int iKbdTip,
|
|
int iPen,
|
|
int iSpeech,
|
|
int iExternal,
|
|
int idxLang)
|
|
{
|
|
HWND hwndLang;
|
|
UINT iCount, ctr;
|
|
BOOL bSameHKLTip = FALSE;
|
|
|
|
TCHAR szLangText[DESC_MAX];
|
|
TCHAR szLayoutName[DESC_MAX];
|
|
LPINPUTLANG pInpLang;
|
|
LPTVITEMNODE pTVItemNode = NULL;
|
|
HTREEITEM hTVItem;
|
|
|
|
if (pLangNode && iKbdTip == -1)
|
|
{
|
|
//
|
|
// See if the user has Admin privileges. If not, then don't allow
|
|
// them to install any NEW layouts.
|
|
//
|
|
if ((!g_bAdmin_Privileges) &&
|
|
(!g_lpLayout[pLangNode->iLayout].bInstalled))
|
|
{
|
|
//
|
|
// The layout is not currently installed, so don't allow it
|
|
// to be added.
|
|
//
|
|
Locale_ErrorMsg(hwndMain, IDS_KBD_LAYOUT_FAILED, NULL);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Set the language to active.
|
|
// Also, set the status to changed so that the layout will be added.
|
|
//
|
|
pLangNode->wStatus |= (LANG_CHANGED | LANG_ACTIVE);
|
|
|
|
//
|
|
// Get language name and add it to treeview
|
|
//
|
|
pInpLang = &g_lpLang[pLangNode->iLang];
|
|
GetAtomName(pInpLang->atmLanguageName, szLangText, ARRAYSIZE(szLangText));
|
|
|
|
if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
|
|
return FALSE;
|
|
|
|
pTVItemNode->lParam = (LPARAM)pLangNode;
|
|
AddTreeViewItems(TV_ITEM_TYPE_LANG,
|
|
szLangText, NULL, NULL, &pTVItemNode);
|
|
|
|
|
|
//
|
|
// Get keyboard layout name and add it to treeview
|
|
//
|
|
GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
|
|
szLayoutName,
|
|
ARRAYSIZE(szLayoutName));
|
|
|
|
//
|
|
// Adding the default layout name for each language
|
|
//
|
|
if (pTVItemNode && !pTVItemNode->atmDefTipName)
|
|
pTVItemNode->atmDefTipName = AddAtom(szLayoutName);
|
|
|
|
if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
|
|
return FALSE;
|
|
|
|
pTVItemNode->lParam = (LPARAM)pLangNode;
|
|
hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
|
|
szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode);
|
|
|
|
if (hTVItem)
|
|
TreeView_SelectItem(g_hwndTV, hTVItem);
|
|
|
|
//
|
|
// Check Thai layout.
|
|
//
|
|
if (g_dwPrimLangID == LANG_THAI && hTVItem)
|
|
{
|
|
if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
|
|
g_iThaiLayout++;
|
|
}
|
|
|
|
g_dwChanges |= CHANGE_NEWKBDLAYOUT;
|
|
}
|
|
|
|
//
|
|
// Get kbd tip name and add it to treeview
|
|
//
|
|
if ((iKbdTip != CB_ERR) && !(g_lpTips[iKbdTip].bEnabled))
|
|
{
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hTVLangItem;
|
|
|
|
if (g_lpTips[iKbdTip].hklSub)
|
|
{
|
|
//
|
|
// Looking for the same substitute HKL
|
|
//
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if (ctr == iKbdTip)
|
|
continue;
|
|
|
|
if (g_lpTips[ctr].hklSub == g_lpTips[iKbdTip].hklSub)
|
|
{
|
|
bSameHKLTip = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get TIP name description
|
|
//
|
|
GetAtomName(g_lpTips[iKbdTip].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName));
|
|
|
|
hTVLangItem = FindTVLangItem(g_lpTips[iKbdTip].dwLangID, NULL);
|
|
|
|
if (hTVLangItem)
|
|
{
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVLangItem;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get language name and add it to treeview
|
|
//
|
|
if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iKbdTip].dwLangID)))
|
|
return FALSE;
|
|
|
|
GetLanguageName(MAKELCID(g_lpTips[iKbdTip].dwLangID, SORT_DEFAULT),
|
|
szLangText,
|
|
ARRAYSIZE(szLangText));
|
|
|
|
AddTreeViewItems(TV_ITEM_TYPE_LANG,
|
|
szLangText, NULL, NULL, &pTVItemNode);
|
|
}
|
|
|
|
if (pTVItemNode && g_lpTips[iKbdTip].hklSub)
|
|
{
|
|
//
|
|
// Set the index of keyboard Tip.
|
|
//
|
|
pTVItemNode->iIdxTips = iKbdTip;
|
|
|
|
if (!pTVItemNode->atmDefTipName)
|
|
pTVItemNode->atmDefTipName = AddAtom(szLayoutName);
|
|
|
|
}
|
|
|
|
//
|
|
// Create TIP layout
|
|
//
|
|
if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iKbdTip].dwLangID)))
|
|
return FALSE;
|
|
|
|
if (pTVItemNode && g_lpTips[iKbdTip].hklSub)
|
|
{
|
|
//
|
|
// Insert a new language node.
|
|
//
|
|
pLangNode = Locale_AddToLinkedList(idxLang, 0);
|
|
|
|
if (pLangNode)
|
|
{
|
|
pLangNode->iLayout = (UINT) g_lpTips[iKbdTip].iLayout;
|
|
pLangNode->wStatus |= (LANG_CHANGED | LANG_ACTIVE);
|
|
pTVItemNode->lParam = (LPARAM)pLangNode;
|
|
}
|
|
}
|
|
|
|
pTVItemNode->iIdxTips = iKbdTip;
|
|
pTVItemNode->clsid = g_lpTips[iKbdTip].clsid;
|
|
pTVItemNode->guidProfile = g_lpTips[iKbdTip].guidProfile;
|
|
pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_KBD;
|
|
pTVItemNode->hklSub = g_lpTips[iKbdTip].hklSub;
|
|
|
|
//
|
|
// Get language name from LangID.
|
|
//
|
|
GetLanguageName(MAKELCID(g_lpTips[iKbdTip].dwLangID, SORT_DEFAULT),
|
|
szLangText,
|
|
ARRAYSIZE(szLangText));
|
|
|
|
hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
|
|
szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode);
|
|
if (hTVItem)
|
|
{
|
|
TreeView_SelectItem(g_hwndTV, hTVItem);
|
|
g_lpTips[iKbdTip].bEnabled = TRUE;
|
|
g_iEnabledTips++;
|
|
g_iEnabledKbdTips++;
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
}
|
|
|
|
if (bSameHKLTip)
|
|
{
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if (!(g_lpTips[ctr].bEnabled) &&
|
|
g_lpTips[ctr].hklSub == g_lpTips[iKbdTip].hklSub)
|
|
{
|
|
//
|
|
// Create TIP layout
|
|
//
|
|
if (!(pTVItemNode = CreateTVItemNode(g_lpTips[ctr].dwLangID)))
|
|
return FALSE;
|
|
|
|
pTVItemNode->iIdxTips = ctr;
|
|
pTVItemNode->clsid = g_lpTips[ctr].clsid;
|
|
pTVItemNode->guidProfile = g_lpTips[ctr].guidProfile;
|
|
pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_KBD;
|
|
pTVItemNode->hklSub = g_lpTips[ctr].hklSub;
|
|
|
|
if (pLangNode)
|
|
pTVItemNode->lParam = (LPARAM)pLangNode;
|
|
|
|
//
|
|
// Get language name from LangID and layout name.
|
|
//
|
|
GetLanguageName(MAKELCID(g_lpTips[ctr].dwLangID, SORT_DEFAULT),
|
|
szLangText,
|
|
ARRAYSIZE(szLangText));
|
|
GetAtomName(g_lpTips[ctr].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName));
|
|
|
|
hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
|
|
szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode);
|
|
if (hTVItem)
|
|
{
|
|
TreeView_SelectItem(g_hwndTV, hTVItem);
|
|
g_lpTips[ctr].bEnabled = TRUE;
|
|
g_iEnabledTips++;
|
|
g_iEnabledKbdTips++;
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get pen tip name and add it to treeview
|
|
//
|
|
if ((iPen != CB_ERR) && !(g_lpTips[iPen].bEnabled))
|
|
{
|
|
GetAtomName(g_lpTips[iPen].atmTipText,
|
|
szLayoutName,
|
|
ARRAYSIZE(szLayoutName));
|
|
|
|
if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iPen].dwLangID)))
|
|
return FALSE;
|
|
|
|
pTVItemNode->iIdxTips = iPen;
|
|
pTVItemNode->clsid = g_lpTips[iPen].clsid;
|
|
pTVItemNode->guidProfile = g_lpTips[iPen].guidProfile;
|
|
pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_PEN;
|
|
|
|
//
|
|
// Get language name from LangID.
|
|
//
|
|
GetLanguageName(MAKELCID(g_lpTips[iPen].dwLangID, SORT_DEFAULT),
|
|
szLangText,
|
|
ARRAYSIZE(szLangText));
|
|
|
|
hTVItem = AddTreeViewItems(TV_ITEM_TYPE_PEN,
|
|
szLangText, szInputTypePen, szLayoutName, &pTVItemNode);
|
|
if (hTVItem)
|
|
{
|
|
g_lpTips[iPen].bEnabled = TRUE;
|
|
g_iEnabledTips++;
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get speech tip name and add it to treeview
|
|
//
|
|
if ((iSpeech != CB_ERR) && !(g_lpTips[iSpeech].bEnabled))
|
|
{
|
|
GetAtomName(g_lpTips[iSpeech].atmTipText,
|
|
szLayoutName,
|
|
ARRAYSIZE(szLayoutName));
|
|
|
|
if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iSpeech].dwLangID)))
|
|
return FALSE;
|
|
|
|
pTVItemNode->iIdxTips = iSpeech;
|
|
pTVItemNode->clsid = g_lpTips[iSpeech].clsid;
|
|
pTVItemNode->guidProfile = g_lpTips[iSpeech].guidProfile;
|
|
pTVItemNode->bNoAddCat = g_lpTips[iSpeech].bNoAddCat;
|
|
pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_SPEECH;
|
|
|
|
//
|
|
// Get language name from LangID.
|
|
//
|
|
GetLanguageName(MAKELCID(g_lpTips[iSpeech].dwLangID, SORT_DEFAULT),
|
|
szLangText,
|
|
ARRAYSIZE(szLangText));
|
|
|
|
hTVItem = AddTreeViewItems(TV_ITEM_TYPE_SPEECH,
|
|
szLangText, szInputTypeSpeech, szLayoutName, &pTVItemNode);
|
|
|
|
if (hTVItem)
|
|
{
|
|
g_lpTips[iSpeech].bEnabled = TRUE;
|
|
g_iEnabledTips++;
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
MarkSptipRemoved(FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get external tip name and add it to treeview
|
|
//
|
|
if ((iExternal != CB_ERR) && !(g_lpTips[iExternal].bEnabled))
|
|
{
|
|
BSTR bstr = NULL;
|
|
TCHAR szTipTypeName[MAX_PATH];
|
|
ITfCategoryMgr *pCategory = NULL;
|
|
|
|
GetAtomName(g_lpTips[iExternal].atmTipText,
|
|
szLayoutName,
|
|
ARRAYSIZE(szLayoutName));
|
|
|
|
if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iExternal].dwLangID)))
|
|
return FALSE;
|
|
|
|
pTVItemNode->iIdxTips = iExternal;
|
|
pTVItemNode->clsid = g_lpTips[iExternal].clsid;
|
|
pTVItemNode->guidProfile = g_lpTips[iExternal].guidProfile;
|
|
pTVItemNode->bNoAddCat = g_lpTips[iExternal].bNoAddCat;
|
|
pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_EXTERNAL;
|
|
|
|
if (g_lpTips[iExternal].uInputType & INPUT_TYPE_SMARTTAG)
|
|
{
|
|
pTVItemNode->uInputType |= INPUT_TYPE_SMARTTAG;
|
|
}
|
|
|
|
//
|
|
// Get language name from LangID.
|
|
//
|
|
GetLanguageName(MAKELCID(g_lpTips[iExternal].dwLangID, SORT_DEFAULT),
|
|
szLangText,
|
|
ARRAYSIZE(szLangText));
|
|
|
|
if (CoCreateInstance(&CLSID_TF_CategoryMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfCategoryMgr,
|
|
(LPVOID *) &pCategory) != S_OK)
|
|
return FALSE;
|
|
|
|
if (pCategory->lpVtbl->GetGUIDDescription(pCategory,
|
|
&g_lpTips[iExternal].clsid,
|
|
&bstr) == S_OK)
|
|
{
|
|
StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), bstr);
|
|
}
|
|
else
|
|
{
|
|
StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeExternal);
|
|
}
|
|
|
|
if (bstr)
|
|
SysFreeString(bstr);
|
|
|
|
if (pCategory)
|
|
pCategory->lpVtbl->Release(pCategory);
|
|
|
|
hTVItem = AddTreeViewItems(TV_ITEM_TYPE_EXTERNAL,
|
|
szLangText, szInputTypeExternal, szLayoutName, &pTVItemNode);
|
|
|
|
if (hTVItem)
|
|
{
|
|
g_lpTips[iExternal].bEnabled = TRUE;
|
|
g_iEnabledTips++;
|
|
g_dwChanges |= CHANGE_TIPCHANGE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// See the secondary controls according to input layout.
|
|
//
|
|
Locale_SetSecondaryControls(hwndMain);
|
|
|
|
//
|
|
// Add the default language switch hotkey.
|
|
//
|
|
Locale_SetDefaultHotKey(hwndMain, TRUE);
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_SetupKeyboardLayouts
|
|
//
|
|
// Calls setup to get all of the new keyboard layout files.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_SetupKeyboardLayoutsNT4(
|
|
HWND hwnd)
|
|
{
|
|
HINF hKbdInf;
|
|
HSPFILEQ FileQueue;
|
|
PVOID QueueContext;
|
|
UINT i;
|
|
LPLANGNODE pLangNode;
|
|
int count;
|
|
BOOL bInitInf = FALSE;
|
|
TCHAR szSection[MAX_PATH];
|
|
BOOL bRet = TRUE;
|
|
|
|
HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
if (pLangNode == NULL)
|
|
continue;
|
|
}
|
|
else
|
|
continue;
|
|
|
|
|
|
if ((pLangNode->wStatus & LANG_CHANGED) &&
|
|
(pLangNode->wStatus & LANG_ACTIVE))
|
|
{
|
|
if (!bInitInf)
|
|
{
|
|
//
|
|
// Open the Inf file.
|
|
//
|
|
hKbdInf = SetupOpenInfFile(c_szKbdInf, NULL, INF_STYLE_WIN4, NULL);
|
|
if (hKbdInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
if (!SetupOpenAppendInfFile(NULL, hKbdInf, NULL))
|
|
{
|
|
SetupCloseInfFile(hKbdInf);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Create a setup file queue and initialize default setup
|
|
// copy queue callback context.
|
|
//
|
|
FileQueue = SetupOpenFileQueue();
|
|
if ((!FileQueue) || (FileQueue == INVALID_HANDLE_VALUE))
|
|
{
|
|
SetupCloseInfFile(hKbdInf);
|
|
return (FALSE);
|
|
}
|
|
|
|
QueueContext = SetupInitDefaultQueueCallback(hwnd);
|
|
if (!QueueContext)
|
|
{
|
|
SetupCloseFileQueue(FileQueue);
|
|
SetupCloseInfFile(hKbdInf);
|
|
return (FALSE);
|
|
}
|
|
|
|
bInitInf = TRUE;
|
|
}
|
|
|
|
//
|
|
// Get the layout name.
|
|
//
|
|
StringCchPrintf(szSection,
|
|
ARRAYSIZE(szSection),
|
|
TEXT("%s%8.8lx"),
|
|
c_szPrefixCopy,
|
|
g_lpLayout[pLangNode->iLayout].dwID );
|
|
|
|
//
|
|
// Enqueue the keyboard layout files so that they may be
|
|
// copied. This only handles the CopyFiles entries in the
|
|
// inf file.
|
|
//
|
|
if (!SetupInstallFilesFromInfSection( hKbdInf,
|
|
NULL,
|
|
FileQueue,
|
|
szSection,
|
|
NULL,
|
|
SP_COPY_NEWER ))
|
|
{
|
|
//
|
|
// Setup failed to find the keyboard. Make it inactive
|
|
// and remove it from the list.
|
|
//
|
|
// This shouldn't happen - the inf file is messed up.
|
|
//
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_SETUP_FAILED, NULL);
|
|
|
|
pLangNode->wStatus &= ~(LANG_CHANGED | LANG_ACTIVE);
|
|
|
|
if (pTVItemNode)
|
|
{
|
|
RemoveTVItemNode(pTVItemNode);
|
|
}
|
|
TreeView_DeleteItem(hwndTV, tvItem.hItem );
|
|
|
|
if ((g_lpLang[pLangNode->iLang].iNumCount) > 1)
|
|
{
|
|
(g_lpLang[pLangNode->iLang].iNumCount)--;
|
|
Locale_RemoveFromLinkedList(pLangNode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bInitInf)
|
|
{
|
|
DWORD d;
|
|
|
|
//
|
|
// See if we need to install any files.
|
|
//
|
|
// d = 0: User wants new files or some files were missing;
|
|
// Must commit queue.
|
|
//
|
|
// d = 1: User wants to use existing files and queue is empty;
|
|
// Can skip committing queue.
|
|
//
|
|
// d = 2: User wants to use existing files, but del/ren queues
|
|
// not empty. Must commit queue. The copy queue will
|
|
// have been emptied, so only del/ren functions will be
|
|
// performed.
|
|
//
|
|
if ((SetupScanFileQueue( FileQueue,
|
|
SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_INFORM_USER,
|
|
hwnd,
|
|
NULL,
|
|
NULL,
|
|
&d )) && (d != 1))
|
|
{
|
|
//
|
|
// Copy the files in the queue.
|
|
//
|
|
if (!SetupCommitFileQueue( hwnd,
|
|
FileQueue,
|
|
SetupDefaultQueueCallback,
|
|
QueueContext ))
|
|
{
|
|
//
|
|
// This can happen if the user hits Cancel from within
|
|
// the setup dialog.
|
|
//
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_SETUP_FAILED, NULL);
|
|
bRet = FALSE;
|
|
goto Locale_SetupError;
|
|
}
|
|
}
|
|
|
|
Locale_SetupError:
|
|
//
|
|
// Terminate the Queue.
|
|
//
|
|
SetupTermDefaultQueueCallback(QueueContext);
|
|
|
|
//
|
|
// Close the file queue.
|
|
//
|
|
SetupCloseFileQueue(FileQueue);
|
|
|
|
//
|
|
// Close the Inf file.
|
|
//
|
|
SetupCloseInfFile(hKbdInf);
|
|
}
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_ApplyInputs
|
|
//
|
|
// 1. make sure we have all the layout files required.
|
|
// 2. write the information into the registry
|
|
// 3. call Load/UnloadKeyboardLayout where relevant
|
|
//
|
|
// Note that this will trash the previous preload and substitutes sections,
|
|
// based on what is actually loaded. Thus if something was wrong before in
|
|
// the registry, it will be corrected now.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_ApplyInputs(
|
|
HWND hwnd)
|
|
{
|
|
BOOL bSetDef = FALSE;
|
|
UINT iVal, idx, ctr, ctr2, nHotKeys;
|
|
UINT nLocales = 0;
|
|
UINT iPreload = 0;
|
|
LPLANGNODE pLangNode, pTemp;
|
|
LPINPUTLANG pInpLang;
|
|
DWORD dwID;
|
|
TCHAR sz[DESC_MAX]; // temp - build the name of the reg entry
|
|
TCHAR szPreload10[10];
|
|
TCHAR szTemp[MAX_PATH];
|
|
HKEY hkeyLayouts;
|
|
HKEY hkeySubst;
|
|
HKEY hkeyPreload;
|
|
HKEY hKeyImm;
|
|
HKEY hkeyTip;
|
|
HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
|
|
HKL hklDefault = 0;
|
|
HKL hklLoad, hklUnload;
|
|
HKL hklSub[MAX_DUPLICATED_HKL];
|
|
HCURSOR hcurSave;
|
|
HKEY hkeyScanCode;
|
|
DWORD cb;
|
|
TCHAR szShiftL[8];
|
|
TCHAR szShiftR[8];
|
|
BOOL bHasIme = FALSE;
|
|
BOOL bReplaced = FALSE;
|
|
BOOL bCheckedSubhkl;
|
|
BOOL bDisableCtfmon = FALSE;
|
|
BOOL bRebootForCUAS = FALSE;
|
|
BOOL bAlreadyLoadCtfmon = FALSE;
|
|
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
|
|
|
|
//
|
|
// See if the pane is disabled. If so, then there is nothing to
|
|
// Apply.
|
|
//
|
|
if (!IsWindowEnabled(hwndTV))
|
|
{
|
|
return (TRUE);
|
|
}
|
|
|
|
//
|
|
// Put up the hour glass.
|
|
//
|
|
hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
//
|
|
// Make sure there are actually changes since the last save when
|
|
// OK is selected. If the user hits OK without anything to Apply,
|
|
// then we should do nothing.
|
|
//
|
|
if (g_dwChanges == 0 && !g_bAdvChanged)
|
|
{
|
|
pLangNode = NULL;
|
|
for (idx = 0; idx < g_iLangBuff; idx++)
|
|
{
|
|
pLangNode = g_lpLang[idx].pNext;
|
|
while (pLangNode != NULL)
|
|
{
|
|
if (pLangNode->wStatus & (LANG_CHANGED | LANG_DEF_CHANGE))
|
|
{
|
|
break;
|
|
}
|
|
pLangNode = pLangNode->pNext;
|
|
}
|
|
if (pLangNode != NULL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ((idx == g_iLangBuff) && (pLangNode == NULL))
|
|
{
|
|
SetCursor(hcurSave);
|
|
PropSheet_UnChanged(GetParent(hwnd), hwnd);
|
|
return (TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
if (g_OSNT4)
|
|
{
|
|
//
|
|
// Queue up the new layouts and copy the appropriate files to
|
|
// disk using the setup apis. Only do this if the user has
|
|
// Admin privileges.
|
|
//
|
|
if (g_bAdmin_Privileges &&
|
|
!Locale_SetupKeyboardLayoutsNT4(hwnd))
|
|
{
|
|
SetCursor(hcurSave);
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean up the registry.
|
|
//
|
|
|
|
//
|
|
// For FE languages, there is a keyboard which has a different
|
|
// scan code for shift keys - eg. NEC PC9801.
|
|
// We have to keep information about scan codes for shift keys in
|
|
// the registry under the 'toggle' sub key as named values.
|
|
//
|
|
szShiftL[0] = TEXT('\0');
|
|
szShiftR[0] = TEXT('\0');
|
|
if (RegOpenKey( HKEY_CURRENT_USER,
|
|
c_szScanCodeKey,
|
|
&hkeyScanCode ) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(szShiftL);
|
|
RegQueryValueEx( hkeyScanCode,
|
|
c_szValueShiftLeft,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szShiftL,
|
|
&cb );
|
|
|
|
cb = sizeof(szShiftR);
|
|
RegQueryValueEx( hkeyScanCode,
|
|
c_szValueShiftRight,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szShiftR,
|
|
&cb );
|
|
|
|
RegCloseKey(hkeyScanCode);
|
|
}
|
|
|
|
//
|
|
// Delete the HKCU\Keyboard Layout key and all subkeys.
|
|
//
|
|
if (RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
c_szKbdLayouts,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkeyLayouts ) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Delete the HKCU\Keyboard Layout\Preload, Substitutes, and Toggle
|
|
// keys in the registry so that the Keyboard Layout section can be
|
|
// rebuilt.
|
|
//
|
|
RegDeleteKey(hkeyLayouts, c_szPreloadKey);
|
|
RegDeleteKey(hkeyLayouts, c_szSubstKey);
|
|
|
|
RegCloseKey(hkeyLayouts);
|
|
}
|
|
|
|
//
|
|
// Create the HKCU\Keyboard Layout key.
|
|
//
|
|
if (RegCreateKey( HKEY_CURRENT_USER,
|
|
c_szKbdLayouts,
|
|
&hkeyLayouts ) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Create the HKCU\Keyboard Layout\Substitutes key.
|
|
//
|
|
if (RegCreateKey( hkeyLayouts,
|
|
c_szSubstKey,
|
|
&hkeySubst ) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Create the HKCU\Keyboard Layout\Preload key.
|
|
//
|
|
if (RegCreateKey( hkeyLayouts,
|
|
c_szPreloadKey,
|
|
&hkeyPreload ) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Initialize the iPreload variable to 1 to show
|
|
// that the key has been created.
|
|
//
|
|
iPreload = 1;
|
|
}
|
|
else
|
|
{
|
|
RegCloseKey(hkeySubst);
|
|
}
|
|
}
|
|
RegCloseKey(hkeyLayouts);
|
|
}
|
|
if (!iPreload)
|
|
{
|
|
//
|
|
// Registry keys could not be created. Now what?
|
|
//
|
|
MessageBeep(MB_OK);
|
|
SetCursor(hcurSave);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Set all usage counts to zero in the language array.
|
|
//
|
|
for (idx = 0; idx < g_iLangBuff; idx++)
|
|
{
|
|
g_lpLang[idx].iUseCount = 0;
|
|
}
|
|
|
|
//
|
|
// Search through the list to see if any keyboard layouts need to be
|
|
// unloaded from the system.
|
|
//
|
|
for (idx = 0; idx < g_iLangBuff; idx++)
|
|
{
|
|
pLangNode = g_lpLang[idx].pNext;
|
|
while (pLangNode != NULL)
|
|
{
|
|
if ( (pLangNode->wStatus & LANG_ORIGACTIVE) &&
|
|
!(pLangNode->wStatus & LANG_ACTIVE) )
|
|
{
|
|
//
|
|
// Before unloading the hkl, look for the corresponding
|
|
// hotkey and remove it.
|
|
//
|
|
DWORD dwHotKeyID = 0;
|
|
|
|
for (ctr = 0; ctr < DSWITCH_HOTKEY_SIZE; ctr++)
|
|
{
|
|
if (g_aDirectSwitchHotKey[ctr].hkl == pLangNode->hkl)
|
|
{
|
|
//
|
|
// Found an hkl match. Remember the hotkey ID so
|
|
// we can delete the hotkey entry later if the
|
|
// unload of the hkl succeeds.
|
|
//
|
|
dwHotKeyID = g_aDirectSwitchHotKey[ctr].dwHotKeyID;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Started off with this active, deleting it now.
|
|
// Failure is not fatal.
|
|
//
|
|
if (!UnloadKeyboardLayout(pLangNode->hkl))
|
|
{
|
|
LPLANGNODE pLangNodeNext = NULL;
|
|
|
|
pLangNode->wStatus |= LANG_UNLOAD;
|
|
pLangNodeNext = pLangNode->pNext;
|
|
|
|
//
|
|
// Don't need to check TIP case and TIP case also display
|
|
// message and add the substitute hkl into the tree view.
|
|
//
|
|
//if (!IsTipSubstituteHKL((HKL) ((DWORD_PTR)(pLangNode->hkl))))
|
|
{
|
|
Locale_ApplyError( hwnd,
|
|
pLangNode,
|
|
IDS_KBD_UNLOAD_KBD_FAILED,
|
|
MB_OK_OOPS );
|
|
|
|
//
|
|
// Failed to unload layout, put it back in the list,
|
|
// and turn ON the indicator whether it needs it or not.
|
|
//
|
|
if (Locale_AddLanguage(hwnd, pLangNode, -1, -1, -1, -1, 0))
|
|
{
|
|
Locale_SetSecondaryControls(hwnd);
|
|
}
|
|
}
|
|
|
|
pLangNode = pLangNodeNext;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Succeeded, no longer in USER's list.
|
|
//
|
|
// Reset flag, this could be from ApplyInput and we'll
|
|
// fail on the OK if we leave it marked as original
|
|
// active.
|
|
//
|
|
pLangNode->wStatus &= ~(LANG_ORIGACTIVE | LANG_CHANGED);
|
|
|
|
//
|
|
// Remove the hotkey entry for this hkl.
|
|
//
|
|
if (dwHotKeyID)
|
|
{
|
|
ImmSetHotKey(dwHotKeyID, 0, 0, (HKL)NULL);
|
|
}
|
|
|
|
//
|
|
// Remove the link in the language array.
|
|
//
|
|
// NOTE: pLangNode could be null here.
|
|
//
|
|
pTemp = pLangNode->pNext;
|
|
Locale_RemoveFromLinkedList(pLangNode);
|
|
pLangNode = pTemp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pLangNode = pLangNode->pNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// The order in the registry is based on the order in which they
|
|
// appear in the list box.
|
|
//
|
|
// The only exception to this is that the default will be number 1.
|
|
//
|
|
// If no default is found, the last one in the list will be used as
|
|
// the default.
|
|
//
|
|
iVal = 2;
|
|
ctr = 0;
|
|
|
|
//
|
|
// Check the default keyboard layout not to lose the default HKL.
|
|
//
|
|
EnsureDefaultKbdLayout(&nLocales);
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
|
|
{
|
|
bCheckedSubhkl = FALSE;
|
|
//
|
|
// Clear the duplicated HKL buffer index
|
|
//
|
|
ctr2 = 0;
|
|
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
pLangNode = NULL;
|
|
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
|
|
if (!pLangNode && !bCheckedSubhkl &&
|
|
(pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
|
|
pTVItemNode->hklSub)
|
|
{
|
|
bCheckedSubhkl = TRUE;
|
|
|
|
if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
|
|
{
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
LPTVITEMNODE pTVLangItemNode;
|
|
|
|
pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVLangItemNode->lParam;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!pLangNode)
|
|
continue;
|
|
|
|
if (pTVItemNode->hklSub)
|
|
{
|
|
UINT uHklIdx;
|
|
BOOL bFoundSameHkl = FALSE;
|
|
|
|
for (uHklIdx = 0; uHklIdx < ctr2; uHklIdx++)
|
|
{
|
|
if (pTVItemNode->hklSub == hklSub[uHklIdx])
|
|
{
|
|
bFoundSameHkl = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// This substitute HKL is already registered. Skip this HKL.
|
|
//
|
|
if (bFoundSameHkl)
|
|
continue;
|
|
|
|
hklSub[ctr2] = pTVItemNode->hklSub;
|
|
ctr2++;
|
|
}
|
|
|
|
if (pLangNode->wStatus & LANG_UNLOAD)
|
|
{
|
|
pLangNode->wStatus &= ~LANG_UNLOAD;
|
|
pLangNode->wStatus &= ~(LANG_CHANGED | LANG_DEF_CHANGE);
|
|
nLocales--;
|
|
continue;
|
|
}
|
|
|
|
pInpLang = &(g_lpLang[pLangNode->iLang]);
|
|
|
|
//
|
|
// Clear the "set hot key" field, since we will be writing to the
|
|
// registry.
|
|
//
|
|
pLangNode->wStatus &= ~LANG_HOTKEY;
|
|
|
|
//
|
|
// See if it's the default input locale.
|
|
//
|
|
if (!bSetDef && (pLangNode->wStatus & LANG_DEFAULT))
|
|
{
|
|
//
|
|
// Default input locale, so the preload value should be
|
|
// set to 1.
|
|
//
|
|
iPreload = 1;
|
|
bSetDef = TRUE;
|
|
|
|
if (pTVItemNode->hklSub)
|
|
{
|
|
TCHAR szDefTip[MAX_PATH];
|
|
|
|
if (g_lpTips &&
|
|
g_lpTips[pTVItemNode->iIdxTips].hklSub == pTVItemNode->hklSub)
|
|
{
|
|
BOOL bSave = FALSE;
|
|
|
|
SaveLanguageProfileStatus(bSave,
|
|
pTVItemNode->iIdxTips,
|
|
pTVItemNode->hklSub);
|
|
}
|
|
}
|
|
}
|
|
else if (ctr == (nLocales - 1))
|
|
{
|
|
//
|
|
// We're on the last one. Make sure there was a default.
|
|
//
|
|
iPreload = (iVal <= nLocales) ? iVal : 1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set the preload value to the next value.
|
|
//
|
|
iPreload = iVal;
|
|
iVal++;
|
|
}
|
|
|
|
ctr++;
|
|
|
|
//
|
|
// Store the preload value as a string so that it can be written
|
|
// into the registry (as a value name).
|
|
//
|
|
StringCchPrintf(sz, ARRAYSIZE(sz), TEXT("%d"), iPreload);
|
|
|
|
//
|
|
// Store the locale id as a string so that it can be written
|
|
// into the registry (as a value).
|
|
//
|
|
if ((HIWORD(g_lpLayout[pLangNode->iLayout].dwID) & 0xf000) == 0xe000)
|
|
{
|
|
pLangNode->wStatus |= LANG_IME;
|
|
StringCchPrintf(szPreload10,
|
|
ARRAYSIZE(szPreload10),
|
|
TEXT("%8.8lx"),
|
|
g_lpLayout[pLangNode->iLayout].dwID );
|
|
bHasIme = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pLangNode->wStatus &= ~LANG_IME;
|
|
dwID = pInpLang->dwID;
|
|
idx = pInpLang->iUseCount;
|
|
if ((idx == 0) || (idx > 0xfff))
|
|
{
|
|
idx = 0;
|
|
}
|
|
else
|
|
{
|
|
dwID |= ((DWORD)(0xd000 | ((WORD)(idx - 1))) << 16);
|
|
}
|
|
StringCchPrintf(szPreload10, ARRAYSIZE(szPreload10), TEXT("%08.8x"), dwID);
|
|
(pInpLang->iUseCount)++;
|
|
}
|
|
|
|
//
|
|
// Set the new entry in the registry. It is of the form:
|
|
//
|
|
// HKCU\Keyboard Layout
|
|
// Preload: 1 = <locale id>
|
|
// 2 = <locale id>
|
|
// etc...
|
|
//
|
|
RegSetValueEx( hkeyPreload,
|
|
sz,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szPreload10,
|
|
(DWORD)(lstrlen(szPreload10) + 1) * sizeof(TCHAR) );
|
|
|
|
//
|
|
// See if we need to add a substitute for this input locale.
|
|
//
|
|
if (((pInpLang->dwID != g_lpLayout[pLangNode->iLayout].dwID) || idx) &&
|
|
(!(pLangNode->wStatus & LANG_IME)))
|
|
{
|
|
//
|
|
// Get the layout id as a string so that it can be written
|
|
// into the registry (as a value).
|
|
//
|
|
StringCchPrintf(szTemp,
|
|
ARRAYSIZE(szTemp),
|
|
TEXT("%8.8lx"),
|
|
g_lpLayout[pLangNode->iLayout].dwID );
|
|
|
|
//
|
|
// Set the new entry in the registry. It is of the form:
|
|
//
|
|
// HKCU\Keyboard Layout
|
|
// Substitutes: <locale id> = <layout id>
|
|
// <locale id> = <layout id>
|
|
// etc...
|
|
//
|
|
RegSetValueEx( hkeySubst,
|
|
szPreload10,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szTemp,
|
|
(DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
|
|
}
|
|
|
|
//
|
|
// Make sure all of the changes are written to disk.
|
|
//
|
|
RegFlushKey(hkeySubst);
|
|
RegFlushKey(hkeyPreload);
|
|
RegFlushKey(HKEY_CURRENT_USER);
|
|
|
|
//
|
|
// See if the keyboard layout needs to be loaded.
|
|
//
|
|
if (pLangNode->wStatus & (LANG_CHANGED | LANG_DEF_CHANGE))
|
|
{
|
|
//
|
|
// Load the keyboard layout into the system.
|
|
//
|
|
if (pLangNode->hklUnload)
|
|
{
|
|
hklLoad = LoadKeyboardLayoutEx( pLangNode->hklUnload,
|
|
szPreload10,
|
|
KLF_SUBSTITUTE_OK |
|
|
KLF_NOTELLSHELL |
|
|
g_dwAttributes );
|
|
if (hklLoad != pLangNode->hklUnload)
|
|
{
|
|
bReplaced = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hklLoad = LoadKeyboardLayout( szPreload10,
|
|
KLF_SUBSTITUTE_OK |
|
|
KLF_NOTELLSHELL |
|
|
g_dwAttributes );
|
|
}
|
|
|
|
if (hklLoad)
|
|
{
|
|
pLangNode->wStatus &= ~(LANG_CHANGED | LANG_DEF_CHANGE);
|
|
pLangNode->wStatus |= (LANG_ACTIVE | LANG_ORIGACTIVE);
|
|
|
|
if (pLangNode->wStatus & LANG_DEFAULT)
|
|
{
|
|
hklDefault = hklLoad;
|
|
}
|
|
|
|
pLangNode->hkl = hklLoad;
|
|
pLangNode->hklUnload = hklLoad;
|
|
}
|
|
else
|
|
{
|
|
Locale_ApplyError( hwnd,
|
|
pLangNode,
|
|
IDS_KBD_LOAD_KBD_FAILED,
|
|
MB_OK_OOPS );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close the handles to the registry keys.
|
|
//
|
|
RegCloseKey(hkeySubst);
|
|
RegCloseKey(hkeyPreload);
|
|
|
|
//
|
|
// If TIP setting is changed, save the enable/disable status into
|
|
// registry TIP section.
|
|
//
|
|
if ((g_dwChanges & CHANGE_TIPCHANGE) && g_iTipsBuff)
|
|
{
|
|
int iIdxDefTip = -1;
|
|
BOOL bSave = TRUE;
|
|
|
|
SaveLanguageProfileStatus(bSave, iIdxDefTip, NULL);
|
|
|
|
g_dwChanges &= ~CHANGE_TIPCHANGE;
|
|
}
|
|
|
|
//
|
|
// Make sure the default is set properly. The layout id for the
|
|
// current default input locale may have been changed.
|
|
//
|
|
// NOTE: This should be done before the Unloads occur in case one
|
|
// of the layouts to unload is the old default layout.
|
|
//
|
|
if (hklDefault != 0)
|
|
{
|
|
if (!SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
|
|
0,
|
|
(LPVOID)((LPDWORD)&hklDefault),
|
|
0 ))
|
|
{
|
|
//
|
|
// Failure is not fatal. The old default language will
|
|
// still work.
|
|
//
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_NO_DEF_LANG2, NULL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Try to make everything switch to the new default input locale:
|
|
// if we are in setup OR
|
|
// if it is the only one (but not if we just replaced the layout
|
|
// within the Input Locale without changing the input locale)
|
|
//
|
|
if (g_bSetupCase || ((nLocales == 1) && !bReplaced))
|
|
{
|
|
DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
|
|
BroadcastSystemMessage( BSF_POSTMESSAGE,
|
|
&dwRecipients,
|
|
WM_INPUTLANGCHANGEREQUEST,
|
|
1, // IS compatible with system font
|
|
(LPARAM)hklDefault );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Apply the advanced tab changes.
|
|
//
|
|
if (g_hwndAdvanced != NULL && g_bAdvChanged)
|
|
{
|
|
DWORD dwDisableCtfmon;
|
|
BOOL bPrevDisableCUAS;
|
|
BOOL bDisabledCUAS;
|
|
|
|
//
|
|
// Get the previous CUAS status from the registry.
|
|
//
|
|
bPrevDisableCUAS = IsDisableCUAS();
|
|
|
|
//
|
|
// Save enable/disable CUAS info into the regitry.
|
|
//
|
|
if (IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CUAS_ENABLE))
|
|
{
|
|
//
|
|
// Enalbe Cicero Unaware Application Support.
|
|
//
|
|
SetDisableCUAS(FALSE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable Cicero Unaware Application Support.
|
|
//
|
|
SetDisableCUAS(TRUE);
|
|
}
|
|
|
|
bDisabledCUAS = IsDisableCUAS();
|
|
|
|
if (!g_bSetupCase)
|
|
{
|
|
TCHAR szTitle[MAX_PATH];
|
|
TCHAR szMsg[MAX_PATH];
|
|
BOOL bPrevCtfmon;
|
|
|
|
if (bPrevDisableCUAS != bDisabledCUAS)
|
|
{
|
|
//
|
|
// CUAS option is changed, so need to require the system reboot.
|
|
//
|
|
bRebootForCUAS = TRUE;
|
|
}
|
|
|
|
//
|
|
// Find language tool bar module(CTFMON.EXE)
|
|
//
|
|
if (FindWindow(c_szCTFMonClass, NULL) == NULL)
|
|
bPrevCtfmon = FALSE;
|
|
else
|
|
bPrevCtfmon = TRUE;
|
|
|
|
if (!bPrevCtfmon &&
|
|
!bRebootForCUAS &&
|
|
!IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CTFMON_DISABLE))
|
|
{
|
|
// Turn on CTFMON.EXE
|
|
CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle));
|
|
CicLoadString(hInstance, IDS_ENABLE_CICERO, szMsg, ARRAYSIZE(szMsg));
|
|
|
|
//
|
|
// Notice - Need to restart apps that are already running.
|
|
//
|
|
MessageBox(hwnd, szMsg, szTitle, MB_OK);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save enable/disable CTFMON info into the regitry.
|
|
//
|
|
if (IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CTFMON_DISABLE))
|
|
{
|
|
//
|
|
// Set the ctfmon disable flag
|
|
//
|
|
dwDisableCtfmon = 1;
|
|
SetDisalbeCtfmon(dwDisableCtfmon);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set the ctfmon enable flag
|
|
//
|
|
dwDisableCtfmon = 0;
|
|
SetDisalbeCtfmon(dwDisableCtfmon);
|
|
|
|
//
|
|
// Run ctfmon.exe immediately
|
|
//
|
|
if (!g_bSetupCase &&
|
|
IsEnabledTipOrMultiLayouts() &&
|
|
IsInteractiveUserLogon())
|
|
{
|
|
RunCtfmonProcess();
|
|
bAlreadyLoadCtfmon = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Load the language tool bar if there is any enabled tip, otherwise
|
|
// disable tool bar
|
|
//
|
|
bDisableCtfmon = IsDisableCtfmon();
|
|
|
|
if (!bDisableCtfmon && g_iInputs >= 2)
|
|
{
|
|
//
|
|
// Load language bar or language icon(ctfmon.exe)
|
|
//
|
|
if (!bAlreadyLoadCtfmon && (g_iInputs != g_iOrgInputs))
|
|
LoadCtfmon(TRUE, 0, FALSE);
|
|
|
|
if(!g_bSetupCase)
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_SETTING), TRUE);
|
|
}
|
|
else
|
|
{
|
|
if (bDisableCtfmon || !bHasIme)
|
|
{
|
|
LoadCtfmon(FALSE, 0, FALSE);
|
|
|
|
//
|
|
// Disable language bar setting option button
|
|
//
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_SETTING), FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Reset ctfmon change status.
|
|
//
|
|
g_bAdvChanged = FALSE;
|
|
|
|
if (g_dwChanges & CHANGE_LANGSWITCH)
|
|
{
|
|
Locale_SetLanguageHotkey();
|
|
}
|
|
|
|
//
|
|
// Set the scan code entries in the registry.
|
|
//
|
|
if (RegCreateKey( HKEY_CURRENT_USER,
|
|
c_szScanCodeKey,
|
|
&hkeyScanCode ) == ERROR_SUCCESS)
|
|
{
|
|
if (szShiftL[0])
|
|
{
|
|
RegSetValueEx( hkeyScanCode,
|
|
c_szValueShiftLeft,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szShiftL,
|
|
(DWORD)(lstrlen(szShiftL) + 1) * sizeof(TCHAR) );
|
|
}
|
|
|
|
if (szShiftR[0])
|
|
{
|
|
RegSetValueEx( hkeyScanCode,
|
|
c_szValueShiftRight,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szShiftR,
|
|
(DWORD)(lstrlen(szShiftR) + 1) * sizeof(TCHAR) );
|
|
}
|
|
RegCloseKey(hkeyScanCode);
|
|
}
|
|
|
|
//
|
|
// Call SystemParametersInfo to enable the toggle.
|
|
//
|
|
SystemParametersInfo(SPI_SETLANGTOGGLE, 0, NULL, 0);
|
|
|
|
//
|
|
// Turn off the hour glass.
|
|
//
|
|
SetCursor(hcurSave);
|
|
|
|
if ((g_dwChanges & CHANGE_DIRECTSWITCH) || bHasIme || bRebootForCUAS)
|
|
{
|
|
g_dwChanges &= ~CHANGE_DIRECTSWITCH;
|
|
|
|
if (RegOpenKey( HKEY_LOCAL_MACHINE,
|
|
c_szLoadImmPath,
|
|
&hKeyImm ) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwValue = 1;
|
|
|
|
if ((g_dwChanges & CHANGE_DIRECTSWITCH) || bHasIme)
|
|
{
|
|
RegSetValueEx( hKeyImm,
|
|
TEXT("LoadIMM"),
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwValue,
|
|
sizeof(DWORD) );
|
|
}
|
|
|
|
RegCloseKey(hKeyImm);
|
|
|
|
if (g_bAdmin_Privileges &&
|
|
((!g_bSetupCase &&
|
|
!GetSystemMetrics(SM_IMMENABLED) &&
|
|
!GetSystemMetrics(SM_DBCSENABLED)) ||
|
|
bRebootForCUAS))
|
|
{
|
|
//
|
|
// Imm was not loaded. Ask user to reboot and let
|
|
// it be loaded.
|
|
//
|
|
TCHAR szReboot[DESC_MAX];
|
|
TCHAR szTitle[DESC_MAX];
|
|
|
|
CicLoadString(hInstance, IDS_REBOOT_STRING, szReboot, ARRAYSIZE(szReboot));
|
|
CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle));
|
|
if (MessageBox( hwnd,
|
|
szReboot,
|
|
szTitle,
|
|
MB_YESNO | MB_ICONQUESTION ) == IDYES)
|
|
{
|
|
Region_RebootTheSystem();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update the originial input layouts
|
|
//
|
|
g_iOrgInputs = g_iInputs;
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
g_dwChanges = 0;
|
|
PropSheet_UnChanged(GetParent(hwnd), hwnd);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// TVSubCVlassProc
|
|
//
|
|
// Ignore TreeView item expand or contractibility
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LRESULT WINAPI TVSubClassProc(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case (WM_LBUTTONDBLCLK):
|
|
{
|
|
return TRUE;
|
|
}
|
|
case (WM_KEYDOWN):
|
|
{
|
|
if (wParam == VK_LEFT || wParam == VK_RIGHT)
|
|
return TRUE;
|
|
}
|
|
default:
|
|
{
|
|
return CallWindowProc(g_lpfnTVWndProc, hwnd, message, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
return CallWindowProc(g_lpfnTVWndProc, hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InputLocaleDlgProc
|
|
//
|
|
// This is the dialog proc for the Input Locales property sheet.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK InputLocaleDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
HWND hwndTV = GetDlgItem(hDlg, IDC_INPUT_LIST);
|
|
|
|
switch (message)
|
|
{
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
Locale_KillPaneDialog(hDlg);
|
|
|
|
if (g_lpfnTVWndProc)
|
|
SetWindowLongPtr(hwndTV, GWLP_WNDPROC, (LONG_PTR)g_lpfnTVWndProc);
|
|
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aInputHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aInputHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
HWND hwndDefList = GetDlgItem(hDlg, IDC_LOCALE_DEFAULT);
|
|
|
|
g_hDlg = hDlg;
|
|
g_hwndTV = hwndTV;
|
|
|
|
InitPropSheet(hDlg, (LPPROPSHEETPAGE)lParam);
|
|
|
|
//
|
|
// Create image icons for Language tree view control
|
|
//
|
|
CreateImageIcons();
|
|
|
|
//
|
|
// Reset the contents of the default locale combo box.
|
|
//
|
|
ComboBox_ResetContent(hwndDefList);
|
|
|
|
g_hTVRoot = TreeView_GetRoot(hwndTV);
|
|
|
|
//
|
|
// Get all installed input information
|
|
//
|
|
GetInstalledInput(hDlg);
|
|
|
|
//
|
|
// Set subclass for treeview control to ignore treeview item expand
|
|
// or contractibility by mouse or keyboard.
|
|
//
|
|
g_lpfnTVWndProc = (WNDPROC) SetWindowLongPtr(hwndTV, GWLP_WNDPROC, (LONG_PTR) TVSubClassProc);
|
|
|
|
Locale_CommandSetDefault(hDlg);
|
|
|
|
//
|
|
// No longer supporting set default button.
|
|
//
|
|
//if (!g_bSetupCase && !g_bCHSystem)
|
|
{
|
|
HWND hwndDefBtn;
|
|
|
|
hwndDefBtn = GetDlgItem(hDlg, IDC_KBDL_SET_DEFAULT);
|
|
EnableWindow(hwndDefBtn, FALSE);
|
|
ShowWindow(hwndDefBtn, SW_HIDE);
|
|
}
|
|
|
|
if (FindWindow(c_szCTFMonClass, NULL) == NULL || g_bSetupCase)
|
|
{
|
|
//
|
|
// Disable language bar setting option during the setup mode,
|
|
// or turned off ctfmon.
|
|
//
|
|
EnableWindow(GetDlgItem(hDlg, IDC_TB_SETTING), FALSE);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_TB_SETTING), TRUE);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ( WM_NOTIFY ) :
|
|
{
|
|
switch (((NMHDR *)lParam)->code)
|
|
{
|
|
case TVN_SELCHANGED:
|
|
{
|
|
CheckButtons(hDlg);
|
|
break;
|
|
}
|
|
case ( PSN_QUERYCANCEL ) :
|
|
case ( PSN_KILLACTIVE ) :
|
|
case ( PSN_RESET ) :
|
|
break;
|
|
|
|
case ( PSN_APPLY ) :
|
|
{
|
|
Locale_ApplyInputs(hDlg);
|
|
CheckButtons(hDlg);
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDC_KBDL_SET_DEFAULT ) :
|
|
{
|
|
Locale_CommandSetDefaultLayout(hDlg);
|
|
break;
|
|
}
|
|
case ( IDC_KBDL_ADD ) :
|
|
{
|
|
Locale_CommandAdd(hDlg);
|
|
break;
|
|
}
|
|
case ( IDC_KBDL_EDIT ) :
|
|
{
|
|
Locale_CommandEdit(hDlg, NULL);
|
|
break;
|
|
}
|
|
case ( IDC_KBDL_DELETE ) :
|
|
{
|
|
Locale_CommandDelete(hDlg);
|
|
break;
|
|
}
|
|
case ( IDC_LOCALE_DEFAULT ) :
|
|
{
|
|
if (HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
Locale_CommandSetDefault(hDlg);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_HOTKEY_SETTING ) :
|
|
{
|
|
if (g_dwChanges & CHANGE_NEWKBDLAYOUT)
|
|
{
|
|
TCHAR szApplyMsg[MAX_PATH];
|
|
TCHAR szTitle[MAX_PATH];
|
|
|
|
CicLoadString(hInstance, IDS_KBD_APPLY_WARN, szApplyMsg, ARRAYSIZE(szApplyMsg));
|
|
CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle));
|
|
|
|
if (MessageBox(hDlg,
|
|
szApplyMsg,
|
|
szTitle,
|
|
MB_YESNO | MB_ICONQUESTION) == IDYES)
|
|
{
|
|
Locale_ApplyInputs(hDlg);
|
|
}
|
|
g_dwChanges &= ~CHANGE_NEWKBDLAYOUT;
|
|
}
|
|
|
|
Locale_CommandHotKeySetting(hDlg);
|
|
break;
|
|
}
|
|
case ( IDC_TB_SETTING ) :
|
|
{
|
|
Locale_CommandToolBarSetting(hDlg);
|
|
break;
|
|
}
|
|
|
|
case ( IDOK ) :
|
|
{
|
|
if (!Locale_ApplyInputs(hDlg))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// fall thru...
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hDlg, TRUE);
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_GetLayoutList
|
|
//
|
|
// Fills in the given listbox with the appropriate list of layouts.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_GetLayoutList(
|
|
HWND hwndLayout,
|
|
UINT idxLang,
|
|
UINT idxLayout,
|
|
BOOL *pfNoDefLayout)
|
|
{
|
|
UINT ctr;
|
|
UINT idx;
|
|
int idxSel = -1;
|
|
int idxSame = -1;
|
|
int idxOther = -1;
|
|
int idxBase = -1;
|
|
int idxUSA = -1; // last resort default
|
|
TCHAR sz[DESC_MAX];
|
|
LPLANGNODE pTemp;
|
|
DWORD LangID = g_lpLang[idxLang].dwID;
|
|
DWORD BaseLangID = (LOWORD(LangID) & 0xff) | 0x400;
|
|
|
|
//
|
|
// Reset the contents of the combo box.
|
|
//
|
|
ComboBox_ResetContent(hwndLayout);
|
|
|
|
//
|
|
// Search through all of the layouts.
|
|
//
|
|
for (ctr = 0; ctr < g_iLayoutBuff; ctr++)
|
|
{
|
|
//
|
|
// Filter out IME layout if it is not under native locale.
|
|
//
|
|
if (((HIWORD(g_lpLayout[ctr].dwID) & 0xf000) == 0xe000) &&
|
|
(LOWORD(g_lpLayout[ctr].dwID) != LOWORD(LangID)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Make sure this layout isn't already used for this input locale.
|
|
// If it is, then don't display it in the properties dialog.
|
|
//
|
|
if (ctr != idxLayout)
|
|
{
|
|
pTemp = g_lpLang[idxLang].pNext;
|
|
while (pTemp)
|
|
{
|
|
if (pTemp->wStatus & LANG_ACTIVE)
|
|
{
|
|
if (ctr == pTemp->iLayout)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
pTemp = pTemp->pNext;
|
|
}
|
|
if (pTemp && (ctr == pTemp->iLayout))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the layout text. If it doesn't already exist in the
|
|
// combo box, then add it to the list of possible layouts.
|
|
//
|
|
GetAtomName(g_lpLayout[ctr].atmLayoutText, sz, ARRAYSIZE(sz));
|
|
if ((idx = ComboBox_FindStringExact(hwndLayout, 0, sz)) == CB_ERR)
|
|
{
|
|
//
|
|
// Filter out TIP substitute HKL.
|
|
//
|
|
if (IsTipSubstituteHKL(IntToPtr(g_lpLayout[ctr].dwID)))
|
|
{
|
|
AddKbdLayoutOnKbdTip(IntToPtr(g_lpLayout[ctr].dwID), ctr);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Add the layout string and set the item data to be the
|
|
// index into the g_lpLayout array.
|
|
//
|
|
idx = ComboBox_AddString(hwndLayout, sz);
|
|
ComboBox_SetItemData(hwndLayout, idx, MAKELONG(ctr, 0));
|
|
|
|
//
|
|
// See if it's the US layout. If so, save the index.
|
|
//
|
|
if (g_lpLayout[ctr].dwID == US_LOCALE)
|
|
{
|
|
idxUSA = ctr;
|
|
}
|
|
}
|
|
|
|
if (idxLayout == -1)
|
|
{
|
|
//
|
|
// If the caller does not specify a layout, it must be the
|
|
// Add dialog. First we want the default layout. If the
|
|
// default layout is not an option (eg. it's already used),
|
|
// then we want any layout that has the same id as the locale
|
|
// to be the default.
|
|
//
|
|
if (idxSel == -1)
|
|
{
|
|
if (g_lpLayout[ctr].dwID == g_lpLang[idxLang].dwDefaultLayout)
|
|
{
|
|
idxSel = ctr;
|
|
}
|
|
else if (idxSame == -1)
|
|
{
|
|
if ((LOWORD(g_lpLayout[ctr].dwID) == LOWORD(LangID)) &&
|
|
(HIWORD(g_lpLayout[ctr].dwID) == 0))
|
|
{
|
|
idxSame = ctr;
|
|
}
|
|
else if (idxOther == -1)
|
|
{
|
|
if (LOWORD(g_lpLayout[ctr].dwID) == LOWORD(LangID))
|
|
{
|
|
idxOther = ctr;
|
|
}
|
|
else if ((idxBase == -1) &&
|
|
(LOWORD(g_lpLayout[ctr].dwID) == LOWORD(BaseLangID)))
|
|
{
|
|
idxBase = ctr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (ctr == idxLayout)
|
|
{
|
|
//
|
|
// For the properties dialog, we want the one ALREADY associated.
|
|
//
|
|
idxSel = ctr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If it's the Add dialog, do some extra checking for the layout to use.
|
|
//
|
|
if (idxLayout == -1)
|
|
{
|
|
if (idxSel == -1)
|
|
{
|
|
idxSel = (idxSame != -1)
|
|
? idxSame
|
|
: ((idxOther != -1) ? idxOther : idxBase);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If a default layout was not found, then set it to the US layout.
|
|
//
|
|
if (idxSel == -1)
|
|
{
|
|
idxSel = idxUSA;
|
|
*pfNoDefLayout = TRUE;
|
|
}
|
|
|
|
//
|
|
// Set the current selection.
|
|
//
|
|
if (idxSel == -1)
|
|
{
|
|
//
|
|
// Simply set the current selection to be the first entry
|
|
// in the list.
|
|
//
|
|
ComboBox_SetCurSel(hwndLayout, 0);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The combo box is sorted, but we need to know where
|
|
// g_lpLayout[idxSel] was stored. So, get the atom again, and
|
|
// search the list.
|
|
//
|
|
GetAtomName(g_lpLayout[idxSel].atmLayoutText, sz, ARRAYSIZE(sz));
|
|
idx = ComboBox_FindStringExact(hwndLayout, 0, sz);
|
|
ComboBox_SetCurSel(hwndLayout, idx);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_GetTipList
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_GetTipList(
|
|
HWND hwnd,
|
|
UINT uInxLang,
|
|
BOOL bNoDefKbd)
|
|
{
|
|
UINT ctr;
|
|
int idxDefKbd = -1;
|
|
BOOL bPenOn = FALSE;
|
|
BOOL bSpeechOn = FALSE;
|
|
BOOL bExternalOn = FALSE;
|
|
TCHAR szTipName[DESC_MAX];
|
|
TCHAR szNone[DESC_MAX];
|
|
UINT uIdx;
|
|
|
|
|
|
DWORD dwLangID = g_lpLang[uInxLang].dwID;
|
|
HWND hwndKbd = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT);
|
|
HWND hwndPen = GetDlgItem(hwnd, IDC_PEN_TIP);
|
|
HWND hwndPenText = GetDlgItem(hwnd, IDC_PEN_TEXT);
|
|
HWND hwndSpeech = GetDlgItem(hwnd, IDC_SPEECH_TIP);
|
|
HWND hwndSpeechText = GetDlgItem(hwnd, IDC_SPEECH_TEXT);
|
|
HWND hwndExternal = GetDlgItem(hwnd, IDC_EXTERNAL_TIP);
|
|
HWND hwndExternalText = GetDlgItem(hwnd, IDC_EXTERNAL_TEXT);
|
|
|
|
//
|
|
// Reset the contents of the combo box.
|
|
//
|
|
ComboBox_ResetContent(hwndPen);
|
|
ComboBox_ResetContent(hwndSpeech);
|
|
ComboBox_ResetContent(hwndExternal);
|
|
|
|
if (g_iTipsBuff == 0)
|
|
{
|
|
EnableWindow(hwndPen, FALSE);
|
|
EnableWindow(hwndPenText, FALSE);
|
|
EnableWindow(hwndSpeech, FALSE);
|
|
EnableWindow(hwndSpeechText, FALSE);
|
|
EnableWindow(hwndExternal, FALSE);
|
|
EnableWindow(hwndExternalText, FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
for (ctr = 0; ctr < g_iTipsBuff; ctr++)
|
|
{
|
|
if ((dwLangID == g_lpTips[ctr].dwLangID) &&
|
|
(g_lpTips[ctr].uInputType != INPUT_TYPE_KBD))
|
|
{
|
|
//
|
|
// Get the Tips text.
|
|
//
|
|
GetAtomName(g_lpTips[ctr].atmTipText, szTipName, ARRAYSIZE(szTipName));
|
|
|
|
if ((g_lpTips[ctr].uInputType & INPUT_TYPE_PEN) &&
|
|
!(g_lpTips[ctr].bEnabled))
|
|
{
|
|
uIdx = ComboBox_AddString(hwndPen, szTipName);
|
|
ComboBox_SetItemData(hwndPen, uIdx, MAKELONG(ctr, 0));
|
|
bPenOn = TRUE;
|
|
}
|
|
else if ((g_lpTips[ctr].uInputType & INPUT_TYPE_SPEECH) &&
|
|
!(g_lpTips[ctr].bEnabled) &&
|
|
g_lpTips[ctr].fEngineAvailable)
|
|
{
|
|
uIdx = ComboBox_AddString(hwndSpeech, szTipName);
|
|
ComboBox_SetItemData(hwndSpeech, uIdx, MAKELONG(ctr, 0));
|
|
bSpeechOn = TRUE;
|
|
}
|
|
else if ((g_lpTips[ctr].uInputType & INPUT_TYPE_KBD) &&
|
|
!(g_lpTips[ctr].bEnabled))
|
|
{
|
|
uIdx = ComboBox_AddString(hwndKbd, szTipName);
|
|
ComboBox_SetItemData(hwndKbd, uIdx, MAKELONG(ctr, 1));
|
|
idxDefKbd = uIdx;
|
|
}
|
|
else if((g_lpTips[ctr].uInputType & INPUT_TYPE_EXTERNAL) &&
|
|
!(g_lpTips[ctr].bEnabled))
|
|
{
|
|
uIdx = ComboBox_AddString(hwndExternal, szTipName);
|
|
ComboBox_SetItemData(hwndExternal, uIdx, MAKELONG(ctr, 0));
|
|
bExternalOn = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (idxDefKbd != -1)
|
|
{
|
|
ComboBox_SetCurSel(hwndKbd, idxDefKbd);
|
|
}
|
|
|
|
EnableWindow(hwndPen, IsDlgButtonChecked(hwnd, IDC_PEN_TEXT));
|
|
EnableWindow(hwndPenText, bPenOn);
|
|
ComboBox_SetCurSel(hwndPen, 0);
|
|
|
|
EnableWindow(hwndSpeech, IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT));
|
|
EnableWindow(hwndSpeechText, bSpeechOn);
|
|
ComboBox_SetCurSel(hwndSpeech, 0);
|
|
|
|
EnableWindow(hwndExternal, IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT));
|
|
EnableWindow(hwndExternalText, bExternalOn);
|
|
ComboBox_SetCurSel(hwndExternal, 0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_AddDlgInit
|
|
//
|
|
// Processing for a WM_INITDIALOG message for the Add dialog box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_AddDlgInit(
|
|
HWND hwnd,
|
|
LPARAM lParam)
|
|
{
|
|
UINT ctr1;
|
|
UINT idx;
|
|
TCHAR sz[DESC_MAX];
|
|
LPLANGNODE pLangNode;
|
|
int nLocales, idxList, IMELayoutExist = 0;
|
|
UINT ctr2, ListCount, DefaultIdx = 0;
|
|
LRESULT LCSelectData = (LONG)-1;
|
|
BOOL bNoDefLayout = FALSE;
|
|
DWORD dwCurLang = 0;
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hTVItem;
|
|
HWND hwndLang = GetDlgItem(hwnd, IDC_KBDLA_LOCALE);
|
|
|
|
//
|
|
// Get the currently chosen input locale in the parent dialog's
|
|
// treeview list box.
|
|
//
|
|
hTVItem = TreeView_GetSelection(g_hwndTV);
|
|
|
|
if (!hTVItem)
|
|
return FALSE;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hTVItem;
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem))
|
|
{
|
|
if ((LPTVITEMNODE) tvItem.lParam)
|
|
{
|
|
dwCurLang = ((LPTVITEMNODE) tvItem.lParam)->dwLangID;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go through all of the input locales. Display all of them,
|
|
// since we can have multiple layouts per locale.
|
|
//
|
|
// Do NOT go down the links in this case. We don't want to display
|
|
// the language choice multiple times.
|
|
//
|
|
for (ctr1 = 0; ctr1 < g_iLangBuff; ctr1++)
|
|
{
|
|
//
|
|
// If the language does not contain an IME layout, then
|
|
// compare with layout counts without IME.
|
|
//
|
|
for (ctr2 = 0; ctr2 < g_iLayoutBuff; ctr2++)
|
|
{
|
|
if ((LOWORD(g_lpLayout[ctr2].dwID) == LOWORD(g_lpLang[ctr1].dwID)) &&
|
|
((HIWORD(g_lpLayout[ctr2].dwID) & 0xf000) == 0xe000))
|
|
{
|
|
IMELayoutExist = 1;
|
|
break;
|
|
}
|
|
}
|
|
if ((!IMELayoutExist) &&
|
|
(g_lpLang[ctr1].iNumCount == (g_iLayoutBuff - g_iLayoutIME)) &&
|
|
(g_iTipsBuff == 0))
|
|
{
|
|
//
|
|
// No more layouts to be added for this language.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Make sure there are layouts to be added for this
|
|
// input locale.
|
|
//
|
|
if ((g_lpLang[ctr1].iNumCount != g_iLayoutBuff) ||
|
|
(g_iTipsBuff != 0 && IsTipAvailableForAdd(g_lpLang[ctr1].dwID)))
|
|
{
|
|
//
|
|
// Get the language name, add the string to the
|
|
// combo box, and set the index into the g_lpLang
|
|
// array as the item data.
|
|
//
|
|
GetAtomName(g_lpLang[ctr1].atmLanguageName, sz, ARRAYSIZE(sz));
|
|
idx = ComboBox_AddString(hwndLang, sz);
|
|
ComboBox_SetItemData(hwndLang, idx, MAKELONG(ctr1, 0));
|
|
|
|
//
|
|
// Save system default locale.
|
|
//
|
|
if (LCSelectData == -1)
|
|
{
|
|
if (g_lpLang[ctr1].dwID == GetSystemDefaultLCID())
|
|
{
|
|
LCSelectData = MAKELONG(ctr1, 0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save chosen input locale.
|
|
//
|
|
if (dwCurLang && (g_lpLang[ctr1].dwID == dwCurLang))
|
|
{
|
|
LCSelectData = MAKELONG(ctr1, 0);
|
|
dwCurLang = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the current selection to the currently chosen input locale
|
|
// or the default system locale entry.
|
|
//
|
|
if (LCSelectData != -1)
|
|
{
|
|
ListCount = ComboBox_GetCount(hwndLang);
|
|
for (ctr1 = 0; ctr1 < ListCount; ctr1++)
|
|
{
|
|
if (LCSelectData == ComboBox_GetItemData(hwndLang, ctr1))
|
|
{
|
|
DefaultIdx = ctr1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
ComboBox_SetCurSel(hwndLang, DefaultIdx);
|
|
idx = (UINT)ComboBox_GetItemData(hwndLang, DefaultIdx);
|
|
|
|
SetProp(hwnd, szPropHwnd, (HANDLE)((LPINITINFO)lParam)->hwndMain);
|
|
SetProp(hwnd, szPropIdx, (HANDLE)UIntToPtr(idx));
|
|
|
|
//
|
|
// Check available language.
|
|
//
|
|
if (idx == -1)
|
|
{
|
|
//
|
|
// No languages
|
|
//
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_NO_MORE_TO_ADD, NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Display the keyboard layout.
|
|
//
|
|
Locale_GetLayoutList(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), idx, -1, &bNoDefLayout);
|
|
|
|
Locale_GetTipList(hwnd, idx, bNoDefLayout);
|
|
|
|
//
|
|
// Checking for keyboard layout. If user already has this language,
|
|
// we want to give a choice to enable/disable keyboard layout. Otherwise,
|
|
// just enable the adding keyboard layouts.
|
|
//
|
|
if (g_bPenOrSapiTip || g_bExtraTip)
|
|
{
|
|
if (FindTVLangItem(g_lpLang[idx].dwID, NULL))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), FALSE);
|
|
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_CHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), TRUE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Disable the keyboard layout if there is no available layout.
|
|
//
|
|
if (!ComboBox_GetCount(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT)))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_AddCommandOK
|
|
//
|
|
// Gets the currently selected input locale from the combo box and marks
|
|
// it as active in the g_lpLang list. It then gets the requested layout
|
|
// and sets that in the list. It then adds the new input locale string
|
|
// to the input locale list in the property sheet.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int Locale_AddCommandOK(
|
|
HWND hwnd)
|
|
{
|
|
LPLANGNODE pLangNode = NULL;
|
|
HWND hwndLang = GetDlgItem(hwnd, IDC_KBDLA_LOCALE);
|
|
HWND hwndLayout = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT);
|
|
HWND hwndPen = GetDlgItem(hwnd, IDC_PEN_TIP);
|
|
HWND hwndSpeech = GetDlgItem(hwnd, IDC_SPEECH_TIP);
|
|
HWND hwndExternal = GetDlgItem(hwnd, IDC_EXTERNAL_TIP);
|
|
int idxLang = ComboBox_GetCurSel(hwndLang);
|
|
int idxLayout = ComboBox_GetCurSel(hwndLayout);
|
|
int idxPen = ComboBox_GetCurSel(hwndPen);
|
|
int idxSpeech = ComboBox_GetCurSel(hwndSpeech);
|
|
int idxExternal = ComboBox_GetCurSel(hwndExternal);
|
|
int iPen = -1;
|
|
int iSpeech = -1;
|
|
int iExternal = -1;
|
|
int iKbdLayout = -1;
|
|
WORD wDefault = 0;
|
|
|
|
//
|
|
// Get the offset for the language to add.
|
|
//
|
|
idxLang = (int)ComboBox_GetItemData(hwndLang, idxLang);
|
|
|
|
//
|
|
// Get the offset for the chosen keyboard layout.
|
|
//
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLA_LAYOUT_TEXT) ||
|
|
!(g_bPenOrSapiTip || g_bExtraTip))
|
|
iKbdLayout = (int)ComboBox_GetItemData(hwndLayout, idxLayout);
|
|
|
|
//
|
|
// Get the offset for the chosen Tips.
|
|
//
|
|
if (hwndPen && hwndSpeech)
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_PEN_TEXT))
|
|
iPen = (int) ComboBox_GetItemData(hwndPen, idxPen);
|
|
if (IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT))
|
|
iSpeech = (int) ComboBox_GetItemData(hwndSpeech, idxSpeech);
|
|
}
|
|
|
|
if (hwndExternal)
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT))
|
|
iExternal = (int) ComboBox_GetItemData(hwndExternal, idxExternal);
|
|
}
|
|
|
|
|
|
//
|
|
// Selected no keyboard layout
|
|
//
|
|
if (iKbdLayout == CB_ERR)
|
|
goto AddLang;
|
|
|
|
if (HIWORD(iKbdLayout))
|
|
{
|
|
iKbdLayout = LOWORD(iKbdLayout);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Need to check win9x system, since win9x doesn't support multiple
|
|
// keyboard layout on the same language. But FE system can have multiple
|
|
// IME layouts
|
|
//
|
|
if ((g_OSWIN95 && !IsFELangID(g_lpLang[idxLang].dwID)) &&
|
|
(g_lpLang[idxLang].iNumCount))
|
|
{
|
|
TCHAR szTemp[DESC_MAX];
|
|
TCHAR szMsg[DESC_MAX];
|
|
TCHAR szNewLayout[DESC_MAX];
|
|
|
|
CicLoadString(hInstance, IDS_KBD_LAYOUTEDIT, szMsg, ARRAYSIZE(szMsg));
|
|
GetAtomName(g_lpLayout[iKbdLayout].atmLayoutText, szNewLayout, ARRAYSIZE(szNewLayout));
|
|
StringCchPrintf(szTemp, ARRAYSIZE(szTemp), szMsg, szNewLayout);
|
|
|
|
//
|
|
// Ask user whether new selected keyboard layout will be replaced
|
|
// or not.
|
|
//
|
|
if (MessageBox(hwnd, szTemp, NULL, MB_YESNO | MB_ICONQUESTION) == IDYES)
|
|
{
|
|
HTREEITEM hItem;
|
|
LPLANGNODE pOldLangNode = g_lpLang[idxLang].pNext;
|
|
|
|
GetAtomName(g_lpLayout[pOldLangNode->iLayout].atmLayoutText, szTemp, ARRAYSIZE(szTemp));
|
|
|
|
//
|
|
// Find installed keyboard layout to delete it.
|
|
//
|
|
if (hItem = FindTVItem(g_lpLang[idxLang].dwID, szTemp))
|
|
{
|
|
TV_ITEM tvItem;
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
tvItem.hItem = hItem;
|
|
|
|
pOldLangNode->wStatus &= ~LANG_ACTIVE;
|
|
pOldLangNode->wStatus |= LANG_CHANGED;
|
|
|
|
if (pOldLangNode->wStatus & LANG_DEFAULT)
|
|
wDefault = LANG_DEFAULT;
|
|
|
|
g_lpLang[pOldLangNode->iLang].iNumCount--;
|
|
|
|
Locale_RemoveFromLinkedList(pOldLangNode);
|
|
|
|
if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
RemoveTVItemNode((LPTVITEMNODE)tvItem.lParam);
|
|
TreeView_DeleteItem(g_hwndTV, tvItem.hItem );
|
|
}
|
|
|
|
g_iInputs--;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Cancel - leave installed keyboard layout without changing.
|
|
// Check if there are other tips to be installed.
|
|
//
|
|
iKbdLayout = -1;
|
|
goto AddLang;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Insert a new language node.
|
|
//
|
|
pLangNode = Locale_AddToLinkedList(idxLang, 0);
|
|
if (!pLangNode)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Get the offset for the chosen keyboard layout.
|
|
//
|
|
pLangNode->iLayout = (UINT) iKbdLayout;
|
|
|
|
//
|
|
// Set ikbdLayout as the default to distinguish keyboard tip from layouts.
|
|
//
|
|
iKbdLayout = -1;
|
|
|
|
//
|
|
// Set the default hkl after replacing the default hkl with new one.
|
|
//
|
|
if (g_OSWIN95)
|
|
pLangNode->wStatus |= wDefault;
|
|
|
|
//
|
|
// See if the layout is an IME and mark the status bits accordingly.
|
|
//
|
|
if ((HIWORD(g_lpLayout[pLangNode->iLayout].dwID) & 0xf000) == 0xe000)
|
|
{
|
|
pLangNode->wStatus |= LANG_IME;
|
|
}
|
|
else
|
|
{
|
|
pLangNode->wStatus &= ~LANG_IME;
|
|
}
|
|
}
|
|
|
|
AddLang:
|
|
//
|
|
// Add the new language.
|
|
//
|
|
if (!Locale_AddLanguage(GetProp(hwnd, szPropHwnd), pLangNode, iKbdLayout, iPen, iSpeech, iExternal, idxLang))
|
|
{
|
|
//
|
|
// Unable to add the language. Need to return the user back
|
|
// to the Add dialog.
|
|
//
|
|
if (pLangNode)
|
|
Locale_RemoveFromLinkedList(pLangNode);
|
|
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (1);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KbdLocaleAddDlg
|
|
//
|
|
// This is the dialog proc for the Add button of the Input Locales
|
|
// property sheet.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK KbdLocaleAddDlg(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
if (!Locale_AddDlgInit(hwnd, lParam))
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aLocaleAddHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aLocaleAddHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
RemoveProp(hwnd, szPropHwnd);
|
|
RemoveProp(hwnd, szPropIdx);
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDOK ) :
|
|
{
|
|
if (!Locale_AddCommandOK(hwnd))
|
|
{
|
|
//
|
|
// This means the properties dialog was cancelled.
|
|
// The Add dialog should remain active.
|
|
//
|
|
break;
|
|
}
|
|
|
|
// fall thru...
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, (wParam == IDOK) ? 1 : 0);
|
|
break;
|
|
}
|
|
case ( IDC_KBDLA_LOCALE ) :
|
|
{
|
|
if (HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
HWND hwndLocale = (HWND)lParam;
|
|
HWND hwndLayout = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT);
|
|
BOOL bNoDefLayout = FALSE;
|
|
int idx;
|
|
|
|
//
|
|
// Update the keyboard layout lists.
|
|
//
|
|
if ((idx = ComboBox_GetCurSel(hwndLocale)) != CB_ERR)
|
|
{
|
|
idx = (int)ComboBox_GetItemData(hwndLocale, idx);
|
|
Locale_GetLayoutList(hwndLayout, idx, -1, &bNoDefLayout);
|
|
|
|
Locale_GetTipList(hwnd, idx, bNoDefLayout);
|
|
}
|
|
|
|
//
|
|
// Check the keyboard layout visibility
|
|
//
|
|
if (g_bPenOrSapiTip || g_bExtraTip)
|
|
{
|
|
|
|
if (FindTVLangItem(g_lpLang[idx].dwID, NULL))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), FALSE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// There isn't this language in the user configuration, so
|
|
// force to add a keyboard layout for this language.
|
|
//
|
|
CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_CHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), TRUE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Disable the keyboard layout if there is no available layout.
|
|
//
|
|
if (!ComboBox_GetCount(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT)))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case (IDC_KBDLA_LAYOUT_TEXT) :
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), IsDlgButtonChecked(hwnd, IDC_KBDLA_LAYOUT_TEXT));
|
|
break;
|
|
}
|
|
case (IDC_PEN_TEXT) :
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_PEN_TIP), IsDlgButtonChecked(hwnd, IDC_PEN_TEXT));
|
|
break;
|
|
}
|
|
case (IDC_SPEECH_TEXT) :
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SPEECH_TIP), IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT));
|
|
break;
|
|
}
|
|
case (IDC_EXTERNAL_TEXT) :
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_EXTERNAL_TIP), IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT));
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetToolBarSetting
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void GetToolBarSetting(
|
|
HWND hwnd)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwTBFlag = 0;
|
|
ITfLangBarMgr *pLangBar = NULL;
|
|
|
|
if (!g_OSNT5)
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE);
|
|
}
|
|
|
|
//
|
|
// load LangBar manager
|
|
//
|
|
hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfLangBarMgr,
|
|
(LPVOID *) &pLangBar);
|
|
|
|
if (SUCCEEDED(hr))
|
|
pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
|
|
|
|
//
|
|
// Set the language bar show/close.
|
|
//
|
|
CheckDlgButton(hwnd, IDC_TB_SHOWLANGBAR, !(dwTBFlag & TF_SFT_HIDDEN));
|
|
|
|
if (!(dwTBFlag & TF_SFT_SHOWNORMAL))
|
|
{
|
|
// Disable langbar setting options
|
|
//EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), FALSE);
|
|
}
|
|
|
|
//
|
|
// Set language bar extra icons in case of minimized.
|
|
//
|
|
CheckDlgButton(hwnd, IDC_TB_EXTRAICON, dwTBFlag & TF_SFT_EXTRAICONSONMINIMIZED);
|
|
|
|
//
|
|
// Set the default toolbar transparency option.
|
|
//
|
|
CheckDlgButton(hwnd, IDC_TB_HIGHTRANS, !(dwTBFlag & TF_SFT_NOTRANSPARENCY));
|
|
|
|
//
|
|
// Set the default toolbar show text option.
|
|
//
|
|
CheckDlgButton(hwnd, IDC_TB_TEXTLABELS, dwTBFlag & TF_SFT_LABELS);
|
|
|
|
if (pLangBar)
|
|
pLangBar->lpVtbl->Release(pLangBar);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ToolBarSettingInit
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ToolBarSettingInit(
|
|
HWND hwnd)
|
|
{
|
|
HWND hwndCTFMon = NULL;
|
|
|
|
//
|
|
// Find language tool bar module(CTFMON.EXE)
|
|
//
|
|
hwndCTFMon = FindWindow(c_szCTFMonClass, NULL);
|
|
|
|
if (hwndCTFMon)
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_SHOWLANGBAR), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), TRUE);
|
|
|
|
GetToolBarSetting(hwnd);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_SHOWLANGBAR), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ToolBarSettingOK
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ToolBarSettingOK(
|
|
HWND hwnd)
|
|
{
|
|
DWORD dwDisableCtfmon;
|
|
HRESULT hr;
|
|
DWORD dwTBFlag = 0;
|
|
ITfLangBarMgr *pLangBar = NULL;
|
|
|
|
g_dwToolBar = 0;
|
|
|
|
//
|
|
// Load LangBar manager and get the current status.
|
|
//
|
|
hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_ITfLangBarMgr,
|
|
(LPVOID *) &pLangBar);
|
|
|
|
if (SUCCEEDED(hr))
|
|
pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
|
|
|
|
if (pLangBar)
|
|
pLangBar->lpVtbl->Release(pLangBar);
|
|
|
|
if (IsDlgButtonChecked(hwnd, IDC_TB_SHOWLANGBAR))
|
|
{
|
|
if (dwTBFlag & TF_SFT_HIDDEN)
|
|
{
|
|
g_dwToolBar |= TF_SFT_SHOWNORMAL;
|
|
}
|
|
else
|
|
{
|
|
if (dwTBFlag & TF_SFT_SHOWNORMAL)
|
|
g_dwToolBar |= TF_SFT_SHOWNORMAL;
|
|
else if (dwTBFlag & TF_SFT_DOCK)
|
|
g_dwToolBar |= TF_SFT_DOCK;
|
|
else if (dwTBFlag & TF_SFT_MINIMIZED)
|
|
g_dwToolBar |= TF_SFT_MINIMIZED;
|
|
else if (dwTBFlag & TF_SFT_DESKBAND)
|
|
g_dwToolBar |= TF_SFT_DESKBAND;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_dwToolBar |= TF_SFT_HIDDEN;
|
|
}
|
|
|
|
//
|
|
// Get the extra icons
|
|
//
|
|
if (IsDlgButtonChecked(hwnd, IDC_TB_EXTRAICON))
|
|
g_dwToolBar |= TF_SFT_EXTRAICONSONMINIMIZED;
|
|
else
|
|
g_dwToolBar |= TF_SFT_NOEXTRAICONSONMINIMIZED;
|
|
|
|
//
|
|
// Get the transparency setting
|
|
//
|
|
if (IsDlgButtonChecked(hwnd, IDC_TB_HIGHTRANS))
|
|
g_dwToolBar |= TF_SFT_LOWTRANSPARENCY;
|
|
else
|
|
g_dwToolBar |= TF_SFT_NOTRANSPARENCY;
|
|
|
|
//
|
|
// Get the label setting
|
|
//
|
|
if (IsDlgButtonChecked(hwnd, IDC_TB_TEXTLABELS))
|
|
g_dwToolBar |= TF_SFT_LABELS;
|
|
else
|
|
g_dwToolBar |= TF_SFT_NOLABELS;
|
|
|
|
//
|
|
// Update toolbar setting on the Apply button.
|
|
//
|
|
UpdateToolBarSetting();
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ToolBarSettingDlg
|
|
//
|
|
// This is the dialog proc for the ToolBar Setting Dlg.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK ToolBarSettingDlg(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
ToolBarSettingInit(hwnd);
|
|
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aToolbarSettingsHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aToolbarSettingsHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDOK ) :
|
|
{
|
|
ToolBarSettingOK(hwnd);
|
|
// fall thru...
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, (wParam == IDOK) ? 1 : 0);
|
|
break;
|
|
}
|
|
case ( IDC_TB_SHOWLANGBAR ) :
|
|
{
|
|
BOOL bShowLangBar;
|
|
|
|
bShowLangBar = IsDlgButtonChecked(hwnd, IDC_TB_SHOWLANGBAR);
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), bShowLangBar);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), bShowLangBar);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), bShowLangBar);
|
|
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_TranslateHotKey
|
|
//
|
|
// Translates hotkey modifiers and values into key names.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_TranslateHotKey(
|
|
LPTSTR lpString,
|
|
UINT cchString,
|
|
UINT uVKey,
|
|
UINT uModifiers)
|
|
{
|
|
UINT ctr;
|
|
TCHAR szBuffer[DESC_MAX];
|
|
BOOL bMod = FALSE;
|
|
|
|
lpString[0] = 0;
|
|
|
|
if (uModifiers & MOD_CONTROL)
|
|
{
|
|
CicLoadString(hInstance, IDS_KBD_MOD_CONTROL, szBuffer, ARRAYSIZE(szBuffer));
|
|
StringCchCat(lpString, cchString, szBuffer);
|
|
bMod = TRUE;
|
|
}
|
|
|
|
if (uModifiers & MOD_ALT)
|
|
{
|
|
CicLoadString(hInstance, IDS_KBD_MOD_LEFT_ALT, szBuffer, ARRAYSIZE(szBuffer));
|
|
StringCchCat(lpString, cchString, szBuffer);
|
|
bMod = TRUE;
|
|
}
|
|
|
|
if (uModifiers & MOD_SHIFT)
|
|
{
|
|
CicLoadString(hInstance, IDS_KBD_MOD_SHIFT, szBuffer, ARRAYSIZE(szBuffer));
|
|
|
|
StringCchCat(lpString, cchString, szBuffer);
|
|
bMod = TRUE;
|
|
}
|
|
|
|
if (uVKey == 0)
|
|
{
|
|
if (!bMod)
|
|
{
|
|
GetAtomName( g_aVirtKeyDesc[0].atVirtKeyName,
|
|
szBuffer,
|
|
sizeof(szBuffer) / sizeof(TCHAR) );
|
|
StringCchCat(lpString, cchString, szBuffer);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Only modifiers, remove the "+" at the end.
|
|
//
|
|
lpString[lstrlen(lpString) - 1] = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (ctr = 0; (ctr < sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC)); ctr++)
|
|
{
|
|
if (g_aVirtKeyDesc[ctr].uVirtKeyValue == uVKey)
|
|
{
|
|
GetAtomName( g_aVirtKeyDesc[ctr].atVirtKeyName,
|
|
szBuffer,
|
|
sizeof(szBuffer) / sizeof(TCHAR) );
|
|
StringCchCat(lpString, cchString, szBuffer);
|
|
return;
|
|
}
|
|
}
|
|
|
|
GetAtomName( g_aVirtKeyDesc[0].atVirtKeyName,
|
|
szBuffer,
|
|
sizeof(szBuffer) / sizeof(TCHAR) );
|
|
StringCchCat(lpString, cchString, szBuffer);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_HotKeyDrawItem
|
|
//
|
|
// Draws the hotkey list box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_HotKeyDrawItem(
|
|
HWND hWnd,
|
|
LPDRAWITEMSTRUCT lpDis)
|
|
{
|
|
LPHOTKEYINFO pHotKeyNode;
|
|
COLORREF crBk, crTxt;
|
|
UINT uStrLen, uAlign;
|
|
TCHAR szString[DESC_MAX];
|
|
TCHAR szHotKey[DESC_MAX];
|
|
SIZE Size;
|
|
UINT iMaxChars;
|
|
int iMaxWidth;
|
|
|
|
if (!ListBox_GetCount(lpDis->hwndItem))
|
|
{
|
|
return;
|
|
}
|
|
|
|
pHotKeyNode = (LPHOTKEYINFO)lpDis->itemData;
|
|
|
|
crBk = SetBkColor( lpDis->hDC,
|
|
(lpDis->itemState & ODS_SELECTED)
|
|
? GetSysColor(COLOR_HIGHLIGHT)
|
|
: GetSysColor(COLOR_WINDOW) );
|
|
|
|
crTxt = SetTextColor( lpDis->hDC,
|
|
(lpDis->itemState & ODS_SELECTED)
|
|
? GetSysColor(COLOR_HIGHLIGHTTEXT)
|
|
: GetSysColor(COLOR_WINDOWTEXT) );
|
|
|
|
if (g_bMESystem && (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG))
|
|
Locale_TranslateHotKey( szHotKey,
|
|
ARRAYSIZE(szHotKey),
|
|
0,
|
|
pHotKeyNode->uModifiers );
|
|
else
|
|
Locale_TranslateHotKey( szHotKey,
|
|
ARRAYSIZE(szHotKey),
|
|
pHotKeyNode->uVKey,
|
|
pHotKeyNode->uModifiers );
|
|
|
|
GetTextExtentExPoint( lpDis->hDC,
|
|
szHotKey,
|
|
lstrlen(szHotKey),
|
|
0,
|
|
NULL,
|
|
NULL ,
|
|
&Size );
|
|
|
|
iMaxWidth = lpDis->rcItem.right - lpDis->rcItem.left - Size.cx - LIST_MARGIN * 8;
|
|
|
|
uStrLen = GetAtomName( pHotKeyNode->atmHotKeyName,
|
|
szString,
|
|
sizeof(szString) / sizeof(TCHAR) );
|
|
|
|
GetTextExtentExPoint( lpDis->hDC,
|
|
szString,
|
|
uStrLen,
|
|
iMaxWidth,
|
|
&iMaxChars,
|
|
NULL ,
|
|
&Size );
|
|
|
|
if (uStrLen > iMaxChars)
|
|
{
|
|
szString[iMaxChars-3] = TEXT('.');
|
|
szString[iMaxChars-2] = TEXT('.');
|
|
szString[iMaxChars-1] = TEXT('.');
|
|
szString[iMaxChars] = 0;
|
|
}
|
|
|
|
ExtTextOut( lpDis->hDC,
|
|
lpDis->rcItem.left + LIST_MARGIN,
|
|
lpDis->rcItem.top + (g_cyListItem - g_cyText) / 2,
|
|
ETO_OPAQUE,
|
|
&lpDis->rcItem,
|
|
szString,
|
|
iMaxChars,
|
|
NULL );
|
|
|
|
uAlign = GetTextAlign(lpDis->hDC);
|
|
|
|
SetTextAlign(lpDis->hDC, TA_RIGHT);
|
|
|
|
ExtTextOut( lpDis->hDC,
|
|
lpDis->rcItem.right - LIST_MARGIN,
|
|
lpDis->rcItem.top + (g_cyListItem - g_cyText) / 2,
|
|
0,
|
|
NULL,
|
|
szHotKey,
|
|
lstrlen(szHotKey),
|
|
NULL );
|
|
|
|
SetTextAlign(lpDis->hDC, uAlign);
|
|
|
|
SetBkColor(lpDis->hDC, crBk);
|
|
|
|
SetTextColor(lpDis->hDC, crTxt);
|
|
|
|
if (lpDis->itemState & ODS_FOCUS)
|
|
{
|
|
DrawFocusRect(lpDis->hDC, &lpDis->rcItem);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_DrawItem
|
|
//
|
|
// Processing for a WM_DRAWITEM message.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_DrawItem(
|
|
HWND hwnd,
|
|
LPDRAWITEMSTRUCT lpdi)
|
|
{
|
|
switch (lpdi->CtlID)
|
|
{
|
|
case ( IDC_KBDL_HOTKEY_LIST ) :
|
|
{
|
|
Locale_HotKeyDrawItem(hwnd, lpdi);
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_MeasureItem
|
|
//
|
|
// Processing for a WM_MEASUREITEM message.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_MeasureItem(
|
|
HWND hwnd,
|
|
LPMEASUREITEMSTRUCT lpmi)
|
|
{
|
|
HFONT hfont;
|
|
HDC hdc;
|
|
TEXTMETRIC tm;
|
|
|
|
switch (lpmi->CtlID)
|
|
{
|
|
case ( IDC_KBDL_HOTKEY_LIST ) :
|
|
{
|
|
hfont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
|
|
hdc = GetDC(NULL);
|
|
hfont = SelectObject(hdc, hfont);
|
|
|
|
GetTextMetrics(hdc, &tm);
|
|
SelectObject(hdc, hfont);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
g_cyText = tm.tmHeight;
|
|
lpmi->itemHeight = g_cyListItem =
|
|
MAX(g_cyText, GetSystemMetrics(SM_CYSMICON)) + 2 * LIST_MARGIN;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_CommandChangeHotKey
|
|
//
|
|
// Brings up change hotkey dialog box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_CommandChangeHotKey(
|
|
HWND hwnd)
|
|
{
|
|
HWND hwndHotkey = GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST);
|
|
LPHOTKEYINFO pHotKeyNode;
|
|
int iIndex;
|
|
INITINFO InitInfo;
|
|
|
|
iIndex = ListBox_GetCurSel(hwndHotkey);
|
|
pHotKeyNode = (LPHOTKEYINFO)ListBox_GetItemData(hwndHotkey, iIndex);
|
|
|
|
InitInfo.hwndMain = hwnd;
|
|
InitInfo.pHotKeyNode = pHotKeyNode;
|
|
|
|
if (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG)
|
|
{
|
|
if (g_iThaiLayout)
|
|
DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_THAI),
|
|
MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_THAI),
|
|
hwnd,
|
|
KbdLocaleChangeThaiInputLocaleHotkey,
|
|
(LPARAM)&InitInfo);
|
|
else if (g_bMESystem)
|
|
DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_ME),
|
|
MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_ME),
|
|
hwnd,
|
|
KbdLocaleChangeMEInputLocaleHotkey,
|
|
(LPARAM)&InitInfo);
|
|
else
|
|
DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
|
|
MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
|
|
hwnd,
|
|
KbdLocaleChangeInputLocaleHotkey,
|
|
(LPARAM)&InitInfo);
|
|
}
|
|
else
|
|
DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_KEYBOARD_LAYOUT),
|
|
MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_KEYBOARD_LAYOUT),
|
|
hwnd,
|
|
KbdLocaleChangeKeyboardLayoutHotkey,
|
|
(LPARAM)&InitInfo);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KbdLocaleHotKeyDlg
|
|
//
|
|
// This is the dialog proc for the Input Locales HotKey Setting Dlg.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
INT_PTR CALLBACK KbdLocaleHotKeyDlg(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
static BOOL bHasIme;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
UINT ctr;
|
|
TCHAR szItem[DESC_MAX];
|
|
|
|
//
|
|
// Get hotkey information.
|
|
//
|
|
bHasIme = FALSE;
|
|
Locale_GetHotkeys(hwnd, &bHasIme);
|
|
|
|
if (!ListBox_GetCount(GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST)))
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDL_CHANGE_HOTKEY), FALSE);
|
|
}
|
|
|
|
//
|
|
// Get Attributes information (CapsLock/ShiftLock etc.)
|
|
//
|
|
Locale_GetAttributes(hwnd);
|
|
|
|
//
|
|
// Load virtual key description.
|
|
//
|
|
for (ctr = 0; (ctr < sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC)); ctr++)
|
|
{
|
|
CicLoadString(hInstance,
|
|
g_aVirtKeyDesc[ctr].idVirtKeyName,
|
|
szItem,
|
|
sizeof(szItem) / sizeof(TCHAR) );
|
|
g_aVirtKeyDesc[ctr].atVirtKeyName = AddAtom(szItem);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aLocaleKeysSettingsHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aLocaleKeysSettingsHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_MEASUREITEM ) :
|
|
{
|
|
Locale_MeasureItem(hwnd, (LPMEASUREITEMSTRUCT)lParam);
|
|
break;
|
|
}
|
|
case ( WM_DRAWITEM ) :
|
|
{
|
|
return (Locale_DrawItem(hwnd, (LPDRAWITEMSTRUCT)lParam));
|
|
}
|
|
|
|
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDC_KBDL_CAPSLOCK ) :
|
|
case ( IDC_KBDL_SHIFTLOCK ) :
|
|
{
|
|
break;
|
|
}
|
|
case ( IDC_KBDL_HOTKEY_LIST ):
|
|
{
|
|
if (HIWORD(wParam) == LBN_DBLCLK)
|
|
{
|
|
//
|
|
// User double clicked on a hotkey. Invoke the
|
|
// change hotkey dialog.
|
|
//
|
|
Locale_CommandChangeHotKey(hwnd);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDL_CHANGE_HOTKEY ) :
|
|
{
|
|
Locale_CommandChangeHotKey(hwnd);
|
|
break;
|
|
}
|
|
case ( IDOK ) :
|
|
{
|
|
DWORD dwAttributes = 0;
|
|
HKEY hkeyLayouts;
|
|
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDL_SHIFTLOCK))
|
|
dwAttributes |= KLF_SHIFTLOCK;
|
|
else
|
|
dwAttributes &= ~KLF_SHIFTLOCK;
|
|
|
|
if (dwAttributes != g_dwAttributes)
|
|
{
|
|
DWORD cb;
|
|
HKEY hkey;
|
|
|
|
if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdLayouts, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
|
|
RegSetValueEx(hkey,
|
|
c_szAttributes,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwAttributes,
|
|
sizeof(DWORD) );
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
ActivateKeyboardLayout(GetKeyboardLayout(0), KLF_RESET | dwAttributes);
|
|
}
|
|
|
|
if (g_dwChanges & CHANGE_SWITCH)
|
|
{
|
|
UINT nLangs;
|
|
HKL *pLangs = NULL;
|
|
BOOL bDirectSwitch = FALSE;
|
|
TV_ITEM tvItem;
|
|
HTREEITEM hItem;
|
|
HTREEITEM hLangItem;
|
|
HTREEITEM hGroupItem;
|
|
LPLANGNODE pLangNode;
|
|
HWND hwndTV = g_hwndTV;
|
|
|
|
|
|
Locale_SetLanguageHotkey();
|
|
|
|
//
|
|
// Set Imm hotkeys.
|
|
//
|
|
// Get the list of the currently active keyboard layouts from
|
|
// the system. We will possibly need to sync up all IMEs with new
|
|
// hotkeys.
|
|
//
|
|
nLangs = GetKeyboardLayoutList(0, NULL);
|
|
if (nLangs != 0)
|
|
{
|
|
pLangs = (HKL *)LocalAlloc(LPTR, sizeof(DWORD_PTR) * nLangs);
|
|
if (!pLangs)
|
|
return (FALSE);
|
|
|
|
GetKeyboardLayoutList(nLangs, (HKL *)pLangs);
|
|
}
|
|
|
|
tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
|
|
|
|
//
|
|
// Try to find either a matching hkl or empty spot in the array
|
|
// for each of the hkls in the locale list.
|
|
//
|
|
for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
|
|
hLangItem != NULL ;
|
|
hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
|
|
)
|
|
{
|
|
for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
|
|
hGroupItem != NULL;
|
|
hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
|
|
{
|
|
|
|
for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
|
|
hItem != NULL;
|
|
hItem = TreeView_GetNextSibling(hwndTV, hItem))
|
|
{
|
|
LPTVITEMNODE pTVItemNode;
|
|
|
|
tvItem.hItem = hItem;
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
else
|
|
break;
|
|
|
|
if (pLangNode == NULL &&
|
|
(pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
|
|
pTVItemNode->hklSub)
|
|
{
|
|
if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
|
|
{
|
|
if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
|
|
{
|
|
pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
|
|
pLangNode = (LPLANGNODE)pTVItemNode->lParam;
|
|
}
|
|
}
|
|
}
|
|
if (pLangNode == NULL)
|
|
continue;
|
|
//
|
|
// Set Imm hotkeys.
|
|
//
|
|
Locale_SetImmHotkey(hwnd, pLangNode, nLangs, pLangs, &bDirectSwitch);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bDirectSwitch)
|
|
g_dwChanges |= CHANGE_DIRECTSWITCH;
|
|
|
|
if (bHasIme)
|
|
{
|
|
Locale_SetImmCHxHotkey(hwnd, nLangs, pLangs);
|
|
}
|
|
|
|
//
|
|
// Free any allocated memory.
|
|
//
|
|
if (pLangs != NULL)
|
|
{
|
|
LocalFree((HANDLE)pLangs);
|
|
}
|
|
|
|
g_dwChanges &= ~CHANGE_SWITCH;
|
|
}
|
|
|
|
EndDialog(hwnd, 1);
|
|
break;
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_VirtKeyList
|
|
//
|
|
// Initializes the virtual key combo box and sets the current selection.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_VirtKeyList(
|
|
HWND hwnd,
|
|
UINT uVKey,
|
|
BOOL bDirectSwitch)
|
|
{
|
|
int ctr, iStart, iEnd, iIndex;
|
|
UINT iSel = 0;
|
|
TCHAR szString[DESC_MAX];
|
|
HWND hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO);
|
|
|
|
//
|
|
// Look for hot keys for direct switch.
|
|
//
|
|
for (ctr = sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC) - 1;
|
|
ctr >= 0;
|
|
ctr--)
|
|
{
|
|
if (g_aVirtKeyDesc[ctr].idVirtKeyName == IDS_VK_NONE1)
|
|
{
|
|
//
|
|
// Found it. Remove "(None)" from hwndKey list box.
|
|
//
|
|
ctr++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ctr < 0) return;
|
|
|
|
iStart = bDirectSwitch ? ctr : 0;
|
|
iEnd = bDirectSwitch ? sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC) : ctr;
|
|
|
|
ComboBox_ResetContent(hwndKey);
|
|
|
|
for (ctr = iStart; ctr < iEnd; ctr++)
|
|
{
|
|
GetAtomName( g_aVirtKeyDesc[ctr].atVirtKeyName,
|
|
szString,
|
|
sizeof(szString) / sizeof(TCHAR) );
|
|
|
|
iIndex = ComboBox_InsertString(hwndKey, -1, szString);
|
|
ComboBox_SetItemData(hwndKey, iIndex, g_aVirtKeyDesc[ctr].uVirtKeyValue);
|
|
if (g_aVirtKeyDesc[ctr].uVirtKeyValue == uVKey)
|
|
{
|
|
iSel = iIndex;
|
|
}
|
|
}
|
|
ComboBox_SetCurSel(hwndKey, iSel);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_ChangeHotKeyDlgInit
|
|
//
|
|
// Initializes the change hotkey dialog box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Locale_ChangeHotKeyDlgInit(
|
|
HWND hwnd,
|
|
LPARAM lParam)
|
|
{
|
|
TCHAR szHotKeyName[DESC_MAX];
|
|
LPHOTKEYINFO pHotKeyNode = ((LPINITINFO)lParam)->pHotKeyNode;
|
|
BOOL bCtrl = TRUE;
|
|
BOOL bAlt = TRUE;
|
|
BOOL bGrave = TRUE;
|
|
|
|
GetAtomName(pHotKeyNode->atmHotKeyName, szHotKeyName, ARRAYSIZE(szHotKeyName));
|
|
SetDlgItemText(hwnd, IDC_KBDLH_LAYOUT_TEXT, szHotKeyName);
|
|
|
|
//
|
|
// Set the language switch hotkey
|
|
//
|
|
if (pHotKeyNode->uModifiers & MOD_CONTROL)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, TRUE);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, FALSE);
|
|
bCtrl = FALSE;
|
|
}
|
|
|
|
if (pHotKeyNode->uModifiers & MOD_ALT)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, TRUE);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, FALSE);
|
|
bAlt = FALSE;
|
|
}
|
|
|
|
if (GetDlgItem(hwnd, IDC_KBDLH_GRAVE) && (pHotKeyNode->uVKey == CHAR_GRAVE))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, TRUE);
|
|
bGrave = FALSE;
|
|
}
|
|
|
|
if (bCtrl && bAlt && bGrave)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
|
|
ComboBox_SetCurSel(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), 0);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), FALSE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, TRUE);
|
|
}
|
|
|
|
//
|
|
// Set the layout switch hotkey
|
|
//
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, TRUE);
|
|
if (pHotKeyNode->uLayoutHotKey & MOD_CONTROL)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, TRUE);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, FALSE);
|
|
}
|
|
else if (pHotKeyNode->uLayoutHotKey & MOD_ALT)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, TRUE);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, FALSE);
|
|
}
|
|
else if (g_bMESystem && pHotKeyNode->uVKey == CHAR_GRAVE)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, TRUE);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, FALSE);
|
|
|
|
if (g_bMESystem)
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
|
|
}
|
|
|
|
//
|
|
// There is no ctfmon.exe process during the setup, so disable layout
|
|
// hotkey settings.
|
|
//
|
|
if (g_bSetupCase)
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_LAYOUTHOTKEY), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_SHIFT2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_PLUS2), FALSE);
|
|
|
|
if (g_bMESystem)
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
|
|
|
|
#if 0
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_LAYOUTHOTKEY), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_SHIFT2), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_PLUS2), SW_HIDE);
|
|
|
|
if (g_bMESystem)
|
|
ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), SW_HIDE);
|
|
#endif
|
|
|
|
}
|
|
|
|
if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
|
|
{
|
|
Locale_VirtKeyList(hwnd, pHotKeyNode->uVKey, TRUE);
|
|
}
|
|
else
|
|
{
|
|
Locale_VirtKeyList(hwnd, pHotKeyNode->uVKey, FALSE);
|
|
}
|
|
|
|
SetProp(hwnd, szPropHwnd, (HANDLE)((LPINITINFO)lParam)->hwndMain);
|
|
SetProp(hwnd, szPropIdx, (HANDLE)pHotKeyNode);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Locale_ChangeHotKeyCommandOK
|
|
//
|
|
// Records hotkey changes made in change hotkey dialog box.
|
|
// Warns if duplicate hotkeys are selected.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Locale_ChangeHotKeyCommandOK(
|
|
HWND hwnd)
|
|
{
|
|
LPHOTKEYINFO pHotKeyNode, pHotKeyTemp;
|
|
UINT iIndex;
|
|
HWND hwndHotkey, hwndMain, hwndKey;
|
|
UINT uOldVKey, uOldModifiers, uOldLayoutHotKey;
|
|
int ctr;
|
|
int iNumMods = 0;
|
|
int DialogType;
|
|
|
|
pHotKeyNode = GetProp(hwnd, szPropIdx);
|
|
hwndMain = GetProp(hwnd, szPropHwnd);
|
|
hwndHotkey = GetDlgItem(hwndMain, IDC_KBDL_HOTKEY_LIST);
|
|
hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO);
|
|
|
|
uOldVKey = pHotKeyNode->uVKey;
|
|
uOldModifiers = pHotKeyNode->uModifiers;
|
|
uOldLayoutHotKey = pHotKeyNode->uLayoutHotKey;
|
|
|
|
if (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG)
|
|
{
|
|
DialogType = DIALOG_SWITCH_INPUT_LOCALES;
|
|
}
|
|
else if (GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO) &&
|
|
(GetWindowLong( GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO),
|
|
GWL_STYLE) & BS_RADIOBUTTON))
|
|
{
|
|
DialogType = DIALOG_SWITCH_KEYBOARD_LAYOUT;
|
|
}
|
|
else
|
|
{
|
|
DialogType = DIALOG_SWITCH_IME;
|
|
}
|
|
|
|
pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
|
|
pHotKeyNode->uVKey = 0;
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL))
|
|
{
|
|
pHotKeyNode->uModifiers |= MOD_CONTROL;
|
|
iNumMods++;
|
|
}
|
|
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT))
|
|
{
|
|
pHotKeyNode->uModifiers |= MOD_ALT;
|
|
iNumMods++;
|
|
}
|
|
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
|
|
{
|
|
//
|
|
// Assign Grave key.
|
|
//
|
|
pHotKeyNode->uVKey = CHAR_GRAVE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Shift key is mandatory.
|
|
//
|
|
pHotKeyNode->uModifiers |= MOD_SHIFT;
|
|
iNumMods++;
|
|
|
|
if ((iIndex = ComboBox_GetCurSel(hwndKey)) == CB_ERR)
|
|
{
|
|
pHotKeyNode->uVKey = 0;
|
|
}
|
|
else
|
|
{
|
|
pHotKeyNode->uVKey = (UINT)ComboBox_GetItemData(hwndKey, iIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the layout switch hotkey
|
|
//
|
|
pHotKeyNode->uLayoutHotKey = 0;
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL2))
|
|
{
|
|
pHotKeyNode->uLayoutHotKey |= MOD_CONTROL;
|
|
}
|
|
else if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
|
|
{
|
|
pHotKeyNode->uLayoutHotKey |= MOD_ALT;
|
|
}
|
|
else if (IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
|
|
{
|
|
pHotKeyNode->uVKey = CHAR_GRAVE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Key sequence with only one modifier and without a key,
|
|
// or without any modifier is invalid.
|
|
//
|
|
if (((pHotKeyNode->uVKey != 0) && (iNumMods == 0) &&
|
|
(DialogType != DIALOG_SWITCH_INPUT_LOCALES)) ||
|
|
((pHotKeyNode->uVKey == 0) && (iNumMods != 0) &&
|
|
(DialogType != DIALOG_SWITCH_INPUT_LOCALES)))
|
|
{
|
|
TCHAR szName[DESC_MAX];
|
|
|
|
Locale_TranslateHotKey( szName,
|
|
ARRAYSIZE(szName),
|
|
pHotKeyNode->uVKey,
|
|
pHotKeyNode->uModifiers );
|
|
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_INVALID_HOTKEY, szName);
|
|
|
|
pHotKeyNode->uModifiers = uOldModifiers;
|
|
pHotKeyNode->uVKey = uOldVKey;
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Do not allow duplicate hot keys.
|
|
//
|
|
for (ctr = 0; ctr < ListBox_GetCount(hwndHotkey); ctr++)
|
|
{
|
|
pHotKeyTemp = (LPHOTKEYINFO)ListBox_GetItemData(hwndHotkey, ctr);
|
|
if ((pHotKeyTemp != pHotKeyNode) &&
|
|
((pHotKeyNode->uModifiers & (MOD_CONTROL | MOD_ALT | MOD_SHIFT)) ==
|
|
(pHotKeyTemp->uModifiers & (MOD_CONTROL | MOD_ALT | MOD_SHIFT))) &&
|
|
(pHotKeyNode->uVKey == pHotKeyTemp->uVKey) &&
|
|
(iNumMods || pHotKeyNode->uVKey != 0))
|
|
{
|
|
TCHAR szName[DESC_MAX];
|
|
|
|
Locale_TranslateHotKey( szName,
|
|
ARRAYSIZE(szName),
|
|
pHotKeyNode->uVKey,
|
|
pHotKeyNode->uModifiers );
|
|
Locale_ErrorMsg(hwnd, IDS_KBD_CONFLICT_HOTKEY, szName);
|
|
|
|
pHotKeyNode->uModifiers = uOldModifiers;
|
|
pHotKeyNode->uVKey = uOldVKey;
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
InvalidateRect(hwndHotkey, NULL, FALSE);
|
|
|
|
if ((uOldVKey != pHotKeyNode->uVKey) ||
|
|
(uOldModifiers != pHotKeyNode->uModifiers) ||
|
|
(uOldLayoutHotKey != pHotKeyNode->uLayoutHotKey))
|
|
{
|
|
g_dwChanges |= CHANGE_SWITCH;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KbdLocaleSimpleHotkey
|
|
//
|
|
// Dlgproc for hotkey on NT4 and Win9x platform
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK KbdLocaleSimpleHotkey(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
TCHAR szHotKey[10];
|
|
TCHAR szLayoutHotKey[10];
|
|
|
|
GetLanguageHotkeyFromRegistry(szHotKey, ARRAYSIZE(szHotKey),
|
|
szLayoutHotKey, ARRAYSIZE(szLayoutHotKey));
|
|
|
|
//
|
|
// Set the modifiers.
|
|
//
|
|
if (szHotKey[1] == 0)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, TRUE);
|
|
|
|
switch (szHotKey[0])
|
|
{
|
|
case ( TEXT('1') ) :
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, TRUE);
|
|
break;
|
|
}
|
|
case ( TEXT('2') ) :
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, TRUE);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
}
|
|
|
|
if (szLayoutHotKey[1] == 0)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, TRUE);
|
|
|
|
switch (szLayoutHotKey[0])
|
|
{
|
|
case ( TEXT('1') ) :
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, TRUE);
|
|
break;
|
|
}
|
|
case ( TEXT('2') ) :
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, TRUE);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
}
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDOK ) :
|
|
{
|
|
DWORD dwLangHotKey;
|
|
DWORD dwLayoutHotKey;
|
|
HKEY hkeyToggle;
|
|
TCHAR szTemp[10];
|
|
TCHAR szTemp2[10];
|
|
|
|
//
|
|
// Language switch hotkey
|
|
//
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT))
|
|
{
|
|
dwLangHotKey = 1;
|
|
}
|
|
else
|
|
{
|
|
dwLangHotKey = 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwLangHotKey = 3;
|
|
}
|
|
|
|
//
|
|
// Layout swtich hotkey
|
|
//
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
|
|
{
|
|
dwLayoutHotKey = 1;
|
|
}
|
|
else
|
|
{
|
|
dwLayoutHotKey = 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwLayoutHotKey = 3;
|
|
}
|
|
|
|
//
|
|
// Get the toggle hotkey as a string so that it can be written
|
|
// into the registry (as data).
|
|
//
|
|
StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), dwLangHotKey);
|
|
StringCchPrintf(szTemp2, ARRAYSIZE(szTemp2), TEXT("%d"), dwLayoutHotKey);
|
|
|
|
//
|
|
// Create the HKCU\Keyboard Layout\Toggle key.
|
|
//
|
|
if (RegCreateKey(HKEY_CURRENT_USER,
|
|
c_szKbdToggleKey,
|
|
&hkeyToggle ) == ERROR_SUCCESS)
|
|
{
|
|
|
|
RegSetValueEx(hkeyToggle,
|
|
g_OSNT4? c_szToggleHotKey : NULL,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szTemp,
|
|
(DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
|
|
|
|
RegSetValueEx(hkeyToggle,
|
|
c_szToggleLang,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szTemp,
|
|
(DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
|
|
|
|
RegSetValueEx(hkeyToggle,
|
|
c_szToggleLayout,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szTemp2,
|
|
(DWORD)(lstrlen(szTemp2) + 1) * sizeof(TCHAR) );
|
|
|
|
RegCloseKey(hkeyToggle);
|
|
}
|
|
|
|
EndDialog(hwnd, 1);
|
|
|
|
break;
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LANGHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LAYOUTHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KbdLocaleChangeInputLocaleHotkey
|
|
//
|
|
// Dlgproc for changing input locale hotkey dialog box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK KbdLocaleChangeInputLocaleHotkey(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
Locale_ChangeHotKeyDlgInit(hwnd, lParam);
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
RemoveProp(hwnd, szPropHwnd);
|
|
RemoveProp(hwnd, szPropIdx);
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDOK ) :
|
|
{
|
|
if (Locale_ChangeHotKeyCommandOK(hwnd))
|
|
{
|
|
EndDialog(hwnd, 1);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LANGHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LAYOUTHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KbdLocaleChangeThaiInputLocaleHotkey
|
|
//
|
|
// Dlgproc for changing Thai input locale hotkey dialog box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK KbdLocaleChangeThaiInputLocaleHotkey(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
Locale_ChangeHotKeyDlgInit(hwnd, lParam);
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
RemoveProp(hwnd, szPropHwnd);
|
|
RemoveProp(hwnd, szPropIdx);
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) :
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_DRAWITEM ) :
|
|
{
|
|
if (wParam == IDC_KBDLH_VLINE)
|
|
{
|
|
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
|
|
RECT rect;
|
|
HPEN hPenHilite, hPenShadow, hPenOriginal;
|
|
|
|
GetClientRect(lpdis->hwndItem, &rect);
|
|
hPenHilite = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
|
|
hPenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
|
|
|
|
hPenOriginal = SelectObject(lpdis->hDC, hPenShadow);
|
|
MoveToEx(lpdis->hDC, rect.right / 2, 0, NULL);
|
|
LineTo(lpdis->hDC, rect.right / 2, rect.bottom);
|
|
|
|
SelectObject(lpdis->hDC, hPenHilite);
|
|
MoveToEx(lpdis->hDC, rect.right / 2 + 1, 0, NULL);
|
|
LineTo(lpdis->hDC, rect.right / 2 + 1, rect.bottom);
|
|
|
|
SelectObject(lpdis->hDC, hPenOriginal);
|
|
|
|
if (hPenShadow)
|
|
{
|
|
DeleteObject(hPenShadow);
|
|
}
|
|
if (hPenHilite)
|
|
{
|
|
DeleteObject(hPenHilite);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
return (FALSE);
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDOK ) :
|
|
{
|
|
if (Locale_ChangeHotKeyCommandOK(hwnd))
|
|
{
|
|
EndDialog(hwnd, 1);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LANGHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_CHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LAYOUTHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY) &&
|
|
!IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY) &&
|
|
!IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KbdLocaleChangeMEInputLocaleHotkey
|
|
//
|
|
// Dlgproc for changing Thai input locale hotkey dialog box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK KbdLocaleChangeMEInputLocaleHotkey(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
Locale_ChangeHotKeyDlgInit(hwnd, lParam);
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
RemoveProp(hwnd, szPropHwnd);
|
|
RemoveProp(hwnd, szPropIdx);
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) :
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_DRAWITEM ) :
|
|
{
|
|
if (wParam == IDC_KBDLH_VLINE)
|
|
{
|
|
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
|
|
RECT rect;
|
|
HPEN hPenHilite, hPenShadow, hPenOriginal;
|
|
|
|
GetClientRect(lpdis->hwndItem, &rect);
|
|
hPenHilite = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
|
|
hPenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
|
|
|
|
hPenOriginal = SelectObject(lpdis->hDC, hPenShadow);
|
|
MoveToEx(lpdis->hDC, rect.right / 2, 0, NULL);
|
|
LineTo(lpdis->hDC, rect.right / 2, rect.bottom);
|
|
|
|
SelectObject(lpdis->hDC, hPenHilite);
|
|
MoveToEx(lpdis->hDC, rect.right / 2 + 1, 0, NULL);
|
|
LineTo(lpdis->hDC, rect.right / 2 + 1, rect.bottom);
|
|
|
|
SelectObject(lpdis->hDC, hPenOriginal);
|
|
|
|
if (hPenShadow)
|
|
{
|
|
DeleteObject(hPenShadow);
|
|
}
|
|
if (hPenHilite)
|
|
{
|
|
DeleteObject(hPenHilite);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
return (FALSE);
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDOK ) :
|
|
{
|
|
if (Locale_ChangeHotKeyCommandOK(hwnd))
|
|
{
|
|
EndDialog(hwnd, 1);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LANGHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LAYOUTHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_CHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY) &&
|
|
!IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY) &&
|
|
!IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT2 ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KbdLocaleChangeKeyboardLayoutHotkey
|
|
//
|
|
// Dlgproc for changing direct switch keyboard layout hotkey dialog box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK KbdLocaleChangeKeyboardLayoutHotkey(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
Locale_ChangeHotKeyDlgInit(hwnd, lParam);
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
c_szHelpFile,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aLayoutHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) : // right mouse click
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
c_szHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPTSTR)aLayoutHotkeyHelpIds );
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
RemoveProp(hwnd, szPropHwnd);
|
|
RemoveProp(hwnd, szPropIdx);
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
HWND hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO);
|
|
LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( IDOK ) :
|
|
{
|
|
if (Locale_ChangeHotKeyCommandOK(hwnd))
|
|
{
|
|
EndDialog(hwnd, 1);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_LANGHOTKEY ) :
|
|
{
|
|
if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
|
|
ComboBox_SetCurSel(hwndKey, 0);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), TRUE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
|
|
CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
|
|
ComboBox_SetCurSel(hwndKey, 0);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_CTRL ) :
|
|
{
|
|
break;
|
|
}
|
|
case ( IDC_KBDLH_L_ALT ) :
|
|
{
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////// END ////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////
|