- Implement add input methods
- Some improvents

svn path=/trunk/; revision=72160
This commit is contained in:
Dmitry Chapyshev 2016-08-08 20:30:36 +00:00
parent 3185db7675
commit 8a32608dfe
14 changed files with 836 additions and 127 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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"

View file

@ -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);
}

View file

@ -11,6 +11,8 @@
#include <winuser.h>
#include <wingdi.h>
#include <commctrl.h>
#include <windowsx.h>
#include <setupapi.h>
#include <wchar.h>
#include <strsafe.h>
#include <stdlib.h>
@ -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 */

View file

@ -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;
}

View file

@ -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);

View file

@ -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"

View file

@ -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;
}
}
}

View file

@ -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);

View file

@ -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)
{

View file

@ -17,5 +17,8 @@ LocaleList_Create(VOID);
VOID
LocaleList_Destroy(VOID);
LOCALE_LIST_NODE*
LocaleList_GetByHkl(HKL hkl);
LOCALE_LIST_NODE*
LocaleList_Get(VOID);

View file

@ -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:
{
OnCommandSettingsPage(hwndDlg, wParam);
break;
}
break;
case WM_NOTIFY:
OnNotifySettingsPage(hwndDlg, lParam);
break;
}
return FALSE;