https://git.reactos.org/?p=reactos.git;a=commitdiff;h=596f04be6b1710bb255b34...
commit 596f04be6b1710bb255b346bc9bc7153c7d6eb0c Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Fri Sep 16 08:09:37 2022 +0900 Commit: GitHub noreply@github.com CommitDate: Fri Sep 16 08:09:37 2022 +0900
[USER32][INPUT] Support various keyboard layouts (#4666)
- Fix IntLoadKeyboardLayout function to return the correct HKL value. - Modify LAYOUT_LIST_NODE structure to add more information. - Fix LayoutList_GetByHkl function to choose the IME HKLs correctly. - Ignore DELETED entries correctly. - Improve UI/UX. CORE-11700, CORE-13244, CORE-18364 --- dll/cpl/input/add_dialog.c | 4 +- dll/cpl/input/input.h | 13 ++ dll/cpl/input/input_list.c | 438 +++++++++++++++++++++--------------- dll/cpl/input/input_list.h | 24 +- dll/cpl/input/layout_list.c | 198 ++++++++++------ dll/cpl/input/layout_list.h | 9 +- dll/cpl/input/settings_page.c | 202 ++++++----------- win32ss/user/user32/windows/input.c | 58 +++-- 8 files changed, 536 insertions(+), 410 deletions(-)
diff --git a/dll/cpl/input/add_dialog.c b/dll/cpl/input/add_dialog.c index 5156b190834..96567cf8d8a 100644 --- a/dll/cpl/input/add_dialog.c +++ b/dll/cpl/input/add_dialog.c @@ -93,7 +93,7 @@ OnInitAddDialog(HWND hwndDlg) iItemIndex = ComboBox_AddString(hwndLayoutCombo, pCurrentLayout->pszName); ComboBox_SetItemData(hwndLayoutCombo, iItemIndex, pCurrentLayout);
- if (pCurrentLayout->dwId == dwDefaultLayoutId) + if (pCurrentLayout->dwKLID == dwDefaultLayoutId) { ComboBox_SetCurSel(hwndLayoutCombo, iItemIndex); } @@ -159,7 +159,7 @@ OnCommandAddDialog(HWND hwndDlg, WPARAM wParam)
pCurrentLayout = (LAYOUT_LIST_NODE*)ComboBox_GetItemData(hwndLayoutCombo, iIndex);
- if (pCurrentLayout != NULL && pCurrentLayout->dwId == dwLayoutId) + if (pCurrentLayout != NULL && pCurrentLayout->dwKLID == dwLayoutId) { ComboBox_SetCurSel(hwndLayoutCombo, iIndex); break; diff --git a/dll/cpl/input/input.h b/dll/cpl/input/input.h index f7ab1f47141..4f06ea66ac6 100644 --- a/dll/cpl/input/input.h +++ b/dll/cpl/input/input.h @@ -81,4 +81,17 @@ DWORDfromString(const WCHAR *pszString) return wcstoul(pszString, &pszEnd, 16); }
+#define IME_MASK (0xE0000000UL) +#define SUBST_MASK (0xD0000000UL) +#define SPECIAL_MASK (0xF0000000UL) + +#define IS_IME_HKL(hKL) ((((ULONG_PTR)(hKL)) & 0xF0000000) == IME_MASK) +#define IS_SPECIAL_HKL(hKL) ((((ULONG_PTR)(hKL)) & 0xF0000000) == SPECIAL_MASK) +#define SPECIALIDFROMHKL(hKL) ((WORD)(HIWORD(hKL) & 0x0FFF)) + +#define IS_IME_KLID(dwKLID) ((((ULONG)(dwKLID)) & 0xF0000000) == IME_MASK) +#define IS_SUBST_KLID(dwKLID) ((((ULONG)(dwKLID)) & 0xF0000000) == SUBST_MASK) + +VOID GetSystemLibraryPath(LPWSTR pszPath, INT cchPath, LPCWSTR pszFileName); + #endif /* _INPUT_H */ diff --git a/dll/cpl/input/input_list.c b/dll/cpl/input/input_list.c index e0a409f5a72..97fe16a13b6 100644 --- a/dll/cpl/input/input_list.c +++ b/dll/cpl/input/input_list.c @@ -23,9 +23,7 @@ BOOL UpdateRegistryForFontSubstitutes(MUI_SUBFONT *pSubstitutes) static const WCHAR pszKey[] = L"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes";
- hKey = NULL; - RegOpenKeyExW(HKEY_LOCAL_MACHINE, pszKey, 0, KEY_ALL_ACCESS, &hKey); - if (hKey == NULL) + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, pszKey, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) return FALSE;
/* Overwrite only */ @@ -37,10 +35,16 @@ BOOL UpdateRegistryForFontSubstitutes(MUI_SUBFONT *pSubstitutes) }
RegCloseKey(hKey); - return TRUE; }
+VOID GetSystemLibraryPath(LPWSTR pszPath, INT cchPath, LPCWSTR pszFileName) +{ + WCHAR szSysDir[MAX_PATH]; + GetSystemDirectoryW(szSysDir, ARRAYSIZE(szSysDir)); + StringCchPrintfW(pszPath, cchPath, L"%s\%s", szSysDir, pszFileName); +} + BOOL InputList_SetFontSubstitutes(LCID dwLocaleId) { @@ -135,29 +139,28 @@ InputList_AppendNode(VOID) INPUT_LIST_NODE *pCurrent; INPUT_LIST_NODE *pNew;
- pCurrent = _InputList; - pNew = (INPUT_LIST_NODE*)malloc(sizeof(INPUT_LIST_NODE)); if (pNew == NULL) return NULL;
ZeroMemory(pNew, sizeof(INPUT_LIST_NODE));
- if (pCurrent == NULL) + if (_InputList == NULL) /* Empty? */ { _InputList = pNew; + return pNew; } - else - { - while (pCurrent->pNext != NULL) - { - pCurrent = pCurrent->pNext; - }
- pNew->pPrev = pCurrent; - pCurrent->pNext = pNew; + /* Find last node */ + for (pCurrent = _InputList; pCurrent->pNext; pCurrent = pCurrent->pNext) + { + ; }
+ /* Add to the end */ + pCurrent->pNext = pNew; + pNew->pPrev = pCurrent; + return pNew; }
@@ -193,20 +196,17 @@ VOID InputList_Destroy(VOID) { INPUT_LIST_NODE *pCurrent; + INPUT_LIST_NODE *pNext;
if (_InputList == NULL) return;
- pCurrent = _InputList; - - while (pCurrent != NULL) + for (pCurrent = _InputList; pCurrent; pCurrent = pNext) { - INPUT_LIST_NODE *pNext = pCurrent->pNext; + pNext = pCurrent->pNext;
free(pCurrent->pszIndicator); free(pCurrent); - - pCurrent = pNext; }
_InputList = NULL; @@ -214,11 +214,12 @@ InputList_Destroy(VOID)
static BOOL -InputList_PrepareUserRegistry(VOID) +InputList_PrepareUserRegistry(PHKEY phPreloadKey, PHKEY phSubstKey) { BOOL bResult = FALSE; - HKEY hTempKey = NULL; - HKEY hKey = NULL; + HKEY hKey; + + *phPreloadKey = *phSubstKey = NULL;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout", @@ -232,101 +233,143 @@ InputList_PrepareUserRegistry(VOID) RegCloseKey(hKey); }
- if (RegCreateKeyW(HKEY_CURRENT_USER, L"Keyboard Layout", &hKey) != ERROR_SUCCESS) + if (RegCreateKeyW(HKEY_CURRENT_USER, L"Keyboard Layout", &hKey) == ERROR_SUCCESS && + RegCreateKeyW(hKey, L"Preload", phPreloadKey) == ERROR_SUCCESS && + RegCreateKeyW(hKey, L"Substitutes", phSubstKey) == ERROR_SUCCESS) { - goto Cleanup; + bResult = TRUE; }
- if (RegCreateKeyW(hKey, L"Preload", &hTempKey) != ERROR_SUCCESS) - { - goto Cleanup; - } + if (hKey) + RegCloseKey(hKey);
- RegCloseKey(hTempKey); + return bResult; +}
- if (RegCreateKeyW(hKey, L"Substitutes", &hTempKey) != ERROR_SUCCESS) +static BOOL +InputList_FindPreloadKLID(HKEY hPreloadKey, DWORD dwKLID) +{ + DWORD dwNumber, dwType, cbValue; + WCHAR szNumber[16], szValue[KL_NAMELENGTH], szKLID[KL_NAMELENGTH]; + + StringCchPrintfW(szKLID, ARRAYSIZE(szKLID), L"%08x", dwKLID); + + for (dwNumber = 1; dwNumber <= 1000; ++dwNumber) { - goto Cleanup; - } + StringCchPrintfW(szNumber, ARRAYSIZE(szNumber), L"%u", dwNumber);
- RegCloseKey(hTempKey); + cbValue = ARRAYSIZE(szValue) * sizeof(WCHAR); + if (RegQueryValueExW(hPreloadKey, szNumber, NULL, &dwType, + (LPBYTE)szValue, &cbValue) != ERROR_SUCCESS) + { + break; + }
- bResult = TRUE; + if (dwType != REG_SZ) + continue;
-Cleanup: - if (hTempKey != NULL) - RegCloseKey(hTempKey); - if (hKey != NULL) - RegCloseKey(hKey); + szValue[ARRAYSIZE(szValue) - 1] = 0; + if (_wcsicmp(szKLID, szValue) == 0) + return TRUE; + }
- return bResult; + return FALSE; }
- -static VOID -InputList_AddInputMethodToUserRegistry(DWORD dwIndex, INPUT_LIST_NODE *pNode) +static BOOL +InputList_WriteSubst(HKEY hSubstKey, DWORD dwPhysicalKLID, DWORD dwLogicalKLID) { - WCHAR szMethodIndex[MAX_PATH]; - WCHAR szPreload[MAX_PATH]; - BOOL bIsImeMethod = FALSE; - HKEY hKey; + DWORD cbValue; + WCHAR szLogicalKLID[KL_NAMELENGTH], szPhysicalKLID[KL_NAMELENGTH];
- StringCchPrintfW(szMethodIndex, ARRAYSIZE(szMethodIndex), L"%lu", dwIndex); + StringCchPrintfW(szLogicalKLID, ARRAYSIZE(szLogicalKLID), L"%08x", dwLogicalKLID); + StringCchPrintfW(szPhysicalKLID, ARRAYSIZE(szPhysicalKLID), L"%08x", dwPhysicalKLID);
- /* Check is IME method */ - if ((HIWORD(pNode->pLayout->dwId) & 0xF000) == 0xE000) - { - StringCchPrintfW(szPreload, ARRAYSIZE(szPreload), L"%08X", pNode->pLayout->dwId); - bIsImeMethod = TRUE; - } - else - { - StringCchPrintfW(szPreload, ARRAYSIZE(szPreload), L"%08X", pNode->pLocale->dwId); - } + cbValue = (wcslen(szPhysicalKLID) + 1) * sizeof(WCHAR); + return RegSetValueExW(hSubstKey, szLogicalKLID, 0, REG_SZ, (LPBYTE)szPhysicalKLID, + cbValue) == ERROR_SUCCESS; +}
- if (RegOpenKeyExW(HKEY_CURRENT_USER, - L"Keyboard Layout\Preload", - 0, - KEY_SET_VALUE, - &hKey) == ERROR_SUCCESS) +static DWORD +InputList_DoSubst(HKEY hPreloadKey, HKEY hSubstKey, + DWORD dwPhysicalKLID, DWORD dwLogicalKLID) +{ + DWORD iTrial; + BOOL bSubstNeeded = (dwPhysicalKLID != dwLogicalKLID) || (HIWORD(dwPhysicalKLID) != 0); + + for (iTrial = 1; iTrial <= 1000; ++iTrial) { - RegSetValueExW(hKey, - szMethodIndex, - 0, - REG_SZ, - (LPBYTE)szPreload, - (wcslen(szPreload) + 1) * sizeof(WCHAR)); + if (!InputList_FindPreloadKLID(hPreloadKey, dwLogicalKLID)) /* Not found? */ + { + if (bSubstNeeded) + { + /* Write now */ + InputList_WriteSubst(hSubstKey, dwPhysicalKLID, dwLogicalKLID); + } + return dwLogicalKLID; + }
- RegCloseKey(hKey); - } + bSubstNeeded = TRUE;
- if (pNode->pLocale->dwId != pNode->pLayout->dwId && bIsImeMethod == FALSE) - { - if (RegOpenKeyExW(HKEY_CURRENT_USER, - L"Keyboard Layout\Substitutes", - 0, - KEY_SET_VALUE, - &hKey) == ERROR_SUCCESS) + /* Calculate the next logical KLID */ + if (!IS_SUBST_KLID(dwLogicalKLID)) + { + dwLogicalKLID |= SUBST_MASK; + } + else { - WCHAR szSubstitutes[MAX_PATH]; + WORD wLow = LOWORD(dwLogicalKLID); + WORD wHigh = HIWORD(dwLogicalKLID); + dwLogicalKLID = MAKELONG(wLow, wHigh + 1); + } + }
- StringCchPrintfW(szSubstitutes, ARRAYSIZE(szSubstitutes), L"%08X", pNode->pLayout->dwId); + return 0; +}
- RegSetValueExW(hKey, - szPreload, - 0, - REG_SZ, - (LPBYTE)szSubstitutes, - (wcslen(szSubstitutes) + 1) * sizeof(WCHAR)); +static VOID +InputList_AddInputMethodToUserRegistry( + HKEY hPreloadKey, + HKEY hSubstKey, + DWORD dwNumber, + INPUT_LIST_NODE *pNode) +{ + WCHAR szNumber[32], szLogicalKLID[KL_NAMELENGTH]; + DWORD dwPhysicalKLID, dwLogicalKLID, cbValue; + HKL hKL = pNode->hkl;
- RegCloseKey(hKey); - } + if (IS_IME_HKL(hKL)) /* IME? */ + { + /* Do not substitute the IME KLID */ + dwLogicalKLID = dwPhysicalKLID = HandleToUlong(hKL); + } + else + { + /* Substitute the KLID if necessary */ + dwPhysicalKLID = pNode->pLayout->dwKLID; + dwLogicalKLID = pNode->pLocale->dwId; + dwLogicalKLID = InputList_DoSubst(hPreloadKey, hSubstKey, dwPhysicalKLID, dwLogicalKLID); }
+ /* Write the Preload value (number |--> logical KLID) */ + StringCchPrintfW(szNumber, ARRAYSIZE(szNumber), L"%lu", dwNumber); + StringCchPrintfW(szLogicalKLID, ARRAYSIZE(szLogicalKLID), L"%08x", dwLogicalKLID); + cbValue = (wcslen(szLogicalKLID) + 1) * sizeof(WCHAR); + RegSetValueExW(hPreloadKey, + szNumber, + 0, + REG_SZ, + (LPBYTE)szLogicalKLID, + cbValue); + if ((pNode->wFlags & INPUT_LIST_NODE_FLAG_ADDED) || (pNode->wFlags & INPUT_LIST_NODE_FLAG_EDITED)) { - pNode->hkl = LoadKeyboardLayoutW(szPreload, KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL); + UINT uFlags = KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL; + if (pNode->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT) + uFlags |= KLF_REPLACELANG; + + pNode->hkl = LoadKeyboardLayoutW(szLogicalKLID, uFlags); } }
@@ -338,19 +381,30 @@ BOOL InputList_Process(VOID) { INPUT_LIST_NODE *pCurrent; - DWORD dwIndex; + DWORD dwNumber; BOOL bRet = FALSE; + HKEY hPreloadKey, hSubstKey;
- /* Process deleted and edited input methods */ + if (!InputList_PrepareUserRegistry(&hPreloadKey, &hSubstKey)) + { + if (hPreloadKey) + RegCloseKey(hPreloadKey); + if (hSubstKey) + RegCloseKey(hSubstKey); + return FALSE; + } + + /* Process DELETED and EDITED entries */ for (pCurrent = _InputList; pCurrent != NULL; pCurrent = pCurrent->pNext) { if ((pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DELETED) || (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_EDITED)) { + /* Only unload the DELETED and EDITED entries */ if (UnloadKeyboardLayout(pCurrent->hkl)) { - /* Only unload the edited input method, but does not delete it from the list */ - if (!(pCurrent->wFlags & INPUT_LIST_NODE_FLAG_EDITED)) + /* But the EDITED entries are used later */ + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DELETED) { InputList_RemoveNode(pCurrent); } @@ -358,27 +412,44 @@ InputList_Process(VOID) } }
- InputList_PrepareUserRegistry(); - - /* Find default input method */ + /* Add the DEFAULT entry and set font substitutes */ for (pCurrent = _InputList; pCurrent != NULL; pCurrent = pCurrent->pNext) { + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DELETED) + continue; + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT) { bRet = InputList_SetFontSubstitutes(pCurrent->pLocale->dwId); - InputList_AddInputMethodToUserRegistry(1, pCurrent); + InputList_AddInputMethodToUserRegistry(hPreloadKey, hSubstKey, 1, pCurrent); break; } }
- if (SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, - 0, - (LPVOID)((LPDWORD)&pCurrent->hkl), - 0)) + /* Add entries except DEFAULT to registry */ + dwNumber = 2; + for (pCurrent = _InputList; pCurrent != NULL; pCurrent = pCurrent->pNext) { - DWORD dwRecipients; + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DELETED) + continue; + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT) + continue;
- dwRecipients = BSM_ALLCOMPONENTS; + InputList_AddInputMethodToUserRegistry(hPreloadKey, hSubstKey, dwNumber, pCurrent); + + ++dwNumber; + } + + /* Remove ADDED and EDITED flags */ + for (pCurrent = _InputList; pCurrent != NULL; pCurrent = pCurrent->pNext) + { + pCurrent->wFlags &= ~(INPUT_LIST_NODE_FLAG_ADDED | INPUT_LIST_NODE_FLAG_EDITED); + } + + /* Change the default keyboard language */ + if (SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, 0, &pCurrent->hkl, 0)) + { + DWORD dwRecipients = BSM_ALLCOMPONENTS | BSM_ALLDESKTOPS;
BroadcastSystemMessageW(BSF_POSTMESSAGE, &dwRecipients, @@ -387,19 +458,18 @@ InputList_Process(VOID) (LPARAM)pCurrent->hkl); }
- /* Add methods to registry */ - dwIndex = 2; - + /* Retry to delete (in case of failure to delete the default keyboard) */ for (pCurrent = _InputList; pCurrent != NULL; pCurrent = pCurrent->pNext) { - if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT) - continue; - - InputList_AddInputMethodToUserRegistry(dwIndex, pCurrent); - - dwIndex++; + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DELETED) + { + UnloadKeyboardLayout(pCurrent->hkl); + InputList_RemoveNode(pCurrent); + } }
+ RegCloseKey(hPreloadKey); + RegCloseKey(hSubstKey); return bRet; }
@@ -408,7 +478,7 @@ BOOL InputList_Add(LOCALE_LIST_NODE *pLocale, LAYOUT_LIST_NODE *pLayout) { WCHAR szIndicator[MAX_STR_LEN]; - INPUT_LIST_NODE *pInput; + INPUT_LIST_NODE *pInput = NULL;
if (pLocale == NULL || pLayout == NULL) { @@ -417,16 +487,17 @@ InputList_Add(LOCALE_LIST_NODE *pLocale, LAYOUT_LIST_NODE *pLayout)
for (pInput = _InputList; pInput != NULL; pInput = pInput->pNext) { + if (pInput->wFlags & INPUT_LIST_NODE_FLAG_DELETED) + continue; + if (pInput->pLocale == pLocale && pInput->pLayout == pLayout) { - return FALSE; + return FALSE; /* Already exists */ } }
pInput = InputList_AppendNode(); - pInput->wFlags = INPUT_LIST_NODE_FLAG_ADDED; - pInput->pLocale = pLocale; pInput->pLayout = pLayout;
@@ -469,6 +540,29 @@ InputList_SetDefault(INPUT_LIST_NODE *pNode) } }
+INPUT_LIST_NODE * +InputList_FindNextDefault(INPUT_LIST_NODE *pNode) +{ + INPUT_LIST_NODE *pCurrent; + + for (pCurrent = pNode->pNext; pCurrent; pCurrent = pCurrent->pNext) + { + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DELETED) + continue; + + return pCurrent; + } + + for (pCurrent = pNode->pPrev; pCurrent; pCurrent = pCurrent->pPrev) + { + if (pCurrent->wFlags & INPUT_LIST_NODE_FLAG_DELETED) + continue; + + return pCurrent; + } + + return NULL; +}
/* * It marks the input method for deletion, but does not delete it directly. @@ -492,22 +586,19 @@ InputList_Remove(INPUT_LIST_NODE *pNode) } else { - pNode->wFlags = INPUT_LIST_NODE_FLAG_DELETED; + pNode->wFlags |= INPUT_LIST_NODE_FLAG_DELETED; }
if (pNode->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT) { - if (pNode->pNext != NULL) - { - pNode->pNext->wFlags |= INPUT_LIST_NODE_FLAG_DEFAULT; - } - else if (pNode->pPrev != NULL) - { - pNode->pPrev->wFlags |= INPUT_LIST_NODE_FLAG_DEFAULT; - } + INPUT_LIST_NODE *pCurrent = InputList_FindNextDefault(pNode); + if (pCurrent) + pCurrent->wFlags |= INPUT_LIST_NODE_FLAG_DEFAULT; + + pNode->wFlags &= ~INPUT_LIST_NODE_FLAG_DEFAULT; }
- if (bRemoveNode != FALSE) + if (bRemoveNode) { InputList_RemoveNode(pNode); } @@ -517,67 +608,58 @@ InputList_Remove(INPUT_LIST_NODE *pNode) VOID InputList_Create(VOID) { - INT iLayoutCount; - HKL *pLayoutList; + INT iLayoutCount, iIndex; + WCHAR szIndicator[MAX_STR_LEN]; + INPUT_LIST_NODE *pInput; + HKL *pLayoutList, hklDefault; + + SystemParametersInfoW(SPI_GETDEFAULTINPUTLANG, 0, &hklDefault, 0);
iLayoutCount = GetKeyboardLayoutList(0, NULL); pLayoutList = (HKL*) malloc(iLayoutCount * sizeof(HKL));
- if (pLayoutList != NULL) + if (!pLayoutList || GetKeyboardLayoutList(iLayoutCount, pLayoutList) <= 0) { - if (GetKeyboardLayoutList(iLayoutCount, pLayoutList) > 0) + free(pLayoutList); + return; + } + + for (iIndex = 0; iIndex < iLayoutCount; ++iIndex) + { + HKL hKL = pLayoutList[iIndex]; + LOCALE_LIST_NODE *pLocale = LocaleList_GetByHkl(hKL); + LAYOUT_LIST_NODE *pLayout = LayoutList_GetByHkl(hKL); + if (!pLocale || !pLayout) + continue; + + pInput = InputList_AppendNode(); + pInput->pLocale = pLocale; + pInput->pLayout = pLayout; + pInput->hkl = hKL; + + if (pInput->hkl == hklDefault) /* Default HKL? */ { - INT iIndex; + pInput->wFlags |= INPUT_LIST_NODE_FLAG_DEFAULT; + hklDefault = NULL; /* No more default item */ + }
- for (iIndex = 0; iIndex < iLayoutCount; iIndex++) + /* Get abbrev language name */ + szIndicator[0] = 0; + if (GetLocaleInfoW(LOWORD(pInput->pLocale->dwId), + LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE, + szIndicator, + ARRAYSIZE(szIndicator))) + { + size_t len = wcslen(szIndicator); + if (len > 0) { - LOCALE_LIST_NODE *pLocale = LocaleList_GetByHkl(pLayoutList[iIndex]); - LAYOUT_LIST_NODE *pLayout = LayoutList_GetByHkl(pLayoutList[iIndex]); - - if (pLocale != NULL && pLayout != NULL) - { - WCHAR szIndicator[MAX_STR_LEN] = { 0 }; - INPUT_LIST_NODE *pInput; - HKL hklDefault; - - pInput = InputList_AppendNode(); - - pInput->pLocale = pLocale; - pInput->pLayout = pLayout; - pInput->hkl = pLayoutList[iIndex]; - - if (SystemParametersInfoW(SPI_GETDEFAULTINPUTLANG, - 0, - (LPVOID)((LPDWORD)&hklDefault), - 0) == FALSE) - { - hklDefault = GetKeyboardLayout(0); - } - - if (pInput->hkl == hklDefault) - { - pInput->wFlags |= INPUT_LIST_NODE_FLAG_DEFAULT; - } - - if (GetLocaleInfoW(LOWORD(pInput->pLocale->dwId), - LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE, - szIndicator, - ARRAYSIZE(szIndicator))) - { - size_t len = wcslen(szIndicator); - - if (len > 0) - { - szIndicator[len - 1] = 0; - pInput->pszIndicator = _wcsdup(szIndicator); - } - } - } + szIndicator[len - 1] = 0; + pInput->pszIndicator = _wcsdup(szIndicator); } } - - free(pLayoutList); } + + free(pLayoutList); }
diff --git a/dll/cpl/input/input_list.h b/dll/cpl/input/input_list.h index e578cc70423..5c947dbaae2 100644 --- a/dll/cpl/input/input_list.h +++ b/dll/cpl/input/input_list.h @@ -4,12 +4,30 @@ #include "locale_list.h" #include "layout_list.h"
- +/* + * INPUT_LIST_NODE_FLAG_EDITED + * --- The modification flag. Since previous time, this entry is modified. + */ #define INPUT_LIST_NODE_FLAG_EDITED 0x0001 + +/* + * INPUT_LIST_NODE_FLAG_ADDED + * --- The addition flag. Since previous time, this entry is newly added. + */ #define INPUT_LIST_NODE_FLAG_ADDED 0x0002 + +/* + * INPUT_LIST_NODE_FLAG_DELETED + * --- The deletion flag. + * The application should ignore the entry with this flag if necessary. + */ #define INPUT_LIST_NODE_FLAG_DELETED 0x0004 -#define INPUT_LIST_NODE_FLAG_DEFAULT 0x0008
+/* + * INPUT_LIST_NODE_FLAG_DEFAULT + * --- The default flag. The entry with this flag should be single in the list. + */ +#define INPUT_LIST_NODE_FLAG_DEFAULT 0x0008
typedef struct _INPUT_LIST_NODE { @@ -20,7 +38,7 @@ typedef struct _INPUT_LIST_NODE
HKL hkl; /* Only for loaded input methods */
- WCHAR *pszIndicator; + LPWSTR pszIndicator;
struct _INPUT_LIST_NODE *pPrev; struct _INPUT_LIST_NODE *pNext; diff --git a/dll/cpl/input/layout_list.c b/dll/cpl/input/layout_list.c index 7a06ea77f70..9d6622312ee 100644 --- a/dll/cpl/input/layout_list.c +++ b/dll/cpl/input/layout_list.c @@ -3,16 +3,16 @@ * FILE: dll/cpl/input/layout_list.c * PURPOSE: input.dll * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) + * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) */
#include "layout_list.h"
- static LAYOUT_LIST_NODE *_LayoutList = NULL;
- static LAYOUT_LIST_NODE* -LayoutList_AppendNode(DWORD dwId, DWORD dwSpecialId, const WCHAR *pszName) +LayoutList_AppendNode(DWORD dwKLID, WORD wSpecialId, LPCWSTR pszFile, LPCWSTR pszName, + LPCWSTR pszImeFile) { LAYOUT_LIST_NODE *pCurrent; LAYOUT_LIST_NODE *pNew; @@ -28,16 +28,22 @@ LayoutList_AppendNode(DWORD dwId, DWORD dwSpecialId, const WCHAR *pszName)
ZeroMemory(pNew, sizeof(LAYOUT_LIST_NODE));
+ pNew->dwKLID = dwKLID; + pNew->wSpecialId = wSpecialId; + pNew->pszName = _wcsdup(pszName); - if (pNew->pszName == NULL) + pNew->pszFile = _wcsdup(pszFile); + pNew->pszImeFile = _wcsdup(pszImeFile); + if (pNew->pszName == NULL || pNew->pszFile == NULL || + (pszImeFile && pNew->pszImeFile == NULL)) { + free(pNew->pszName); + free(pNew->pszFile); + free(pNew->pszImeFile); free(pNew); return NULL; }
- pNew->dwId = dwId; - pNew->dwSpecialId = dwSpecialId; - if (pCurrent == NULL) { _LayoutList = pNew; @@ -61,90 +67,136 @@ VOID LayoutList_Destroy(VOID) { LAYOUT_LIST_NODE *pCurrent; + LAYOUT_LIST_NODE *pNext;
if (_LayoutList == NULL) return;
- pCurrent = _LayoutList; - - while (pCurrent != NULL) + for (pCurrent = _LayoutList; pCurrent; pCurrent = pNext) { - LAYOUT_LIST_NODE *pNext = pCurrent->pNext; + pNext = pCurrent->pNext;
free(pCurrent->pszName); + free(pCurrent->pszFile); + free(pCurrent->pszImeFile); free(pCurrent); - - pCurrent = pNext; }
_LayoutList = NULL; }
-static BOOL -LayoutList_ReadLayout(HKEY hLayoutKey, LPCWSTR szLayoutId, LPCWSTR szSystemDirectory) +typedef HRESULT (WINAPI *FN_SHLoadRegUIStringW)(HKEY, LPCWSTR, LPWSTR, DWORD); + +/* FIXME: Use shlwapi!SHLoadRegUIStringW instead when it is fully implemented */ +HRESULT FakeSHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size) { - WCHAR szBuffer[MAX_PATH], szFilePath[MAX_PATH], szDllPath[MAX_PATH]; - INT iIndex, iLength = 0; - DWORD dwSize, dwSpecialId, dwLayoutId = DWORDfromString(szLayoutId); +#if 1 + PWCHAR pBuffer, pIndex; + WCHAR szDllPath[MAX_PATH]; + DWORD dwSize; HINSTANCE hDllInst; + INT iIndex, iLength;
- dwSize = sizeof(szBuffer); + dwSize = size * sizeof(WCHAR); + if (RegQueryValueExW(hkey, value, NULL, NULL, (LPBYTE)buf, &dwSize) != ERROR_SUCCESS) + return E_FAIL; + + if (buf[0] != L'@') + return S_OK; + + /* Move to the position after the character "@" */ + pBuffer = buf + 1; + + /* Get a pointer to the beginning ",-" */ + pIndex = wcsstr(pBuffer, L",-"); + if (!pIndex) + return E_FAIL; + + /* Convert the number in the string after the ",-" */ + iIndex = _wtoi(pIndex + 2); + + *pIndex = 0; /* Cut the string */ + + if (ExpandEnvironmentStringsW(pBuffer, szDllPath, ARRAYSIZE(szDllPath)) == 0) + return E_FAIL; + + hDllInst = LoadLibraryW(szDllPath); + if (!hDllInst) + return E_FAIL; + + iLength = LoadStringW(hDllInst, iIndex, buf, size); + FreeLibrary(hDllInst); + + if (iLength <= 0) + return E_FAIL; + + return S_OK; +#else + HRESULT hr = E_FAIL; + HINSTANCE hSHLWAPI = LoadLibraryW(L"shlwapi"); + FN_SHLoadRegUIStringW fn; + fn = (FN_SHLoadRegUIStringW)GetProcAddress(hSHLWAPI, (LPCSTR)(INT_PTR)439); + if (fn) + hr = fn(hkey, value, buf, size); + FreeLibrary(hSHLWAPI); + return hr; +#endif +} + +static BOOL +LayoutList_ReadLayout(HKEY hLayoutKey, LPCWSTR szKLID, LPCWSTR szSystemDirectory) +{ + WCHAR szFile[80], szImeFile[80], szBuffer[MAX_PATH], szFilePath[MAX_PATH]; + DWORD dwSize, dwKLID = DWORDfromString(szKLID); + WORD wSpecialId = 0; + LPWSTR pszImeFile = NULL; + + dwSize = sizeof(szFile); if (RegQueryValueExW(hLayoutKey, L"Layout File", NULL, NULL, - (LPBYTE)szBuffer, &dwSize) != ERROR_SUCCESS) + (LPBYTE)szFile, &dwSize) != ERROR_SUCCESS) { return FALSE; /* No "Layout File" value */ }
+ if (IS_IME_KLID(dwKLID)) + { + WCHAR szPath[MAX_PATH]; + dwSize = sizeof(szImeFile); + if (RegQueryValueExW(hLayoutKey, L"IME File", NULL, NULL, + (LPBYTE)szImeFile, &dwSize) != ERROR_SUCCESS) + { + return FALSE; /* No "IME File" value */ + } + + if (wcschr(szImeFile, L'\') != NULL) + return FALSE; /* Invalid character */ + + GetSystemLibraryPath(szPath, ARRAYSIZE(szPath), szImeFile); + if (GetFileAttributesW(szPath) == INVALID_FILE_ATTRIBUTES) + return FALSE; /* Does not exist */ + + pszImeFile = szImeFile; + } + /* Build the "Layout File" full path and check existence */ - StringCchPrintfW(szFilePath, ARRAYSIZE(szFilePath), L"%s\%s", szSystemDirectory, szBuffer); + StringCchPrintfW(szFilePath, ARRAYSIZE(szFilePath), L"%s\%s", szSystemDirectory, szFile); if (GetFileAttributesW(szFilePath) == INVALID_FILE_ATTRIBUTES) return FALSE; /* No layout file found */
/* Get the special ID */ - dwSpecialId = 0; dwSize = sizeof(szBuffer); if (RegQueryValueExW(hLayoutKey, L"Layout Id", NULL, NULL, (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS) { - dwSpecialId = DWORDfromString(szBuffer); + wSpecialId = LOWORD(DWORDfromString(szBuffer)); }
/* If there is a valid "Layout Display Name", then use it as the entry name */ - dwSize = sizeof(szBuffer); - if (RegQueryValueExW(hLayoutKey, L"Layout Display Name", NULL, NULL, - (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS && szBuffer[0] == L'@') + if (FakeSHLoadRegUIStringW(hLayoutKey, L"Layout Display Name", + szBuffer, ARRAYSIZE(szBuffer)) == S_OK) { - /* FIXME: Use shlwapi!SHLoadRegUIStringW instead if it had fully implemented */ - - /* Move to the position after the character "@" */ - WCHAR *pBuffer = szBuffer + 1; - - /* Get a pointer to the beginning ",-" */ - WCHAR *pIndex = wcsstr(pBuffer, L",-"); - - if (pIndex) - { - /* Convert the number in the string after the ",-" */ - iIndex = _wtoi(pIndex + 2); - - *pIndex = 0; /* Cut the string */ - - if (ExpandEnvironmentStringsW(pBuffer, szDllPath, ARRAYSIZE(szDllPath)) != 0) - { - hDllInst = LoadLibraryW(szDllPath); - if (hDllInst) - { - iLength = LoadStringW(hDllInst, iIndex, szBuffer, ARRAYSIZE(szBuffer)); - FreeLibrary(hDllInst); - - if (iLength > 0) - { - LayoutList_AppendNode(dwLayoutId, dwSpecialId, szBuffer); - return TRUE; - } - } - } - } + LayoutList_AppendNode(dwKLID, wSpecialId, szFile, szBuffer, pszImeFile); + return TRUE; }
/* Otherwise, use "Layout Text" value as the entry name */ @@ -152,7 +204,7 @@ LayoutList_ReadLayout(HKEY hLayoutKey, LPCWSTR szLayoutId, LPCWSTR szSystemDirec if (RegQueryValueExW(hLayoutKey, L"Layout Text", NULL, NULL, (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS) { - LayoutList_AppendNode(dwLayoutId, dwSpecialId, szBuffer); + LayoutList_AppendNode(dwKLID, wSpecialId, szFile, szBuffer, pszImeFile); return TRUE; }
@@ -162,7 +214,7 @@ LayoutList_ReadLayout(HKEY hLayoutKey, LPCWSTR szLayoutId, LPCWSTR szSystemDirec VOID LayoutList_Create(VOID) { - WCHAR szSystemDirectory[MAX_PATH], szLayoutId[MAX_PATH]; + WCHAR szSystemDirectory[MAX_PATH], szKLID[KL_NAMELENGTH]; DWORD dwSize, dwIndex; HKEY hKey, hLayoutKey;
@@ -170,23 +222,23 @@ LayoutList_Create(VOID) return;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\CurrentControlSet\Control\Keyboard Layouts", - 0, KEY_ENUMERATE_SUB_KEYS, &hKey) != ERROR_SUCCESS) + 0, KEY_READ, &hKey) != ERROR_SUCCESS) { return; }
for (dwIndex = 0; ; ++dwIndex) { - dwSize = ARRAYSIZE(szLayoutId); - if (RegEnumKeyExW(hKey, dwIndex, szLayoutId, &dwSize, NULL, NULL, + dwSize = ARRAYSIZE(szKLID); + if (RegEnumKeyExW(hKey, dwIndex, szKLID, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { break; }
- if (RegOpenKeyExW(hKey, szLayoutId, 0, KEY_QUERY_VALUE, &hLayoutKey) == ERROR_SUCCESS) + if (RegOpenKeyExW(hKey, szKLID, 0, KEY_QUERY_VALUE, &hLayoutKey) == ERROR_SUCCESS) { - LayoutList_ReadLayout(hLayoutKey, szLayoutId, szSystemDirectory); + LayoutList_ReadLayout(hLayoutKey, szKLID, szSystemDirectory); RegCloseKey(hLayoutKey); } } @@ -200,13 +252,23 @@ LayoutList_GetByHkl(HKL hkl) { LAYOUT_LIST_NODE *pCurrent;
- if ((HIWORD(hkl) & 0xF000) == 0xF000) + if (IS_SPECIAL_HKL(hkl)) { - DWORD dwSpecialId = (HIWORD(hkl) & 0x0FFF); + WORD wSpecialId = SPECIALIDFROMHKL(hkl);
for (pCurrent = _LayoutList; pCurrent != NULL; pCurrent = pCurrent->pNext) { - if (dwSpecialId == pCurrent->dwSpecialId) + if (wSpecialId == pCurrent->wSpecialId) + { + return pCurrent; + } + } + } + else if (IS_IME_HKL(hkl)) + { + for (pCurrent = _LayoutList; pCurrent != NULL; pCurrent = pCurrent->pNext) + { + if (hkl == UlongToHandle(pCurrent->dwKLID)) { return pCurrent; } @@ -216,7 +278,7 @@ LayoutList_GetByHkl(HKL hkl) { for (pCurrent = _LayoutList; pCurrent != NULL; pCurrent = pCurrent->pNext) { - if (HIWORD(hkl) == LOWORD(pCurrent->dwId)) + if (HIWORD(hkl) == LOWORD(pCurrent->dwKLID)) { return pCurrent; } diff --git a/dll/cpl/input/layout_list.h b/dll/cpl/input/layout_list.h index bbd0a0d0740..630fff7b1c5 100644 --- a/dll/cpl/input/layout_list.h +++ b/dll/cpl/input/layout_list.h @@ -4,10 +4,11 @@
typedef struct _LAYOUT_LIST_NODE { - WCHAR *pszName; - - DWORD dwId; - DWORD dwSpecialId; + DWORD dwKLID; /* The physical KLID */ + WORD wSpecialId; /* The special ID */ + LPWSTR pszName; /* The layout text */ + LPWSTR pszFile; /* The layout file */ + LPWSTR pszImeFile; /* The IME file */
struct _LAYOUT_LIST_NODE *pPrev; struct _LAYOUT_LIST_NODE *pNext; diff --git a/dll/cpl/input/settings_page.c b/dll/cpl/input/settings_page.c index 7785528dc4f..aeed2ad7e2c 100644 --- a/dll/cpl/input/settings_page.c +++ b/dll/cpl/input/settings_page.c @@ -11,7 +11,6 @@ #include "locale_list.h" #include "input_list.h"
- static HICON CreateLayoutIcon(LPWSTR szLayout, BOOL bIsDefault) { @@ -112,23 +111,37 @@ CreateLayoutIcon(LPWSTR szLayout, BOOL bIsDefault)
static VOID -SetControlsState(HWND hwndDlg, BOOL bIsEnabled) +SetControlsState(HWND hwndDlg) { - EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE_BUTTON), bIsEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROP_BUTTON), bIsEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_SET_DEFAULT), bIsEnabled); -} + HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); + INT iSelected = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED); + INT nCount = ListView_GetItemCount(hwndList); + BOOL bCanRemove = (iSelected != -1) && (nCount >= 2); + BOOL bCanDefault = (iSelected != -1) && (nCount >= 2); + BOOL bCanProp = (iSelected != -1); + + LV_ITEM item = { LVIF_PARAM, iSelected }; + if (ListView_GetItem(hwndList, &item)) + { + INPUT_LIST_NODE *pInput = (INPUT_LIST_NODE*)item.lParam; + + if (pInput && (pInput->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT)) + { + bCanDefault = FALSE; + } + }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE_BUTTON), bCanRemove); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROP_BUTTON), bCanProp); + EnableWindow(GetDlgItem(hwndDlg, IDC_SET_DEFAULT), bCanDefault); +}
static VOID AddToInputListView(HWND hwndList, INPUT_LIST_NODE *pInputNode) { - INT ItemIndex = -1; - INT ImageIndex = -1; + INT ItemIndex, ImageIndex = -1; LV_ITEM item; - HIMAGELIST hImageList; - - hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL); + HIMAGELIST hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL);
if (hImageList != NULL) { @@ -136,7 +149,6 @@ AddToInputListView(HWND hwndList, INPUT_LIST_NODE *pInputNode)
hLayoutIcon = CreateLayoutIcon(pInputNode->pszIndicator, (pInputNode->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT)); - if (hLayoutIcon != NULL) { ImageIndex = ImageList_AddIcon(hImageList, hLayoutIcon); @@ -145,13 +157,11 @@ AddToInputListView(HWND hwndList, INPUT_LIST_NODE *pInputNode) }
ZeroMemory(&item, sizeof(item)); - item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; item.pszText = pInputNode->pLocale->pszName; - item.iItem = ListView_GetItemCount(hwndList) + 1; + item.iItem = ListView_GetItemCount(hwndList); item.lParam = (LPARAM)pInputNode; item.iImage = ImageIndex; - ItemIndex = ListView_InsertItem(hwndList, &item);
ListView_SetItemText(hwndList, ItemIndex, 1, pInputNode->pLayout->pszName); @@ -161,52 +171,55 @@ AddToInputListView(HWND hwndList, INPUT_LIST_NODE *pInputNode) static VOID UpdateInputListView(HWND hwndList) { - INPUT_LIST_NODE *pCurrentInputNode; - HIMAGELIST hImageList; + INPUT_LIST_NODE *pNode; + HIMAGELIST hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL); + INT iSelected = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
- hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL); - if (hImageList != NULL) + if (hImageList) { ImageList_RemoveAll(hImageList); }
ListView_DeleteAllItems(hwndList);
- for (pCurrentInputNode = InputList_GetFirst(); - pCurrentInputNode != NULL; - pCurrentInputNode = pCurrentInputNode->pNext) + for (pNode = InputList_GetFirst(); pNode != NULL; pNode = pNode->pNext) { - if (!(pCurrentInputNode->wFlags & INPUT_LIST_NODE_FLAG_DELETED)) - { - AddToInputListView(hwndList, pCurrentInputNode); - } + if (pNode->wFlags & INPUT_LIST_NODE_FLAG_DELETED) + continue; + + AddToInputListView(hwndList, pNode); + } + + if (iSelected != -1) + { + INT nCount = ListView_GetItemCount(hwndList); + LV_ITEM item = { LVIF_STATE }; + item.state = item.stateMask = LVIS_SELECTED; + item.iItem = ((nCount == iSelected) ? nCount - 1 : iSelected); + ListView_SetItem(hwndList, &item); } + + InvalidateRect(hwndList, NULL, TRUE); }
static VOID OnInitSettingsPage(HWND hwndDlg) { - HWND hwndInputList; + HWND hwndInputList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST);
LayoutList_Create(); LocaleList_Create(); InputList_Create();
- hwndInputList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); - if (hwndInputList != NULL) { WCHAR szBuffer[MAX_STR_LEN]; HIMAGELIST hLayoutImageList; - LV_COLUMN column; + LV_COLUMN column = { LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM };
ListView_SetExtendedListViewStyle(hwndInputList, LVS_EX_FULLROWSELECT);
- ZeroMemory(&column, sizeof(column)); - - column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; - LoadStringW(hApplet, IDS_LANGUAGE, szBuffer, ARRAYSIZE(szBuffer)); column.fmt = LVCFMT_LEFT; column.iSubItem = 0; @@ -233,7 +246,7 @@ OnInitSettingsPage(HWND hwndDlg) UpdateInputListView(hwndInputList); }
- SetControlsState(hwndDlg, FALSE); + SetControlsState(hwndDlg); }
@@ -259,6 +272,7 @@ OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam) AddDialogProc) == IDOK) { UpdateInputListView(GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST)); + SetControlsState(hwndDlg); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } } @@ -266,21 +280,17 @@ OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam)
case IDC_REMOVE_BUTTON: { - HWND hwndList; - - hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); - - if (hwndList != NULL) + HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); + if (hwndList) { - LVITEM item = { 0 }; - - item.mask = LVIF_PARAM; + LVITEM item = { LVIF_PARAM }; item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
- if (ListView_GetItem(hwndList, &item) != FALSE) + if (ListView_GetItem(hwndList, &item)) { InputList_Remove((INPUT_LIST_NODE*) item.lParam); UpdateInputListView(hwndList); + SetControlsState(hwndDlg); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } } @@ -289,18 +299,13 @@ OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam)
case IDC_PROP_BUTTON: { - HWND hwndList; - - hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); - - if (hwndList != NULL) + HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); + if (hwndList) { - LVITEM item = { 0 }; - - item.mask = LVIF_PARAM; + LVITEM item = { LVIF_PARAM }; item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
- if (ListView_GetItem(hwndList, &item) != FALSE) + if (ListView_GetItem(hwndList, &item)) { if (DialogBoxParamW(hApplet, MAKEINTRESOURCEW(IDD_INPUT_LANG_PROP), @@ -309,6 +314,7 @@ OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam) item.lParam) == IDOK) { UpdateInputListView(hwndList); + SetControlsState(hwndDlg); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } } @@ -318,21 +324,17 @@ OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam)
case IDC_SET_DEFAULT: { - HWND hwndList; - - hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); - - if (hwndList != NULL) + HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); + if (hwndList) { - LVITEM item = { 0 }; - - item.mask = LVIF_PARAM; + LVITEM item = { LVIF_PARAM }; item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
- if (ListView_GetItem(hwndList, &item) != FALSE) + if (ListView_GetItem(hwndList, &item)) { InputList_SetDefault((INPUT_LIST_NODE*) item.lParam); UpdateInputListView(hwndList); + SetControlsState(hwndDlg); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } } @@ -350,73 +352,18 @@ OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam) } }
-BOOL EnableProcessPrivileges(LPCWSTR lpPrivilegeName, BOOL bEnable) -{ - HANDLE hToken; - LUID luid; - TOKEN_PRIVILEGES tokenPrivileges; - BOOL Ret; - - Ret = OpenProcessToken(GetCurrentProcess(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - &hToken); - if (!Ret) - return Ret; // failure - - Ret = LookupPrivilegeValueW(NULL, lpPrivilegeName, &luid); - if (Ret) - { - tokenPrivileges.PrivilegeCount = 1; - tokenPrivileges.Privileges[0].Luid = luid; - tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; - - Ret = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0); - } - - CloseHandle(hToken); - return Ret; -} - static VOID OnNotifySettingsPage(HWND hwndDlg, LPARAM lParam) { - LPNMHDR header; - - header = (LPNMHDR)lParam; + LPNMHDR header = (LPNMHDR)lParam;
switch (header->code) { - case NM_CLICK: + case LVN_ITEMCHANGED: { if (header->idFrom == IDC_KEYLAYOUT_LIST) { - INT iSelected = ListView_GetNextItem(header->hwndFrom, -1, LVNI_SELECTED); - - if (iSelected != -1) - { - LVITEM item = { 0 }; - - SetControlsState(hwndDlg, TRUE); - - item.mask = LVIF_PARAM; - item.iItem = iSelected; - - if (ListView_GetItem(header->hwndFrom, &item) != FALSE) - { - INPUT_LIST_NODE *pInput; - - pInput = (INPUT_LIST_NODE*) item.lParam; - - if (pInput != NULL && pInput->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT) - { - EnableWindow(GetDlgItem(hwndDlg, IDC_SET_DEFAULT), FALSE); - } - } - } - else - { - SetControlsState(hwndDlg, FALSE); - } + SetControlsState(hwndDlg); } } break; @@ -424,20 +371,7 @@ OnNotifySettingsPage(HWND hwndDlg, LPARAM lParam) case PSN_APPLY: { /* Write Input Methods list to registry */ - if (InputList_Process()) - { - /* Needs reboot */ - WCHAR szNeedsReboot[128], szLanguage[64]; - LoadStringW(hApplet, IDS_REBOOT_NOW, szNeedsReboot, _countof(szNeedsReboot)); - LoadStringW(hApplet, IDS_LANGUAGE, szLanguage, _countof(szLanguage)); - - if (MessageBoxW(hwndDlg, szNeedsReboot, szLanguage, - MB_ICONINFORMATION | MB_YESNOCANCEL) == IDYES) - { - EnableProcessPrivileges(SE_SHUTDOWN_NAME, TRUE); - ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0); - } - } + InputList_Process(); } break; } diff --git a/win32ss/user/user32/windows/input.c b/win32ss/user/user32/windows/input.c index 87df74fc06b..a9aac9e82a3 100644 --- a/win32ss/user/user32/windows/input.c +++ b/win32ss/user/user32/windows/input.c @@ -706,6 +706,13 @@ inline BOOL IsValidKLID(_In_ LPCWSTR pwszKLID) return (pwszKLID != NULL) && (wcsspn(pwszKLID, L"0123456789ABCDEFabcdef") == (KL_NAMELENGTH - 1)); }
+VOID GetSystemLibraryPath(LPWSTR pszPath, INT cchPath, LPCWSTR pszFileName) +{ + WCHAR szSysDir[MAX_PATH]; + GetSystemDirectoryW(szSysDir, _countof(szSysDir)); + StringCchPrintfW(pszPath, cchPath, L"%s\%s", szSysDir, pszFileName); +} + #define ENGLISH_US MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
/* @@ -722,15 +729,15 @@ IntLoadKeyboardLayout( _In_ UINT Flags, _In_ BOOL unknown5) { - DWORD dwhkl, dwType, dwSize; + DWORD dwKLID, dwHKL, dwType, dwSize; UNICODE_STRING ustrKbdName; UNICODE_STRING ustrKLID; WCHAR wszRegKey[256] = L"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\"; WCHAR wszLayoutId[10], wszNewKLID[KL_NAMELENGTH], szImeFileName[80]; - PWCHAR endptr; HKL hNewKL; HKEY hKey; BOOL bIsIME; + WORD wLow, wHigh;
if (!IsValidKLID(pwszKLID)) { @@ -738,13 +745,11 @@ IntLoadKeyboardLayout( return UlongToHandle(MAKELONG(ENGLISH_US, ENGLISH_US)); }
- dwhkl = wcstoul(pwszKLID, &endptr, 16); + dwKLID = wcstoul(pwszKLID, NULL, 16); + bIsIME = IS_IME_HKL(UlongToHandle(dwKLID));
- bIsIME = IS_IME_HKL(UlongToHandle(dwhkl)); - if (!bIsIME) /* Not IME? */ - { - dwhkl = LOWORD(dwhkl); /* LOWORD of dwhkl is language identifier */ - } + wLow = LOWORD(dwKLID); + wHigh = HIWORD(dwKLID);
if (Flags & KLF_SUBSTITUTE_OK) { @@ -753,10 +758,14 @@ IntLoadKeyboardLayout( KEY_READ, &hKey) == ERROR_SUCCESS) { dwSize = sizeof(wszNewKLID); - if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, &dwSize) == ERROR_SUCCESS) + if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, + &dwSize) == ERROR_SUCCESS && + dwType == REG_SZ) { /* Use new KLID value */ pwszKLID = wszNewKLID; + dwKLID = wcstoul(pwszKLID, NULL, 16); + wHigh = LOWORD(dwKLID); }
/* Close the key now */ @@ -771,14 +780,11 @@ IntLoadKeyboardLayout( if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { dwSize = sizeof(wszLayoutId); - if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS) + if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, + &dwSize) == ERROR_SUCCESS && dwType == REG_SZ) { /* If Layout Id is specified, use this value | f000 as HIWORD */ - /* FIXME: Microsoft Office expects this value to be something specific - * for Japanese and Korean Windows with an IME the value is 0xe001 - */ - if (!bIsIME) - dwhkl |= (0xf000 | wcstol(wszLayoutId, NULL, 16)) << 16; + wHigh = (0xF000 | wcstoul(wszLayoutId, NULL, 16)); }
if (bIsIME) @@ -788,9 +794,18 @@ IntLoadKeyboardLayout( if (RegQueryValueExW(hKey, L"IME File", NULL, &dwType, (LPBYTE)szImeFileName, &dwSize) != ERROR_SUCCESS) { - FIXME("Check IME file existence in system32\n"); bIsIME = FALSE; - dwhkl = LOWORD(dwhkl); + wHigh = 0; + } + else + { + WCHAR szPath[MAX_PATH]; + GetSystemLibraryPath(szPath, _countof(szPath), szImeFileName); + if (GetFileAttributesW(szPath) == INVALID_FILE_ATTRIBUTES) /* Does not exist? */ + { + bIsIME = FALSE; + wHigh = 0; + } } }
@@ -803,13 +818,14 @@ IntLoadKeyboardLayout( return NULL; }
- /* If Layout Id is not given HIWORD == LOWORD (for dwhkl) */ - if (!HIWORD(dwhkl)) - dwhkl |= dwhkl << 16; + if (wHigh == 0) + wHigh = wLow; + + dwHKL = MAKELONG(wLow, wHigh);
ZeroMemory(&ustrKbdName, sizeof(ustrKbdName)); RtlInitUnicodeString(&ustrKLID, pwszKLID); - hNewKL = NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName, NULL, &ustrKLID, dwhkl, Flags); + hNewKL = NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName, NULL, &ustrKLID, dwHKL, Flags); CliImmInitializeHotKeys(SETIMEHOTKEY_ADD, hNewKL); return hNewKL; }