Leaked source code of windows server 2003
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.

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