|
|
/*++
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.
//
// lpSubKey is one of those #defines up there.
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, min(KeyValueInformation->NameLength, dwValueLength)); lpValueName[ KeyValueInformation->NameLength >> 1 ] = UNICODE_NULL;
ASSERT(KeyValueInformation->DataLength <= dwDataLength); RtlMoveMemory(lpData, (PBYTE)KeyValueInformation + KeyValueInformation->DataOffset, min(KeyValueInformation->DataLength, dwDataLength)); if (KeyValueInformation->Type == REG_SZ || KeyValueInformation->Type == REG_MULTI_SZ ) { if (KeyValueInformation->DataLength + sizeof(WCHAR) > dwDataLength) { KeyValueInformation->DataLength -= sizeof(WCHAR); } // WTF is this doing?
if (KeyValueInformation->DataLength < dwDataLength) lpData[KeyValueInformation->DataLength++] = 0; if (KeyValueInformation->DataLength < dwDataLength) 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, UINT cchFaceName ) { 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; StrCpyN(AltFaceName, pcpd->FontInfo[*AltFontIndex].FaceName, cchFaceName); *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; StrCpyN(pTTFontList->FaceName1, pwsz, ARRAYSIZE(pTTFontList->FaceName1));
pwsz += lstrlenW(pwsz) + 1; if (*pwsz == BOLD_MARK) { pTTFontList->fDisableBold = TRUE; pwsz++; } StrCpyN(pTTFontList->FaceName2, pwsz, ARRAYSIZE(pTTFontList->FaceName2));
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; }
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) <= ARRAYSIZE(LocaleList->LC_String) - 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; StrCpyN(TmpList->LC_String, LC_String, ARRAYSIZE(TmpList->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, ARRAYSIZE(awchData)); 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
|