Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1993 lines
51 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This file implements the NT console server font routines.
  7. Author:
  8. Therese Stowell (thereses) 22-Jan-1991
  9. Revision History:
  10. --*/
  11. #include "shellprv.h"
  12. #pragma hdrstop
  13. #include "lnkcon.h"
  14. #define CONSOLE_REGISTRY_STRING (TEXT("Console"))
  15. #define CONSOLE_REGISTRY_FONTSIZE (TEXT("FontSize"))
  16. #define CONSOLE_REGISTRY_FONTFAMILY (TEXT("FontFamily"))
  17. #define CONSOLE_REGISTRY_BUFFERSIZE (TEXT("ScreenBufferSize"))
  18. #define CONSOLE_REGISTRY_CURSORSIZE (TEXT("CursorSize"))
  19. #define CONSOLE_REGISTRY_WINDOWSIZE (TEXT("WindowSize"))
  20. #define CONSOLE_REGISTRY_WINDOWPOS (TEXT("WindowPosition"))
  21. #define CONSOLE_REGISTRY_FILLATTR (TEXT("ScreenColors"))
  22. #define CONSOLE_REGISTRY_POPUPATTR (TEXT("PopupColors"))
  23. #define CONSOLE_REGISTRY_FULLSCR (TEXT("FullScreen"))
  24. #define CONSOLE_REGISTRY_QUICKEDIT (TEXT("QuickEdit"))
  25. #define CONSOLE_REGISTRY_FACENAME (TEXT("FaceName"))
  26. #define CONSOLE_REGISTRY_FONTWEIGHT (TEXT("FontWeight"))
  27. #define CONSOLE_REGISTRY_INSERTMODE (TEXT("InsertMode"))
  28. #define CONSOLE_REGISTRY_HISTORYSIZE (TEXT("HistoryBufferSize"))
  29. #define CONSOLE_REGISTRY_HISTORYBUFS (TEXT("NumberOfHistoryBuffers"))
  30. #define CONSOLE_REGISTRY_HISTORYNODUP (TEXT("HistoryNoDup"))
  31. #define CONSOLE_REGISTRY_COLORTABLE (TEXT("ColorTable%02u"))
  32. #define CONSOLE_REGISTRY_CODEPAGE (TEXT("CodePage"))
  33. /*
  34. * Initial default fonts and face names
  35. */
  36. /*
  37. * TTPoints -- Initial font pixel heights for TT fonts
  38. */
  39. SHORT TTPoints[] = {
  40. 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72
  41. };
  42. /*
  43. * TTPointsDbcs -- Initial font pixel heights for TT fonts of DBCS.
  44. */
  45. SHORT TTPointsDbcs[] = {
  46. 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72
  47. };
  48. typedef struct _FONTENUMDATA {
  49. CONSOLEPROP_DATA *pcpd;
  50. HDC hDC;
  51. BOOL bFindFaces;
  52. ULONG ulFE;
  53. PSHORT pTTPoints;
  54. UINT nTTPoints;
  55. UINT uDefCP;
  56. } FONTENUMDATA, *PFONTENUMDATA;
  57. FACENODE *
  58. AddFaceNode(FACENODE * *ppStart, LPTSTR ptsz) {
  59. FACENODE * pNew;
  60. FACENODE * *ppTmp;
  61. int cb;
  62. /*
  63. * Is it already here?
  64. */
  65. for (ppTmp = ppStart; *ppTmp; ppTmp = &((*ppTmp)->pNext)) {
  66. if (lstrcmp(((*ppTmp)->atch), ptsz) == 0) {
  67. // already there !
  68. return *ppTmp;
  69. }
  70. }
  71. cb = (lstrlen(ptsz) + 1) * sizeof(TCHAR);
  72. pNew = (FACENODE *)LocalAlloc(LPTR ,sizeof(FACENODE) + cb);
  73. if (pNew == NULL) {
  74. return NULL;
  75. }
  76. pNew->pNext = NULL;
  77. pNew->dwFlag = 0;
  78. lstrcpy(pNew->atch, ptsz);
  79. *ppTmp = pNew;
  80. return pNew;
  81. }
  82. VOID
  83. DestroyFaceNodes( CONSOLEPROP_DATA *pcpd ) {
  84. FACENODE * pNext;
  85. FACENODE * pTmp;
  86. pTmp = pcpd->gpFaceNames;
  87. while (pTmp != NULL) {
  88. pNext = pTmp->pNext;
  89. LocalFree(pTmp);
  90. pTmp = pNext;
  91. }
  92. pcpd->gpFaceNames = NULL;
  93. }
  94. int
  95. AddFont(
  96. CONSOLEPROP_DATA *pcpd,
  97. ENUMLOGFONT *pelf,
  98. NEWTEXTMETRIC *pntm,
  99. int nFontType,
  100. HDC hDC,
  101. FACENODE * pFN
  102. )
  103. /*++
  104. Add the font desribed by the LOGFONT structure to the font table if
  105. it's not already there.
  106. --*/
  107. {
  108. HFONT hFont;
  109. TEXTMETRIC tm;
  110. LONG nFont;
  111. COORD SizeToShow;
  112. COORD SizeActual;
  113. COORD SizeWant;
  114. BYTE tmFamily;
  115. SIZE Size;
  116. LPTSTR ptszFace = pelf->elfLogFont.lfFaceName;
  117. /* get font info */
  118. SizeWant.Y = (SHORT)pelf->elfLogFont.lfHeight;
  119. SizeWant.X = (SHORT)pelf->elfLogFont.lfWidth;
  120. CreateBoldFont:
  121. hFont = CreateFontIndirect(&pelf->elfLogFont);
  122. ASSERT(hFont);
  123. if (!hFont) {
  124. return FE_SKIPFONT; // same font in other sizes may still be suitable
  125. }
  126. //
  127. // for reasons unbeknownst to me, removing this code causes GDI
  128. // to yack, claiming that the font is owned by another process.
  129. //
  130. SelectObject(hDC, hFont);
  131. GetTextMetrics(hDC, &tm);
  132. GetTextExtentPoint32(hDC, TEXT("0"), 1, &Size);
  133. SizeActual.X = (SHORT)Size.cx;
  134. SizeActual.Y = (SHORT)(tm.tmHeight + tm.tmExternalLeading);
  135. tmFamily = tm.tmPitchAndFamily;
  136. if (TM_IS_TT_FONT(tmFamily) && (SizeWant.Y >= 0)) {
  137. SizeToShow = SizeWant;
  138. if (SizeWant.X == 0) {
  139. // Asking for zero width height gets a default aspect-ratio width
  140. // It's better to show that width rather than 0.
  141. SizeToShow.X = SizeActual.X;
  142. }
  143. } else {
  144. SizeToShow = SizeActual;
  145. }
  146. // there's a GDI bug - this assert fails occasionally
  147. //ASSERT (tm.tmMaxCharWidth == pntm->tmMaxCharWidth);
  148. /*
  149. * NOW, determine whether this font entry has already been cached
  150. * LATER : it may be possible to do this before creating the font, if
  151. * we can trust the dimensions & other info from pntm.
  152. * Sort by size:
  153. * 1) By pixelheight (negative Y values)
  154. * 2) By height (as shown)
  155. * 3) By width (as shown)
  156. */
  157. for (nFont = 0; nFont < (LONG)pcpd->NumberOfFonts; ++nFont) {
  158. COORD SizeShown;
  159. if (pcpd->FontInfo[nFont].hFont == NULL) {
  160. continue;
  161. }
  162. if (pcpd->FontInfo[nFont].SizeWant.X > 0) {
  163. SizeShown.X = pcpd->FontInfo[nFont].SizeWant.X;
  164. } else {
  165. SizeShown.X = pcpd->FontInfo[nFont].Size.X;
  166. }
  167. if (pcpd->FontInfo[nFont].SizeWant.Y > 0) {
  168. // This is a font specified by cell height.
  169. SizeShown.Y = pcpd->FontInfo[nFont].SizeWant.Y;
  170. } else {
  171. SizeShown.Y = pcpd->FontInfo[nFont].Size.Y;
  172. if (pcpd->FontInfo[nFont].SizeWant.Y < 0) {
  173. // This is a TT font specified by character height.
  174. if (SizeWant.Y < 0 && SizeWant.Y > pcpd->FontInfo[nFont].SizeWant.Y) {
  175. // Requested pixelheight is smaller than this one.
  176. break;
  177. }
  178. }
  179. }
  180. if (SIZE_EQUAL(SizeShown, SizeToShow) &&
  181. pcpd->FontInfo[nFont].Family == tmFamily &&
  182. pcpd->FontInfo[nFont].Weight == tm.tmWeight &&
  183. lstrcmp(pcpd->FontInfo[nFont].FaceName, ptszFace) == 0) {
  184. /*
  185. * Already have this font
  186. */
  187. DeleteObject(hFont);
  188. return FE_FONTOK;
  189. }
  190. if ((SizeToShow.Y < SizeShown.Y) ||
  191. (SizeToShow.Y == SizeShown.Y && SizeToShow.X < SizeShown.X)) {
  192. /*
  193. * This new font is smaller than nFont
  194. */
  195. break;
  196. }
  197. }
  198. /*
  199. * If we have to grow our font table, do it
  200. */
  201. if (pcpd->NumberOfFonts == pcpd->FontInfoLength) {
  202. FONT_INFO *Temp;
  203. pcpd->FontInfoLength += FONT_INCREMENT;
  204. Temp = (FONT_INFO *)LocalReAlloc(pcpd->FontInfo,
  205. sizeof(FONT_INFO) * pcpd->FontInfoLength, LMEM_MOVEABLE|LMEM_ZEROINIT);
  206. ASSERT(Temp);
  207. if (Temp == NULL) {
  208. pcpd->FontInfoLength -= FONT_INCREMENT;
  209. return FE_ABANDONFONT; // no point enumerating more - no memory!
  210. }
  211. pcpd->FontInfo = Temp;
  212. }
  213. /*
  214. * The font we are adding should be inserted into the list,
  215. * if it is smaller than the last one.
  216. */
  217. if (nFont < (LONG)pcpd->NumberOfFonts) {
  218. MoveMemory( &pcpd->FontInfo[nFont+1],
  219. &pcpd->FontInfo[nFont],
  220. sizeof(FONT_INFO) * (pcpd->NumberOfFonts - nFont)
  221. );
  222. }
  223. /*
  224. * Store the font info
  225. */
  226. pcpd->FontInfo[nFont].hFont = hFont;
  227. pcpd->FontInfo[nFont].Family = tmFamily;
  228. pcpd->FontInfo[nFont].Size = SizeActual;
  229. if (TM_IS_TT_FONT(tmFamily)) {
  230. pcpd->FontInfo[nFont].SizeWant = SizeWant;
  231. } else {
  232. pcpd->FontInfo[nFont].SizeWant.X = 0;
  233. pcpd->FontInfo[nFont].SizeWant.Y = 0;
  234. }
  235. pcpd->FontInfo[nFont].Weight = tm.tmWeight;
  236. pcpd->FontInfo[nFont].FaceName = pFN->atch;
  237. pcpd->FontInfo[nFont].tmCharSet = tm.tmCharSet;
  238. ++pcpd->NumberOfFonts;
  239. /*
  240. * If this is a true type font, create a bold version too.
  241. */
  242. if (nFontType == TRUETYPE_FONTTYPE && !IS_BOLD(pcpd->FontInfo[nFont].Weight)) {
  243. pelf->elfLogFont.lfWeight = FW_BOLD;
  244. goto CreateBoldFont;
  245. }
  246. return FE_FONTOK; // and continue enumeration
  247. }
  248. NTSTATUS
  249. InitializeFonts( CONSOLEPROP_DATA *pcpd )
  250. {
  251. return EnumerateFonts( pcpd, EF_DEFFACE); // Just the Default font
  252. }
  253. STDAPI_(void) DestroyFonts( CONSOLEPROP_DATA *pcpd )
  254. {
  255. ULONG FontIndex;
  256. if (pcpd->FontInfo != NULL) {
  257. for (FontIndex = 0; FontIndex < pcpd->NumberOfFonts; FontIndex++) {
  258. DeleteObject(pcpd->FontInfo[FontIndex].hFont);
  259. }
  260. LocalFree(pcpd->FontInfo);
  261. pcpd->FontInfo = NULL;
  262. pcpd->NumberOfFonts = 0;
  263. }
  264. DestroyFaceNodes( pcpd );
  265. }
  266. /*
  267. * Returns bit combination
  268. * FE_ABANDONFONT - do not continue enumerating this font
  269. * FE_SKIPFONT - skip this font but keep enumerating
  270. * FE_FONTOK - font was created and added to cache or already there
  271. */
  272. int
  273. FontEnum(
  274. ENUMLOGFONT *pelf,
  275. NEWTEXTMETRIC *pntm,
  276. int nFontType,
  277. PFONTENUMDATA pfed
  278. )
  279. /*++
  280. Is called exactly once by GDI for each font in the system. This
  281. routine is used to store the FONT_INFO structure.
  282. --*/
  283. {
  284. UINT i;
  285. LPTSTR ptszFace = pelf->elfLogFont.lfFaceName;
  286. FACENODE * pFN;
  287. BOOL bNegAC;
  288. #ifdef DEBUG
  289. OSVERSIONINFO osvi;
  290. osvi.dwOSVersionInfoSize = sizeof(osvi);
  291. GetVersionEx(&osvi);
  292. // NTMW_STRUCTURE is different on 5.0+ platforms and the flag for 5.0+
  293. // platforms now lives in NEWTEXTMETRIC structure.
  294. AssertMsg(osvi.dwMajorVersion > 4, TEXT("We now only support running on Win2k or Millennium and later so we should never hit this."));
  295. #endif
  296. bNegAC = !(pntm->ntmFlags & NTM_NONNEGATIVE_AC);
  297. //
  298. // reject variable width and italic fonts, also tt fonts with neg ac
  299. //
  300. if
  301. (
  302. !(pelf->elfLogFont.lfPitchAndFamily & FIXED_PITCH) ||
  303. (pelf->elfLogFont.lfItalic) ||
  304. bNegAC
  305. )
  306. {
  307. if (!IsAvailableTTFont(pfed->pcpd,ptszFace))
  308. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  309. }
  310. /*
  311. * reject TT fonts for whoom family is not modern, that is do not use
  312. * FF_DONTCARE // may be surprised unpleasantly
  313. * FF_DECORATIVE // likely to be symbol fonts
  314. * FF_SCRIPT // cursive, inappropriate for console
  315. * FF_SWISS OR FF_ROMAN // variable pitch
  316. */
  317. if ((nFontType == TRUETYPE_FONTTYPE) &&
  318. ((pelf->elfLogFont.lfPitchAndFamily & 0xf0) != FF_MODERN)) {
  319. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  320. }
  321. /*
  322. * reject non-TT fonts that aren't OEM
  323. */
  324. if ((nFontType != TRUETYPE_FONTTYPE) &&
  325. (!IsFarEastCP(pfed->uDefCP) || !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet)) &&
  326. (pelf->elfLogFont.lfCharSet != OEM_CHARSET)) {
  327. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  328. }
  329. /*
  330. * reject non-TT vertical/non-Terminal Font for FE
  331. */
  332. if (IsFarEastCP(pfed->uDefCP))
  333. {
  334. if ((nFontType != TRUETYPE_FONTTYPE) &&
  335. ((ptszFace[0] == TEXT('@')) ||
  336. (lstrcmp(ptszFace, TEXT("Terminal")) != 0)))
  337. {
  338. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  339. }
  340. }
  341. /*
  342. * reject Far East TT fonts that aren't Far East charset.
  343. */
  344. if (IsAvailableTTFont(pfed->pcpd, ptszFace) &&
  345. !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet) &&
  346. !IsAvailableTTFontCP(pfed->pcpd, ptszFace,0)
  347. ) {
  348. return FE_SKIPFONT; // should be enumerate next charset.
  349. }
  350. /*
  351. * Add or find the facename
  352. */
  353. pFN = AddFaceNode(&pfed->pcpd->gpFaceNames, ptszFace);
  354. if (pFN == NULL) {
  355. return FE_ABANDONFONT;
  356. }
  357. if (pfed->bFindFaces) {
  358. DWORD dwFontType = 0;
  359. if (nFontType == TRUETYPE_FONTTYPE) {
  360. dwFontType = EF_TTFONT;
  361. } else if (nFontType == RASTER_FONTTYPE) {
  362. dwFontType = EF_OEMFONT;
  363. }
  364. pFN->dwFlag |= dwFontType | EF_NEW;
  365. if (IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet))
  366. pFN->dwFlag |= EF_DBCSFONT;
  367. return FE_SKIPFONT;
  368. }
  369. if (IS_BOLD(pelf->elfLogFont.lfWeight)) {
  370. // return FE_SKIPFONT;
  371. }
  372. /*
  373. * Add the font to the table. If this is a true type font, add the
  374. * sizes from the array. Otherwise, just add the size we got.
  375. */
  376. if (nFontType & TRUETYPE_FONTTYPE) {
  377. for (i = 0; i < pfed->nTTPoints; i++) {
  378. pelf->elfLogFont.lfHeight = pfed->pTTPoints[i];
  379. pelf->elfLogFont.lfWidth = 0;
  380. pelf->elfLogFont.lfWeight = 400;
  381. pfed->ulFE |= AddFont(pfed->pcpd, pelf, pntm, nFontType, pfed->hDC, pFN);
  382. if (pfed->ulFE & FE_ABANDONFONT) {
  383. return FE_ABANDONFONT;
  384. }
  385. }
  386. } else {
  387. pfed->ulFE |= AddFont(pfed->pcpd, pelf, pntm, nFontType, pfed->hDC, pFN);
  388. if (pfed->ulFE & FE_ABANDONFONT) {
  389. return FE_ABANDONFONT;
  390. }
  391. }
  392. return FE_FONTOK; // and continue enumeration
  393. }
  394. BOOL
  395. DoFontEnum(
  396. CONSOLEPROP_DATA *pcpd,
  397. HDC hDC,
  398. LPTSTR ptszFace,
  399. PSHORT pTTPoints,
  400. UINT nTTPoints)
  401. {
  402. BOOL bDeleteDC = FALSE;
  403. FONTENUMDATA fed;
  404. LOGFONT LogFont;
  405. if (hDC == NULL) {
  406. hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  407. bDeleteDC = TRUE;
  408. }
  409. fed.pcpd = pcpd;
  410. fed.hDC = hDC;
  411. fed.bFindFaces = (ptszFace == NULL);
  412. fed.ulFE = 0;
  413. fed.pTTPoints = pTTPoints;
  414. fed.nTTPoints = nTTPoints;
  415. fed.uDefCP = pcpd->uOEMCP;
  416. RtlZeroMemory(&LogFont, sizeof(LOGFONT));
  417. LogFont.lfCharSet = DEFAULT_CHARSET;
  418. if (ptszFace)
  419. _tcscpy(LogFont.lfFaceName, ptszFace);
  420. /*
  421. * EnumFontFamiliesEx function enumerates one font in every face in every character set.
  422. */
  423. EnumFontFamiliesEx(hDC, &LogFont, (FONTENUMPROC)FontEnum, (LPARAM)&fed, 0);
  424. if (bDeleteDC) {
  425. DeleteDC(hDC);
  426. }
  427. return (fed.ulFE & FE_FONTOK) != 0;
  428. }
  429. VOID
  430. RemoveFace(CONSOLEPROP_DATA *pcpd, LPTSTR ptszFace)
  431. {
  432. DWORD i;
  433. int nToRemove = 0;
  434. //
  435. // Delete & Remove fonts with Face Name == ptszFace
  436. //
  437. for (i = 0; i < pcpd->NumberOfFonts; i++) {
  438. if (lstrcmp(pcpd->FontInfo[i].FaceName, ptszFace) == 0) {
  439. BOOL bDeleted = DeleteObject(pcpd->FontInfo[i].hFont);
  440. pcpd->FontInfo[i].hFont = NULL;
  441. nToRemove++;
  442. } else if (nToRemove > 0) {
  443. /*
  444. * Shuffle from FontInfo[i] down nToRemove slots.
  445. */
  446. MoveMemory( &pcpd->FontInfo[i - nToRemove],
  447. &pcpd->FontInfo[i],
  448. sizeof(FONT_INFO)*(pcpd->NumberOfFonts - i)
  449. );
  450. pcpd->NumberOfFonts -= nToRemove;
  451. i -= nToRemove;
  452. nToRemove = 0;
  453. }
  454. }
  455. pcpd->NumberOfFonts -= nToRemove;
  456. }
  457. NTSTATUS
  458. EnumerateFonts(
  459. CONSOLEPROP_DATA *pcpd,
  460. DWORD Flags)
  461. {
  462. TEXTMETRIC tm;
  463. HDC hDC;
  464. FACENODE * pFN;
  465. ULONG ulOldEnumFilter;
  466. BOOL bEnumOEMFace = TRUE;
  467. DWORD FontIndex;
  468. DWORD dwFontType = 0;
  469. dwFontType = (EF_TTFONT|EF_OEMFONT|EF_DEFFACE) & Flags;
  470. if (pcpd->FontInfo == NULL) {
  471. //
  472. // allocate memory for the font array
  473. //
  474. pcpd->NumberOfFonts = 0;
  475. pcpd->FontInfo = (FONT_INFO *)LocalAlloc(LPTR, sizeof(FONT_INFO) * INITIAL_FONTS);
  476. if (pcpd->FontInfo == NULL)
  477. return STATUS_NO_MEMORY;
  478. pcpd->FontInfoLength = INITIAL_FONTS;
  479. }
  480. hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  481. // Before enumeration, turn off font enumeration filters.
  482. ulOldEnumFilter = SetFontEnumeration(FE_FILTER_NONE);
  483. if (Flags & EF_DEFFACE) {
  484. SelectObject(hDC, GetStockObject(OEM_FIXED_FONT));
  485. GetTextFace(hDC, LF_FACESIZE, pcpd->DefaultFaceName);
  486. // Make sure we are going to enumerate the OEM face.
  487. pFN = AddFaceNode(&pcpd->gpFaceNames, pcpd->DefaultFaceName);
  488. if (NULL == pFN)
  489. {
  490. LocalFree(pcpd->FontInfo);
  491. pcpd->FontInfo = NULL;
  492. pcpd->FontInfoLength = 0;
  493. pcpd->NumberOfFonts = 0;
  494. SetFontEnumeration(ulOldEnumFilter);
  495. DeleteDC(hDC);
  496. return STATUS_NO_MEMORY;
  497. }
  498. pFN->dwFlag |= EF_DEFFACE | EF_OEMFONT;
  499. GetTextMetrics(hDC, &tm);
  500. pcpd->DefaultFontSize.X = (SHORT)(tm.tmMaxCharWidth);
  501. pcpd->DefaultFontSize.Y = (SHORT)(tm.tmHeight+tm.tmExternalLeading);
  502. pcpd->DefaultFontFamily = tm.tmPitchAndFamily;
  503. if (IS_ANY_DBCS_CHARSET(tm.tmCharSet))
  504. pcpd->DefaultFontSize.X /= 2;
  505. }
  506. if (pcpd->gbEnumerateFaces) {
  507. /*
  508. * Set the EF_OLD bit and clear the EF_NEW bit
  509. * for all previously available faces
  510. */
  511. for (pFN = pcpd->gpFaceNames; pFN; pFN = pFN->pNext) {
  512. pFN->dwFlag |= EF_OLD;
  513. pFN->dwFlag &= ~EF_NEW;
  514. }
  515. //
  516. // Use DoFontEnum to get the names of all the suitable Faces
  517. // All facenames found will be put in gpFaceNames with
  518. // the EF_NEW bit set.
  519. //
  520. DoFontEnum(pcpd, hDC, NULL, TTPoints, 1);
  521. pcpd->gbEnumerateFaces = FALSE;
  522. }
  523. // Use DoFontEnum to get all fonts from the system. Our FontEnum
  524. // proc puts just the ones we want into an array
  525. //
  526. for (pFN = pcpd->gpFaceNames; pFN; pFN = pFN->pNext) {
  527. if ((pFN->dwFlag & (EF_OLD|EF_NEW)) == EF_OLD) {
  528. // The face is no longer available
  529. RemoveFace(pcpd, pFN->atch);
  530. pFN->dwFlag &= ~EF_ENUMERATED;
  531. continue;
  532. }
  533. if ((pFN->dwFlag & dwFontType) == 0) {
  534. // not the kind of face we want
  535. continue;
  536. }
  537. if (pFN->dwFlag & EF_ENUMERATED) {
  538. // we already enumerated this face
  539. continue;
  540. }
  541. if (pFN->dwFlag & EF_TTFONT) {
  542. if (IsFarEastCP(pcpd->uOEMCP) && !IsAvailableTTFontCP(pcpd, pFN->atch, 0))
  543. DoFontEnum(pcpd, hDC, pFN->atch, TTPointsDbcs, NELEM(TTPointsDbcs));
  544. else
  545. DoFontEnum(pcpd, hDC, pFN->atch, TTPoints, NELEM(TTPoints));
  546. } else {
  547. DoFontEnum(pcpd, hDC, pFN->atch, NULL, 0);
  548. // If we find that the face just enumerated is the same as OEM,
  549. // reset flag so we don't try to enumerate it again.
  550. if (lstrcmpi(pFN->atch, pcpd->DefaultFaceName) == 0)
  551. {
  552. bEnumOEMFace = FALSE;
  553. }
  554. }
  555. pFN->dwFlag |= EF_ENUMERATED;
  556. }
  557. // After enumerating fonts, restore the font enumeration filter.
  558. SetFontEnumeration(ulOldEnumFilter);
  559. DeleteDC(hDC);
  560. for (FontIndex = 0; FontIndex < pcpd->NumberOfFonts; FontIndex++) {
  561. if (pcpd->FontInfo[FontIndex].Size.X == pcpd->DefaultFontSize.X &&
  562. pcpd->FontInfo[FontIndex].Size.Y == pcpd->DefaultFontSize.Y &&
  563. pcpd->FontInfo[FontIndex].Family == pcpd->DefaultFontFamily) {
  564. break;
  565. }
  566. }
  567. ASSERT(FontIndex < pcpd->NumberOfFonts);
  568. if (FontIndex < pcpd->NumberOfFonts) {
  569. pcpd->DefaultFontIndex = FontIndex;
  570. } else {
  571. pcpd->DefaultFontIndex = 0;
  572. }
  573. return STATUS_SUCCESS;
  574. }
  575. NTSTATUS
  576. GetNumFonts(
  577. CONSOLEPROP_DATA *pcpd,
  578. OUT PULONG NumFonts
  579. )
  580. {
  581. *NumFonts = pcpd->NumberOfFonts;
  582. return STATUS_SUCCESS;
  583. }
  584. NTSTATUS
  585. GetFontSize(
  586. CONSOLEPROP_DATA *pcpd,
  587. IN DWORD FontIndex,
  588. OUT PCOORD FontSize
  589. )
  590. {
  591. if (FontIndex >= pcpd->NumberOfFonts)
  592. return STATUS_INVALID_PARAMETER;
  593. *FontSize = pcpd->FontInfo[FontIndex].Size;
  594. return STATUS_SUCCESS;
  595. }
  596. /*
  597. * Get the font index for a new font
  598. * If necessary, attempt to create the font.
  599. * Always return a valid FontIndex (even if not correct)
  600. * Family: Find/Create a font with of this Family
  601. * 0 - don't care
  602. * ptszFace: Find/Create a font with this face name.
  603. * NULL or TEXT("") - use DefaultFaceName
  604. * Size: Must match SizeWant or actual Size.
  605. */
  606. int
  607. FindCreateFont(
  608. CONSOLEPROP_DATA *pcpd,
  609. DWORD Family,
  610. LPTSTR ptszFace,
  611. COORD Size,
  612. LONG Weight)
  613. {
  614. #define NOT_CREATED_NOR_FOUND -1
  615. #define CREATED_BUT_NOT_FOUND -2
  616. int i;
  617. int FontIndex = NOT_CREATED_NOR_FOUND;
  618. BOOL bFontOK;
  619. TCHAR AltFaceName[LF_FACESIZE];
  620. COORD AltFontSize;
  621. BYTE AltFontFamily;
  622. ULONG AltFontIndex = 0;
  623. LPTSTR ptszAltFace = NULL;
  624. UINT uCurrentCP = pcpd->lpFEConsole->uCodePage;
  625. UINT uDefaultCP = pcpd->uOEMCP;
  626. BYTE CharSet = CodePageToCharSet(uCurrentCP);
  627. if (!IsFarEastCP(uDefaultCP) || IS_ANY_DBCS_CHARSET(CharSet))
  628. {
  629. if (ptszFace == NULL || *ptszFace == TEXT('\0')) {
  630. ptszFace = pcpd->DefaultFaceName;
  631. }
  632. if (Size.Y == 0) {
  633. Size = pcpd->DefaultFontSize;
  634. }
  635. }
  636. else
  637. {
  638. MakeAltRasterFont(pcpd, uCurrentCP, &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
  639. if (ptszFace == NULL || *ptszFace == L'\0') {
  640. ptszFace = AltFaceName;
  641. }
  642. if (Size.Y == 0) {
  643. Size.X = AltFontSize.X;
  644. Size.Y = AltFontSize.Y;
  645. }
  646. }
  647. if (IsAvailableTTFont(pcpd, ptszFace)) {
  648. ptszAltFace = GetAltFaceName(pcpd, ptszFace);
  649. }
  650. else {
  651. ptszAltFace = ptszFace;
  652. }
  653. /*
  654. * Try to find the exact font
  655. */
  656. TryFindExactFont:
  657. for (i=0; i < (int)pcpd->NumberOfFonts; i++) {
  658. /*
  659. * If looking for a particular Family, skip non-matches
  660. */
  661. if ((Family != 0) &&
  662. ((BYTE)Family != pcpd->FontInfo[i].Family)) {
  663. continue;
  664. }
  665. /*
  666. * Skip non-matching sizes
  667. */
  668. if ((!SIZE_EQUAL(pcpd->FontInfo[i].SizeWant, Size) &&
  669. !SIZE_EQUAL(pcpd->FontInfo[i].Size, Size))) {
  670. continue;
  671. }
  672. /*
  673. * Skip non-matching weights
  674. */
  675. if ((Weight != 0) && (Weight != pcpd->FontInfo[i].Weight)) {
  676. continue;
  677. }
  678. /*
  679. * Skip fonts that have unmatched charset
  680. */
  681. if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family) &&
  682. pcpd->FontInfo[i].tmCharSet != CharSet) {
  683. continue;
  684. }
  685. /*
  686. * Size (and maybe Family) match.
  687. * If we don't care about the name, or if it matches, use this font.
  688. * Else if name doesn't match and it is a raster font, consider it.
  689. */
  690. if ((ptszFace == NULL) || (ptszFace[0] == TEXT('\0')) ||
  691. (lstrcmp(pcpd->FontInfo[i].FaceName, ptszFace) == 0) ||
  692. (lstrcmp(pcpd->FontInfo[i].FaceName, ptszAltFace) == 0) ) {
  693. FontIndex = i;
  694. goto FoundFont;
  695. } else if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family)) {
  696. FontIndex = i;
  697. }
  698. }
  699. if (FontIndex == NOT_CREATED_NOR_FOUND) {
  700. /*
  701. * Didn't find the exact font, so try to create it
  702. */
  703. ULONG ulOldEnumFilter;
  704. ulOldEnumFilter = SetFontEnumeration(FE_FILTER_NONE);
  705. if (Size.Y < 0) {
  706. Size.Y = -Size.Y;
  707. }
  708. bFontOK = DoFontEnum(pcpd, NULL, ptszFace, &Size.Y, 1);
  709. SetFontEnumeration(ulOldEnumFilter);
  710. if (bFontOK) {
  711. FontIndex = CREATED_BUT_NOT_FOUND;
  712. goto TryFindExactFont;
  713. } else {
  714. }
  715. } else if (FontIndex >= 0) {
  716. // a close Raster Font fit - only the name doesn't match.
  717. goto FoundFont;
  718. }
  719. /*
  720. * Failed to find exact match, even after enumeration, so now try
  721. * to find a font of same family and same size or bigger
  722. */
  723. for (i=0; i < (int)pcpd->NumberOfFonts; i++) {
  724. if ((Family != 0) &&
  725. ((BYTE)Family != pcpd->FontInfo[i].Family)) {
  726. continue;
  727. }
  728. if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family) &&
  729. pcpd->FontInfo[i].tmCharSet != CharSet) {
  730. continue;
  731. }
  732. if (pcpd->FontInfo[i].Size.Y >= Size.Y &&
  733. pcpd->FontInfo[i].Size.X >= Size.X) {
  734. // Same family, size >= desired.
  735. FontIndex = i;
  736. break;
  737. }
  738. }
  739. if (FontIndex < 0) {
  740. if (uCurrentCP == uDefaultCP)
  741. {
  742. FontIndex = pcpd->DefaultFontIndex;
  743. }
  744. else
  745. {
  746. FontIndex = AltFontIndex;
  747. }
  748. }
  749. FoundFont:
  750. return FontIndex;
  751. #undef NOT_CREATED_NOR_FOUND
  752. #undef CREATED_BUT_NOT_FOUND
  753. }
  754. LPTSTR
  755. TranslateConsoleTitle(
  756. LPTSTR ConsoleTitle
  757. )
  758. /*++
  759. this routine translates path characters into '_' characters because
  760. the NT registry apis do not allow the creation of keys with
  761. names that contain path characters. it allocates a buffer that
  762. must be freed.
  763. --*/
  764. {
  765. int ConsoleTitleLength, i;
  766. LPTSTR TranslatedTitle;
  767. ConsoleTitleLength = lstrlen(ConsoleTitle) + 1;
  768. TranslatedTitle = LocalAlloc(LPTR,
  769. ConsoleTitleLength * sizeof(TCHAR));
  770. if (TranslatedTitle == NULL) {
  771. return NULL;
  772. }
  773. for (i = 0; i < ConsoleTitleLength; i++) {
  774. if (ConsoleTitle[i] == TEXT('\\')) {
  775. TranslatedTitle[i] = TEXT('_');
  776. } else {
  777. TranslatedTitle[i] = ConsoleTitle[i];
  778. }
  779. }
  780. return TranslatedTitle;
  781. }
  782. void
  783. InitRegistryValues( CONSOLEPROP_DATA *pcpd )
  784. /*++
  785. Routine Description:
  786. This routine allocates a state info structure and fill it in with
  787. default values. It then tries to load the default settings for
  788. console from the registry.
  789. Arguments:
  790. none
  791. Return Value:
  792. pStateInfo - pointer to structure to receive information
  793. --*/
  794. {
  795. TCHAR chSave;
  796. pcpd->lpConsole->wFillAttribute = 0x07; // white on black
  797. pcpd->lpConsole->wPopupFillAttribute = 0xf5; // purple on white
  798. pcpd->lpConsole->bInsertMode = FALSE;
  799. pcpd->lpConsole->bQuickEdit = FALSE;
  800. pcpd->lpConsole->bFullScreen = FALSE;
  801. pcpd->lpConsole->dwScreenBufferSize.X = 80;
  802. pcpd->lpConsole->dwScreenBufferSize.Y = 25;
  803. pcpd->lpConsole->dwWindowSize.X = 80;
  804. pcpd->lpConsole->dwWindowSize.Y = 25;
  805. pcpd->lpConsole->dwWindowOrigin.X = 0;
  806. pcpd->lpConsole->dwWindowOrigin.Y = 0;
  807. pcpd->lpConsole->bAutoPosition = TRUE;
  808. pcpd->lpConsole->dwFontSize.X = 0;
  809. pcpd->lpConsole->dwFontSize.Y = 0;
  810. pcpd->lpConsole->uFontFamily = 0;
  811. pcpd->lpConsole->uFontWeight = 0;
  812. #ifdef UNICODE
  813. FillMemory( pcpd->lpConsole->FaceName, sizeof(pcpd->lpConsole->FaceName), 0 );
  814. pcpd->lpFaceName = (LPTSTR)pcpd->lpConsole->FaceName;
  815. #else
  816. FillMemory( pcpd->szFaceName, sizeof(pcpd->szFaceName), 0 );
  817. pcpd->lpFaceName = pcpd->szFaceName;
  818. #endif
  819. pcpd->lpConsole->uCursorSize = 25;
  820. pcpd->lpConsole->uHistoryBufferSize = 25;
  821. pcpd->lpConsole->uNumberOfHistoryBuffers = 4;
  822. pcpd->lpConsole->bHistoryNoDup = 0;
  823. pcpd->lpConsole->ColorTable[ 0] = RGB(0, 0, 0 );
  824. pcpd->lpConsole->ColorTable[ 1] = RGB(0, 0, 0x80);
  825. pcpd->lpConsole->ColorTable[ 2] = RGB(0, 0x80,0 );
  826. pcpd->lpConsole->ColorTable[ 3] = RGB(0, 0x80,0x80);
  827. pcpd->lpConsole->ColorTable[ 4] = RGB(0x80,0, 0 );
  828. pcpd->lpConsole->ColorTable[ 5] = RGB(0x80,0, 0x80);
  829. pcpd->lpConsole->ColorTable[ 6] = RGB(0x80,0x80,0 );
  830. pcpd->lpConsole->ColorTable[ 7] = RGB(0xC0,0xC0,0xC0);
  831. pcpd->lpConsole->ColorTable[ 8] = RGB(0x80,0x80,0x80);
  832. pcpd->lpConsole->ColorTable[ 9] = RGB(0, 0, 0xFF);
  833. pcpd->lpConsole->ColorTable[10] = RGB(0, 0xFF,0 );
  834. pcpd->lpConsole->ColorTable[11] = RGB(0, 0xFF,0xFF);
  835. pcpd->lpConsole->ColorTable[12] = RGB(0xFF,0, 0 );
  836. pcpd->lpConsole->ColorTable[13] = RGB(0xFF,0, 0xFF);
  837. pcpd->lpConsole->ColorTable[14] = RGB(0xFF,0xFF,0 );
  838. pcpd->lpConsole->ColorTable[15] = RGB(0xFF,0xFF,0xFF);
  839. pcpd->lpFEConsole->uCodePage = pcpd->uOEMCP;
  840. // make console title NULL so we load the default settings for the console
  841. chSave = pcpd->ConsoleTitle[0];
  842. pcpd->ConsoleTitle[0] = TEXT('\0');
  843. GetRegistryValues( pcpd );
  844. // restore the console title
  845. pcpd->ConsoleTitle[0] = chSave;
  846. }
  847. VOID
  848. GetTitleFromLinkName(
  849. LPTSTR szLinkName,
  850. LPTSTR szTitle
  851. )
  852. {
  853. DWORD dwLen;
  854. LPTSTR pLnk, pDot;
  855. LPTSTR pPath = szLinkName;
  856. // Error checking
  857. if (!szTitle)
  858. return;
  859. if (!szLinkName)
  860. {
  861. szTitle[0] = TEXT('\0');
  862. return;
  863. }
  864. // find filename at end of fully qualified link name and point pLnk to it
  865. for (pLnk = pPath; *pPath; pPath++)
  866. {
  867. if ( (pPath[0] == TEXT('\\') || pPath[0] == TEXT(':')) &&
  868. pPath[1] &&
  869. (pPath[1] != TEXT('\\'))
  870. )
  871. pLnk = pPath + 1;
  872. }
  873. // find extension (.lnk)
  874. pPath = pLnk;
  875. for (pDot = NULL; *pPath; pPath++)
  876. {
  877. switch (*pPath) {
  878. case TEXT('.'):
  879. pDot = pPath; // remember the last dot
  880. break;
  881. case TEXT('\\'):
  882. case TEXT(' '): // extensions can't have spaces
  883. pDot = NULL; // forget last dot, it was in a directory
  884. break;
  885. }
  886. }
  887. // if we found the extension, pDot points to it, if not, pDot
  888. // is NULL.
  889. if (pDot)
  890. {
  891. dwLen = min( (DWORD) (pDot - pLnk), (MAX_TITLE_LEN-1) );
  892. }
  893. else
  894. {
  895. dwLen = min( lstrlen(pLnk), (MAX_TITLE_LEN-1) );
  896. }
  897. CopyMemory(szTitle, pLnk, dwLen*sizeof(TCHAR));
  898. szTitle[ dwLen ] = TEXT('\0');
  899. }
  900. VOID
  901. GetRegistryValues(
  902. CONSOLEPROP_DATA *pcpd
  903. )
  904. /*++
  905. Routine Description:
  906. This routine reads in values from the registry and places them
  907. in the supplied structure.
  908. Arguments:
  909. pStateInfo - optional pointer to structure to receive information
  910. Return Value:
  911. current page number
  912. --*/
  913. {
  914. HKEY hCurrentUserKey;
  915. HKEY hConsoleKey;
  916. HKEY hTitleKey;
  917. LPTSTR TranslatedTitle;
  918. DWORD dwValue, dwSize;
  919. DWORD dwRet = 0;
  920. DWORD i;
  921. WCHAR awchBuffer[LF_FACESIZE];
  922. //
  923. // Open the current user registry key
  924. //
  925. if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey)!=ERROR_SUCCESS)
  926. return;
  927. //
  928. // Open the console registry key
  929. //
  930. if (RegOpenKey(hCurrentUserKey,CONSOLE_REGISTRY_STRING,&hConsoleKey)!=ERROR_SUCCESS)
  931. {
  932. RegCloseKey(hCurrentUserKey);
  933. return;
  934. }
  935. //
  936. // If there is no structure to fill out, just bail out
  937. //
  938. if ((!pcpd) || (!pcpd->lpConsole))
  939. goto CloseKeys;
  940. //
  941. // Open the console title subkey, if there is one
  942. //
  943. if (pcpd->ConsoleTitle[0] != TEXT('\0'))
  944. {
  945. TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle);
  946. if (TranslatedTitle == NULL)
  947. goto GetDefaultConsole;
  948. dwValue = RegOpenKey( hConsoleKey,
  949. TranslatedTitle,
  950. &hTitleKey);
  951. LocalFree(TranslatedTitle);
  952. if (dwValue!=ERROR_SUCCESS)
  953. goto GetDefaultConsole;
  954. } else {
  955. GetDefaultConsole:
  956. hTitleKey = hConsoleKey;
  957. }
  958. //
  959. // Initial screen fill
  960. //
  961. dwSize = sizeof(dwValue);
  962. if (SHQueryValueEx( hTitleKey,
  963. CONSOLE_REGISTRY_FILLATTR,
  964. NULL,
  965. NULL,
  966. (LPBYTE)&dwValue,
  967. &dwSize
  968. ) == ERROR_SUCCESS)
  969. {
  970. pcpd->lpConsole->wFillAttribute = (WORD)dwValue;
  971. }
  972. //
  973. // Initial popup fill
  974. //
  975. dwSize = sizeof(dwValue);
  976. if (SHQueryValueEx( hTitleKey,
  977. CONSOLE_REGISTRY_POPUPATTR,
  978. NULL,
  979. NULL,
  980. (LPBYTE)&dwValue,
  981. &dwSize
  982. ) == ERROR_SUCCESS)
  983. {
  984. pcpd->lpConsole->wPopupFillAttribute = (WORD)dwValue;
  985. }
  986. //
  987. // Initial color table
  988. //
  989. for (i = 0; i < 16; i++)
  990. {
  991. wsprintf((LPTSTR)awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i);
  992. dwSize = sizeof(dwValue);
  993. if (SHQueryValueEx( hTitleKey,
  994. (LPTSTR)awchBuffer,
  995. NULL,
  996. NULL,
  997. (LPBYTE)&dwValue,
  998. &dwSize
  999. ) == ERROR_SUCCESS)
  1000. {
  1001. pcpd->lpConsole->ColorTable[i] = dwValue;
  1002. }
  1003. }
  1004. //
  1005. // Initial insert mode
  1006. //
  1007. dwSize = sizeof(dwValue);
  1008. if (SHQueryValueEx( hTitleKey,
  1009. CONSOLE_REGISTRY_INSERTMODE,
  1010. NULL,
  1011. NULL,
  1012. (LPBYTE)&dwValue,
  1013. &dwSize
  1014. ) == ERROR_SUCCESS)
  1015. {
  1016. pcpd->lpConsole->bInsertMode = !!dwValue;
  1017. }
  1018. //
  1019. // Initial quick edit mode
  1020. //
  1021. dwSize = sizeof(dwValue);
  1022. if (SHQueryValueEx( hTitleKey,
  1023. CONSOLE_REGISTRY_QUICKEDIT,
  1024. NULL,
  1025. NULL,
  1026. (LPBYTE)&dwValue,
  1027. &dwSize
  1028. ) == ERROR_SUCCESS)
  1029. {
  1030. pcpd->lpConsole->bQuickEdit = !!dwValue;
  1031. }
  1032. #ifdef i386
  1033. //
  1034. // Initial full screen mode
  1035. //
  1036. dwSize = sizeof(dwValue);
  1037. if (SHQueryValueEx( hTitleKey,
  1038. CONSOLE_REGISTRY_FULLSCR,
  1039. NULL,
  1040. NULL,
  1041. (LPBYTE)&dwValue,
  1042. &dwSize
  1043. ) == ERROR_SUCCESS)
  1044. {
  1045. pcpd->lpConsole->bFullScreen = !!dwValue;
  1046. }
  1047. #endif
  1048. //
  1049. // Initial code page
  1050. //
  1051. dwSize = sizeof(dwValue);
  1052. if (SHQueryValueEx( hTitleKey,
  1053. CONSOLE_REGISTRY_CODEPAGE,
  1054. NULL,
  1055. NULL,
  1056. (LPBYTE)&dwValue,
  1057. &dwSize
  1058. ) == ERROR_SUCCESS)
  1059. {
  1060. pcpd->lpFEConsole->uCodePage = (UINT)dwValue;
  1061. }
  1062. //
  1063. // Initial screen buffer size
  1064. //
  1065. dwSize = sizeof(dwValue);
  1066. if (SHQueryValueEx( hTitleKey,
  1067. CONSOLE_REGISTRY_BUFFERSIZE,
  1068. NULL,
  1069. NULL,
  1070. (LPBYTE)&dwValue,
  1071. &dwSize
  1072. ) == ERROR_SUCCESS)
  1073. {
  1074. pcpd->lpConsole->dwScreenBufferSize.X = LOWORD(dwValue);
  1075. pcpd->lpConsole->dwScreenBufferSize.Y = HIWORD(dwValue);
  1076. }
  1077. //
  1078. // Initial window size
  1079. //
  1080. dwSize = sizeof(dwValue);
  1081. if (SHQueryValueEx( hTitleKey,
  1082. CONSOLE_REGISTRY_WINDOWSIZE,
  1083. NULL,
  1084. NULL,
  1085. (LPBYTE)&dwValue,
  1086. &dwSize
  1087. ) == ERROR_SUCCESS)
  1088. {
  1089. pcpd->lpConsole->dwWindowSize.X = LOWORD(dwValue);
  1090. pcpd->lpConsole->dwWindowSize.Y = HIWORD(dwValue);
  1091. }
  1092. //
  1093. // Initial window position
  1094. //
  1095. dwSize = sizeof(dwValue);
  1096. if (SHQueryValueEx( hTitleKey,
  1097. CONSOLE_REGISTRY_WINDOWPOS,
  1098. NULL,
  1099. NULL,
  1100. (LPBYTE)&dwValue,
  1101. &dwSize
  1102. ) == ERROR_SUCCESS)
  1103. {
  1104. pcpd->lpConsole->dwWindowOrigin.X = (SHORT)LOWORD(dwValue);
  1105. pcpd->lpConsole->dwWindowOrigin.Y = (SHORT)HIWORD(dwValue);
  1106. pcpd->lpConsole->bAutoPosition = FALSE;
  1107. }
  1108. //
  1109. // Initial font size
  1110. //
  1111. dwSize = sizeof(dwValue);
  1112. if (SHQueryValueEx( hTitleKey,
  1113. CONSOLE_REGISTRY_FONTSIZE,
  1114. NULL,
  1115. NULL,
  1116. (LPBYTE)&dwValue,
  1117. &dwSize
  1118. ) == ERROR_SUCCESS)
  1119. {
  1120. pcpd->lpConsole->dwFontSize.X = LOWORD(dwValue);
  1121. pcpd->lpConsole->dwFontSize.Y = HIWORD(dwValue);
  1122. }
  1123. //
  1124. // Initial font family
  1125. //
  1126. dwSize = sizeof(dwValue);
  1127. if (SHQueryValueEx( hTitleKey,
  1128. CONSOLE_REGISTRY_FONTFAMILY,
  1129. NULL,
  1130. NULL,
  1131. (LPBYTE)&dwValue,
  1132. &dwSize
  1133. ) == ERROR_SUCCESS)
  1134. {
  1135. pcpd->lpConsole->uFontFamily = dwValue;
  1136. }
  1137. //
  1138. // Initial font weight
  1139. //
  1140. dwSize = sizeof(dwValue);
  1141. if (SHQueryValueEx( hTitleKey,
  1142. CONSOLE_REGISTRY_FONTWEIGHT,
  1143. NULL,
  1144. NULL,
  1145. (LPBYTE)&dwValue,
  1146. &dwSize
  1147. ) == ERROR_SUCCESS)
  1148. {
  1149. pcpd->lpConsole->uFontWeight = dwValue;
  1150. }
  1151. //
  1152. // Initial font face name
  1153. //
  1154. dwSize = sizeof(awchBuffer);
  1155. if (SHQueryValueEx( hTitleKey,
  1156. CONSOLE_REGISTRY_FACENAME,
  1157. NULL,
  1158. NULL,
  1159. (LPBYTE)awchBuffer,
  1160. &dwSize
  1161. ) == ERROR_SUCCESS)
  1162. {
  1163. CopyMemory((LPBYTE)pcpd->lpFaceName, (LPBYTE)awchBuffer, LF_FACESIZE*sizeof(TCHAR));
  1164. }
  1165. //
  1166. // Initial cursor size
  1167. //
  1168. dwSize = sizeof(dwValue);
  1169. if (SHQueryValueEx( hTitleKey,
  1170. CONSOLE_REGISTRY_CURSORSIZE,
  1171. NULL,
  1172. NULL,
  1173. (LPBYTE)&dwValue,
  1174. &dwSize
  1175. ) == ERROR_SUCCESS)
  1176. {
  1177. pcpd->lpConsole->uCursorSize = dwValue;
  1178. }
  1179. //
  1180. // Initial history buffer size
  1181. //
  1182. dwSize = sizeof(dwValue);
  1183. if (SHQueryValueEx( hTitleKey,
  1184. CONSOLE_REGISTRY_HISTORYSIZE,
  1185. NULL,
  1186. NULL,
  1187. (LPBYTE)&dwValue,
  1188. &dwSize
  1189. ) == ERROR_SUCCESS)
  1190. {
  1191. pcpd->lpConsole->uHistoryBufferSize = dwValue;
  1192. }
  1193. //
  1194. // Initial number of history buffers
  1195. //
  1196. dwSize = sizeof(dwValue);
  1197. if (SHQueryValueEx( hTitleKey,
  1198. CONSOLE_REGISTRY_HISTORYBUFS,
  1199. NULL,
  1200. NULL,
  1201. (LPBYTE)&dwValue,
  1202. &dwSize
  1203. ) == ERROR_SUCCESS)
  1204. {
  1205. pcpd->lpConsole->uNumberOfHistoryBuffers = dwValue;
  1206. }
  1207. //
  1208. // Initial history duplication mode
  1209. //
  1210. dwSize = sizeof(dwValue);
  1211. if (SHQueryValueEx( hTitleKey,
  1212. CONSOLE_REGISTRY_HISTORYNODUP,
  1213. NULL,
  1214. NULL,
  1215. (LPBYTE)&dwValue,
  1216. &dwSize
  1217. ) == ERROR_SUCCESS)
  1218. {
  1219. pcpd->lpConsole->bHistoryNoDup = dwValue;
  1220. }
  1221. //
  1222. // Close the registry keys
  1223. //
  1224. if (hTitleKey != hConsoleKey) {
  1225. RegCloseKey(hTitleKey);
  1226. }
  1227. CloseKeys:
  1228. RegCloseKey(hConsoleKey);
  1229. RegCloseKey(hCurrentUserKey);
  1230. }
  1231. VOID
  1232. SetRegistryValues(
  1233. CONSOLEPROP_DATA *pcpd
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. This routine writes values to the registry from the supplied
  1238. structure.
  1239. Arguments:
  1240. pStateInfo - optional pointer to structure containing information
  1241. dwPage - current page number
  1242. Return Value:
  1243. none
  1244. --*/
  1245. {
  1246. HKEY hCurrentUserKey;
  1247. HKEY hConsoleKey;
  1248. HKEY hTitleKey;
  1249. LPTSTR TranslatedTitle;
  1250. DWORD dwValue;
  1251. DWORD i;
  1252. WCHAR awchBuffer[LF_FACESIZE];
  1253. //
  1254. // Open the current user registry key
  1255. //
  1256. if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey )!=ERROR_SUCCESS)
  1257. {
  1258. return;
  1259. }
  1260. //
  1261. // Open the console registry key
  1262. //
  1263. if (RegCreateKey( hCurrentUserKey, CONSOLE_REGISTRY_STRING, &hConsoleKey )!=ERROR_SUCCESS)
  1264. {
  1265. RegCloseKey(hCurrentUserKey);
  1266. return;
  1267. }
  1268. //
  1269. // If we only want to save the current page, bail out
  1270. //
  1271. if (pcpd == NULL)
  1272. {
  1273. goto CloseKeys;
  1274. }
  1275. //
  1276. // Open the console title subkey, if there is one
  1277. //
  1278. if (pcpd->ConsoleTitle[0] != TEXT('\0'))
  1279. {
  1280. TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle);
  1281. if (TranslatedTitle == NULL)
  1282. {
  1283. RegCloseKey(hConsoleKey);
  1284. RegCloseKey(hCurrentUserKey);
  1285. return;
  1286. }
  1287. dwValue = RegCreateKey( hConsoleKey,
  1288. TranslatedTitle,
  1289. &hTitleKey);
  1290. LocalFree(TranslatedTitle);
  1291. if (dwValue!=ERROR_SUCCESS)
  1292. {
  1293. RegCloseKey(hConsoleKey);
  1294. RegCloseKey(hCurrentUserKey);
  1295. return;
  1296. }
  1297. } else {
  1298. hTitleKey = hConsoleKey;
  1299. }
  1300. //
  1301. // Save screen and popup colors and color table
  1302. //
  1303. dwValue = pcpd->lpConsole->wFillAttribute;
  1304. RegSetValueEx( hTitleKey,
  1305. CONSOLE_REGISTRY_FILLATTR,
  1306. 0,
  1307. REG_DWORD,
  1308. (LPBYTE)&dwValue,
  1309. sizeof(dwValue)
  1310. );
  1311. dwValue = pcpd->lpConsole->wPopupFillAttribute;
  1312. RegSetValueEx( hTitleKey,
  1313. CONSOLE_REGISTRY_POPUPATTR,
  1314. 0,
  1315. REG_DWORD,
  1316. (LPBYTE)&dwValue,
  1317. sizeof(dwValue)
  1318. );
  1319. for (i = 0; i < 16; i++)
  1320. {
  1321. dwValue = pcpd->lpConsole->ColorTable[i];
  1322. wsprintf((LPTSTR)awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i);
  1323. RegSetValueEx( hTitleKey,
  1324. (LPTSTR)awchBuffer,
  1325. 0,
  1326. REG_DWORD,
  1327. (LPBYTE)&dwValue,
  1328. sizeof(dwValue)
  1329. );
  1330. }
  1331. //
  1332. // Save insert, quickedit, and fullscreen mode settings
  1333. //
  1334. dwValue = pcpd->lpConsole->bInsertMode;
  1335. RegSetValueEx( hTitleKey,
  1336. CONSOLE_REGISTRY_INSERTMODE,
  1337. 0,
  1338. REG_DWORD,
  1339. (LPBYTE)&dwValue,
  1340. sizeof(dwValue)
  1341. );
  1342. dwValue = pcpd->lpConsole->bQuickEdit;
  1343. RegSetValueEx( hTitleKey,
  1344. CONSOLE_REGISTRY_QUICKEDIT,
  1345. 0,
  1346. REG_DWORD,
  1347. (LPBYTE)&dwValue,
  1348. sizeof(dwValue)
  1349. );
  1350. #ifdef i386
  1351. dwValue = pcpd->lpConsole->bFullScreen;
  1352. RegSetValueEx( hTitleKey,
  1353. CONSOLE_REGISTRY_FULLSCR,
  1354. 0,
  1355. REG_DWORD,
  1356. (LPBYTE)&dwValue,
  1357. sizeof(dwValue)
  1358. );
  1359. #endif
  1360. //
  1361. // Save screen buffer size
  1362. //
  1363. dwValue = MAKELONG(pcpd->lpConsole->dwScreenBufferSize.X,
  1364. pcpd->lpConsole->dwScreenBufferSize.Y);
  1365. RegSetValueEx( hTitleKey,
  1366. CONSOLE_REGISTRY_BUFFERSIZE,
  1367. 0,
  1368. REG_DWORD,
  1369. (LPBYTE)&dwValue,
  1370. sizeof(dwValue)
  1371. );
  1372. //
  1373. // Save window size
  1374. //
  1375. dwValue = MAKELONG(pcpd->lpConsole->dwWindowSize.X,
  1376. pcpd->lpConsole->dwWindowSize.Y);
  1377. RegSetValueEx( hTitleKey,
  1378. CONSOLE_REGISTRY_WINDOWSIZE,
  1379. 0,
  1380. REG_DWORD,
  1381. (LPBYTE)&dwValue,
  1382. sizeof(dwValue)
  1383. );
  1384. //
  1385. // Save window position
  1386. //
  1387. if (pcpd->lpConsole->bAutoPosition) {
  1388. RegDeleteKey(hTitleKey, CONSOLE_REGISTRY_WINDOWPOS);
  1389. } else {
  1390. dwValue = MAKELONG(pcpd->lpConsole->dwWindowOrigin.X,
  1391. pcpd->lpConsole->dwWindowOrigin.Y);
  1392. RegSetValueEx( hTitleKey,
  1393. CONSOLE_REGISTRY_WINDOWPOS,
  1394. 0,
  1395. REG_DWORD,
  1396. (LPBYTE)&dwValue,
  1397. sizeof(dwValue)
  1398. );
  1399. }
  1400. //
  1401. // Save font size, family, weight, and face name
  1402. //
  1403. dwValue = MAKELONG(pcpd->lpConsole->dwFontSize.X,
  1404. pcpd->lpConsole->dwFontSize.Y);
  1405. RegSetValueEx( hTitleKey,
  1406. CONSOLE_REGISTRY_FONTSIZE,
  1407. 0,
  1408. REG_DWORD,
  1409. (LPBYTE)&dwValue,
  1410. sizeof(dwValue)
  1411. );
  1412. dwValue = pcpd->lpConsole->uFontFamily;
  1413. RegSetValueEx( hTitleKey,
  1414. CONSOLE_REGISTRY_FONTFAMILY,
  1415. 0,
  1416. REG_DWORD,
  1417. (LPBYTE)&dwValue,
  1418. sizeof(dwValue)
  1419. );
  1420. dwValue = pcpd->lpConsole->uFontWeight;
  1421. RegSetValueEx( hTitleKey,
  1422. CONSOLE_REGISTRY_FONTWEIGHT,
  1423. 0,
  1424. REG_DWORD,
  1425. (LPBYTE)&dwValue,
  1426. sizeof(dwValue)
  1427. );
  1428. RegSetValueEx( hTitleKey,
  1429. CONSOLE_REGISTRY_FACENAME,
  1430. 0,
  1431. REG_SZ,
  1432. (LPBYTE)pcpd->lpFaceName,
  1433. (lstrlen(pcpd->lpFaceName) + 1) * sizeof(TCHAR)
  1434. );
  1435. //
  1436. // Save cursor size
  1437. //
  1438. dwValue = pcpd->lpConsole->uCursorSize;
  1439. RegSetValueEx( hTitleKey,
  1440. CONSOLE_REGISTRY_CURSORSIZE,
  1441. 0,
  1442. REG_DWORD,
  1443. (LPBYTE)&dwValue,
  1444. sizeof(dwValue)
  1445. );
  1446. //
  1447. // Save history buffer size and number
  1448. //
  1449. dwValue = pcpd->lpConsole->uHistoryBufferSize;
  1450. RegSetValueEx( hTitleKey,
  1451. CONSOLE_REGISTRY_HISTORYSIZE,
  1452. 0,
  1453. REG_DWORD,
  1454. (LPBYTE)&dwValue,
  1455. sizeof(dwValue)
  1456. );
  1457. dwValue = pcpd->lpConsole->uNumberOfHistoryBuffers;
  1458. RegSetValueEx( hTitleKey,
  1459. CONSOLE_REGISTRY_HISTORYBUFS,
  1460. 0,
  1461. REG_DWORD,
  1462. (LPBYTE)&dwValue,
  1463. sizeof(dwValue)
  1464. );
  1465. dwValue = pcpd->lpConsole->bHistoryNoDup;
  1466. RegSetValueEx( hTitleKey,
  1467. CONSOLE_REGISTRY_HISTORYNODUP,
  1468. 0,
  1469. REG_DWORD,
  1470. (LPBYTE)&dwValue,
  1471. sizeof(dwValue)
  1472. );
  1473. //
  1474. // Close the registry keys
  1475. //
  1476. if (hTitleKey != hConsoleKey) {
  1477. RegCloseKey(hTitleKey);
  1478. }
  1479. CloseKeys:
  1480. RegCloseKey(hConsoleKey);
  1481. RegCloseKey(hCurrentUserKey);
  1482. }
  1483. void
  1484. InitFERegistryValues( CONSOLEPROP_DATA *pcpd )
  1485. /*++
  1486. Routine Description:
  1487. This routine allocates a state info structure and fill it in with
  1488. default values. It then tries to load the default settings for
  1489. console from the registry.
  1490. Arguments:
  1491. none
  1492. Return Value:
  1493. pStateInfo - pointer to structure to receive information
  1494. --*/
  1495. {
  1496. /*
  1497. * In this case: console reads a property of US version.
  1498. * It doesn't have code page information.
  1499. * Console should sets some code page as default.
  1500. * However, I don't know right value. 437 is temporary value.
  1501. */
  1502. pcpd->lpFEConsole->uCodePage = 437;
  1503. GetFERegistryValues( pcpd );
  1504. }
  1505. VOID
  1506. GetFERegistryValues(
  1507. CONSOLEPROP_DATA *pcpd
  1508. )
  1509. /*++
  1510. Routine Description:
  1511. This routine reads in values from the registry and places them
  1512. in the supplied structure.
  1513. Arguments:
  1514. pStateInfo - optional pointer to structure to receive information
  1515. Return Value:
  1516. current page number
  1517. --*/
  1518. {
  1519. HKEY hCurrentUserKey;
  1520. HKEY hConsoleKey;
  1521. HKEY hTitleKey;
  1522. LPTSTR TranslatedTitle;
  1523. DWORD dwValue, dwSize;
  1524. DWORD dwRet = 0;
  1525. //
  1526. // Open the current user registry key
  1527. //
  1528. if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey)!=ERROR_SUCCESS)
  1529. return;
  1530. //
  1531. // Open the console registry key
  1532. //
  1533. if (RegOpenKey(hCurrentUserKey,CONSOLE_REGISTRY_STRING,&hConsoleKey)!=ERROR_SUCCESS)
  1534. {
  1535. NtClose(hCurrentUserKey);
  1536. return;
  1537. }
  1538. //
  1539. // If there is no structure to fill out, just bail out
  1540. //
  1541. if ((!pcpd) || (!pcpd->lpFEConsole))
  1542. goto CloseKeys;
  1543. //
  1544. // Open the console title subkey, if there is one
  1545. //
  1546. if (pcpd->ConsoleTitle[0] != TEXT('\0'))
  1547. {
  1548. TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle);
  1549. if (TranslatedTitle == NULL)
  1550. goto CloseKeys;
  1551. dwValue = RegOpenKey( hConsoleKey,
  1552. TranslatedTitle,
  1553. &hTitleKey);
  1554. LocalFree(TranslatedTitle);
  1555. if (dwValue!=ERROR_SUCCESS)
  1556. goto CloseKeys;
  1557. } else {
  1558. goto CloseKeys;
  1559. }
  1560. //
  1561. // Initial code page
  1562. //
  1563. dwSize = sizeof(dwValue);
  1564. if (SHQueryValueEx( hTitleKey,
  1565. CONSOLE_REGISTRY_CODEPAGE,
  1566. NULL,
  1567. NULL,
  1568. (LPBYTE)&dwValue,
  1569. &dwSize
  1570. ) == ERROR_SUCCESS)
  1571. {
  1572. pcpd->lpFEConsole->uCodePage = (UINT)dwValue;
  1573. }
  1574. //
  1575. // Close the registry keys
  1576. //
  1577. if (hTitleKey != hConsoleKey) {
  1578. RegCloseKey(hTitleKey);
  1579. }
  1580. CloseKeys:
  1581. RegCloseKey(hConsoleKey);
  1582. RegCloseKey(hCurrentUserKey);
  1583. }
  1584. VOID
  1585. SetFERegistryValues(
  1586. CONSOLEPROP_DATA *pcpd
  1587. )
  1588. /*++
  1589. Routine Description:
  1590. This routine writes values to the registry from the supplied
  1591. structure.
  1592. Arguments:
  1593. pStateInfo - optional pointer to structure containing information
  1594. dwPage - current page number
  1595. Return Value:
  1596. none
  1597. --*/
  1598. {
  1599. HKEY hCurrentUserKey;
  1600. HKEY hConsoleKey;
  1601. HKEY hTitleKey;
  1602. LPTSTR TranslatedTitle;
  1603. DWORD dwValue;
  1604. //
  1605. // Open the current user registry key
  1606. //
  1607. if (RegOpenKey( HKEY_CURRENT_USER, NULL, &hCurrentUserKey )!=ERROR_SUCCESS)
  1608. {
  1609. return;
  1610. }
  1611. //
  1612. // Open the console registry key
  1613. //
  1614. if (RegCreateKey( hCurrentUserKey, CONSOLE_REGISTRY_STRING, &hConsoleKey )!=ERROR_SUCCESS)
  1615. {
  1616. RegCloseKey(hCurrentUserKey);
  1617. return;
  1618. }
  1619. //
  1620. // If we only want to save the current page, bail out
  1621. //
  1622. if (pcpd == NULL)
  1623. {
  1624. goto CloseKeys;
  1625. }
  1626. //
  1627. // Open the console title subkey, if there is one
  1628. //
  1629. if (pcpd->ConsoleTitle[0] != TEXT('\0'))
  1630. {
  1631. TranslatedTitle = TranslateConsoleTitle(pcpd->ConsoleTitle);
  1632. if (TranslatedTitle == NULL)
  1633. {
  1634. RegCloseKey(hConsoleKey);
  1635. RegCloseKey(hCurrentUserKey);
  1636. return;
  1637. }
  1638. dwValue = RegCreateKey( hConsoleKey,
  1639. TranslatedTitle,
  1640. &hTitleKey);
  1641. LocalFree(TranslatedTitle);
  1642. if (dwValue!=ERROR_SUCCESS)
  1643. {
  1644. RegCloseKey(hConsoleKey);
  1645. RegCloseKey(hCurrentUserKey);
  1646. return;
  1647. }
  1648. } else {
  1649. hTitleKey = hConsoleKey;
  1650. }
  1651. // scotthsu
  1652. dwValue = pcpd->lpFEConsole->uCodePage;
  1653. RegSetValueEx( hTitleKey,
  1654. CONSOLE_REGISTRY_CODEPAGE,
  1655. 0,
  1656. REG_DWORD,
  1657. (LPBYTE)&dwValue,
  1658. sizeof(dwValue)
  1659. );
  1660. //
  1661. // Close the registry keys
  1662. //
  1663. if (hTitleKey != hConsoleKey) {
  1664. RegCloseKey(hTitleKey);
  1665. }
  1666. CloseKeys:
  1667. RegCloseKey(hConsoleKey);
  1668. RegCloseKey(hCurrentUserKey);
  1669. }