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.

733 lines
21 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 "precomp.h"
  12. #pragma hdrstop
  13. #ifdef DEBUG_PRINT
  14. ULONG gDebugFlag = 0 ;
  15. // ULONG gDebugFlag = _DBGOUTPUT | _DBGCHARS | _DBGFONTS | _DBGFONTS2 ;
  16. #endif
  17. PFONT_INFO FontInfo = NULL;
  18. ULONG FontInfoLength;
  19. ULONG NumberOfFonts;
  20. BOOL gbEnumerateFaces = FALSE;
  21. #define FE_ABANDONFONT 0
  22. #define FE_SKIPFONT 1
  23. #define FE_FONTOK 2
  24. /*
  25. * Initial default fonts and face names
  26. */
  27. PFACENODE gpFaceNames = NULL;
  28. /*
  29. * TTPoints -- Initial font pixel heights for TT fonts
  30. */
  31. SHORT TTPoints[] = {
  32. 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72
  33. };
  34. #if defined(FE_SB)
  35. /*
  36. * TTPointsDbcs -- Initial font pixel heights for TT fonts of DBCS.
  37. * So, This list except odd point size because font width is (SBCS:DBCS != 1:2).
  38. */
  39. SHORT TTPointsDbcs[] = {
  40. 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72
  41. };
  42. #endif
  43. typedef struct _FONTENUMDATA {
  44. HDC hDC;
  45. BOOL bFindFaces;
  46. ULONG ulFE;
  47. PSHORT pTTPoints;
  48. UINT nTTPoints;
  49. } FONTENUMDATA, *PFONTENUMDATA;
  50. PFACENODE
  51. AddFaceNode(PFACENODE *ppStart, LPTSTR ptsz) {
  52. PFACENODE pNew;
  53. PFACENODE *ppTmp;
  54. int cb;
  55. /*
  56. * Is it already here?
  57. */
  58. for (ppTmp = ppStart; *ppTmp; ppTmp = &((*ppTmp)->pNext)) {
  59. if (_tcscmp(((*ppTmp)->atch), ptsz) == 0) {
  60. // already there !
  61. return *ppTmp;
  62. }
  63. }
  64. cb = (_tcslen(ptsz) + 1) * sizeof(TCHAR);
  65. pNew = (PFACENODE)HeapAlloc(RtlProcessHeap(),0,sizeof(FACENODE) + cb);
  66. if (pNew == NULL) {
  67. return NULL;
  68. }
  69. pNew->pNext = NULL;
  70. pNew->dwFlag = 0;
  71. _tcscpy(pNew->atch, ptsz);
  72. *ppTmp = pNew;
  73. return pNew;
  74. }
  75. VOID
  76. DestroyFaceNodes( VOID ) {
  77. PFACENODE pNext;
  78. PFACENODE pTmp;
  79. pTmp = gpFaceNames;
  80. while (pTmp != NULL) {
  81. pNext = pTmp->pNext;
  82. HeapFree(RtlProcessHeap(), 0, pTmp);
  83. pTmp = pNext;
  84. }
  85. gpFaceNames = NULL;
  86. }
  87. int
  88. AddFont(
  89. ENUMLOGFONT *pelf,
  90. NEWTEXTMETRIC *pntm,
  91. int nFontType,
  92. HDC hDC,
  93. PFACENODE pFN
  94. )
  95. /*++
  96. Add the font desribed by the LOGFONT structure to the font table if
  97. it's not already there.
  98. --*/
  99. {
  100. HFONT hFont;
  101. TEXTMETRIC tm;
  102. LONG nFont;
  103. COORD SizeToShow;
  104. COORD SizeActual;
  105. COORD SizeWant;
  106. BYTE tmFamily;
  107. SIZE Size;
  108. LPTSTR ptszFace = pelf->elfLogFont.lfFaceName;
  109. /* get font info */
  110. SizeWant.X = (SHORT)pelf->elfLogFont.lfWidth;
  111. SizeWant.Y = (SHORT)pelf->elfLogFont.lfHeight;
  112. CreateBoldFont:
  113. pelf->elfLogFont.lfQuality = DEFAULT_QUALITY;
  114. hFont = CreateFontIndirect(&pelf->elfLogFont);
  115. if (!hFont) {
  116. DBGFONTS((" REJECT font (can't create)\n"));
  117. return FE_SKIPFONT; // same font in other sizes may still be suitable
  118. }
  119. DBGFONTS2((" hFont = %lx\n", hFont));
  120. SelectObject(hDC, hFont);
  121. GetTextMetrics(hDC, &tm);
  122. GetTextExtentPoint32(hDC, TEXT("0"), 1, &Size);
  123. SizeActual.X = (SHORT)Size.cx;
  124. SizeActual.Y = (SHORT)(tm.tmHeight + tm.tmExternalLeading);
  125. DBGFONTS2((" actual size %d,%d\n", SizeActual.X, SizeActual.Y));
  126. tmFamily = tm.tmPitchAndFamily;
  127. if (TM_IS_TT_FONT(tmFamily) && (SizeWant.Y >= 0)) {
  128. SizeToShow = SizeWant;
  129. if (SizeWant.X == 0) {
  130. // Asking for zero width height gets a default aspect-ratio width.
  131. // It's better to show that width rather than 0.
  132. SizeToShow.X = SizeActual.X;
  133. }
  134. } else {
  135. SizeToShow = SizeActual;
  136. }
  137. //
  138. // The size shouldn't be zero. This is to help catch Windows Bug #332453.
  139. //
  140. ASSERT(SizeActual.X != 0 && SizeActual.Y != 0 && "If you hit this please e-mail jasonsch");
  141. DBGFONTS2((" SizeToShow = (%d,%d), SizeActual = (%d,%d)\n",
  142. SizeToShow.X, SizeToShow.Y, SizeActual.X, SizeActual.Y));
  143. /*
  144. * NOW, determine whether this font entry has already been cached
  145. * LATER : it may be possible to do this before creating the font, if
  146. * we can trust the dimensions & other info from pntm.
  147. * Sort by size:
  148. * 1) By pixelheight (negative Y values)
  149. * 2) By height (as shown)
  150. * 3) By width (as shown)
  151. */
  152. for (nFont = 0; nFont < (LONG)NumberOfFonts; ++nFont) {
  153. COORD SizeShown;
  154. if (FontInfo[nFont].hFont == NULL) {
  155. DBGFONTS(("! Font %x has a NULL hFont\n", nFont));
  156. continue;
  157. }
  158. if (FontInfo[nFont].SizeWant.X > 0) {
  159. SizeShown.X = FontInfo[nFont].SizeWant.X;
  160. } else {
  161. SizeShown.X = FontInfo[nFont].Size.X;
  162. }
  163. if (FontInfo[nFont].SizeWant.Y > 0) {
  164. // This is a font specified by cell height.
  165. SizeShown.Y = FontInfo[nFont].SizeWant.Y;
  166. } else {
  167. SizeShown.Y = FontInfo[nFont].Size.Y;
  168. if (FontInfo[nFont].SizeWant.Y < 0) {
  169. // This is a TT font specified by character height.
  170. if (SizeWant.Y < 0 && SizeWant.Y > FontInfo[nFont].SizeWant.Y) {
  171. // Requested pixelheight is smaller than this one.
  172. DBGFONTS(("INSERT %d pt at %x, before %d pt\n",
  173. -SizeWant.Y, nFont, -FontInfo[nFont].SizeWant.Y));
  174. break;
  175. }
  176. }
  177. }
  178. // DBGFONTS((" SizeShown(%x) = (%d,%d)\n",nFont,SizeShown.X,SizeShown.Y));
  179. if (SIZE_EQUAL(SizeShown, SizeToShow) &&
  180. FontInfo[nFont].Family == tmFamily &&
  181. FontInfo[nFont].Weight == tm.tmWeight &&
  182. _tcscmp(FontInfo[nFont].FaceName, ptszFace) == 0) {
  183. /*
  184. * Already have this font
  185. */
  186. DBGFONTS2((" Already have the font\n"));
  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. DBGFONTS(("INSERT at %x, SizeToShow = (%d,%d)\n", nFont,
  196. SizeToShow.X,SizeToShow.Y));
  197. break;
  198. }
  199. }
  200. /*
  201. * If we have to grow our font table, do it
  202. */
  203. if (NumberOfFonts == FontInfoLength) {
  204. PFONT_INFO Temp;
  205. FontInfoLength += FONT_INCREMENT;
  206. Temp = (PFONT_INFO)HeapReAlloc(RtlProcessHeap(), 0, FontInfo,
  207. sizeof(FONT_INFO) * FontInfoLength);
  208. if (Temp == NULL) {
  209. FontInfoLength -= FONT_INCREMENT;
  210. return FE_ABANDONFONT; // no point enumerating more - no memory!
  211. }
  212. FontInfo = Temp;
  213. }
  214. /*
  215. * The font we are adding should be inserted into the list,
  216. * if it is smaller than the last one.
  217. */
  218. if (nFont < (LONG)NumberOfFonts) {
  219. RtlMoveMemory(&FontInfo[nFont+1],
  220. &FontInfo[nFont],
  221. sizeof(FONT_INFO) * (NumberOfFonts - nFont));
  222. }
  223. /*
  224. * Store the font info
  225. */
  226. FontInfo[nFont].hFont = hFont;
  227. FontInfo[nFont].Family = tmFamily;
  228. FontInfo[nFont].Size = SizeActual;
  229. if (TM_IS_TT_FONT(tmFamily)) {
  230. FontInfo[nFont].SizeWant = SizeWant;
  231. } else {
  232. FontInfo[nFont].SizeWant.X = 0;
  233. FontInfo[nFont].SizeWant.Y = 0;
  234. }
  235. FontInfo[nFont].Weight = tm.tmWeight;
  236. FontInfo[nFont].FaceName = pFN->atch;
  237. #if defined(FE_SB)
  238. FontInfo[nFont].tmCharSet = tm.tmCharSet;
  239. #endif
  240. ++NumberOfFonts;
  241. /*
  242. * If this is a true type font, create a bold version too.
  243. */
  244. if (nFontType == TRUETYPE_FONTTYPE && !IS_BOLD(FontInfo[nFont].Weight)) {
  245. pelf->elfLogFont.lfWeight = FW_BOLD;
  246. goto CreateBoldFont;
  247. }
  248. return FE_FONTOK; // and continue enumeration
  249. }
  250. VOID
  251. InitializeFonts( VOID )
  252. {
  253. EnumerateFonts(EF_DEFFACE); // Just the Default font
  254. }
  255. VOID
  256. DestroyFonts( VOID )
  257. {
  258. ULONG FontIndex;
  259. if (FontInfo != NULL) {
  260. for (FontIndex = 0; FontIndex < NumberOfFonts; FontIndex++) {
  261. DeleteObject(FontInfo[FontIndex].hFont);
  262. }
  263. HeapFree(RtlProcessHeap(), 0, FontInfo);
  264. FontInfo = NULL;
  265. NumberOfFonts = 0;
  266. }
  267. DestroyFaceNodes();
  268. }
  269. /*
  270. * Returns bit combination
  271. * FE_ABANDONFONT - do not continue enumerating this font
  272. * FE_SKIPFONT - skip this font but keep enumerating
  273. * FE_FONTOK - font was created and added to cache or already there
  274. */
  275. int
  276. FontEnum(
  277. ENUMLOGFONT *pelf,
  278. NEWTEXTMETRIC *pntm,
  279. int nFontType,
  280. PFONTENUMDATA pfed
  281. )
  282. /*++
  283. Is called exactly once by GDI for each font in the system. This
  284. routine is used to store the FONT_INFO structure.
  285. --*/
  286. {
  287. UINT i;
  288. LPTSTR ptszFace = pelf->elfLogFont.lfFaceName;
  289. PFACENODE pFN;
  290. DBGFONTS((" FontEnum \"%ls\" (%d,%d) weight 0x%lx(%d) %x -- %s\n",
  291. ptszFace,
  292. pelf->elfLogFont.lfWidth, pelf->elfLogFont.lfHeight,
  293. pelf->elfLogFont.lfWeight, pelf->elfLogFont.lfWeight,
  294. pelf->elfLogFont.lfCharSet,
  295. pfed->bFindFaces ? "Finding Faces" : "Creating Fonts"));
  296. //
  297. // reject variable width and italic fonts, also tt fonts with neg ac
  298. //
  299. if
  300. (
  301. !(pelf->elfLogFont.lfPitchAndFamily & FIXED_PITCH) ||
  302. (pelf->elfLogFont.lfItalic) ||
  303. !(pntm->ntmFlags & NTM_NONNEGATIVE_AC)
  304. )
  305. {
  306. if (! IsAvailableTTFont(ptszFace)) {
  307. DBGFONTS((" REJECT face (dbcs, variable pitch, italic, or neg a&c)\n"));
  308. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  309. }
  310. }
  311. /*
  312. * reject TT fonts for whoom family is not modern, that is do not use
  313. * FF_DONTCARE // may be surprised unpleasantly
  314. * FF_DECORATIVE // likely to be symbol fonts
  315. * FF_SCRIPT // cursive, inappropriate for console
  316. * FF_SWISS OR FF_ROMAN // variable pitch
  317. */
  318. if ((nFontType == TRUETYPE_FONTTYPE) &&
  319. ((pelf->elfLogFont.lfPitchAndFamily & 0xf0) != FF_MODERN)) {
  320. DBGFONTS((" REJECT face (TT but not FF_MODERN)\n"));
  321. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  322. }
  323. /*
  324. * reject non-TT fonts that aren't OEM
  325. */
  326. if ((nFontType != TRUETYPE_FONTTYPE) &&
  327. #if defined(FE_SB)
  328. (!gfFESystem || !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet)) &&
  329. #endif
  330. (pelf->elfLogFont.lfCharSet != OEM_CHARSET)) {
  331. DBGFONTS((" REJECT face (not TT nor OEM)\n"));
  332. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  333. }
  334. /*
  335. * reject non-TT fonts that are virtical font
  336. */
  337. if ((nFontType != TRUETYPE_FONTTYPE) &&
  338. (ptszFace[0] == TEXT('@'))) {
  339. DBGFONTS((" REJECT face (not TT and TATEGAKI)\n"));
  340. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  341. }
  342. /*
  343. * reject non-TT fonts that aren't Terminal
  344. */
  345. if (gfFESystem && (nFontType != TRUETYPE_FONTTYPE) &&
  346. (_tcscmp(ptszFace, TEXT("Terminal")) != 0)) {
  347. DBGFONTS((" REJECT face (not TT nor Terminal)\n"));
  348. return pfed->bFindFaces ? FE_SKIPFONT : FE_ABANDONFONT;
  349. }
  350. /*
  351. * reject Far East TT fonts that aren't Far East charset.
  352. */
  353. if (IsAvailableTTFont(ptszFace) &&
  354. !IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet) &&
  355. !IsAvailableTTFontCP(ptszFace,0)
  356. ) {
  357. DBGFONTS((" REJECT face (Far East TT and not Far East charset)\n"));
  358. return FE_SKIPFONT; // should be enumerate next charset.
  359. }
  360. /*
  361. * Add or find the facename
  362. */
  363. pFN = AddFaceNode(&gpFaceNames, ptszFace);
  364. if (pFN == NULL) {
  365. return FE_ABANDONFONT;
  366. }
  367. if (pfed->bFindFaces) {
  368. DWORD dwFontType;
  369. if (nFontType == TRUETYPE_FONTTYPE) {
  370. DBGFONTS(("NEW TT FACE %ls\n", ptszFace));
  371. dwFontType = EF_TTFONT;
  372. } else if (nFontType == RASTER_FONTTYPE) {
  373. DBGFONTS(("NEW OEM FACE %ls\n",ptszFace));
  374. dwFontType = EF_OEMFONT;
  375. }
  376. pFN->dwFlag |= dwFontType | EF_NEW;
  377. #if defined(FE_SB)
  378. if (IS_ANY_DBCS_CHARSET(pelf->elfLogFont.lfCharSet))
  379. pFN->dwFlag |= EF_DBCSFONT;
  380. #endif
  381. return FE_SKIPFONT;
  382. }
  383. if (IS_BOLD(pelf->elfLogFont.lfWeight)) {
  384. DBGFONTS2((" A bold font (weight %d)\n", pelf->elfLogFont.lfWeight));
  385. // return FE_SKIPFONT;
  386. }
  387. /*
  388. * Add the font to the table. If this is a true type font, add the
  389. * sizes from the array. Otherwise, just add the size we got.
  390. */
  391. if (nFontType & TRUETYPE_FONTTYPE) {
  392. for (i = 0; i < pfed->nTTPoints; i++) {
  393. pelf->elfLogFont.lfHeight = pfed->pTTPoints[i];
  394. pelf->elfLogFont.lfWidth = 0;
  395. pelf->elfLogFont.lfWeight = 400;
  396. pfed->ulFE |= AddFont(pelf, pntm, nFontType, pfed->hDC, pFN);
  397. if (pfed->ulFE & FE_ABANDONFONT) {
  398. return FE_ABANDONFONT;
  399. }
  400. }
  401. } else {
  402. pfed->ulFE |= AddFont(pelf, pntm, nFontType, pfed->hDC, pFN);
  403. if (pfed->ulFE & FE_ABANDONFONT) {
  404. return FE_ABANDONFONT;
  405. }
  406. }
  407. return FE_FONTOK; // and continue enumeration
  408. }
  409. BOOL
  410. DoFontEnum(
  411. HDC hDC,
  412. LPTSTR ptszFace,
  413. PSHORT pTTPoints,
  414. UINT nTTPoints)
  415. {
  416. BOOL bDeleteDC = FALSE;
  417. FONTENUMDATA fed;
  418. LOGFONT LogFont;
  419. DBGFONTS(("DoFontEnum \"%ls\"\n", ptszFace));
  420. if (hDC == NULL) {
  421. hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  422. bDeleteDC = TRUE;
  423. }
  424. fed.hDC = hDC;
  425. fed.bFindFaces = (ptszFace == NULL);
  426. fed.ulFE = 0;
  427. fed.pTTPoints = pTTPoints;
  428. fed.nTTPoints = nTTPoints;
  429. RtlZeroMemory(&LogFont, sizeof(LOGFONT));
  430. LogFont.lfCharSet = DEFAULT_CHARSET;
  431. if (ptszFace)
  432. _tcscpy(LogFont.lfFaceName, ptszFace);
  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. if (bDeleteDC) {
  438. DeleteDC(hDC);
  439. }
  440. return (fed.ulFE & FE_FONTOK) != 0;
  441. }
  442. VOID
  443. RemoveFace(LPTSTR ptszFace)
  444. {
  445. DWORD i;
  446. int nToRemove = 0;
  447. DBGFONTS(("RemoveFace %ls\n", ptszFace));
  448. //
  449. // Delete & Remove fonts with Face Name == ptszFace
  450. //
  451. for (i = 0; i < NumberOfFonts; i++) {
  452. if (_tcscmp(FontInfo[i].FaceName, ptszFace) == 0) {
  453. BOOL bDeleted = DeleteObject(FontInfo[i].hFont);
  454. DBGPRINT(("RemoveFace: hFont %lx was %sdeleted\n",
  455. FontInfo[i].hFont, bDeleted ? "" : "NOT "));
  456. FontInfo[i].hFont = NULL;
  457. nToRemove++;
  458. } else if (nToRemove > 0) {
  459. /*
  460. * Shuffle from FontInfo[i] down nToRemove slots.
  461. */
  462. RtlMoveMemory(&FontInfo[i - nToRemove],
  463. &FontInfo[i],
  464. sizeof(FONT_INFO)*(NumberOfFonts - i));
  465. NumberOfFonts -= nToRemove;
  466. i -= nToRemove;
  467. nToRemove = 0;
  468. }
  469. }
  470. NumberOfFonts -= nToRemove;
  471. }
  472. TCHAR DefaultFaceName[LF_FACESIZE];
  473. COORD DefaultFontSize;
  474. BYTE DefaultFontFamily;
  475. ULONG DefaultFontIndex = 0;
  476. ULONG CurrentFontIndex = 0;
  477. NTSTATUS
  478. EnumerateFonts(
  479. DWORD Flags)
  480. {
  481. TEXTMETRIC tm;
  482. HDC hDC;
  483. PFACENODE pFN;
  484. ULONG ulOldEnumFilter;
  485. BOOL bEnumOEMFace = TRUE;
  486. DWORD FontIndex;
  487. DWORD dwFontType = 0;
  488. DBGFONTS(("EnumerateFonts %lx\n", Flags));
  489. dwFontType = (EF_TTFONT|EF_OEMFONT|EF_DEFFACE) & Flags;
  490. if (FontInfo == NULL) {
  491. //
  492. // allocate memory for the font array
  493. //
  494. NumberOfFonts = 0;
  495. FontInfo = (PFONT_INFO)HeapAlloc(RtlProcessHeap(),0,sizeof(FONT_INFO) * INITIAL_FONTS);
  496. if (FontInfo == NULL)
  497. return STATUS_NO_MEMORY;
  498. FontInfoLength = INITIAL_FONTS;
  499. }
  500. hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  501. // Before enumeration, turn off font enumeration filters.
  502. ulOldEnumFilter = SetFontEnumeration(0);
  503. SetFontEnumeration(ulOldEnumFilter & ~FE_FILTER_TRUETYPE);
  504. if (Flags & EF_DEFFACE) {
  505. SelectObject(hDC, GetStockObject(OEM_FIXED_FONT));
  506. GetTextMetrics(hDC, &tm);
  507. GetTextFace(hDC, LF_FACESIZE, DefaultFaceName);
  508. DefaultFontSize.X = (SHORT)(tm.tmMaxCharWidth);
  509. DefaultFontSize.Y = (SHORT)(tm.tmHeight+tm.tmExternalLeading);
  510. DefaultFontFamily = tm.tmPitchAndFamily;
  511. #if !defined(FE_SB)
  512. DBGFONTS(("Default (OEM) Font %ls (%d,%d)\n", DefaultFaceName,
  513. DefaultFontSize.X, DefaultFontSize.Y));
  514. #else
  515. if (IS_ANY_DBCS_CHARSET(tm.tmCharSet))
  516. DefaultFontSize.X /= 2;
  517. DBGFONTS(("Default (OEM) Font %ls (%d,%d) CharSet 0x%02X\n", DefaultFaceName,
  518. DefaultFontSize.X, DefaultFontSize.Y,
  519. tm.tmCharSet));
  520. #endif
  521. // Make sure we are going to enumerate the OEM face.
  522. pFN = AddFaceNode(&gpFaceNames, DefaultFaceName);
  523. if (pFN)
  524. pFN->dwFlag |= EF_DEFFACE | EF_OEMFONT;
  525. }
  526. if (gbEnumerateFaces) {
  527. /*
  528. * Set the EF_OLD bit and clear the EF_NEW bit
  529. * for all previously available faces
  530. */
  531. for (pFN = gpFaceNames; pFN; pFN = pFN->pNext) {
  532. pFN->dwFlag |= EF_OLD;
  533. pFN->dwFlag &= ~EF_NEW;
  534. }
  535. //
  536. // Use DoFontEnum to get the names of all the suitable Faces
  537. // All facenames found will be put in gpFaceNames with
  538. // the EF_NEW bit set.
  539. //
  540. DoFontEnum(hDC, NULL, TTPoints, 1);
  541. gbEnumerateFaces = FALSE;
  542. }
  543. // Use DoFontEnum to get all fonts from the system. Our FontEnum
  544. // proc puts just the ones we want into an array
  545. //
  546. for (pFN = gpFaceNames; pFN; pFN = pFN->pNext) {
  547. DBGFONTS(("\"%ls\" is %s%s%s%s%s%s\n", pFN->atch,
  548. pFN->dwFlag & EF_NEW ? "NEW " : " ",
  549. pFN->dwFlag & EF_OLD ? "OLD " : " ",
  550. pFN->dwFlag & EF_ENUMERATED ? "ENUMERATED " : " ",
  551. pFN->dwFlag & EF_OEMFONT ? "OEMFONT " : " ",
  552. pFN->dwFlag & EF_TTFONT ? "TTFONT " : " ",
  553. pFN->dwFlag & EF_DEFFACE ? "DEFFACE " : " "));
  554. if ((pFN->dwFlag & (EF_OLD|EF_NEW)) == EF_OLD) {
  555. // The face is no longer available
  556. RemoveFace(pFN->atch);
  557. pFN->dwFlag &= ~EF_ENUMERATED;
  558. continue;
  559. }
  560. if ((pFN->dwFlag & dwFontType) == 0) {
  561. // not the kind of face we want
  562. continue;
  563. }
  564. if (pFN->dwFlag & EF_ENUMERATED) {
  565. // we already enumerated this face
  566. continue;
  567. }
  568. if (pFN->dwFlag & EF_TTFONT) {
  569. #if defined(FE_SB)
  570. if (gfFESystem && !IsAvailableTTFontCP(pFN->atch,0))
  571. DoFontEnum(hDC, pFN->atch, TTPointsDbcs, NELEM(TTPointsDbcs));
  572. else
  573. #endif
  574. DoFontEnum(hDC, pFN->atch, TTPoints, NELEM(TTPoints));
  575. } else {
  576. DoFontEnum(hDC, pFN->atch, NULL, 0);
  577. // If we find that the face just enumerated is the same as OEM,
  578. // reset flag so we don't try to enumerate it again.
  579. if (!_tcsncmp(pFN->atch, DefaultFaceName, LF_FACESIZE)) {
  580. bEnumOEMFace = FALSE;
  581. }
  582. }
  583. pFN->dwFlag |= EF_ENUMERATED;
  584. }
  585. // After enumerating fonts, restore the font enumeration filter.
  586. SetFontEnumeration(ulOldEnumFilter);
  587. DeleteDC(hDC);
  588. #if defined(FE_SB)
  589. if (gfFESystem )
  590. {
  591. for (FontIndex = 0; FontIndex < NumberOfFonts; FontIndex++) {
  592. if (FontInfo[FontIndex].Size.X == DefaultFontSize.X &&
  593. FontInfo[FontIndex].Size.Y == DefaultFontSize.Y &&
  594. IS_ANY_DBCS_CHARSET(FontInfo[FontIndex].tmCharSet) &&
  595. FontInfo[FontIndex].Family == DefaultFontFamily) {
  596. break;
  597. }
  598. }
  599. }
  600. else
  601. {
  602. #endif
  603. for (FontIndex = 0; FontIndex < NumberOfFonts; FontIndex++) {
  604. if (FontInfo[FontIndex].Size.X == DefaultFontSize.X &&
  605. FontInfo[FontIndex].Size.Y == DefaultFontSize.Y &&
  606. FontInfo[FontIndex].Family == DefaultFontFamily) {
  607. break;
  608. }
  609. }
  610. #if defined(FE_SB)
  611. }
  612. #endif
  613. ASSERT(FontIndex < NumberOfFonts);
  614. if (FontIndex < NumberOfFonts) {
  615. DefaultFontIndex = FontIndex;
  616. } else {
  617. DefaultFontIndex = 0;
  618. }
  619. DBGFONTS(("EnumerateFonts : DefaultFontIndex = %ld\n", DefaultFontIndex));
  620. return STATUS_SUCCESS;
  621. }