|
|
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
misc.c
Abstract:
This file implements the NT console server font routines.
Author:
Therese Stowell (thereses) 22-Jan-1991
Revision History:
--*/
#include "shellprv.h"
#pragma hdrstop
#include "lnkcon.h"
#define CONSOLE_REGISTRY_STRING (TEXT("Console"))
#define CONSOLE_REGISTRY_FONTSIZE (TEXT("FontSize"))
#define CONSOLE_REGISTRY_FONTFAMILY (TEXT("FontFamily"))
#define CONSOLE_REGISTRY_BUFFERSIZE (TEXT("ScreenBufferSize"))
#define CONSOLE_REGISTRY_CURSORSIZE (TEXT("CursorSize"))
#define CONSOLE_REGISTRY_WINDOWSIZE (TEXT("WindowSize"))
#define CONSOLE_REGISTRY_WINDOWPOS (TEXT("WindowPosition"))
#define CONSOLE_REGISTRY_FILLATTR (TEXT("ScreenColors"))
#define CONSOLE_REGISTRY_POPUPATTR (TEXT("PopupColors"))
#define CONSOLE_REGISTRY_FULLSCR (TEXT("FullScreen"))
#define CONSOLE_REGISTRY_QUICKEDIT (TEXT("QuickEdit"))
#define CONSOLE_REGISTRY_FACENAME (TEXT("FaceName"))
#define CONSOLE_REGISTRY_FONTWEIGHT (TEXT("FontWeight"))
#define CONSOLE_REGISTRY_INSERTMODE (TEXT("InsertMode"))
#define CONSOLE_REGISTRY_HISTORYSIZE (TEXT("HistoryBufferSize"))
#define CONSOLE_REGISTRY_HISTORYBUFS (TEXT("NumberOfHistoryBuffers"))
#define CONSOLE_REGISTRY_HISTORYNODUP (TEXT("HistoryNoDup"))
#define CONSOLE_REGISTRY_COLORTABLE (TEXT("ColorTable%02u"))
#define CONSOLE_REGISTRY_CODEPAGE (TEXT("CodePage"))
/*
* Initial default fonts and face names */
/*
* TTPoints -- Initial font pixel heights for TT fonts */ SHORT TTPoints[] = { 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72 }; /*
* TTPointsDbcs -- Initial font pixel heights for TT fonts of DBCS. */ SHORT TTPointsDbcs[] = { 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72 };
typedef struct _FONTENUMDATA { CONSOLEPROP_DATA *pcpd; HDC hDC; BOOL bFindFaces; ULONG ulFE; PSHORT pTTPoints; UINT nTTPoints; UINT uDefCP; } FONTENUMDATA, *PFONTENUMDATA;
FACENODE * AddFaceNode(FACENODE * *ppStart, LPTSTR ptsz) { FACENODE * pNew; FACENODE * *ppTmp; int cb;
/*
* Is it already here? */ for (ppTmp = ppStart; *ppTmp; ppTmp = &((*ppTmp)->pNext)) { if (lstrcmp(((*ppTmp)->atch), ptsz) == 0) { // already there !
return *ppTmp; } }
cb = (lstrlen(ptsz) + 1) * sizeof(TCHAR); pNew = (FACENODE *)LocalAlloc(LPTR ,sizeof(FACENODE) + cb); if (pNew == NULL) { return NULL; }
pNew->pNext = NULL; pNew->dwFlag = 0; lstrcpy(pNew->atch, ptsz); *ppTmp = pNew; return pNew; }
VOID DestroyFaceNodes( CONSOLEPROP_DATA *pcpd ) { FACENODE * pNext; FACENODE * pTmp;
pTmp = pcpd->gpFaceNames; while (pTmp != NULL) { pNext = pTmp->pNext; LocalFree(pTmp); pTmp = pNext; } pcpd->gpFaceNames = NULL; }
int AddFont( CONSOLEPROP_DATA *pcpd, ENUMLOGFONT *pelf, NEWTEXTMETRIC *pntm, int nFontType, HDC hDC, FACENODE * pFN )
/*++
Add the font desribed by the LOGFONT structure to the font table if it's not already there.
--*/
{ HFONT hFont; TEXTMETRIC tm; LONG nFont; COORD SizeToShow; COORD SizeActual; COORD SizeWant; BYTE tmFamily; SIZE Size; LPTSTR ptszFace = pelf->elfLogFont.lfFaceName;
/* get font info */ SizeWant.Y = (SHORT)pelf->elfLogFont.lfHeight; SizeWant.X = (SHORT)pelf->elfLogFont.lfWidth; CreateBoldFont: hFont = CreateFontIndirect(&pelf->elfLogFont); ASSERT(hFont); if (!hFont) { return FE_SKIPFONT; // same font in other sizes may still be suitable
}
//
// for reasons unbeknownst to me, removing this code causes GDI
// to yack, claiming that the font is owned by another process.
//
SelectObject(hDC, hFont); GetTextMetrics(hDC, &tm);
GetTextExtentPoint32(hDC, TEXT("0"), 1, &Size); SizeActual.X = (SHORT)Size.cx; SizeActual.Y = (SHORT)(tm.tmHeight + tm.tmExternalLeading); tmFamily = tm.tmPitchAndFamily; if (TM_IS_TT_FONT(tmFamily) && (SizeWant.Y >= 0)) { SizeToShow = SizeWant; if (SizeWant.X == 0) { // Asking for zero width height gets a default aspect-ratio width
// It's better to show that width rather than 0.
SizeToShow.X = SizeActual.X; } } else { SizeToShow = SizeActual; }
// there's a GDI bug - this assert fails occasionally
//ASSERT (tm.tmMaxCharWidth == pntm->tmMaxCharWidth);
/*
* NOW, determine whether this font entry has already been cached * LATER : it may be possible to do this before creating the font, if * we can trust the dimensions & other info from pntm. * Sort by size: * 1) By pixelheight (negative Y values) * 2) By height (as shown) * 3) By width (as shown) */ for (nFont = 0; nFont < (LONG)pcpd->NumberOfFonts; ++nFont) { COORD SizeShown;
if (pcpd->FontInfo[nFont].hFont == NULL) { continue; }
if (pcpd->FontInfo[nFont].SizeWant.X > 0) { SizeShown.X = pcpd->FontInfo[nFont].SizeWant.X; } else { SizeShown.X = pcpd->FontInfo[nFont].Size.X; }
if (pcpd->FontInfo[nFont].SizeWant.Y > 0) { // This is a font specified by cell height.
SizeShown.Y = pcpd->FontInfo[nFont].SizeWant.Y; } else { SizeShown.Y = pcpd->FontInfo[nFont].Size.Y; if (pcpd->FontInfo[nFont].SizeWant.Y < 0) { // This is a TT font specified by character height.
if (SizeWant.Y < 0 && SizeWant.Y > pcpd->FontInfo[nFont].SizeWant.Y) { // Requested pixelheight is smaller than this one.
break; } } }
if (SIZE_EQUAL(SizeShown, SizeToShow) && pcpd->FontInfo[nFont].Family == tmFamily && pcpd->FontInfo[nFont].Weight == tm.tmWeight && lstrcmp(pcpd->FontInfo[nFont].FaceName, ptszFace) == 0) { /*
* Already have this font */ DeleteObject(hFont); return FE_FONTOK; }
if ((SizeToShow.Y < SizeShown.Y) || (SizeToShow.Y == SizeShown.Y && SizeToShow.X < SizeShown.X)) { /*
* This new font is smaller than nFont */ break; } }
/*
* If we have to grow our font table, do it */ if (pcpd->NumberOfFonts == pcpd->FontInfoLength) { FONT_INFO *Temp;
pcpd->FontInfoLength += FONT_INCREMENT; Temp = (FONT_INFO *)LocalReAlloc(pcpd->FontInfo, sizeof(FONT_INFO) * pcpd->FontInfoLength, LMEM_MOVEABLE|LMEM_ZEROINIT); ASSERT(Temp); if (Temp == NULL) { pcpd->FontInfoLength -= FONT_INCREMENT; return FE_ABANDONFONT; // no point enumerating more - no memory!
} pcpd->FontInfo = Temp; }
/*
* The font we are adding should be inserted into the list, * if it is smaller than the last one. */ if (nFont < (LONG)pcpd->NumberOfFonts) { MoveMemory( &pcpd->FontInfo[nFont+1], &pcpd->FontInfo[nFont], sizeof(FONT_INFO) * (pcpd->NumberOfFonts - nFont) ); }
/*
* Store the font info */ pcpd->FontInfo[nFont].hFont = hFont; pcpd->FontInfo[nFont].Family = tmFamily; pcpd->FontInfo[nFont].Size = SizeActual; if (TM_IS_TT_FONT(tmFamily)) { pcpd->FontInfo[nFont].SizeWant = SizeWant; } else { pcpd->FontInfo[nFont].SizeWant.X = 0; pcpd->FontInfo[nFont].SizeWant.Y = 0; } pcpd->FontInfo[nFont].Weight = tm.tmWeight; pcpd->FontInfo[nFont].FaceName = pFN->atch; pcpd->FontInfo[nFont].tmCharSet = tm.tmCharSet;
++pcpd->NumberOfFonts;
/*
* If this is a true type font, create a bold version too. */ if (nFontType == TRUETYPE_FONTTYPE && !IS_BOLD(pcpd->FontInfo[nFont].Weight)) { pelf->elfLogFont.lfWeight = FW_BOLD; goto CreateBoldFont; }
return FE_FONTOK; // and continue enumeration
}
NTSTATUS InitializeFonts( CONSOLEPROP_DATA *pcpd ) { return EnumerateFonts( pcpd, EF_DEFFACE); // Just the Default font
}
STDAPI_(void) DestroyFonts( CONSOLEPROP_DATA *pcpd ) { ULONG FontIndex;
if (pcpd->FontInfo != NULL) { for (FontIndex = 0; FontIndex < pcpd->NumberOfFonts; FontIndex++) { DeleteObject(pcpd->FontInfo[FontIndex].hFont); } LocalFree(pcpd->FontInfo); pcpd->FontInfo = NULL; pcpd->NumberOfFonts = 0; }
DestroyFaceNodes( pcpd ); }
/*
* Returns bit combination * FE_ABANDONFONT - do not continue enumerating this font * FE_SKIPFONT - skip this font but keep enumerating * FE_FONTOK - font was created and added to cache or already there */ int FontEnum( ENUMLOGFONT *pelf, NEWTEXTMETRIC *pntm, int nFontType, PFONTENUMDATA pfed )
/*++
Is called exactly once by GDI for each font in the system. This routine is used to store the FONT_INFO structure.
--*/
{ UINT i; LPTSTR ptszFace = pelf->elfLogFont.lfFaceName; FACENODE * pFN;
BOOL bNegAC;
#ifdef DEBUG
OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi);
// NTMW_STRUCTURE is different on 5.0+ platforms and the flag for 5.0+
// platforms now lives in NEWTEXTMETRIC structure.
AssertMsg(osvi.dwMajorVersion > 4, TEXT("We now only support running on Win2k or Millennium and later so we should never hit this.")); #endif
bNegAC = !(pntm->ntmFlags & NTM_NONNEGATIVE_AC);
//
// reject variable width and italic fonts, also tt fonts with neg ac
//
if ( !(pelf->elfLogFont.lfPitchAndFamily & FIXED_PITCH) || (pelf->elfLogFont.lfItalic) || bNegAC ) { if (!IsAvailableTTFont(pfed->pcpd,ptszFace)) return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT; }
/*
* reject TT fonts for whoom family is not modern, that is do not use * FF_DONTCARE // may be surprised unpleasantly
* FF_DECORATIVE // likely to be symbol fonts
* FF_SCRIPT // cursive, inappropriate for console
* FF_SWISS OR FF_ROMAN // variable pitch
*/
if ((nFontType == TRUETYPE_FONTTYPE) && ((pelf->elfLogFont.lfPitchAndFamily & 0xf0) != FF_MODERN)) { return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT; }
/*
* reject non-TT fonts that aren't OEM */ if ((nFontType != TRUETYPE_FONTTYPE) && (!IsFarEastCP(pfed->uDefCP) || !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet)) && (pelf->elfLogFont.lfCharSet != OEM_CHARSET)) { return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT; }
/*
* reject non-TT vertical/non-Terminal Font for FE */ if (IsFarEastCP(pfed->uDefCP)) { if ((nFontType != TRUETYPE_FONTTYPE) && ((ptszFace[0] == TEXT('@')) || (lstrcmp(ptszFace, TEXT("Terminal")) != 0))) { return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT; } }
/*
* reject Far East TT fonts that aren't Far East charset. */ if (IsAvailableTTFont(pfed->pcpd, ptszFace) && !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet) && !IsAvailableTTFontCP(pfed->pcpd, ptszFace,0) ) { return FE_SKIPFONT; // should be enumerate next charset.
}
/*
* Add or find the facename */ pFN = AddFaceNode(&pfed->pcpd->gpFaceNames, ptszFace); if (pFN == NULL) { return FE_ABANDONFONT; }
if (pfed->bFindFaces) { DWORD dwFontType = 0; if (nFontType == TRUETYPE_FONTTYPE) { dwFontType = EF_TTFONT; } else if (nFontType == RASTER_FONTTYPE) { dwFontType = EF_OEMFONT; } pFN->dwFlag |= dwFontType | EF_NEW; if (IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet)) pFN->dwFlag |= EF_DBCSFONT; return FE_SKIPFONT; }
if (IS_BOLD(pelf->elfLogFont.lfWeight)) { // return FE_SKIPFONT;
}
/*
* Add the font to the table. If this is a true type font, add the * sizes from the array. Otherwise, just add the size we got. */ if (nFontType & TRUETYPE_FONTTYPE) { for (i = 0; i < pfed->nTTPoints; i++) { pelf->elfLogFont.lfHeight = pfed->pTTPoints[i]; pelf->elfLogFont.lfWidth = 0; pelf->elfLogFont.lfWeight = 400; pfed->ulFE |= AddFont(pfed->pcpd, pelf, pntm, nFontType, pfed->hDC, pFN); if (pfed->ulFE & FE_ABANDONFONT) { return FE_ABANDONFONT; } } } else { pfed->ulFE |= AddFont(pfed->pcpd, pelf, pntm, nFontType, pfed->hDC, pFN); if (pfed->ulFE & FE_ABANDONFONT) { return FE_ABANDONFONT; } }
return FE_FONTOK; // and continue enumeration
}
BOOL DoFontEnum( CONSOLEPROP_DATA *pcpd, HDC hDC, LPTSTR ptszFace, PSHORT pTTPoints, UINT nTTPoints) { BOOL bDeleteDC = FALSE; FONTENUMDATA fed; LOGFONT LogFont;
if (hDC == NULL) { hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); bDeleteDC = TRUE; }
fed.pcpd = pcpd; fed.hDC = hDC; fed.bFindFaces = (ptszFace == NULL); fed.ulFE = 0; fed.pTTPoints = pTTPoints; fed.nTTPoints = nTTPoints; fed.uDefCP = pcpd->uOEMCP; RtlZeroMemory(&LogFont, sizeof(LOGFONT)); LogFont.lfCharSet = DEFAULT_CHARSET; if (ptszFace) _tcscpy(LogFont.lfFaceName, ptszFace); /*
* EnumFontFamiliesEx function enumerates one font in every face in every character set. */ EnumFontFamiliesEx(hDC, &LogFont, (FONTENUMPROC)FontEnum, (LPARAM)&fed, 0); if (bDeleteDC) { DeleteDC(hDC); } return (fed.ulFE & FE_FONTOK) != 0; }
VOID RemoveFace(CONSOLEPROP_DATA *pcpd, LPTSTR ptszFace) { DWORD i; int nToRemove = 0;
//
// Delete & Remove fonts with Face Name == ptszFace
//
for (i = 0; i < pcpd->NumberOfFonts; i++) { if (lstrcmp(pcpd->FontInfo[i].FaceName, ptszFace) == 0) { BOOL bDeleted = DeleteObject(pcpd->FontInfo[i].hFont); pcpd->FontInfo[i].hFont = NULL; nToRemove++; } else if (nToRemove > 0) { /*
* Shuffle from FontInfo[i] down nToRemove slots. */ MoveMemory( &pcpd->FontInfo[i - nToRemove], &pcpd->FontInfo[i], sizeof(FONT_INFO)*(pcpd->NumberOfFonts - i) ); pcpd->NumberOfFonts -= nToRemove; i -= nToRemove; nToRemove = 0; } } pcpd->NumberOfFonts -= nToRemove; }
NTSTATUS EnumerateFonts( CONSOLEPROP_DATA *pcpd, DWORD Flags) { TEXTMETRIC tm; HDC hDC; FACENODE * pFN; ULONG ulOldEnumFilter; BOOL bEnumOEMFace = TRUE; DWORD FontIndex; DWORD dwFontType = 0;
dwFontType = (EF_TTFONT|EF_OEMFONT|EF_DEFFACE) & Flags;
if (pcpd->FontInfo == NULL) { //
// allocate memory for the font array
//
pcpd->NumberOfFonts = 0;
pcpd->FontInfo = (FONT_INFO *)LocalAlloc(LPTR, sizeof(FONT_INFO) * INITIAL_FONTS); if (pcpd->FontInfo == NULL) return STATUS_NO_MEMORY; pcpd->FontInfoLength = INITIAL_FONTS; }
hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
// Before enumeration, turn off font enumeration filters.
ulOldEnumFilter = SetFontEnumeration(FE_FILTER_NONE);
if (Flags & EF_DEFFACE) { SelectObject(hDC, GetStockObject(OEM_FIXED_FONT)); GetTextFace(hDC, LF_FACESIZE, pcpd->DefaultFaceName);
// Make sure we are going to enumerate the OEM face.
pFN = AddFaceNode(&pcpd->gpFaceNames, pcpd->DefaultFaceName); if (NULL == pFN) { LocalFree(pcpd->FontInfo); pcpd->FontInfo = NULL; pcpd->FontInfoLength = 0; pcpd->NumberOfFonts = 0; SetFontEnumeration(ulOldEnumFilter); DeleteDC(hDC); return STATUS_NO_MEMORY; }
pFN->dwFlag |= EF_DEFFACE | EF_OEMFONT; GetTextMetrics(hDC, &tm); pcpd->DefaultFontSize.X = (SHORT)(tm.tmMaxCharWidth); pcpd->DefaultFontSize.Y = (SHORT)(tm.tmHeight+tm.tmExternalLeading); pcpd->DefaultFontFamily = tm.tmPitchAndFamily; if (IS_ANY_DBCS_CHARSET(tm.tmCharSet)) pcpd->DefaultFontSize.X /= 2; }
if (pcpd->gbEnumerateFaces) { /*
* Set the EF_OLD bit and clear the EF_NEW bit * for all previously available faces */ for (pFN = pcpd->gpFaceNames; pFN; pFN = pFN->pNext) { pFN->dwFlag |= EF_OLD; pFN->dwFlag &= ~EF_NEW; }
//
// Use DoFontEnum to get the names of all the suitable Faces
// All facenames found will be put in gpFaceNames with
// the EF_NEW bit set.
//
DoFontEnum(pcpd, hDC, NULL, TTPoints, 1); pcpd->gbEnumerateFaces = FALSE; }
// Use DoFontEnum to get all fonts from the system. Our FontEnum
// proc puts just the ones we want into an array
//
for (pFN = pcpd->gpFaceNames; pFN; pFN = pFN->pNext) {
if ((pFN->dwFlag & (EF_OLD|EF_NEW)) == EF_OLD) { // The face is no longer available
RemoveFace(pcpd, pFN->atch); pFN->dwFlag &= ~EF_ENUMERATED; continue; } if ((pFN->dwFlag & dwFontType) == 0) { // not the kind of face we want
continue; } if (pFN->dwFlag & EF_ENUMERATED) { // we already enumerated this face
continue; }
if (pFN->dwFlag & EF_TTFONT) { if (IsFarEastCP(pcpd->uOEMCP) && !IsAvailableTTFontCP(pcpd, pFN->atch, 0)) DoFontEnum(pcpd, hDC, pFN->atch, TTPointsDbcs, NELEM(TTPointsDbcs)); else DoFontEnum(pcpd, hDC, pFN->atch, TTPoints, NELEM(TTPoints)); } else { DoFontEnum(pcpd, hDC, pFN->atch, NULL, 0);
// If we find that the face just enumerated is the same as OEM,
// reset flag so we don't try to enumerate it again.
if (lstrcmpi(pFN->atch, pcpd->DefaultFaceName) == 0) { bEnumOEMFace = FALSE; } } pFN->dwFlag |= EF_ENUMERATED; }
// After enumerating fonts, restore the font enumeration filter.
SetFontEnumeration(ulOldEnumFilter);
DeleteDC(hDC);
for (FontIndex = 0; FontIndex < pcpd->NumberOfFonts; FontIndex++) { if (pcpd->FontInfo[FontIndex].Size.X == pcpd->DefaultFontSize.X && pcpd->FontInfo[FontIndex].Size.Y == pcpd->DefaultFontSize.Y && pcpd->FontInfo[FontIndex].Family == pcpd->DefaultFontFamily) { break; } } ASSERT(FontIndex < pcpd->NumberOfFonts); if (FontIndex < pcpd->NumberOfFonts) { pcpd->DefaultFontIndex = FontIndex; } else { pcpd->DefaultFontIndex = 0; }
return STATUS_SUCCESS; }
NTSTATUS GetNumFonts( CONSOLEPROP_DATA *pcpd, OUT PULONG NumFonts ) { *NumFonts = pcpd->NumberOfFonts; return STATUS_SUCCESS; }
NTSTATUS GetFontSize( CONSOLEPROP_DATA *pcpd, IN DWORD FontIndex, OUT PCOORD FontSize ) { if (FontIndex >= pcpd->NumberOfFonts) return STATUS_INVALID_PARAMETER; *FontSize = pcpd->FontInfo[FontIndex].Size; return STATUS_SUCCESS; }
/*
* Get the font index for a new font * If necessary, attempt to create the font. * Always return a valid FontIndex (even if not correct) * Family: Find/Create a font with of this Family * 0 - don't care * ptszFace: Find/Create a font with this face name. * NULL or TEXT("") - use DefaultFaceName * Size: Must match SizeWant or actual Size. */ int FindCreateFont( CONSOLEPROP_DATA *pcpd, DWORD Family, LPTSTR ptszFace, COORD Size, LONG Weight) { #define NOT_CREATED_NOR_FOUND -1
#define CREATED_BUT_NOT_FOUND -2
int i; int FontIndex = NOT_CREATED_NOR_FOUND; BOOL bFontOK; TCHAR AltFaceName[LF_FACESIZE]; COORD AltFontSize; BYTE AltFontFamily; ULONG AltFontIndex = 0; LPTSTR ptszAltFace = NULL; UINT uCurrentCP = pcpd->lpFEConsole->uCodePage; UINT uDefaultCP = pcpd->uOEMCP; BYTE CharSet = CodePageToCharSet(uCurrentCP);
if (!IsFarEastCP(uDefaultCP) || IS_ANY_DBCS_CHARSET(CharSet)) { if (ptszFace == NULL || *ptszFace == TEXT('\0')) { ptszFace = pcpd->DefaultFaceName; } if (Size.Y == 0) { Size = pcpd->DefaultFontSize; } } else { MakeAltRasterFont(pcpd, uCurrentCP, &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
if (ptszFace == NULL || *ptszFace == L'\0') { ptszFace = AltFaceName; } if (Size.Y == 0) { Size.X = AltFontSize.X; Size.Y = AltFontSize.Y; } }
if (IsAvailableTTFont(pcpd, ptszFace)) { ptszAltFace = GetAltFaceName(pcpd, ptszFace); } else { ptszAltFace = ptszFace; }
/*
* Try to find the exact font */ TryFindExactFont: for (i=0; i < (int)pcpd->NumberOfFonts; i++) { /*
* If looking for a particular Family, skip non-matches */ if ((Family != 0) && ((BYTE)Family != pcpd->FontInfo[i].Family)) { continue; }
/*
* Skip non-matching sizes */ if ((!SIZE_EQUAL(pcpd->FontInfo[i].SizeWant, Size) && !SIZE_EQUAL(pcpd->FontInfo[i].Size, Size))) { continue; }
/*
* Skip non-matching weights */ if ((Weight != 0) && (Weight != pcpd->FontInfo[i].Weight)) { continue; }
/*
* Skip fonts that have unmatched charset */ if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family) && pcpd->FontInfo[i].tmCharSet != CharSet) { continue; } /*
* Size (and maybe Family) match. * If we don't care about the name, or if it matches, use this font. * Else if name doesn't match and it is a raster font, consider it. */ if ((ptszFace == NULL) || (ptszFace[0] == TEXT('\0')) || (lstrcmp(pcpd->FontInfo[i].FaceName, ptszFace) == 0) || (lstrcmp(pcpd->FontInfo[i].FaceName, ptszAltFace) == 0) ) { FontIndex = i; goto FoundFont; } else if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family)) { FontIndex = i; } }
if (FontIndex == NOT_CREATED_NOR_FOUND) { /*
* Didn't find the exact font, so try to create it */ ULONG ulOldEnumFilter; ulOldEnumFilter = SetFontEnumeration(FE_FILTER_NONE); if (Size.Y < 0) { Size.Y = -Size.Y; } bFontOK = DoFontEnum(pcpd, NULL, ptszFace, &Size.Y, 1); SetFontEnumeration(ulOldEnumFilter); if (bFontOK) { FontIndex = CREATED_BUT_NOT_FOUND; goto TryFindExactFont; } else { } } else if (FontIndex >= 0) { // a close Raster Font fit - only the name doesn't match.
goto FoundFont; }
/*
* Failed to find exact match, even after enumeration, so now try * to find a font of same family and same size or bigger */ for (i=0; i < (int)pcpd->NumberOfFonts; i++) { if ((Family != 0) && ((BYTE)Family != pcpd->FontInfo[i].Family)) { continue; }
if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family) && pcpd->FontInfo[i].tmCharSet != CharSet) { continue; }
if (pcpd->FontInfo[i].Size.Y >= Size.Y && pcpd->FontInfo[i].Size.X >= Size.X) { // Same family, size >= desired.
FontIndex = i; break; } }
if (FontIndex < 0) { if (uCurrentCP == uDefaultCP) { FontIndex = pcpd->DefaultFontIndex; } else { FontIndex = AltFontIndex; } }
FoundFont: return FontIndex;
#undef NOT_CREATED_NOR_FOUND
#undef CREATED_BUT_NOT_FOUND
}
LPTSTR TranslateConsoleTitle( LPTSTR ConsoleTitle ) /*++
this routine translates path characters into '_' characters because the NT registry apis do not allow the creation of keys with names that contain path characters. it allocates a buffer that must be freed.
--*/ { int ConsoleTitleLength, i; LPTSTR TranslatedTitle;
ConsoleTitleLength = lstrlen(ConsoleTitle) + 1; TranslatedTitle = LocalAlloc(LPTR, ConsoleTitleLength * sizeof(TCHAR)); if (TranslatedTitle == NULL) { return NULL; } for (i = 0; i < ConsoleTitleLength; i++) { if (ConsoleTitle[i] == TEXT('\\')) { TranslatedTitle[i] = TEXT('_'); } else { TranslatedTitle[i] = ConsoleTitle[i]; } } return TranslatedTitle; }
void InitRegistryValues( CONSOLEPROP_DATA *pcpd )
/*++
Routine Description:
This routine allocates a state info structure and fill it in with default values. It then tries to load the default settings for console from the registry.
Arguments:
none
Return Value:
pStateInfo - pointer to structure to receive information
--*/
{ TCHAR chSave;
pcpd->lpConsole->wFillAttribute = 0x07; // white on black
pcpd->lpConsole->wPopupFillAttribute = 0xf5; // purple on white
pcpd->lpConsole->bInsertMode = FALSE; pcpd->lpConsole->bQuickEdit = FALSE; pcpd->lpConsole->bFullScreen = FALSE; pcpd->lpConsole->dwScreenBufferSize.X = 80; pcpd->lpConsole->dwScreenBufferSize.Y = 25; pcpd->lpConsole->dwWindowSize.X = 80; pcpd->lpConsole->dwWindowSize.Y = 25; pcpd->lpConsole->dwWindowOrigin.X = 0; pcpd->lpConsole->dwWindowOrigin.Y = 0; pcpd->lpConsole->bAutoPosition = TRUE; pcpd->lpConsole->dwFontSize.X = 0; pcpd->lpConsole->dwFontSize.Y = 0; pcpd->lpConsole->uFontFamily = 0; pcpd->lpConsole->uFontWeight = 0; #ifdef UNICODE
FillMemory( pcpd->lpConsole->FaceName, sizeof(pcpd->lpConsole->FaceName), 0 ); pcpd->lpFaceName = (LPTSTR)pcpd->lpConsole->FaceName; #else
FillMemory( pcpd->szFaceName, sizeof(pcpd->szFaceName), 0 ); pcpd->lpFaceName = pcpd->szFaceName; #endif
pcpd->lpConsole->uCursorSize = 25; pcpd->lpConsole->uHistoryBufferSize = 25; pcpd->lpConsole->uNumberOfHistoryBuffers = 4; pcpd->lpConsole->bHistoryNoDup = 0; pcpd->lpConsole->ColorTable[ 0] = RGB(0, 0, 0 ); pcpd->lpConsole->ColorTable[ 1] = RGB(0, 0, 0x80); pcpd->lpConsole->ColorTable[ 2] = RGB(0, 0x80,0 ); pcpd->lpConsole->ColorTable[ 3] = RGB(0, 0x80,0x80); pcpd->lpConsole->ColorTable[ 4] = RGB(0x80,0, 0 ); pcpd->lpConsole->ColorTable[ 5] = RGB(0x80,0, 0x80); pcpd->lpConsole->ColorTable[ 6] = RGB(0x80,0x80,0 ); pcpd->lpConsole->ColorTable[ 7] = RGB(0xC0,0xC0,0xC0); pcpd->lpConsole->ColorTable[ 8] = RGB(0x80,0x80,0x80); pcpd->lpConsole->ColorTable[ 9] = RGB(0, 0, 0xFF); pcpd->lpConsole->ColorTable[10] = RGB(0, 0xFF,0 ); pcpd->lpConsole->ColorTable[11] = RGB(0, 0xFF,0xFF); pcpd->lpConsole->ColorTable[12] = RGB(0xFF,0, 0 ); pcpd->lpConsole->ColorTable[13] = RGB(0xFF,0, 0xFF); pcpd->lpConsole->ColorTable[14] = RGB(0xFF,0xFF,0 ); pcpd->lpConsole->ColorTable[15] = RGB(0xFF,0xFF,0xFF); pcpd->lpFEConsole->uCodePage = pcpd->uOEMCP; // make console title NULL so we load the default settings for the console
chSave = pcpd->ConsoleTitle[0]; pcpd->ConsoleTitle[0] = TEXT('\0'); GetRegistryValues( pcpd );
// restore the console title
pcpd->ConsoleTitle[0] = chSave;
}
VOID GetTitleFromLinkName( LPTSTR szLinkName, LPTSTR szTitle ) { DWORD dwLen; LPTSTR pLnk, pDot; LPTSTR pPath = szLinkName;
// Error checking
if (!szTitle) return;
if (!szLinkName) { szTitle[0] = TEXT('\0'); return; }
// find filename at end of fully qualified link name and point pLnk to it
for (pLnk = pPath; *pPath; pPath++) { if ( (pPath[0] == TEXT('\\') || pPath[0] == TEXT(':')) && pPath[1] && (pPath[1] != TEXT('\\')) ) pLnk = pPath + 1; }
// find extension (.lnk)
pPath = pLnk; for (pDot = NULL; *pPath; pPath++) { switch (*pPath) { case TEXT('.'): pDot = pPath; // remember the last dot
break; case TEXT('\\'): case TEXT(' '): // extensions can't have spaces
pDot = NULL; // forget last dot, it was in a directory
break; } }
// if we found the extension, pDot points to it, if not, pDot
// is NULL.
if (pDot) { dwLen = min( (DWORD) (pDot - pLnk), (MAX_TITLE_LEN-1) ); } else { dwLen = min( lstrlen(pLnk), (MAX_TITLE_LEN-1) ); }
CopyMemory(szTitle, pLnk, dwLen*sizeof(TCHAR)); szTitle[ dwLen ] = TEXT('\0');
}
VOID GetRegistryValues( CONSOLEPROP_DATA *pcpd )
/*++
Routine Description:
This routine reads in values from the registry and places them in the supplied structure.
Arguments:
pStateInfo - optional pointer to structure to receive information
Return Value:
current page number
--*/
{ HKEY hCurrentUserKey; HKEY hConsoleKey; HKEY hTitleKey; LPTSTR TranslatedTitle; DWORD dwValue, dwSize; DWORD dwRet = 0; DWORD i; WCHAR awchBuffer[LF_FACESIZE];
//
// Open the current user registry key
//
if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey)!=ERROR_SUCCESS) return;
//
// Open the console registry key
//
if (RegOpenKey(hCurrentUserKey,CONSOLE_REGISTRY_STRING,&hConsoleKey)!=ERROR_SUCCESS) { RegCloseKey(hCurrentUserKey); return; }
//
// If there is no structure to fill out, just bail out
//
if ((!pcpd) || (!pcpd->lpConsole)) goto CloseKeys;
//
// Open the console title subkey, if there is one
//
if (pcpd->ConsoleTitle[0] != TEXT('\0')) { TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle); if (TranslatedTitle == NULL) goto GetDefaultConsole; dwValue = RegOpenKey( hConsoleKey, TranslatedTitle, &hTitleKey); LocalFree(TranslatedTitle); if (dwValue!=ERROR_SUCCESS) goto GetDefaultConsole; } else {
GetDefaultConsole: hTitleKey = hConsoleKey; }
//
// Initial screen fill
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_FILLATTR, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->wFillAttribute = (WORD)dwValue; }
//
// Initial popup fill
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_POPUPATTR, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->wPopupFillAttribute = (WORD)dwValue; }
//
// Initial color table
//
for (i = 0; i < 16; i++) { wsprintf((LPTSTR)awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i); dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, (LPTSTR)awchBuffer, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->ColorTable[i] = dwValue; } }
//
// Initial insert mode
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_INSERTMODE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->bInsertMode = !!dwValue; }
//
// Initial quick edit mode
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_QUICKEDIT, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->bQuickEdit = !!dwValue; }
#ifdef i386
//
// Initial full screen mode
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_FULLSCR, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->bFullScreen = !!dwValue; } #endif
//
// Initial code page
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_CODEPAGE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpFEConsole->uCodePage = (UINT)dwValue; } //
// Initial screen buffer size
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_BUFFERSIZE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->dwScreenBufferSize.X = LOWORD(dwValue); pcpd->lpConsole->dwScreenBufferSize.Y = HIWORD(dwValue); }
//
// Initial window size
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_WINDOWSIZE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->dwWindowSize.X = LOWORD(dwValue); pcpd->lpConsole->dwWindowSize.Y = HIWORD(dwValue); }
//
// Initial window position
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_WINDOWPOS, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->dwWindowOrigin.X = (SHORT)LOWORD(dwValue); pcpd->lpConsole->dwWindowOrigin.Y = (SHORT)HIWORD(dwValue); pcpd->lpConsole->bAutoPosition = FALSE; }
//
// Initial font size
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_FONTSIZE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->dwFontSize.X = LOWORD(dwValue); pcpd->lpConsole->dwFontSize.Y = HIWORD(dwValue); }
//
// Initial font family
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_FONTFAMILY, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->uFontFamily = dwValue; }
//
// Initial font weight
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_FONTWEIGHT, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->uFontWeight = dwValue; }
//
// Initial font face name
//
dwSize = sizeof(awchBuffer); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_FACENAME, NULL, NULL, (LPBYTE)awchBuffer, &dwSize ) == ERROR_SUCCESS) { CopyMemory((LPBYTE)pcpd->lpFaceName, (LPBYTE)awchBuffer, LF_FACESIZE*sizeof(TCHAR)); }
//
// Initial cursor size
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_CURSORSIZE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->uCursorSize = dwValue; }
//
// Initial history buffer size
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_HISTORYSIZE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->uHistoryBufferSize = dwValue; }
//
// Initial number of history buffers
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_HISTORYBUFS, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->uNumberOfHistoryBuffers = dwValue; }
//
// Initial history duplication mode
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_HISTORYNODUP, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpConsole->bHistoryNoDup = dwValue; }
//
// Close the registry keys
//
if (hTitleKey != hConsoleKey) { RegCloseKey(hTitleKey); }
CloseKeys: RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey);
}
VOID SetRegistryValues( CONSOLEPROP_DATA *pcpd )
/*++
Routine Description:
This routine writes values to the registry from the supplied structure.
Arguments:
pStateInfo - optional pointer to structure containing information dwPage - current page number
Return Value:
none
--*/
{ HKEY hCurrentUserKey; HKEY hConsoleKey; HKEY hTitleKey; LPTSTR TranslatedTitle; DWORD dwValue; DWORD i; WCHAR awchBuffer[LF_FACESIZE];
//
// Open the current user registry key
//
if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey )!=ERROR_SUCCESS) { return; }
//
// Open the console registry key
//
if (RegCreateKey( hCurrentUserKey, CONSOLE_REGISTRY_STRING, &hConsoleKey )!=ERROR_SUCCESS) { RegCloseKey(hCurrentUserKey); return; }
//
// If we only want to save the current page, bail out
//
if (pcpd == NULL) { goto CloseKeys; }
//
// Open the console title subkey, if there is one
//
if (pcpd->ConsoleTitle[0] != TEXT('\0')) { TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle); if (TranslatedTitle == NULL) { RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey); return; } dwValue = RegCreateKey( hConsoleKey, TranslatedTitle, &hTitleKey); LocalFree(TranslatedTitle); if (dwValue!=ERROR_SUCCESS) { RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey); return; } } else { hTitleKey = hConsoleKey; }
//
// Save screen and popup colors and color table
//
dwValue = pcpd->lpConsole->wFillAttribute; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_FILLATTR, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); dwValue = pcpd->lpConsole->wPopupFillAttribute; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_POPUPATTR, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); for (i = 0; i < 16; i++) { dwValue = pcpd->lpConsole->ColorTable[i]; wsprintf((LPTSTR)awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i); RegSetValueEx( hTitleKey, (LPTSTR)awchBuffer, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); }
//
// Save insert, quickedit, and fullscreen mode settings
//
dwValue = pcpd->lpConsole->bInsertMode; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_INSERTMODE, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); dwValue = pcpd->lpConsole->bQuickEdit; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_QUICKEDIT, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); #ifdef i386
dwValue = pcpd->lpConsole->bFullScreen; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_FULLSCR, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); #endif
//
// Save screen buffer size
//
dwValue = MAKELONG(pcpd->lpConsole->dwScreenBufferSize.X, pcpd->lpConsole->dwScreenBufferSize.Y); RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_BUFFERSIZE, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) );
//
// Save window size
//
dwValue = MAKELONG(pcpd->lpConsole->dwWindowSize.X, pcpd->lpConsole->dwWindowSize.Y); RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_WINDOWSIZE, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) );
//
// Save window position
//
if (pcpd->lpConsole->bAutoPosition) { RegDeleteKey(hTitleKey, CONSOLE_REGISTRY_WINDOWPOS); } else { dwValue = MAKELONG(pcpd->lpConsole->dwWindowOrigin.X, pcpd->lpConsole->dwWindowOrigin.Y); RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_WINDOWPOS, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); }
//
// Save font size, family, weight, and face name
//
dwValue = MAKELONG(pcpd->lpConsole->dwFontSize.X, pcpd->lpConsole->dwFontSize.Y); RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_FONTSIZE, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); dwValue = pcpd->lpConsole->uFontFamily; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_FONTFAMILY, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); dwValue = pcpd->lpConsole->uFontWeight; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_FONTWEIGHT, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_FACENAME, 0, REG_SZ, (LPBYTE)pcpd->lpFaceName, (lstrlen(pcpd->lpFaceName) + 1) * sizeof(TCHAR) );
//
// Save cursor size
//
dwValue = pcpd->lpConsole->uCursorSize; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_CURSORSIZE, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) );
//
// Save history buffer size and number
//
dwValue = pcpd->lpConsole->uHistoryBufferSize; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_HISTORYSIZE, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); dwValue = pcpd->lpConsole->uNumberOfHistoryBuffers; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_HISTORYBUFS, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) ); dwValue = pcpd->lpConsole->bHistoryNoDup; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_HISTORYNODUP, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) );
//
// Close the registry keys
//
if (hTitleKey != hConsoleKey) { RegCloseKey(hTitleKey); }
CloseKeys: RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey); }
void InitFERegistryValues( CONSOLEPROP_DATA *pcpd )
/*++
Routine Description:
This routine allocates a state info structure and fill it in with default values. It then tries to load the default settings for console from the registry.
Arguments:
none
Return Value:
pStateInfo - pointer to structure to receive information
--*/
{ /*
* In this case: console reads a property of US version. * It doesn't have code page information. * Console should sets some code page as default. * However, I don't know right value. 437 is temporary value. */ pcpd->lpFEConsole->uCodePage = 437;
GetFERegistryValues( pcpd ); }
VOID GetFERegistryValues( CONSOLEPROP_DATA *pcpd )
/*++
Routine Description:
This routine reads in values from the registry and places them in the supplied structure.
Arguments:
pStateInfo - optional pointer to structure to receive information
Return Value:
current page number
--*/
{ HKEY hCurrentUserKey; HKEY hConsoleKey; HKEY hTitleKey; LPTSTR TranslatedTitle; DWORD dwValue, dwSize; DWORD dwRet = 0;
//
// Open the current user registry key
//
if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey)!=ERROR_SUCCESS) return;
//
// Open the console registry key
//
if (RegOpenKey(hCurrentUserKey,CONSOLE_REGISTRY_STRING,&hConsoleKey)!=ERROR_SUCCESS) { NtClose(hCurrentUserKey); return; }
//
// If there is no structure to fill out, just bail out
//
if ((!pcpd) || (!pcpd->lpFEConsole)) goto CloseKeys;
//
// Open the console title subkey, if there is one
//
if (pcpd->ConsoleTitle[0] != TEXT('\0')) { TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle); if (TranslatedTitle == NULL) goto CloseKeys; dwValue = RegOpenKey( hConsoleKey, TranslatedTitle, &hTitleKey); LocalFree(TranslatedTitle); if (dwValue!=ERROR_SUCCESS) goto CloseKeys; } else { goto CloseKeys; }
//
// Initial code page
//
dwSize = sizeof(dwValue); if (SHQueryValueEx( hTitleKey, CONSOLE_REGISTRY_CODEPAGE, NULL, NULL, (LPBYTE)&dwValue, &dwSize ) == ERROR_SUCCESS) { pcpd->lpFEConsole->uCodePage = (UINT)dwValue; }
//
// Close the registry keys
//
if (hTitleKey != hConsoleKey) { RegCloseKey(hTitleKey); }
CloseKeys: RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey);
}
VOID SetFERegistryValues( CONSOLEPROP_DATA *pcpd )
/*++
Routine Description:
This routine writes values to the registry from the supplied structure.
Arguments:
pStateInfo - optional pointer to structure containing information dwPage - current page number
Return Value:
none
--*/
{ HKEY hCurrentUserKey; HKEY hConsoleKey; HKEY hTitleKey; LPTSTR TranslatedTitle; DWORD dwValue;
//
// Open the current user registry key
//
if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey )!=ERROR_SUCCESS) { return; }
//
// Open the console registry key
//
if (RegCreateKey( hCurrentUserKey, CONSOLE_REGISTRY_STRING, &hConsoleKey )!=ERROR_SUCCESS) { RegCloseKey(hCurrentUserKey); return; }
//
// If we only want to save the current page, bail out
//
if (pcpd == NULL) { goto CloseKeys; }
//
// Open the console title subkey, if there is one
//
if (pcpd->ConsoleTitle[0] != TEXT('\0')) { TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle); if (TranslatedTitle == NULL) { RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey); return; } dwValue = RegCreateKey( hConsoleKey, TranslatedTitle, &hTitleKey); LocalFree(TranslatedTitle); if (dwValue!=ERROR_SUCCESS) { RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey); return; } } else { hTitleKey = hConsoleKey; }
// scotthsu
dwValue = pcpd->lpFEConsole->uCodePage; RegSetValueEx( hTitleKey, CONSOLE_REGISTRY_CODEPAGE, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue) );
//
// Close the registry keys
//
if (hTitleKey != hConsoleKey) { RegCloseKey(hTitleKey); }
CloseKeys: RegCloseKey(hConsoleKey); RegCloseKey(hCurrentUserKey); }
|