From 8a32608dfe5485a4ce06cb1dee5b07f552742f17 Mon Sep 17 00:00:00 2001 From: Dmitry Chapyshev Date: Mon, 8 Aug 2016 20:30:36 +0000 Subject: [PATCH] [INPUT] - Implement add input methods - Some improvents svn path=/trunk/; revision=72160 --- reactos/dll/cpl/input_new/CMakeLists.txt | 11 +- reactos/dll/cpl/input_new/add_dialog.c | 192 ++++++++++ .../cpl/input_new/advanced_settings_page.c | 15 + reactos/dll/cpl/input_new/edit_dialog.c | 8 + reactos/dll/cpl/input_new/input.c | 34 +- reactos/dll/cpl/input_new/input.h | 24 +- reactos/dll/cpl/input_new/input_list.c | 342 ++++++++++++++++++ reactos/dll/cpl/input_new/input_list.h | 44 +++ .../dll/cpl/input_new/key_settings_dialog.c | 8 + reactos/dll/cpl/input_new/layout_list.c | 24 +- reactos/dll/cpl/input_new/layout_list.h | 4 +- reactos/dll/cpl/input_new/locale_list.c | 25 +- reactos/dll/cpl/input_new/locale_list.h | 3 + reactos/dll/cpl/input_new/settings_page.c | 229 +++++++----- 14 files changed, 836 insertions(+), 127 deletions(-) create mode 100644 reactos/dll/cpl/input_new/add_dialog.c create mode 100644 reactos/dll/cpl/input_new/advanced_settings_page.c create mode 100644 reactos/dll/cpl/input_new/edit_dialog.c create mode 100644 reactos/dll/cpl/input_new/input_list.c create mode 100644 reactos/dll/cpl/input_new/input_list.h create mode 100644 reactos/dll/cpl/input_new/key_settings_dialog.c diff --git a/reactos/dll/cpl/input_new/CMakeLists.txt b/reactos/dll/cpl/input_new/CMakeLists.txt index f1662c99ba6..3a1529cdb20 100644 --- a/reactos/dll/cpl/input_new/CMakeLists.txt +++ b/reactos/dll/cpl/input_new/CMakeLists.txt @@ -1,14 +1,21 @@ +PROJECT(INPUT_NEW) spec2def(input_new.dll input.spec) list(APPEND SOURCE input.c input.h + input_list.c + input_list.h layout_list.c layout_list.h locale_list.c locale_list.h - settings_page.c) + settings_page.c + advanced_settings_page.c + add_dialog.c + edit_dialog.c + key_settings_dialog.c) add_rc_deps(input.rc ${CMAKE_CURRENT_SOURCE_DIR}/resources/keyboard-shortcuts.ico) @@ -18,6 +25,6 @@ add_library(input_new SHARED ${CMAKE_CURRENT_BINARY_DIR}/input_new.def) set_module_type(input_new win32dll UNICODE) -add_importlibs(input_new advapi32 user32 comctl32 gdi32 msvcrt kernel32) +add_importlibs(input_new advapi32 user32 comctl32 gdi32 msvcrt kernel32 setupapi) add_pch(input_new input.h SOURCE) add_cd_file(TARGET input_new DESTINATION reactos/system32 FOR all) diff --git a/reactos/dll/cpl/input_new/add_dialog.c b/reactos/dll/cpl/input_new/add_dialog.c new file mode 100644 index 00000000000..e0c0c57c481 --- /dev/null +++ b/reactos/dll/cpl/input_new/add_dialog.c @@ -0,0 +1,192 @@ +/* +* PROJECT: input.dll +* FILE: dll/cpl/input/add_dialog.c +* PURPOSE: input.dll +* PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) +*/ + +#include "input.h" +#include "locale_list.h" +#include "layout_list.h" +#include "input_list.h" + + +static DWORD +GetDefaultLayoutForLocale(DWORD dwLocaleId) +{ + DWORD dwResult = 0; + HINF hIntlInf; + + hIntlInf = SetupOpenInfFileW(L"intl.inf", NULL, INF_STYLE_WIN4, NULL); + if (hIntlInf != INVALID_HANDLE_VALUE) + { + WCHAR szLangID[MAX_STR_LEN]; + INFCONTEXT InfContext; + + StringCchPrintfW(szLangID, ARRAYSIZE(szLangID), L"%08X", dwLocaleId); + + if (SetupFindFirstLineW(hIntlInf, L"Locales", szLangID, &InfContext)) + { + if (SetupGetFieldCount(&InfContext) >= 5) + { + WCHAR szField[MAX_STR_LEN]; + + if (SetupGetStringFieldW(&InfContext, 5, szField, ARRAYSIZE(szField), NULL)) + { + if (wcslen(szField) == 13) // like 0409:00000409 (13 chars) + { + WCHAR *pszSeparator = L":"; + WCHAR *pszToken; + + pszToken = wcstok(szField, pszSeparator); + if (pszToken != NULL) + pszToken = wcstok(NULL, pszSeparator); + + if (pszToken != NULL) + { + dwResult = DWORDfromString(pszToken); + } + } + } + } + } + + SetupCloseInfFile(hIntlInf); + } + + return dwResult; +} + + +static VOID +OnInitAddDialog(HWND hwndDlg) +{ + HWND hwndLocaleCombo = GetDlgItem(hwndDlg, IDC_INPUT_LANG_COMBO); + HWND hwndLayoutCombo = GetDlgItem(hwndDlg, IDC_KEYBOARD_LO_COMBO); + LOCALE_LIST_NODE *pCurrentLocale; + LAYOUT_LIST_NODE *pCurrentLayout; + DWORD dwDefaultLocaleId; + DWORD dwDefaultLayoutId; + INT iItemIndex; + + dwDefaultLocaleId = GetSystemDefaultLCID(); + + for (pCurrentLocale = LocaleList_Get(); + pCurrentLocale != NULL; + pCurrentLocale = pCurrentLocale->pNext) + { + iItemIndex = ComboBox_AddString(hwndLocaleCombo, pCurrentLocale->pszName); + ComboBox_SetItemData(hwndLocaleCombo, iItemIndex, pCurrentLocale); + + if (pCurrentLocale->dwId == dwDefaultLocaleId) + { + ComboBox_SetCurSel(hwndLocaleCombo, iItemIndex); + } + } + + dwDefaultLayoutId = GetDefaultLayoutForLocale(dwDefaultLocaleId); + + for (pCurrentLayout = LayoutList_Get(); + pCurrentLayout != NULL; + pCurrentLayout = pCurrentLayout->pNext) + { + iItemIndex = ComboBox_AddString(hwndLayoutCombo, pCurrentLayout->pszName); + ComboBox_SetItemData(hwndLayoutCombo, iItemIndex, pCurrentLayout); + + if (pCurrentLayout->dwId == dwDefaultLayoutId) + { + ComboBox_SetCurSel(hwndLayoutCombo, iItemIndex); + } + } + + if (dwDefaultLayoutId == 0) + ComboBox_SetCurSel(hwndLayoutCombo, 0); +} + + +static VOID +OnCommandAddDialog(HWND hwndDlg, WPARAM wParam) +{ + switch (LOWORD(wParam)) + { + case IDOK: + { + HWND hwndLocaleCombo = GetDlgItem(hwndDlg, IDC_INPUT_LANG_COMBO); + HWND hwndLayoutCombo = GetDlgItem(hwndDlg, IDC_KEYBOARD_LO_COMBO); + LOCALE_LIST_NODE *pCurrentLocale; + LAYOUT_LIST_NODE *pCurrentLayout; + + pCurrentLocale = (LOCALE_LIST_NODE*)ComboBox_GetItemData(hwndLocaleCombo, + ComboBox_GetCurSel(hwndLocaleCombo)); + pCurrentLayout = (LAYOUT_LIST_NODE*)ComboBox_GetItemData(hwndLayoutCombo, + ComboBox_GetCurSel(hwndLayoutCombo)); + + InputList_Add(pCurrentLocale, pCurrentLayout); + + EndDialog(hwndDlg, LOWORD(wParam)); + } + break; + + case IDCANCEL: + { + EndDialog(hwndDlg, LOWORD(wParam)); + } + break; + + case IDC_INPUT_LANG_COMBO: + { + if (HIWORD(wParam) == CBN_SELCHANGE) + { + HWND hwndLocaleCombo = GetDlgItem(hwndDlg, IDC_INPUT_LANG_COMBO); + HWND hwndLayoutCombo = GetDlgItem(hwndDlg, IDC_KEYBOARD_LO_COMBO); + LOCALE_LIST_NODE *pCurrentLocale; + + pCurrentLocale = (LOCALE_LIST_NODE*)ComboBox_GetItemData(hwndLocaleCombo, + ComboBox_GetCurSel(hwndLocaleCombo)); + if (pCurrentLocale != NULL) + { + DWORD dwLayoutId; + INT iIndex; + INT iCount; + + dwLayoutId = GetDefaultLayoutForLocale(pCurrentLocale->dwId); + + iCount = ComboBox_GetCount(hwndLayoutCombo); + + for (iIndex = 0; iIndex < iCount; iIndex++) + { + LAYOUT_LIST_NODE *pCurrentLayout; + + pCurrentLayout = (LAYOUT_LIST_NODE*)ComboBox_GetItemData(hwndLayoutCombo, iIndex); + if (pCurrentLayout != NULL && pCurrentLayout->dwId == dwLayoutId) + { + ComboBox_SetCurSel(hwndLayoutCombo, iIndex); + } + } + } + } + } + break; + } +} + + +INT_PTR CALLBACK +AddDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + OnInitAddDialog(hwndDlg); + break; + + case WM_COMMAND: + OnCommandAddDialog(hwndDlg, wParam); + break; + + case WM_DESTROY: + break; + } + + return FALSE; +} diff --git a/reactos/dll/cpl/input_new/advanced_settings_page.c b/reactos/dll/cpl/input_new/advanced_settings_page.c new file mode 100644 index 00000000000..77536525a34 --- /dev/null +++ b/reactos/dll/cpl/input_new/advanced_settings_page.c @@ -0,0 +1,15 @@ +/* +* PROJECT: input.dll +* FILE: dll/cpl/input/advanced_settings_page.c +* PURPOSE: input.dll +* PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) +*/ + +#include "input.h" + + +INT_PTR CALLBACK +AdvancedSettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return FALSE; +} diff --git a/reactos/dll/cpl/input_new/edit_dialog.c b/reactos/dll/cpl/input_new/edit_dialog.c new file mode 100644 index 00000000000..a9798bf195a --- /dev/null +++ b/reactos/dll/cpl/input_new/edit_dialog.c @@ -0,0 +1,8 @@ +/* +* PROJECT: input.dll +* FILE: dll/cpl/input/edit_dialog.c +* PURPOSE: input.dll +* PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) +*/ + +#include "input.h" diff --git a/reactos/dll/cpl/input_new/input.c b/reactos/dll/cpl/input_new/input.c index 9c8b12a88f8..3aa47a9b18c 100644 --- a/reactos/dll/cpl/input_new/input.c +++ b/reactos/dll/cpl/input_new/input.c @@ -14,9 +14,10 @@ #define NUM_APPLETS (1) -LONG CALLBACK SystemApplet(VOID); +static LONG CALLBACK SystemApplet(VOID); + HINSTANCE hApplet = NULL; -HWND hCPLWindow; +static HWND hCPLWindow; /* Applets */ static APPLET Applets[NUM_APPLETS] = @@ -25,35 +26,28 @@ static APPLET Applets[NUM_APPLETS] = }; -VOID -InitPropSheetPage(PROPSHEETPAGE *page, WORD idDlg, DLGPROC DlgProc) +static VOID +InitPropSheetPage(PROPSHEETPAGEW *page, WORD idDlg, DLGPROC DlgProc) { - memset(page, 0, sizeof(PROPSHEETPAGE)); + memset(page, 0, sizeof(PROPSHEETPAGEW)); - page->dwSize = sizeof(PROPSHEETPAGE); + page->dwSize = sizeof(PROPSHEETPAGEW); page->dwFlags = PSP_DEFAULT; page->hInstance = hApplet; - page->pszTemplate = MAKEINTRESOURCE(idDlg); + page->pszTemplate = MAKEINTRESOURCEW(idDlg); page->pfnDlgProc = DlgProc; } -INT_PTR CALLBACK -AdvancedSettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return FALSE; -} - - /* First Applet */ -LONG CALLBACK +static LONG CALLBACK SystemApplet(VOID) { - PROPSHEETPAGE page[2]; - PROPSHEETHEADER header; + PROPSHEETPAGEW page[2]; + PROPSHEETHEADERW header; WCHAR szCaption[MAX_STR_LEN]; - LoadString(hApplet, IDS_CPLSYSTEMNAME, szCaption, ARRAYSIZE(szCaption)); + LoadStringW(hApplet, IDS_CPLSYSTEMNAME, szCaption, ARRAYSIZE(szCaption)); memset(&header, 0, sizeof(PROPSHEETHEADER)); @@ -61,7 +55,7 @@ SystemApplet(VOID) header.dwFlags = PSH_PROPSHEETPAGE; header.hwndParent = hCPLWindow; header.hInstance = hApplet; - header.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM)); + header.hIcon = LoadIconW(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM)); header.pszCaption = szCaption; header.nPages = ARRAYSIZE(page); header.nStartPage = 0; @@ -74,7 +68,7 @@ SystemApplet(VOID) /* Advanced Settings */ InitPropSheetPage(&page[1], IDD_PROPPAGEADVANCEDSETTINGS, AdvancedSettingsPageProc); - return (LONG)(PropertySheet(&header) != -1); + return (LONG)(PropertySheetW(&header) != -1); } diff --git a/reactos/dll/cpl/input_new/input.h b/reactos/dll/cpl/input_new/input.h index 5c0b60c5985..bcba8e4bd27 100644 --- a/reactos/dll/cpl/input_new/input.h +++ b/reactos/dll/cpl/input_new/input.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,15 +39,17 @@ extern HINSTANCE hApplet; #define MAX_STR_LEN 256 -/* input.c */ -VOID -InitPropSheetPage(PROPSHEETPAGE *page, WORD idDlg, DLGPROC DlgProc); - -/* settings_dialog.c */ +/* settings_page.c */ INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -void ShowLastWin32Error(HWND hWndOwner); +/* advanced_settings_page.c */ +INT_PTR CALLBACK +AdvancedSettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +/* add_dialog.c */ +INT_PTR CALLBACK +AddDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); static inline WCHAR* DublicateString(const WCHAR *pszString) @@ -64,4 +68,12 @@ DublicateString(const WCHAR *pszString) return pszDublicate; } +static inline DWORD +DWORDfromString(const WCHAR *pszString) +{ + WCHAR *pszEnd; + + return wcstoul(pszString, &pszEnd, 16); +} + #endif /* _INPUT_H */ diff --git a/reactos/dll/cpl/input_new/input_list.c b/reactos/dll/cpl/input_new/input_list.c new file mode 100644 index 00000000000..d4baa5ece60 --- /dev/null +++ b/reactos/dll/cpl/input_new/input_list.c @@ -0,0 +1,342 @@ +/* +* PROJECT: input.dll +* FILE: dll/cpl/input/input_list.c +* PURPOSE: input.dll +* PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) +*/ + +#include "input_list.h" + + +static INPUT_LIST_NODE *_InputList = NULL; + + +static INPUT_LIST_NODE* +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; + + memset(pNew, 0, sizeof(INPUT_LIST_NODE)); + + if (pCurrent == NULL) + { + _InputList = pNew; + } + else + { + while (pCurrent->pNext != NULL) + { + pCurrent = pCurrent->pNext; + } + + pNew->pPrev = pCurrent; + pCurrent->pNext = pNew; + } + + return pNew; +} + + +VOID +InputList_Remove(INPUT_LIST_NODE *pNode) +{ + INPUT_LIST_NODE *pCurrent = pNode; + + if (_InputList == NULL) + return; + + if (pCurrent != NULL) + { + INPUT_LIST_NODE *pNext = pCurrent->pNext; + INPUT_LIST_NODE *pPrev = pCurrent->pPrev; + + free(pCurrent); + + if (pNext != NULL) + pNext->pPrev = pPrev; + + if (pPrev != NULL) + pPrev->pNext = pNext; + else + _InputList = pNext; + } +} + + +VOID +InputList_Destroy(VOID) +{ + INPUT_LIST_NODE *pCurrent; + + if (_InputList == NULL) + return; + + pCurrent = _InputList; + + while (pCurrent != NULL) + { + INPUT_LIST_NODE *pNext = pCurrent->pNext; + + free(pCurrent); + + pCurrent = pNext; + } + + _InputList = NULL; +} + + +static BOOL +InputList_PrepareUserRegistry(VOID) +{ + BOOL bResult = FALSE; + HKEY hTempKey = NULL; + HKEY hKey = NULL; + + if (RegOpenKeyExW(HKEY_CURRENT_USER, + L"Keyboard Layout", + 0, + KEY_ALL_ACCESS, + &hKey) == ERROR_SUCCESS) + { + RegDeleteKeyW(hKey, L"Preload"); + RegDeleteKeyW(hKey, L"Substitutes"); + //RegDeleteKeyW(hKey, L"Toggle"); + + RegCloseKey(hKey); + + RegDeleteKeyW(HKEY_CURRENT_USER, L"Keyboard Layout"); + } + + if (RegCreateKeyW(HKEY_CURRENT_USER, L"Keyboard Layout", &hKey) != ERROR_SUCCESS) + { + goto Cleanup; + } + + if (RegCreateKeyW(hKey, L"Preload", &hTempKey) != ERROR_SUCCESS) + { + goto Cleanup; + } + + RegCloseKey(hTempKey); + + if (RegCreateKeyW(hKey, L"Substitutes", &hTempKey) != ERROR_SUCCESS) + { + goto Cleanup; + } + + RegCloseKey(hTempKey); + + if (RegCreateKeyW(hKey, L"Toggle", &hTempKey) != ERROR_SUCCESS) + { + goto Cleanup; + } + + RegCloseKey(hTempKey); + + bResult = TRUE; + +Cleanup: + if (hTempKey != NULL) + RegCloseKey(hTempKey); + if (hKey != NULL) + RegCloseKey(hKey); + + return bResult; +} + + +static VOID +InputList_AddInputMethodToUserRegistry(DWORD dwIndex, INPUT_LIST_NODE *pNode) +{ + WCHAR szMethodIndex[MAX_PATH]; + WCHAR szPreload[MAX_PATH]; + BOOL bIsImeMethod = FALSE; + HKEY hKey; + + StringCchPrintfW(szMethodIndex, ARRAYSIZE(szMethodIndex), L"%lu", dwIndex); + + /* 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); + } + + if (RegOpenKeyExW(HKEY_CURRENT_USER, + L"Keyboard Layout\\Preload", + 0, + KEY_SET_VALUE, + &hKey) == ERROR_SUCCESS) + { + RegSetValueExW(hKey, + szMethodIndex, + 0, + REG_SZ, + (LPBYTE)szPreload, + (wcslen(szPreload) + 1) * sizeof(WCHAR)); + + RegCloseKey(hKey); + } + + 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) + { + WCHAR szSubstitues[MAX_PATH]; + + StringCchPrintfW(szSubstitues, ARRAYSIZE(szSubstitues), L"%08X", pNode->pLayout->dwId); + + RegSetValueExW(hKey, + szPreload, + 0, + REG_SZ, + (LPBYTE)szSubstitues, + (wcslen(szSubstitues) + 1) * sizeof(WCHAR)); + + RegCloseKey(hKey); + } + } + + if (pNode->dwFlags & INPUT_LIST_NODE_FLAG_ADDED) + { + pNode->hkl = LoadKeyboardLayoutW(szPreload, KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL); + } +} + + +VOID +InputList_Process(VOID) +{ + INPUT_LIST_NODE *pCurrent; + DWORD dwIndex; + + /* Process deleted input methods */ + for (pCurrent = _InputList; pCurrent != NULL; pCurrent = pCurrent->pNext) + { + if (!(pCurrent->dwFlags & INPUT_LIST_NODE_FLAG_DELETED)) + continue; + + if (UnloadKeyboardLayout(pCurrent->hkl)) + { + InputList_Remove(pCurrent); + } + } + + InputList_PrepareUserRegistry(); + + /* Find default input method */ + for (pCurrent = _InputList; pCurrent != NULL; pCurrent = pCurrent->pNext) + { + if (pCurrent->dwFlags & INPUT_LIST_NODE_FLAG_DEFAULT) + { + InputList_AddInputMethodToUserRegistry(1, pCurrent); + break; + } + } + + if (SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, + 0, + (LPVOID)((LPDWORD)&pCurrent->hkl), + 0)) + { + DWORD dwRecipients; + + dwRecipients = BSM_ALLCOMPONENTS; + + BroadcastSystemMessageW(BSF_POSTMESSAGE, + &dwRecipients, + WM_INPUTLANGCHANGEREQUEST, + 0, + (LPARAM)pCurrent->hkl); + } + + /* Add methods to registry */ + for (pCurrent = _InputList, dwIndex = 2; pCurrent != NULL; pCurrent = pCurrent->pNext, dwIndex++) + { + if (pCurrent->dwFlags & INPUT_LIST_NODE_FLAG_DEFAULT) + continue; + + InputList_AddInputMethodToUserRegistry(dwIndex, pCurrent); + } +} + + +VOID +InputList_Add(LOCALE_LIST_NODE *pLocale, LAYOUT_LIST_NODE *pLayout) +{ + INPUT_LIST_NODE *pInput; + + if (pLocale == NULL || pLayout == NULL) + { + return; + } + + pInput = InputList_AppendNode(); + + pInput->dwFlags |= INPUT_LIST_NODE_FLAG_ADDED; + + pInput->pLocale = pLocale; + pInput->pLayout = pLayout; +} + + +VOID +InputList_Create(VOID) +{ + INT iLayoutCount; + HKL *pLayoutList; + + iLayoutCount = GetKeyboardLayoutList(0, NULL); + pLayoutList = (HKL*)malloc(iLayoutCount * sizeof(HKL)); + + if (pLayoutList != NULL) + { + if (GetKeyboardLayoutList(iLayoutCount, pLayoutList) > 0) + { + INT iIndex; + + for (iIndex = 0; iIndex < iLayoutCount; iIndex++) + { + LOCALE_LIST_NODE *pLocale = LocaleList_GetByHkl(pLayoutList[iIndex]); + LAYOUT_LIST_NODE *pLayout = LayoutList_GetByHkl(pLayoutList[iIndex]); + + if (pLocale != NULL && pLayout != NULL) + { + INPUT_LIST_NODE *pInput; + + pInput = InputList_AppendNode(); + + pInput->dwFlags = 0; + pInput->pLocale = pLocale; + pInput->pLayout = pLayout; + pInput->hkl = pLayoutList[iIndex]; + } + } + } + + free(pLayoutList); + } +} + + +INPUT_LIST_NODE* +InputList_Get(VOID) +{ + return _InputList; +} diff --git a/reactos/dll/cpl/input_new/input_list.h b/reactos/dll/cpl/input_new/input_list.h new file mode 100644 index 00000000000..c371d4da405 --- /dev/null +++ b/reactos/dll/cpl/input_new/input_list.h @@ -0,0 +1,44 @@ +#pragma once + +#include "input.h" +#include "locale_list.h" +#include "layout_list.h" + + +#define INPUT_LIST_NODE_FLAG_EDITED 0x00000001 +#define INPUT_LIST_NODE_FLAG_ADDED 0x00000002 +#define INPUT_LIST_NODE_FLAG_DELETED 0x00000004 +#define INPUT_LIST_NODE_FLAG_DEFAULT 0x00000008 + + +typedef struct _INPUT_LIST_NODE +{ + DWORD dwFlags; + + LOCALE_LIST_NODE *pLocale; + LAYOUT_LIST_NODE *pLayout; + + HKL hkl; + + struct _INPUT_LIST_NODE *pPrev; + struct _INPUT_LIST_NODE *pNext; +} INPUT_LIST_NODE; + + +VOID +InputList_Create(VOID); + +VOID +InputList_Process(VOID); + +VOID +InputList_Add(LOCALE_LIST_NODE *pLocale, LAYOUT_LIST_NODE *pLayout); + +VOID +InputList_Remove(INPUT_LIST_NODE *pNode); + +VOID +InputList_Destroy(VOID); + +INPUT_LIST_NODE* +InputList_Get(VOID); diff --git a/reactos/dll/cpl/input_new/key_settings_dialog.c b/reactos/dll/cpl/input_new/key_settings_dialog.c new file mode 100644 index 00000000000..1675da63800 --- /dev/null +++ b/reactos/dll/cpl/input_new/key_settings_dialog.c @@ -0,0 +1,8 @@ +/* +* PROJECT: input.dll +* FILE: dll/cpl/input/key_settings_dialog.c +* PURPOSE: input.dll +* PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) +*/ + +#include "input.h" diff --git a/reactos/dll/cpl/input_new/layout_list.c b/reactos/dll/cpl/input_new/layout_list.c index 309d9142961..a1c6255546a 100644 --- a/reactos/dll/cpl/input_new/layout_list.c +++ b/reactos/dll/cpl/input_new/layout_list.c @@ -22,7 +22,7 @@ LayoutList_Append(DWORD dwId, DWORD dwSpecialId, const WCHAR *pszName, const WCH pCurrent = _LayoutList; - pNew = (LAYOUT_LIST_NODE*)malloc(sizeof(LAYOUT_LIST_NODE)); + pNew = (LAYOUT_LIST_NODE*) malloc(sizeof(LAYOUT_LIST_NODE)); if (pNew == NULL) return NULL; @@ -99,7 +99,10 @@ LayoutList_Create(VOID) DWORD dwSize; HKEY hKey; - GetSystemDirectoryW(szSystemDirectory, ARRAYSIZE(szSystemDirectory)); + if (!GetSystemDirectoryW(szSystemDirectory, ARRAYSIZE(szSystemDirectory))) + { + return; + } if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts", @@ -137,10 +140,9 @@ LayoutList_Create(VOID) StringCchPrintfW(szFilePath, ARRAYSIZE(szFilePath), L"%s\\%s", szSystemDirectory, szBuffer); - if (GetFileAttributes(szFilePath) != INVALID_FILE_ATTRIBUTES) + if (GetFileAttributesW(szFilePath) != INVALID_FILE_ATTRIBUTES) { DWORD dwSpecialId = 0; - WCHAR *pszEnd; dwSize = sizeof(szBuffer); @@ -149,7 +151,7 @@ LayoutList_Create(VOID) NULL, NULL, (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS) { - dwSpecialId = wcstoul(szBuffer, &pszEnd, 16); + dwSpecialId = DWORDfromString(szBuffer); } dwSize = sizeof(szBuffer); @@ -159,9 +161,7 @@ LayoutList_Create(VOID) NULL, NULL, (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS) { - DWORD dwLayoutId; - - dwLayoutId = wcstoul(szLayoutId, &pszEnd, 16); + DWORD dwLayoutId = DWORDfromString(szLayoutId); LayoutList_Append(dwLayoutId, dwSpecialId, @@ -182,8 +182,8 @@ LayoutList_Create(VOID) } -WCHAR* -LayoutList_GetNameByHkl(HKL hkl) +LAYOUT_LIST_NODE* +LayoutList_GetByHkl(HKL hkl) { LAYOUT_LIST_NODE *pCurrent; @@ -195,7 +195,7 @@ LayoutList_GetNameByHkl(HKL hkl) { if (dwSpecialId == pCurrent->dwSpecialId) { - return pCurrent->pszName; + return pCurrent; } } } @@ -205,7 +205,7 @@ LayoutList_GetNameByHkl(HKL hkl) { if (HIWORD(hkl) == LOWORD(pCurrent->dwId)) { - return pCurrent->pszName; + return pCurrent; } } } diff --git a/reactos/dll/cpl/input_new/layout_list.h b/reactos/dll/cpl/input_new/layout_list.h index 065d58a8a02..26ffb59f057 100644 --- a/reactos/dll/cpl/input_new/layout_list.h +++ b/reactos/dll/cpl/input_new/layout_list.h @@ -18,8 +18,8 @@ LayoutList_Create(VOID); VOID LayoutList_Destroy(VOID); -WCHAR* -LayoutList_GetNameByHkl(HKL hkl); +LAYOUT_LIST_NODE* +LayoutList_GetByHkl(HKL hkl); LAYOUT_LIST_NODE* LayoutList_Get(VOID); diff --git a/reactos/dll/cpl/input_new/locale_list.c b/reactos/dll/cpl/input_new/locale_list.c index 7d7e8771171..626439704d1 100644 --- a/reactos/dll/cpl/input_new/locale_list.c +++ b/reactos/dll/cpl/input_new/locale_list.c @@ -12,7 +12,7 @@ static LOCALE_LIST_NODE *_LocaleList = NULL; static LOCALE_LIST_NODE* -LocaleList_Append(DWORD dwId, WCHAR *pszName, WCHAR *pszIndicator) +LocaleList_Append(DWORD dwId, const WCHAR *pszName, const WCHAR *pszIndicator) { LOCALE_LIST_NODE *pCurrent; LOCALE_LIST_NODE *pNew; @@ -79,6 +79,7 @@ LocaleList_Destroy(VOID) LOCALE_LIST_NODE *pNext = pCurrent->pNext; free(pCurrent->pszName); + free(pCurrent->pszIndicator); free(pCurrent); pCurrent = pNext; @@ -112,16 +113,15 @@ LocaleList_Create(VOID) NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { WCHAR szName[MAX_STR_LEN]; - WCHAR *End; DWORD dwId; - dwId = wcstoul(szValue, &End, 16); + dwId = DWORDfromString(szValue); if (GetLocaleInfoW(LOWORD(dwId), LOCALE_SLANGUAGE, szName, ARRAYSIZE(szName))) { - WCHAR szIndicator[MAX_STR_LEN]; + WCHAR szIndicator[MAX_STR_LEN] = { 0 }; if (GetLocaleInfoW(LOWORD(dwId), LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE, @@ -147,6 +147,23 @@ LocaleList_Create(VOID) } +LOCALE_LIST_NODE* +LocaleList_GetByHkl(HKL hkl) +{ + LOCALE_LIST_NODE *pCurrent; + + for (pCurrent = _LocaleList; pCurrent != NULL; pCurrent = pCurrent->pNext) + { + if (LOWORD(pCurrent->dwId) == LOWORD(hkl)) + { + return pCurrent; + } + } + + return NULL; +} + + LOCALE_LIST_NODE* LocaleList_Get(VOID) { diff --git a/reactos/dll/cpl/input_new/locale_list.h b/reactos/dll/cpl/input_new/locale_list.h index 4f6915611c0..6a856562c6a 100644 --- a/reactos/dll/cpl/input_new/locale_list.h +++ b/reactos/dll/cpl/input_new/locale_list.h @@ -17,5 +17,8 @@ LocaleList_Create(VOID); VOID LocaleList_Destroy(VOID); +LOCALE_LIST_NODE* +LocaleList_GetByHkl(HKL hkl); + LOCALE_LIST_NODE* LocaleList_Get(VOID); diff --git a/reactos/dll/cpl/input_new/settings_page.c b/reactos/dll/cpl/input_new/settings_page.c index 672885574b7..47f36d028e6 100644 --- a/reactos/dll/cpl/input_new/settings_page.c +++ b/reactos/dll/cpl/input_new/settings_page.c @@ -8,16 +8,15 @@ #include "input.h" #include "layout_list.h" #include "locale_list.h" +#include "input_list.h" static HICON CreateLayoutIcon(LPWSTR szLayout) { - HDC hdc, hdcsrc; - HBITMAP hBitmap, hBmpNew, hBmpOld; - RECT rect; - HFONT hFont = NULL; - ICONINFO IconInfo; + HDC hdc; + HDC hdcsrc; + HBITMAP hBitmap; HICON hIcon = NULL; hdcsrc = GetDC(NULL); @@ -29,11 +28,18 @@ CreateLayoutIcon(LPWSTR szLayout) if (hdc && hBitmap) { + HBITMAP hBmpNew; + hBmpNew = CreateBitmap(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 1, 1, NULL); if (hBmpNew) { + ICONINFO IconInfo; + HBITMAP hBmpOld; + HFONT hFont; + RECT rect; + hBmpOld = SelectObject(hdc, hBitmap); rect.right = GetSystemMetrics(SM_CXSMICON); rect.left = 0; @@ -45,12 +51,12 @@ CreateLayoutIcon(LPWSTR szLayout) ExtTextOut(hdc, rect.left, rect.top, ETO_OPAQUE, &rect, L"", 0, NULL); - hFont = CreateFont(-11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, - OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, - DEFAULT_QUALITY, FF_DONTCARE, L"Tahoma"); + hFont = CreateFontW(-11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FF_DONTCARE, L"Tahoma"); SelectObject(hdc, hFont); - DrawText(hdc, szLayout, 2, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER); + DrawTextW(hdc, szLayout, 2, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER); SelectObject(hdc, hBmpNew); PatBlt(hdc, 0, 0, @@ -80,10 +86,7 @@ CreateLayoutIcon(LPWSTR szLayout) static VOID -AddToLayoutListView(HWND hwndList, - WCHAR *pszLanguageName, - WCHAR *pszLayoutName, - WCHAR *pszIndicatorTitle) +AddToInputListView(HWND hwndList, INPUT_LIST_NODE *pInputNode) { INT ItemIndex = -1; INT ImageIndex = -1; @@ -91,11 +94,13 @@ AddToLayoutListView(HWND hwndList, HIMAGELIST hImageList; hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL); + if (hImageList != NULL) { HICON hLayoutIcon; - hLayoutIcon = CreateLayoutIcon(pszIndicatorTitle); + hLayoutIcon = CreateLayoutIcon(pInputNode->pLocale->pszIndicator); + if (hLayoutIcon != NULL) { ImageIndex = ImageList_AddIcon(hImageList, hLayoutIcon); @@ -106,88 +111,92 @@ AddToLayoutListView(HWND hwndList, memset(&item, 0, sizeof(LV_ITEM)); item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; - item.pszText = pszLanguageName; + item.pszText = pInputNode->pLocale->pszName; item.iItem = -1; - item.lParam = (LPARAM)NULL; + item.lParam = (LPARAM)pInputNode; item.iImage = ImageIndex; ItemIndex = ListView_InsertItem(hwndList, &item); - ListView_SetItemText(hwndList, ItemIndex, 1, pszLayoutName); + ListView_SetItemText(hwndList, ItemIndex, 1, pInputNode->pLayout->pszName); +} + + +static VOID +UpdateInputListView(HWND hwndList) +{ + INPUT_LIST_NODE *pCurrentInputNode; + HIMAGELIST hImageList; + + hImageList = ListView_GetImageList(hwndList, LVSIL_SMALL); + if (hImageList != NULL) + { + ImageList_RemoveAll(hImageList); + } + + ListView_DeleteAllItems(hwndList); + + for (pCurrentInputNode = InputList_Get(); + pCurrentInputNode != NULL; + pCurrentInputNode = pCurrentInputNode->pNext) + { + AddToInputListView(hwndList, pCurrentInputNode); + } } static VOID OnInitSettingsPage(HWND hwndDlg) { - WCHAR szBuffer[MAX_STR_LEN]; - LV_COLUMN column; - HWND hLayoutList; - HIMAGELIST hLayoutImageList; - INT iLayoutCount; - HKL *pActiveLayoutList; - - hLayoutList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); - - ListView_SetExtendedListViewStyle(hLayoutList, LVS_EX_FULLROWSELECT); - - memset(&column, 0, sizeof(LV_COLUMN)); - - column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; - - LoadString(hApplet, IDS_LANGUAGE, szBuffer, ARRAYSIZE(szBuffer)); - column.fmt = LVCFMT_LEFT; - column.iSubItem = 0; - column.pszText = szBuffer; - column.cx = 175; - ListView_InsertColumn(hLayoutList, 0, &column); - - LoadString(hApplet, IDS_LAYOUT, szBuffer, ARRAYSIZE(szBuffer)); - column.fmt = LVCFMT_RIGHT; - column.cx = 155; - column.iSubItem = 1; - column.pszText = szBuffer; - ListView_InsertColumn(hLayoutList, 1, &column); - - hLayoutImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - ILC_COLOR8 | ILC_MASK, 0, 0); - if (hLayoutImageList != NULL) - { - ListView_SetImageList(hLayoutList, hLayoutImageList, LVSIL_SMALL); - } + HWND hwndInputList; LayoutList_Create(); LocaleList_Create(); + InputList_Create(); - iLayoutCount = GetKeyboardLayoutList(0, NULL); - pActiveLayoutList = (HKL*) malloc(iLayoutCount * sizeof(HKL)); - if (pActiveLayoutList != NULL) + hwndInputList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); + + if (hwndInputList != NULL) { - if (GetKeyboardLayoutList(iLayoutCount, pActiveLayoutList) > 0) + INPUT_LIST_NODE *pCurrentInputNode; + WCHAR szBuffer[MAX_STR_LEN]; + HIMAGELIST hLayoutImageList; + LV_COLUMN column; + + ListView_SetExtendedListViewStyle(hwndInputList, LVS_EX_FULLROWSELECT); + + memset(&column, 0, sizeof(LV_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; + column.pszText = szBuffer; + column.cx = 175; + ListView_InsertColumn(hwndInputList, 0, &column); + + LoadStringW(hApplet, IDS_LAYOUT, szBuffer, ARRAYSIZE(szBuffer)); + column.fmt = LVCFMT_RIGHT; + column.cx = 155; + column.iSubItem = 1; + column.pszText = szBuffer; + ListView_InsertColumn(hwndInputList, 1, &column); + + hLayoutImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLOR8 | ILC_MASK, 0, 0); + if (hLayoutImageList != NULL) { - INT iIndex; - - for (iIndex = 0; iIndex < iLayoutCount; iIndex++) - { - LOCALE_LIST_NODE *CurrentLocale; - - for (CurrentLocale = LocaleList_Get(); - CurrentLocale != NULL; - CurrentLocale = CurrentLocale->pNext) - { - if (LOWORD(CurrentLocale->dwId) == LOWORD(pActiveLayoutList[iIndex])) - { - AddToLayoutListView(hLayoutList, - CurrentLocale->pszName, - LayoutList_GetNameByHkl(pActiveLayoutList[iIndex]), - CurrentLocale->pszIndicator); - } - } - } + ListView_SetImageList(hwndInputList, hLayoutImageList, LVSIL_SMALL); } - free(pActiveLayoutList); + for (pCurrentInputNode = InputList_Get(); + pCurrentInputNode != NULL; + pCurrentInputNode = pCurrentInputNode->pNext) + { + AddToInputListView(hwndInputList, pCurrentInputNode); + } } } @@ -199,6 +208,7 @@ OnDestroySettingsPage(HWND hwndDlg) LayoutList_Destroy(); LocaleList_Destroy(); + InputList_Destroy(); hImageList = ListView_GetImageList(GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST), LVSIL_SMALL); @@ -209,6 +219,61 @@ OnDestroySettingsPage(HWND hwndDlg) } +VOID +OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam) +{ + switch (LOWORD(wParam)) + { + case IDC_ADD_BUTTON: + { + if (DialogBoxW(hApplet, + MAKEINTRESOURCEW(IDD_ADD), + hwndDlg, + AddDialogProc) == IDOK) + { + UpdateInputListView(GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST)); + PropSheet_Changed(GetParent(hwndDlg), hwndDlg); + } + } + break; + + case IDC_REMOVE_BUTTON: + { + PropSheet_Changed(GetParent(hwndDlg), hwndDlg); + } + break; + + case IDC_PROP_BUTTON: + { + + } + break; + + case IDC_SET_DEFAULT: + { + PropSheet_Changed(GetParent(hwndDlg), hwndDlg); + } + break; + + case IDC_KEY_SET_BTN: + { + + } + break; + } +} + + +static VOID +OnNotifySettingsPage(HWND hwndDlg, LPARAM lParam) +{ + if (((LPPSHNOTIFY)lParam)->hdr.code == PSN_APPLY) + { + InputList_Process(); + } +} + + INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -223,10 +288,12 @@ SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case WM_COMMAND: - { - - } - break; + OnCommandSettingsPage(hwndDlg, wParam); + break; + + case WM_NOTIFY: + OnNotifySettingsPage(hwndDlg, lParam); + break; } return FALSE;