reactos/dll/cpl/intl/advanced.c
Timo Kreuzer 0182dcd71b [PSDK][REACTOS] Fix definitions and usage of DWLP_MSGRESULT, DWLP_DLGPROC, and DWLP_USER
- Make sure the DWLP_* values are correct on _WIN64
- Don't use the DWL_* constants, they are not portable. Enforce this by removing them entirely from winuser.h
- Make sure Get/SetWindowLong*Ptr* is used and pointers are not truncated to LONG
2018-03-04 16:27:07 +01:00

510 lines
13 KiB
C

#include "intl.h"
#include <wingdi.h>
#include <debug.h>
typedef struct CPStruct
{
UINT CodePage;
DWORD Flags;
WCHAR Name[MAX_PATH];
struct CPStruct *NextItem;
} CPAGE, *PCPAGE;
#define CODEPAGE_INSTALLED 0x00000001
#define CODEPAGE_NOT_REMOVEABLE 0x00000002
#define CODEPAGE_INSTALL 0x00000004
#define CODEPAGE_REMOVE 0x00000008
static PCPAGE PCPage = NULL;
static BOOL bSpain = FALSE;
static HWND hLangList;
static BOOL
GetSupportedCP(
HINF hInf)
{
WCHAR szSection[MAX_PATH];
INFCONTEXT Context, Context2;
PCPAGE pCodePage;
CPINFOEX cpInfEx;
UINT uiCodePage;
if (!SetupFindFirstLine(hInf,
L"CodePages",
NULL,
&Context))
return FALSE;
for (;;)
{
if (SetupGetIntField(&Context, 0, (PINT)&uiCodePage))
{
pCodePage = HeapAlloc(GetProcessHeap(), 0, sizeof(CPAGE));
if (pCodePage == NULL)
return FALSE;
pCodePage->CodePage = uiCodePage;
pCodePage->Flags = 0;
(pCodePage->Name)[0] = UNICODE_NULL;
if (GetCPInfoExW(uiCodePage, 0, &cpInfEx))
{
wcscpy(pCodePage->Name, cpInfEx.CodePageName);
}
else
{
SetupGetStringFieldW(&Context, 1, pCodePage->Name, MAX_PATH, NULL);
}
if (wcslen(pCodePage->Name) != 0)
{
pCodePage->NextItem = PCPage;
PCPage = pCodePage;
wsprintf(szSection, L"CODEPAGE_REMOVE_%d", uiCodePage);
if ((uiCodePage == GetACP()) ||
(uiCodePage == GetOEMCP()) ||
(!SetupFindFirstLineW(hInf, szSection, L"AddReg", &Context2)))
{
pCodePage->Flags |= CODEPAGE_NOT_REMOVEABLE;
}
}
else
{
HeapFree(GetProcessHeap(), 0, pCodePage);
}
}
if (!SetupFindNextLine(&Context, &Context))
break;
}
return TRUE;
}
static BOOL CALLBACK
InstalledCPProc(PWSTR lpStr)
{
PCPAGE lpCP;
UINT uiCP;
lpCP = PCPage;
uiCP = _wtol(lpStr);
for (;;)
{
if (!lpCP)
break;
if (lpCP->CodePage == uiCP)
{
lpCP->Flags |= CODEPAGE_INSTALLED;
break;
}
lpCP = lpCP->NextItem;
}
return TRUE;
}
static VOID
InitCodePagesList(HWND hwndDlg)
{
PCPAGE pCodePage;
INT ItemIndex;
HWND hList;
LV_COLUMN column;
LV_ITEM item;
RECT ListRect;
HINF hIntlInf;
hIntlInf = SetupOpenInfFileW(L"intl.inf", NULL, INF_STYLE_WIN4, NULL);
if (hIntlInf == INVALID_HANDLE_VALUE)
return;
if (!SetupOpenAppendInfFile(NULL, hIntlInf, NULL))
{
SetupCloseInfFile(hIntlInf);
hIntlInf = NULL;
return;
}
if (!GetSupportedCP(hIntlInf))
return;
SetupCloseInfFile(hIntlInf);
if (!EnumSystemCodePagesW(InstalledCPProc, CP_INSTALLED))
{
/* Hack: EnumSystemCodePages returns FALSE on successful completion! */
/* return; */
}
hList = GetDlgItem(hwndDlg, IDC_CONV_TABLES);
ZeroMemory(&column, sizeof(LV_COLUMN));
column.mask = LVCF_FMT | LVCF_WIDTH;
column.fmt = LVCFMT_LEFT;
GetClientRect(hList, &ListRect);
column.cx = ListRect.right - GetSystemMetrics(SM_CYHSCROLL);
ListView_InsertColumn(hList, 0, &column);
(VOID) ListView_SetExtendedListViewStyle(hList, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
pCodePage = PCPage;
for (;;)
{
if (pCodePage == NULL)
break;
ZeroMemory(&item, sizeof(LV_ITEM));
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
item.state = 0;
item.stateMask = LVIS_STATEIMAGEMASK;
item.pszText = pCodePage->Name;
item.lParam = (LPARAM)pCodePage;
ItemIndex = ListView_InsertItem(hList, &item);
if (ItemIndex != -1)
{
if (pCodePage->Flags & CODEPAGE_INSTALLED)
{
ListView_SetItemState(hList, ItemIndex,
INDEXTOSTATEIMAGEMASK(LVIS_SELECTED),
LVIS_STATEIMAGEMASK);
}
else
{
ListView_SetItemState(hList, ItemIndex,
INDEXTOSTATEIMAGEMASK(LVIS_FOCUSED),
LVIS_STATEIMAGEMASK);
}
}
pCodePage = pCodePage->NextItem;
}
}
static BOOL CALLBACK
LocalesEnumProc(PWSTR lpLocale)
{
LCID lcid;
WCHAR lang[255];
INT index;
BOOL bNoShow = FALSE;
lcid = wcstoul(lpLocale, NULL, 16);
if (lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) ||
lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT))
{
if (bSpain == FALSE)
{
LoadStringW(hApplet, IDS_SPAIN, lang, 255);
bSpain = TRUE;
}
else
{
bNoShow = TRUE;
}
}
else
{
GetLocaleInfoW(lcid, LOCALE_SLANGUAGE, lang, sizeof(lang)/sizeof(WCHAR));
}
if (bNoShow == FALSE)
{
index = SendMessageW(hLangList,
CB_ADDSTRING,
0,
(LPARAM)lang);
SendMessageW(hLangList,
CB_SETITEMDATA,
index,
(LPARAM)lcid);
}
return TRUE;
}
static VOID
InitLanguagesList(
HWND hwndDlg,
PGLOBALDATA pGlobalData)
{
WCHAR langSel[255];
hLangList = GetDlgItem(hwndDlg, IDC_LANGUAGE_COMBO);
bSpain = FALSE;
EnumSystemLocalesW(LocalesEnumProc, LCID_SUPPORTED);
/* Select current locale */
GetLocaleInfoW(pGlobalData->SystemLCID, LOCALE_SLANGUAGE, langSel, sizeof(langSel)/sizeof(WCHAR));
SendMessageW(hLangList, CB_SELECTSTRING, -1, (LPARAM)langSel);
}
static VOID
GetCurrentDPI(LPTSTR szDPI)
{
DWORD dwType, dwSize, dwDPI, dwDefDPI = 0x00000060; // Default 96 DPI
HKEY hKey;
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontDPI", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS)
{
wcscpy(szDPI, L"96");
return;
}
dwType = REG_DWORD;
dwSize = sizeof(DWORD);
if (RegQueryValueExW(hKey, L"LogPixels", NULL, &dwType, (LPBYTE)&dwDPI, &dwSize) != ERROR_SUCCESS)
{
if (RegSetValueExW(hKey, L"LogPixels", 0, REG_DWORD, (LPBYTE)&dwDefDPI, sizeof(DWORD)) == ERROR_SUCCESS)
{
wcscpy(szDPI, L"96");
RegCloseKey(hKey);
return;
}
}
else
{
wsprintf(szDPI, L"%d", dwDPI);
}
RegCloseKey(hKey);
}
static
VOID
SaveFontSubstitutionSettings(
HWND hwnd,
PGLOBALDATA pGlobalData)
{
WCHAR szDefCP[5 + 1], szSection[MAX_PATH], szDPI[3 + 1];
HINF hFontInf;
UINT Count;
GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, szDefCP, sizeof(szDefCP) / sizeof(WCHAR));
GetCurrentDPI(szDPI);
wsprintf(szSection, L"Font.CP%s.%s", szDefCP, szDPI);
hFontInf = SetupOpenInfFileW(L"font.inf", NULL, INF_STYLE_WIN4, NULL);
if (hFontInf == INVALID_HANDLE_VALUE)
return;
if (!SetupOpenAppendInfFile(NULL, hFontInf, NULL))
{
SetupCloseInfFile(hFontInf);
return;
}
Count = (UINT)SetupGetLineCount(hFontInf, szSection);
if (Count <= 0)
return;
if (!SetupInstallFromInfSectionW(hwnd, hFontInf, szSection, SPINST_REGISTRY & ~SPINST_FILES,
NULL, NULL, 0, NULL, NULL, NULL, NULL))
{
MessageBoxW(hwnd, L"Unable to install a new language for programs don't support unicode!",
NULL, MB_ICONERROR | MB_OK);
}
SetupCloseInfFile(hFontInf);
}
static
VOID
SaveFontLinkingSettings(
HWND hwnd,
PGLOBALDATA pGlobalData)
{
/* TODO */
}
static
VOID
SaveSystemSettings(
PGLOBALDATA pGlobalData)
{
WCHAR ACPPage[9];
WCHAR OEMPage[9];
HKEY langKey;
DWORD ret;
WCHAR value[5];
DWORD valuesize;
ret = GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, OEMPage, sizeof(OEMPage)/sizeof(WCHAR));
if (ret == 0)
{
PrintErrorMsgBox(IDS_ERROR_OEM_CODE_PAGE);
return;
}
ret = GetLocaleInfoW(MAKELCID(pGlobalData->SystemLCID, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, ACPPage, sizeof(ACPPage)/sizeof(WCHAR));
if (ret == 0)
{
PrintErrorMsgBox(IDS_ERROR_ANSI_CODE_PAGE);
return;
}
/* Set codepages */
ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage", &langKey);
if (ret != ERROR_SUCCESS)
{
PrintErrorMsgBox(IDS_ERROR_NLS_CODE_REG);
return;
}
RegSetValueExW(langKey, L"OEMCP", 0, REG_SZ, (BYTE *)OEMPage, (wcslen(OEMPage) +1 ) * sizeof(WCHAR));
RegSetValueExW(langKey, L"ACP", 0, REG_SZ, (BYTE *)ACPPage, (wcslen(ACPPage) +1 ) * sizeof(WCHAR));
RegCloseKey(langKey);
wsprintf(value, L"%04hX", LANGIDFROMLCID(pGlobalData->SystemLCID));
valuesize = (wcslen(value) + 1) * sizeof(WCHAR);
/* Set language */
ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language", &langKey);
if (ret != ERROR_SUCCESS)
{
PrintErrorMsgBox(IDS_ERROR_NLS_KEY_REG);
return;
}
RegSetValueExW(langKey, L"Default", 0, REG_SZ, (BYTE *)value, valuesize);
RegCloseKey(langKey);
}
LRESULT
ListViewCustomDraw(
LPARAM lParam)
{
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
switch (lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
if (((PCPAGE)lplvcd->nmcd.lItemlParam)->Flags & CODEPAGE_NOT_REMOVEABLE)
{
lplvcd->clrText = GetSysColor(COLOR_GRAYTEXT);
}
else
{
lplvcd->clrText = GetSysColor(COLOR_WINDOWTEXT);
}
lplvcd->clrTextBk = GetSysColor(COLOR_WINDOW);
return CDRF_NEWFONT;
}
return CDRF_DODEFAULT;
}
/* Property page dialog callback */
INT_PTR CALLBACK
AdvancedPageProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PGLOBALDATA pGlobalData;
pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
InitLanguagesList(hwndDlg, pGlobalData);
InitCodePagesList(hwndDlg);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_LANGUAGE_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
LCID lcid;
INT iIndex;
iIndex = SendMessage(hLangList, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
break;
lcid = SendMessage(hLangList, CB_GETITEMDATA, iIndex, 0);
if (lcid == (LCID)CB_ERR)
break;
pGlobalData->SystemLCID = lcid;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
}
break;
case IDC_APPLY_CUR_USER_DEF_PROFILE:
if (HIWORD(wParam) == BN_CLICKED)
{
if (SendDlgItemMessageW(hwndDlg, IDC_APPLY_CUR_USER_DEF_PROFILE, BM_GETCHECK, 0, 0))
{
ResourceMessageBox(hwndDlg,
MB_OK | MB_ICONWARNING,
IDS_APPLY_DEFAULT_TITLE,
IDS_APPLY_DEFAULT_TEXT);
pGlobalData->bApplyToDefaultUser = TRUE;
}
else
{
pGlobalData->bApplyToDefaultUser = FALSE;
}
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
}
break;
}
break;
case WM_NOTIFY:
if (((LPNMHDR)lParam)->code == PSN_APPLY)
{
PropSheet_UnChanged(GetParent(hwndDlg), hwndDlg);
SaveSystemSettings(pGlobalData);
SaveFontSubstitutionSettings(hwndDlg, pGlobalData);
SaveFontLinkingSettings(hwndDlg, pGlobalData);
}
else if (((LPNMHDR)lParam)->idFrom == IDC_CONV_TABLES &&
((LPNMHDR)lParam)->code == NM_CUSTOMDRAW)
{
SetWindowLongPtr(hwndDlg,
DWLP_MSGRESULT,
(LONG_PTR)ListViewCustomDraw(lParam));
return TRUE;
}
break;
}
return FALSE;
}
/* EOF */