Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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 ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////