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.

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