WindowsXP-SP1/shell/shell32/dbcs.c

619 lines
15 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
dbcs.c
Abstract:
This module contains the code for console DBCS font dialog
Author:
kazum Feb-27-1995
Revision History:
--*/
#include "shellprv.h"
#pragma hdrstop
#include "lnkcon.h"
#ifdef DBCS
// This definition shares in windows\inc\wincon.w file
//
#define MACHINE_REGISTRY_CONSOLE_TTFONT (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont")
#define MACHINE_REGISTRY_CONSOLE_NLS (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\Nls")
NTSTATUS
MyRegOpenKey(
IN HANDLE hKey,
IN LPWSTR lpSubKey,
OUT PHANDLE phResult
)
{
OBJECT_ATTRIBUTES Obja;
UNICODE_STRING SubKey;
//
// Convert the subkey to a counted Unicode string.
//
RtlInitUnicodeString( &SubKey, lpSubKey );
//
// Initialize the OBJECT_ATTRIBUTES structure and open the key.
//
InitializeObjectAttributes(
&Obja,
&SubKey,
OBJ_CASE_INSENSITIVE,
hKey,
NULL
);
return NtOpenKey(
phResult,
KEY_READ,
&Obja
);
}
NTSTATUS
MyRegEnumValue(
IN HANDLE hKey,
IN DWORD dwIndex,
OUT DWORD dwValueLength,
OUT LPWSTR lpValueName,
OUT DWORD dwDataLength,
OUT LPBYTE lpData
)
{
ULONG BufferLength;
ULONG ResultLength;
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
NTSTATUS Status;
//
// Convert the subkey to a counted Unicode string.
//
BufferLength = sizeof(KEY_VALUE_FULL_INFORMATION) + dwValueLength + dwDataLength;
KeyValueInformation = LocalAlloc(LPTR,BufferLength);
if (KeyValueInformation == NULL)
return STATUS_NO_MEMORY;
Status = NtEnumerateValueKey(
hKey,
dwIndex,
KeyValueFullInformation,
KeyValueInformation,
BufferLength,
&ResultLength
);
if (NT_SUCCESS(Status)) {
ASSERT(KeyValueInformation->NameLength <= dwValueLength);
RtlMoveMemory(lpValueName,
KeyValueInformation->Name,
KeyValueInformation->NameLength);
lpValueName[ KeyValueInformation->NameLength >> 1 ] = UNICODE_NULL;
ASSERT(KeyValueInformation->DataLength <= dwDataLength);
RtlMoveMemory(lpData,
(PBYTE)KeyValueInformation + KeyValueInformation->DataOffset,
KeyValueInformation->DataLength);
if (KeyValueInformation->Type == REG_SZ ||
KeyValueInformation->Type == REG_MULTI_SZ
) {
if (KeyValueInformation->DataLength + sizeof(WCHAR) > dwDataLength) {
KeyValueInformation->DataLength -= sizeof(WCHAR);
}
lpData[KeyValueInformation->DataLength++] = 0;
lpData[KeyValueInformation->DataLength] = 0;
}
}
LocalFree(KeyValueInformation);
return Status;
}
WORD
ConvertStringToDec(
LPWSTR lpch,
LPWSTR *endptr
)
{
WCHAR ch;
WORD val = 0;
while ( (ch=*lpch) != L'\0')
{
if (L'0' <= ch && ch <= L'9')
val = (val * 10) + (ch - L'0');
else
break;
lpch++;
}
if (endptr)
*endptr = lpch;
return val;
}
WORD
ConvertStringToHex(
LPWSTR lpch,
LPWSTR *endptr
)
{
WCHAR ch;
WORD val = 0;
while ( (ch=*lpch) != L'\0')
{
if (L'0' <= ch && ch <= L'9')
val = (val << 4) + (ch - L'0');
else if (L'A' <= ch && ch <= L'F')
val = (val << 4) + (ch - L'A' + 10);
else if (L'a' <= ch && ch <= L'f')
val = (val << 4) + (ch - L'a' + 10);
else
break;
lpch++;
}
if (endptr)
*endptr = lpch;
return val;
}
NTSTATUS
MakeAltRasterFont(
CONSOLEPROP_DATA * pcpd,
UINT CodePage,
COORD *AltFontSize,
BYTE *AltFontFamily,
ULONG *AltFontIndex,
LPTSTR AltFaceName
)
{
DWORD i;
DWORD Find;
ULONG FontIndex;
COORD FontSize = pcpd->FontInfo[pcpd->DefaultFontIndex].Size;
COORD FontDelta;
BOOL fDbcsCharSet = IS_ANY_DBCS_CHARSET( CodePageToCharSet( CodePage ) );
FontIndex = 0;
Find = (DWORD)-1;
for (i=0; i < pcpd->NumberOfFonts; i++)
{
if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family) &&
IS_ANY_DBCS_CHARSET(pcpd->FontInfo[i].tmCharSet) == fDbcsCharSet
)
{
FontDelta.X = (SHORT)abs(FontSize.X - pcpd->FontInfo[i].Size.X);
FontDelta.Y = (SHORT)abs(FontSize.Y - pcpd->FontInfo[i].Size.Y);
if (Find > (DWORD)(FontDelta.X + FontDelta.Y))
{
Find = (DWORD)(FontDelta.X + FontDelta.Y);
FontIndex = i;
}
}
}
*AltFontIndex = FontIndex;
lstrcpy(AltFaceName, pcpd->FontInfo[*AltFontIndex].FaceName);
*AltFontSize = pcpd->FontInfo[*AltFontIndex].Size;
*AltFontFamily = pcpd->FontInfo[*AltFontIndex].Family;
return STATUS_SUCCESS;
}
NTSTATUS
InitializeDbcsMisc(
CONSOLEPROP_DATA * pcpd
)
{
HANDLE hkRegistry = NULL;
NTSTATUS Status;
WCHAR awchValue[ 512 ];
WCHAR awchData[ 512 ];
DWORD dwIndex;
LPWSTR pwsz;
pcpd->gTTFontList.Next = NULL;
Status = MyRegOpenKey(NULL,
MACHINE_REGISTRY_CONSOLE_TTFONT,
&hkRegistry);
if (NT_SUCCESS( Status )) {
TTFONTLIST *pTTFontList;
for( dwIndex = 0; ; dwIndex++) {
Status = MyRegEnumValue(hkRegistry,
dwIndex,
sizeof(awchValue), (LPWSTR)&awchValue,
sizeof(awchData), (PBYTE)&awchData);
if (!NT_SUCCESS( Status )) {
break;
}
pTTFontList = LocalAlloc(LPTR, sizeof(TTFONTLIST));
if (pTTFontList == NULL) {
break;
}
pTTFontList->List.Next = NULL;
pTTFontList->CodePage = ConvertStringToDec(awchValue, NULL);
pwsz = awchData;
if (*pwsz == BOLD_MARK) {
pTTFontList->fDisableBold = TRUE;
pwsz++;
}
else
pTTFontList->fDisableBold = FALSE;
#ifdef UNICODE
lstrcpyW(pTTFontList->FaceName1, pwsz);
pwsz += lstrlenW(pwsz) + 1;
if (*pwsz == BOLD_MARK)
{
pTTFontList->fDisableBold = TRUE;
pwsz++;
}
lstrcpyW(pTTFontList->FaceName2, pwsz);
#else
// if we're the ANSI shell, we need to convert FACENAME
// over to ASCII before saving...
{
CHAR szFaceName[LF_FACESIZE];
SHUnicodeToAnsi(pwsz, szFaceName, ARRAYSIZE(szFaceName));
lstrcpyA(pTTFontList->FaceName1, szFaceName);
pwsz += lstrlenW(pwsz) + 1;
if (*pwsz == BOLD_MARK)
{
pTTFontList->fDisableBold = TRUE;
pwsz++;
}
SHUnicodeToAnsi(pwsz, szFaceName, ARRAYSIZE(szFaceName));
lstrcpyA(pTTFontList->FaceName2, szFaceName);
}
#endif
PushEntryList(&pcpd->gTTFontList, &(pTTFontList->List));
}
NtClose(hkRegistry);
}
pcpd->fChangeCodePage = FALSE;
pcpd->uOEMCP = GetOEMCP();
return STATUS_SUCCESS;
}
BYTE
CodePageToCharSet(
UINT CodePage
)
{
CHARSETINFO csi;
if (!TranslateCharsetInfo((DWORD *)UIntToPtr( CodePage ), &csi, TCI_SRCCODEPAGE)) // Sundown: valid zero-extension of CodePage for TCI_SRCCOPAGE.
csi.ciCharset = OEM_CHARSET;
return (BYTE)csi.ciCharset;
}
TTFONTLIST *SearchTTFont(CONSOLEPROP_DATA * pcpd, LPTSTR ptszFace, BOOL fCodePage, UINT CodePage)
{
PSINGLE_LIST_ENTRY pTemp = pcpd->gTTFontList.Next;
if (ptszFace) {
while (pTemp != NULL) {
TTFONTLIST *pTTFontList = (TTFONTLIST *)pTemp;
if (wcscmp(ptszFace, pTTFontList->FaceName1) == 0 ||
wcscmp(ptszFace, pTTFontList->FaceName2) == 0 ) {
if (fCodePage)
if (pTTFontList->CodePage == CodePage )
return pTTFontList;
else
return NULL;
else
return pTTFontList;
}
pTemp = pTemp->Next;
}
}
return NULL;
}
BOOL
IsAvailableTTFont(
CONSOLEPROP_DATA * pcpd,
LPTSTR ptszFace
)
{
if (SearchTTFont(pcpd, ptszFace, FALSE, 0))
return TRUE;
else
return FALSE;
}
BOOL
IsAvailableTTFontCP(
CONSOLEPROP_DATA * pcpd,
LPTSTR ptszFace,
UINT CodePage
)
{
if (SearchTTFont(pcpd, ptszFace, TRUE, CodePage))
return TRUE;
else
return FALSE;
}
BOOL
IsDisableBoldTTFont(
CONSOLEPROP_DATA * pcpd,
LPTSTR ptszFace
)
{
TTFONTLIST *pTTFontList;
pTTFontList = SearchTTFont(pcpd, ptszFace, FALSE, 0);
if (pTTFontList != NULL)
return pTTFontList->fDisableBold;
else
return FALSE;
}
LPTSTR
GetAltFaceName(
CONSOLEPROP_DATA * pcpd,
LPTSTR ptszFace
)
{
TTFONTLIST *pTTFontList;
pTTFontList = SearchTTFont(pcpd, ptszFace, FALSE, 0);
if (pTTFontList) {
if (wcscmp(ptszFace, pTTFontList->FaceName1) == 0) {
return pTTFontList->FaceName2;
}
if (wcscmp(ptszFace, pTTFontList->FaceName2) == 0) {
return pTTFontList->FaceName1;
}
return NULL;
}
else
return NULL;
}
NTSTATUS DestroyDbcsMisc(CONSOLEPROP_DATA * pcpd)
{
while (pcpd->gTTFontList.Next != NULL)
{
TTFONTLIST *pTTFontList = (TTFONTLIST *)PopEntryList(&pcpd->gTTFontList);
if (pTTFontList != NULL)
LocalFree(pTTFontList);
}
return STATUS_SUCCESS;
}
typedef struct _LC_List {
struct _LC_List* Next;
BOOL FindFlag;
WCHAR LC_String[9];
} LC_List, *PLC_List;
static PLC_List LocaleList;
BOOL CALLBACK
EnumProc(
LPWSTR LC_String
)
{
PLC_List TmpList;
if (lstrlenW(LC_String) <= (sizeof(LocaleList->LC_String)/sizeof(WCHAR))-1)
{
TmpList = (PLC_List)&LocaleList;
while(TmpList->Next != NULL)
TmpList = TmpList->Next;
TmpList->Next = LocalAlloc(LPTR, sizeof(LC_List));
if (TmpList->Next != NULL)
{
TmpList = TmpList->Next;
lstrcpyW(TmpList->LC_String, LC_String);
}
}
return TRUE;
}
int
LanguageListCreate(
HWND hDlg,
UINT CodePage
)
/*++
Initializes the Language list by enumerating all Locale Information.
Returns
--*/
{
HWND hWndLanguageCombo;
HANDLE hkRegistry = NULL;
NTSTATUS Status;
WCHAR awchValue[ 512 ];
WCHAR awchData[ 512 ];
DWORD dwIndex;
PLC_List TmpList;
WORD LangID;
LCID Locale;
int cchData;
LONG lListIndex;
UINT cp;
ENTERCRITICAL;
/*
* Enumrate system locale information
*/
EnumSystemLocalesW( EnumProc, CP_INSTALLED );
/*
* Enumrate registory key
*/
Status = MyRegOpenKey(NULL,
MACHINE_REGISTRY_CONSOLE_NLS,
&hkRegistry);
if (NT_SUCCESS( Status )) {
for( dwIndex = 0; ; dwIndex++)
{
Status = MyRegEnumValue(hkRegistry,
dwIndex,
sizeof(awchValue), (LPWSTR)&awchValue,
sizeof(awchData), (PBYTE)&awchData);
if (!NT_SUCCESS( Status ))
{
break;
}
TmpList = (PLC_List)&LocaleList;
while(TmpList->Next != NULL)
{
TmpList = TmpList->Next;
if (lstrcmpW(awchValue, TmpList->LC_String) == 0)
{
TmpList->FindFlag = TRUE;
break;
}
}
}
NtClose(hkRegistry);
}
/*
* Create ComboBox items
*/
hWndLanguageCombo = GetDlgItem(hDlg, IDC_CNSL_LANGUAGELIST);
SendMessage(hWndLanguageCombo, CB_RESETCONTENT, 0, 0L);
TmpList = (PLC_List)&LocaleList;
while(TmpList->Next != NULL)
{
TmpList = TmpList->Next;
if (TmpList->FindFlag)
{
LangID = ConvertStringToHex(TmpList->LC_String, NULL);
Locale = MAKELCID( LangID, SORT_DEFAULT );
awchValue[0] = L'\0';
cp = 0;
{
#define KERNEL32 _T("KERNEL32.DLL")
#ifdef UNICODE
#define GETCPINFOEX "GetCPInfoExW"
#else
#define GETCPINFOEX "GetCPInfoExA"
#endif
typedef BOOL (CALLBACK *LPFNGETCPINFOEX)(UINT, DWORD, LPCPINFOEX);
LPFNGETCPINFOEX lpfnGetCPInfoEx;
BOOL fRet = FALSE;
CPINFOEX cpinfo;
HMODULE hMod;
cchData = GetLocaleInfoW(Locale, LOCALE_IDEFAULTCODEPAGE,
awchData, sizeof(awchData)/sizeof(TCHAR));
if (cchData)
{
cp = ConvertStringToDec(awchData, NULL);
hMod = GetModuleHandle(KERNEL32);
if (hMod) {
lpfnGetCPInfoEx = (LPFNGETCPINFOEX)GetProcAddress(hMod,GETCPINFOEX);
if (lpfnGetCPInfoEx)
fRet = (*lpfnGetCPInfoEx)(cp, 0, &cpinfo);
}
if (fRet) {
lListIndex = (LONG) SendMessageW(hWndLanguageCombo, CB_ADDSTRING, 0, (LPARAM)cpinfo.CodePageName);
SendMessage(hWndLanguageCombo, CB_SETITEMDATA, (DWORD)lListIndex, cp);
if (CodePage == cp) {
SendMessage(hWndLanguageCombo, CB_SETCURSEL, lListIndex, 0L);
}
}
}
}
if (CodePage == cp) {
SendMessage(hWndLanguageCombo, CB_SETCURSEL, lListIndex, 0L);
}
}
}
{
PLC_List Tmp;
TmpList = (PLC_List)&LocaleList;
while(TmpList->Next != NULL)
{
Tmp = TmpList;
TmpList = TmpList->Next;
if (Tmp != (PLC_List)&LocaleList)
LocalFree(Tmp);
}
LocaleList = NULL;
}
LEAVECRITICAL;
/*
* Get the LocaleIndex from the currently selected item.
* (i will be LB_ERR if no currently selected item).
*/
lListIndex = (LONG) SendMessage(hWndLanguageCombo, CB_GETCURSEL, 0, 0L);
return (int) SendMessage(hWndLanguageCombo, CB_GETITEMDATA, lListIndex, 0L);
}
#endif // DBCS