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.

1252 lines
36 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fontdlg.dlg
  5. Abstract:
  6. This module contains the code for console font dialog
  7. Author:
  8. Therese Stowell (thereses) Feb-3-1992 (swiped from Win3.1)
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "fontdlg.h"
  14. /* ----- Prototypes ----- */
  15. int FontListCreate(
  16. HWND hDlg,
  17. LPTSTR ptszTTFace,
  18. BOOL bNewFaceList
  19. );
  20. BOOL PreviewUpdate(
  21. HWND hDlg,
  22. BOOL bLB
  23. );
  24. int SelectCurrentSize(
  25. HWND hDlg,
  26. BOOL bLB,
  27. int FontIndex);
  28. BOOL PreviewInit(
  29. HWND hDlg);
  30. VOID DrawItemFontList(
  31. const LPDRAWITEMSTRUCT lpdis);
  32. /* ----- Globals ----- */
  33. const TCHAR g_szPreviewText[] = \
  34. TEXT("C:\\WINDOWS> dir \n") \
  35. TEXT("SYSTEM <DIR> 10-01-99 5:00a\n") \
  36. TEXT("SYSTEM32 <DIR> 10-01-99 5:00a\n") \
  37. TEXT("README TXT 26926 10-01-99 5:00a\n") \
  38. TEXT("WINDOWS BMP 46080 10-01-99 5:00a\n") \
  39. TEXT("NOTEPAD EXE 337232 10-01-99 5:00a\n") \
  40. TEXT("CLOCK AVI 39594 10-01-99 5:00p\n") \
  41. TEXT("WIN INI 7005 10-01-99 5:00a\n");
  42. HBITMAP hbmTT = NULL; // handle of TT logo bitmap
  43. BITMAP bmTT; // attributes of TT source bitmap
  44. int dyFacelistItem; // height of Item in Facelist listbox
  45. BOOL gbPointSizeError = FALSE;
  46. BOOL gbBold = FALSE;
  47. #if defined(FE_SB)
  48. BOOL fChangeCodePage = FALSE;
  49. BOOL
  50. SelectCurrentFont(
  51. HWND hDlg,
  52. int FontIndex
  53. );
  54. #endif
  55. // Globals strings loaded from resource
  56. TCHAR tszSelectedFont[CCH_SELECTEDFONT+1];
  57. TCHAR tszRasterFonts[CCH_RASTERFONTS+1];
  58. INT_PTR
  59. APIENTRY
  60. FontDlgProc(
  61. HWND hDlg,
  62. UINT wMsg,
  63. WPARAM wParam,
  64. LPARAM lParam
  65. )
  66. /*++
  67. Dialog proc for the font selection dialog box.
  68. Returns the near offset into the far table of LOGFONT structures.
  69. --*/
  70. {
  71. HWND hWndFocus;
  72. HWND hWndList;
  73. int FontIndex;
  74. BOOL bLB;
  75. TEXTMETRIC tm;
  76. HDC hDC;
  77. switch (wMsg) {
  78. case WM_INITDIALOG:
  79. /*
  80. * Load the font description strings
  81. */
  82. LoadString(ghInstance, IDS_RASTERFONT,
  83. tszRasterFonts, NELEM(tszRasterFonts));
  84. DBGPRINT(("tszRasterFonts = \"%ls\"\n", tszRasterFonts));
  85. ASSERT(_tcslen(tszRasterFonts) < CCH_RASTERFONTS);
  86. LoadString(ghInstance, IDS_SELECTEDFONT,
  87. tszSelectedFont, NELEM(tszSelectedFont));
  88. DBGPRINT(("tszSelectedFont = \"%ls\"\n", tszSelectedFont));
  89. ASSERT(_tcslen(tszSelectedFont) < CCH_SELECTEDFONT);
  90. /* Save current font size as dialog window's user data */
  91. #if defined(FE_SB)
  92. ASSERT(OEMCP != 0);
  93. if (gfFESystem) {
  94. SetWindowLongPtr(hDlg, GWLP_USERDATA,
  95. MAKELONG(FontInfo[CurrentFontIndex].tmCharSet,
  96. FontInfo[CurrentFontIndex].Size.Y));
  97. } else {
  98. #endif
  99. SetWindowLongPtr(hDlg, GWLP_USERDATA,
  100. MAKELONG(FontInfo[CurrentFontIndex].Size.X,
  101. FontInfo[CurrentFontIndex].Size.Y));
  102. #if defined(FE_SB)
  103. }
  104. #endif
  105. /* Create the list of suitable fonts */
  106. gbEnumerateFaces = TRUE;
  107. bLB = !TM_IS_TT_FONT(gpStateInfo->FontFamily);
  108. gbBold = IS_BOLD(gpStateInfo->FontWeight);
  109. CheckDlgButton(hDlg, IDD_BOLDFONT, gbBold);
  110. FontListCreate(hDlg, bLB ? NULL : gpStateInfo->FaceName, TRUE);
  111. /* Initialize the preview window - selects current face & size too */
  112. bLB = PreviewInit(hDlg);
  113. PreviewUpdate(hDlg, bLB);
  114. /* Make sure the list box has the focus */
  115. hWndList = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
  116. SetFocus(hWndList);
  117. break;
  118. case WM_FONTCHANGE:
  119. gbEnumerateFaces = TRUE;
  120. bLB = !TM_IS_TT_FONT(gpStateInfo->FontFamily);
  121. FontListCreate(hDlg, NULL, TRUE);
  122. FontIndex = FindCreateFont(gpStateInfo->FontFamily,
  123. gpStateInfo->FaceName,
  124. gpStateInfo->FontSize,
  125. gpStateInfo->FontWeight,
  126. gpStateInfo->CodePage);
  127. SelectCurrentSize(hDlg, bLB, FontIndex);
  128. return TRUE;
  129. #if defined(FE_SB)
  130. case WM_PAINT:
  131. if (fChangeCodePage)
  132. {
  133. fChangeCodePage = FALSE;
  134. /* Create the list of suitable fonts */
  135. bLB = !TM_IS_TT_FONT(gpStateInfo->FontFamily);
  136. FontIndex = FontListCreate(hDlg, !bLB ? NULL : gpStateInfo->FaceName, TRUE);
  137. FontIndex = FontListCreate(hDlg, bLB ? NULL : gpStateInfo->FaceName, TRUE);
  138. CurrentFontIndex = FontIndex;
  139. FontIndex = SelectCurrentSize(hDlg, bLB, FontIndex);
  140. SelectCurrentFont(hDlg, FontIndex);
  141. PreviewUpdate(hDlg, bLB);
  142. }
  143. break;
  144. #endif
  145. case WM_COMMAND:
  146. switch (LOWORD(wParam))
  147. {
  148. case IDD_BOLDFONT:
  149. DBGPRINT(("WM_COMMAND to Bold Font checkbox %x\n", HIWORD(wParam)));
  150. gbBold = IsDlgButtonChecked(hDlg, IDD_BOLDFONT);
  151. goto RedoFontListAndPreview;
  152. case IDD_FACENAME:
  153. switch (HIWORD(wParam))
  154. {
  155. case LBN_SELCHANGE:
  156. RedoFontListAndPreview:
  157. {
  158. TCHAR atchNewFace[LF_FACESIZE];
  159. LONG l;
  160. DBGFONTS(("LBN_SELCHANGE from FACENAME\n"));
  161. l = (LONG)SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETCURSEL, 0, 0L);
  162. bLB = (BOOL)SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETITEMDATA, l, 0L);
  163. if (!bLB) {
  164. SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETTEXT, l, (LPARAM)atchNewFace);
  165. DBGFONTS(("LBN_EDITUPDATE, got TT face \"%ls\"\n", atchNewFace));
  166. }
  167. FontIndex = FontListCreate(hDlg, bLB ? NULL : atchNewFace, FALSE);
  168. FontIndex = SelectCurrentSize(hDlg, bLB, FontIndex);
  169. PreviewUpdate(hDlg, bLB);
  170. return TRUE;
  171. }
  172. }
  173. break;
  174. case IDD_POINTSLIST:
  175. switch (HIWORD(wParam)) {
  176. case CBN_SELCHANGE:
  177. DBGFONTS(("CBN_SELCHANGE from POINTSLIST\n"));
  178. PreviewUpdate(hDlg, FALSE);
  179. return TRUE;
  180. case CBN_KILLFOCUS:
  181. DBGFONTS(("CBN_KILLFOCUS from POINTSLIST\n"));
  182. if (!gbPointSizeError) {
  183. hWndFocus = GetFocus();
  184. if (hWndFocus != NULL && IsChild(hDlg, hWndFocus) &&
  185. hWndFocus != GetDlgItem(hDlg, IDCANCEL)) {
  186. PreviewUpdate(hDlg, FALSE);
  187. }
  188. }
  189. return TRUE;
  190. default:
  191. DBGFONTS(("unhandled CBN_%x from POINTSLIST\n",HIWORD(wParam)));
  192. break;
  193. }
  194. break;
  195. case IDD_PIXELSLIST:
  196. switch (HIWORD(wParam)) {
  197. case LBN_SELCHANGE:
  198. DBGFONTS(("LBN_SELCHANGE from PIXELSLIST\n"));
  199. PreviewUpdate(hDlg, TRUE);
  200. return TRUE;
  201. default:
  202. break;
  203. }
  204. break;
  205. default:
  206. break;
  207. }
  208. break;
  209. case WM_NOTIFY:
  210. switch (((LPNMHDR)lParam)->code) {
  211. case PSN_KILLACTIVE:
  212. //
  213. // If the TT combo box is visible, update selection
  214. //
  215. hWndList = GetDlgItem(hDlg, IDD_POINTSLIST);
  216. if (hWndList != NULL && IsWindowVisible(hWndList)) {
  217. if (!PreviewUpdate(hDlg, FALSE)) {
  218. SetDlgMsgResult(hDlg, PSN_KILLACTIVE, TRUE);
  219. return TRUE;
  220. }
  221. SetDlgMsgResult(hDlg, PSN_KILLACTIVE, FALSE);
  222. }
  223. FontIndex = CurrentFontIndex;
  224. if (FontInfo[FontIndex].SizeWant.Y == 0) {
  225. // Raster Font, so save actual size
  226. gpStateInfo->FontSize = FontInfo[FontIndex].Size;
  227. } else {
  228. // TT Font, so save desired size
  229. gpStateInfo->FontSize = FontInfo[FontIndex].SizeWant;
  230. }
  231. gpStateInfo->FontWeight = FontInfo[FontIndex].Weight;
  232. gpStateInfo->FontFamily = FontInfo[FontIndex].Family;
  233. wcscpy(gpStateInfo->FaceName, FontInfo[FontIndex].FaceName);
  234. return TRUE;
  235. case PSN_APPLY:
  236. /*
  237. * Write out the state values and exit.
  238. */
  239. EndDlgPage(hDlg);
  240. return TRUE;
  241. }
  242. break;
  243. /*
  244. * For WM_MEASUREITEM and WM_DRAWITEM, since there is only one
  245. * owner-draw item (combobox) in the entire dialog box, we don't have
  246. * to do a GetDlgItem to figure out who he is.
  247. */
  248. case WM_MEASUREITEM:
  249. /*
  250. * Load the TrueType logo bitmap
  251. */
  252. if (hbmTT == NULL) {
  253. hbmTT = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_TRUETYPE));
  254. GetObject(hbmTT, sizeof(BITMAP), &bmTT);
  255. }
  256. /*
  257. * Compute the height of face name listbox entries
  258. */
  259. if (dyFacelistItem == 0) {
  260. HFONT hFont;
  261. hDC = GetDC(hDlg);
  262. hFont = GetWindowFont(hDlg);
  263. if (hFont) {
  264. hFont = SelectObject(hDC, hFont);
  265. }
  266. GetTextMetrics(hDC, &tm);
  267. if (hFont) {
  268. SelectObject(hDC, hFont);
  269. }
  270. ReleaseDC(hDlg, hDC);
  271. dyFacelistItem = max(tm.tmHeight, bmTT.bmHeight);
  272. }
  273. ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = dyFacelistItem;
  274. return TRUE;
  275. case WM_DRAWITEM:
  276. DrawItemFontList((LPDRAWITEMSTRUCT)lParam);
  277. return TRUE;
  278. case WM_DESTROY:
  279. /*
  280. * Delete the TrueType logo bitmap
  281. */
  282. if (hbmTT != NULL) {
  283. DeleteObject(hbmTT);
  284. hbmTT = NULL;
  285. }
  286. return TRUE;
  287. default:
  288. break;
  289. }
  290. return CommonDlgProc(hDlg, wMsg, wParam, lParam);
  291. }
  292. int
  293. FontListCreate(
  294. HWND hDlg,
  295. LPTSTR ptszTTFace,
  296. BOOL bNewFaceList
  297. )
  298. /*++
  299. Initializes the font list by enumerating all fonts and picking the
  300. proper ones for our list.
  301. Returns
  302. FontIndex of selected font (LB_ERR if none)
  303. --*/
  304. {
  305. TCHAR tszText[80];
  306. LONG lListIndex;
  307. ULONG i;
  308. HWND hWndShow; // List or Combo box
  309. HWND hWndHide; // Combo or List box
  310. HWND hWndFaceCombo;
  311. HANDLE hStockFont;
  312. BOOL bLB;
  313. int LastShowX = 0;
  314. int LastShowY = 0;
  315. int nSameSize = 0;
  316. UINT CodePage = gpStateInfo->CodePage;
  317. BOOL fDbcsCharSet = IS_ANY_DBCS_CHARSET( CodePageToCharSet( CodePage ) );
  318. BOOL fFindTTFont = FALSE;
  319. LPTSTR ptszAltTTFace = NULL;
  320. LONG_PTR dwExStyle = 0L;
  321. ASSERT(OEMCP != 0); // must be initialized
  322. bLB = ((ptszTTFace == NULL) || (ptszTTFace[0] == TEXT('\0')));
  323. if (! bLB) {
  324. if (IsAvailableTTFont(ptszTTFace)) {
  325. ptszAltTTFace = GetAltFaceName(ptszTTFace);
  326. }
  327. else {
  328. ptszAltTTFace = ptszTTFace;
  329. }
  330. }
  331. DBGFONTS(("FontListCreate %lx, %s, %s new FaceList\n", hDlg,
  332. bLB ? "Raster" : "TrueType",
  333. bNewFaceList ? "Make" : "No" ));
  334. /*
  335. * This only enumerates face names if necessary, and
  336. * it only enumerates font sizes if necessary
  337. */
  338. EnumerateFonts(bLB ? EF_OEMFONT : EF_TTFONT);
  339. /* init the TTFaceNames */
  340. DBGFONTS((" Create %s fonts\n", bLB ? "Raster" : "TrueType"));
  341. if (bNewFaceList) {
  342. PFACENODE panFace;
  343. hWndFaceCombo = GetDlgItem(hDlg, IDD_FACENAME);
  344. SendMessage(hWndFaceCombo, LB_RESETCONTENT, 0, 0);
  345. lListIndex = (LONG)SendMessage(hWndFaceCombo, LB_ADDSTRING, 0, (LPARAM)tszRasterFonts);
  346. SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, TRUE);
  347. DBGFONTS(("Added \"%ls\", set Item Data %d = TRUE\n", tszRasterFonts, lListIndex));
  348. for (panFace = gpFaceNames; panFace; panFace = panFace->pNext) {
  349. if ((panFace->dwFlag & (EF_TTFONT|EF_NEW)) != (EF_TTFONT|EF_NEW)) {
  350. continue;
  351. }
  352. if (!fDbcsCharSet && (panFace->dwFlag & EF_DBCSFONT)) {
  353. continue;
  354. }
  355. if ((fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, CodePage)) ||
  356. (!fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, 0)))
  357. {
  358. if ( !bLB &&
  359. (_tcscmp(ptszTTFace, panFace->atch) == 0 ||
  360. _tcscmp(ptszAltTTFace, panFace->atch) == 0)
  361. ) {
  362. fFindTTFont = TRUE;
  363. }
  364. lListIndex = (LONG)SendMessage(hWndFaceCombo, LB_ADDSTRING, 0,
  365. (LPARAM)panFace->atch);
  366. SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, FALSE);
  367. DBGFONTS(("Added \"%ls\", set Item Data %d = FALSE\n",
  368. panFace->atch, lListIndex));
  369. }
  370. }
  371. if (!bLB && !fFindTTFont) {
  372. for (panFace = gpFaceNames; panFace; panFace = panFace->pNext) {
  373. if ((panFace->dwFlag & (EF_TTFONT|EF_NEW)) != (EF_TTFONT|EF_NEW)) {
  374. continue;
  375. }
  376. if (!fDbcsCharSet && (panFace->dwFlag & EF_DBCSFONT)) {
  377. continue;
  378. }
  379. if (( fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, CodePage)) ||
  380. (!fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, 0)))
  381. {
  382. if (_tcscmp(ptszTTFace, panFace->atch) != 0) {
  383. _tcscpy(ptszTTFace, panFace->atch);
  384. break;
  385. }
  386. }
  387. }
  388. }
  389. } // if(bNewFaceList)
  390. hWndShow = GetDlgItem(hDlg, IDD_BOLDFONT);
  391. #if defined(FE_SB)
  392. /*
  393. * For JAPAN, We uses "MS Gothic" TT font.
  394. * So, Bold of this font is not 1:2 width between SBCS:DBCS.
  395. */
  396. if (fDbcsCharSet && IsDisableBoldTTFont(ptszTTFace)) {
  397. EnableWindow(hWndShow, FALSE);
  398. gbBold = FALSE;
  399. CheckDlgButton(hDlg, IDD_BOLDFONT, FALSE);
  400. } else {
  401. #endif
  402. CheckDlgButton(hDlg, IDD_BOLDFONT, (bLB || !gbBold) ? FALSE : TRUE);
  403. EnableWindow(hWndShow, bLB ? FALSE : TRUE);
  404. #if defined(FE_SB)
  405. }
  406. #endif
  407. hWndHide = GetDlgItem(hDlg, bLB ? IDD_POINTSLIST : IDD_PIXELSLIST);
  408. ShowWindow(hWndHide, SW_HIDE);
  409. EnableWindow(hWndHide, FALSE);
  410. hWndShow = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
  411. // hStockFont = GetStockObject(SYSTEM_FIXED_FONT);
  412. // SendMessage(hWndShow, WM_SETFONT, (DWORD)hStockFont, FALSE);
  413. ShowWindow(hWndShow, SW_SHOW);
  414. EnableWindow(hWndShow, TRUE);
  415. #if defined(FE_SB)
  416. if (bNewFaceList) {
  417. lcbRESETCONTENT(hWndShow, bLB);
  418. }
  419. #endif
  420. dwExStyle = GetWindowLongPtr(hWndShow, GWL_EXSTYLE);
  421. if((dwExStyle & WS_EX_LAYOUTRTL) && !(dwExStyle & WS_EX_RTLREADING))
  422. {
  423. // if mirrored RTL Reading means LTR !!
  424. SetWindowLongPtr(hWndShow, GWL_EXSTYLE, dwExStyle | WS_EX_RTLREADING);
  425. }
  426. /* Initialize hWndShow list/combo box */
  427. for (i=0;i<NumberOfFonts;i++) {
  428. int ShowX, ShowY;
  429. if (!bLB == !TM_IS_TT_FONT(FontInfo[i].Family)) {
  430. DBGFONTS((" Font %x not right type\n", i));
  431. continue;
  432. }
  433. #if defined(FE_SB)
  434. if (fDbcsCharSet) {
  435. if (!IS_ANY_DBCS_CHARSET(FontInfo[i].tmCharSet)) {
  436. DBGFONTS((" Font %x not right type for DBCS character set\n", i));
  437. continue;
  438. }
  439. }
  440. else {
  441. if (IS_ANY_DBCS_CHARSET(FontInfo[i].tmCharSet)) {
  442. DBGFONTS((" Font %x not right type for SBCS character set\n", i));
  443. continue;
  444. }
  445. }
  446. #endif
  447. if (!bLB) {
  448. if (_tcscmp(FontInfo[i].FaceName, ptszTTFace) != 0 &&
  449. _tcscmp(FontInfo[i].FaceName, ptszAltTTFace) != 0
  450. ) {
  451. /*
  452. * A TrueType font, but not the one we're interested in,
  453. * so don't add it to the list of point sizes.
  454. */
  455. DBGFONTS((" Font %x is TT, but not %ls\n", i, ptszTTFace));
  456. continue;
  457. }
  458. if (gbBold != IS_BOLD(FontInfo[i].Weight)) {
  459. DBGFONTS((" Font %x has weight %d, but we wanted %sbold\n",
  460. i, FontInfo[i].Weight, gbBold ? "" : "not "));
  461. continue;
  462. }
  463. }
  464. if (FontInfo[i].SizeWant.X > 0) {
  465. ShowX = FontInfo[i].SizeWant.X;
  466. } else {
  467. ShowX = FontInfo[i].Size.X;
  468. }
  469. if (FontInfo[i].SizeWant.Y > 0) {
  470. ShowY = FontInfo[i].SizeWant.Y;
  471. } else {
  472. ShowY = FontInfo[i].Size.Y;
  473. }
  474. /*
  475. * Add the size description string to the end of the right list
  476. */
  477. if (TM_IS_TT_FONT(FontInfo[i].Family)) {
  478. // point size
  479. wsprintf(tszText, TEXT("%2d"), FontInfo[i].SizeWant.Y);
  480. } else {
  481. // pixel size
  482. if ((LastShowX == ShowX) && (LastShowY == ShowY)) {
  483. nSameSize++;
  484. } else {
  485. LastShowX = ShowX;
  486. LastShowY = ShowY;
  487. nSameSize = 0;
  488. }
  489. /*
  490. * The number nSameSize is appended to the string to distinguish
  491. * between Raster fonts of the same size. It is not intended to
  492. * be visible and exists off the edge of the list
  493. */
  494. if(((dwExStyle & WS_EX_RIGHT) && !(dwExStyle & WS_EX_LAYOUTRTL))
  495. || (!(dwExStyle & WS_EX_RIGHT) && (dwExStyle & WS_EX_LAYOUTRTL))) {
  496. // flip it so that the hidden part be at the far left
  497. wsprintf(tszText, TEXT("#%d %2d x %2d"),
  498. nSameSize, ShowX, ShowY);
  499. } else {
  500. wsprintf(tszText, TEXT("%2d x %2d #%d"),
  501. ShowX, ShowY, nSameSize);
  502. }
  503. }
  504. lListIndex = lcbFINDSTRINGEXACT(hWndShow, bLB, tszText);
  505. if (lListIndex == LB_ERR) {
  506. lListIndex = lcbADDSTRING(hWndShow, bLB, tszText);
  507. }
  508. DBGFONTS((" added %ls to %sSLIST(%lx) index %lx\n",
  509. tszText,
  510. bLB ? "PIXEL" : "POINT",
  511. hWndShow, lListIndex));
  512. lcbSETITEMDATA(hWndShow, bLB, (DWORD)lListIndex, i);
  513. }
  514. /*
  515. * Get the FontIndex from the currently selected item.
  516. * (i will be LB_ERR if no currently selected item).
  517. */
  518. lListIndex = lcbGETCURSEL(hWndShow, bLB);
  519. i = lcbGETITEMDATA(hWndShow, bLB, lListIndex);
  520. DBGFONTS(("FontListCreate returns 0x%x\n", i));
  521. return i;
  522. }
  523. /** DrawItemFontList
  524. *
  525. * Answer the WM_DRAWITEM message sent from the font list box or
  526. * facename list box.
  527. *
  528. * Entry:
  529. * lpdis -> DRAWITEMSTRUCT describing object to be drawn
  530. *
  531. * Returns:
  532. * None.
  533. *
  534. * The object is drawn.
  535. */
  536. VOID WINAPI
  537. DrawItemFontList(const LPDRAWITEMSTRUCT lpdis)
  538. {
  539. HDC hDC, hdcMem;
  540. DWORD rgbBack, rgbText, rgbFill;
  541. TCHAR tszFace[LF_FACESIZE];
  542. HBITMAP hOld;
  543. int dy;
  544. HBRUSH hbrFill;
  545. HWND hWndItem;
  546. BOOL bLB;
  547. int dxttbmp;
  548. if ((int)lpdis->itemID < 0)
  549. return;
  550. hDC = lpdis->hDC;
  551. if (lpdis->itemAction & ODA_FOCUS) {
  552. if (lpdis->itemState & ODS_SELECTED) {
  553. DrawFocusRect(hDC, &lpdis->rcItem);
  554. }
  555. } else {
  556. if (lpdis->itemState & ODS_SELECTED) {
  557. rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  558. rgbBack = SetBkColor(hDC, rgbFill = GetSysColor(COLOR_HIGHLIGHT));
  559. } else {
  560. rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  561. rgbBack = SetBkColor(hDC, rgbFill = GetSysColor(COLOR_WINDOW));
  562. }
  563. // draw selection background
  564. hbrFill = CreateSolidBrush(rgbFill);
  565. if (hbrFill) {
  566. FillRect(hDC, &lpdis->rcItem, hbrFill);
  567. DeleteObject(hbrFill);
  568. }
  569. // get the string
  570. if (IsWindow(hWndItem = lpdis->hwndItem) == FALSE) {
  571. return;
  572. }
  573. SendMessage(hWndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)tszFace);
  574. bLB = (BOOL)SendMessage(hWndItem, LB_GETITEMDATA, lpdis->itemID, 0L);
  575. dxttbmp = bLB ? 0 : bmTT.bmWidth;
  576. DBGFONTS(("DrawItemFontList must redraw \"%ls\" %s\n", tszFace,
  577. bLB ? "Raster" : "TrueType"));
  578. // draw the text
  579. TabbedTextOut(hDC, lpdis->rcItem.left + dxttbmp,
  580. lpdis->rcItem.top, tszFace,
  581. _tcslen(tszFace), 0, NULL, dxttbmp);
  582. // and the TT bitmap if needed
  583. if (!bLB) {
  584. hdcMem = CreateCompatibleDC(hDC);
  585. if (hdcMem) {
  586. hOld = SelectObject(hdcMem, hbmTT);
  587. dy = ((lpdis->rcItem.bottom - lpdis->rcItem.top) - bmTT.bmHeight) / 2;
  588. BitBlt(hDC, lpdis->rcItem.left, lpdis->rcItem.top + dy,
  589. dxttbmp, dyFacelistItem, hdcMem,
  590. 0, 0, SRCINVERT);
  591. if (hOld)
  592. SelectObject(hdcMem, hOld);
  593. DeleteDC(hdcMem);
  594. }
  595. }
  596. SetTextColor(hDC, rgbText);
  597. SetBkColor(hDC, rgbBack);
  598. if (lpdis->itemState & ODS_FOCUS) {
  599. DrawFocusRect(hDC, &lpdis->rcItem);
  600. }
  601. }
  602. }
  603. UINT
  604. GetPointSizeInRange(
  605. HWND hDlg,
  606. INT Min,
  607. INT Max)
  608. /*++
  609. Routine Description:
  610. Get a size from the Point Size ComboBox edit field
  611. Return Value:
  612. Point Size - of the edit field limited by Min/Max size
  613. 0 - if the field is empty or invalid
  614. --*/
  615. {
  616. TCHAR szBuf[90];
  617. int nTmp = 0;
  618. BOOL bOK;
  619. if (GetDlgItemText(hDlg, IDD_POINTSLIST, szBuf, NELEM(szBuf))) {
  620. nTmp = GetDlgItemInt(hDlg, IDD_POINTSLIST, &bOK, TRUE);
  621. if (bOK && nTmp >= Min && nTmp <= Max) {
  622. return nTmp;
  623. }
  624. }
  625. return 0;
  626. }
  627. /* ----- Preview routines ----- */
  628. LRESULT
  629. FontPreviewWndProc(
  630. HWND hWnd,
  631. UINT wMessage,
  632. WPARAM wParam,
  633. LPARAM lParam
  634. )
  635. /* FontPreviewWndProc
  636. * Handles the font preview window
  637. */
  638. {
  639. PAINTSTRUCT ps;
  640. RECT rect;
  641. HFONT hfontOld;
  642. HBRUSH hbrNew;
  643. HBRUSH hbrOld;
  644. COLORREF rgbText;
  645. COLORREF rgbBk;
  646. switch (wMessage) {
  647. case WM_ERASEBKGND:
  648. break;
  649. case WM_PAINT:
  650. BeginPaint(hWnd, &ps);
  651. /* Draw the font sample */
  652. if (GetWindowLong(hWnd, GWL_ID) == IDD_COLOR_POPUP_COLORS) {
  653. rgbText = GetNearestColor(ps.hdc, PopupTextColor(gpStateInfo));
  654. rgbBk = GetNearestColor(ps.hdc, PopupBkColor(gpStateInfo));
  655. } else {
  656. rgbText = GetNearestColor(ps.hdc, ScreenTextColor(gpStateInfo));
  657. rgbBk = GetNearestColor(ps.hdc, ScreenBkColor(gpStateInfo));
  658. }
  659. SetTextColor(ps.hdc, rgbText);
  660. SetBkColor(ps.hdc, rgbBk);
  661. GetClientRect(hWnd, &rect);
  662. hfontOld = SelectObject(ps.hdc, FontInfo[CurrentFontIndex].hFont);
  663. hbrNew = CreateSolidBrush(rgbBk);
  664. hbrOld = SelectObject(ps.hdc, hbrNew);
  665. PatBlt(ps.hdc, rect.left, rect.top,
  666. rect.right - rect.left, rect.bottom - rect.top,
  667. PATCOPY);
  668. InflateRect(&rect, -2, -2);
  669. DrawText(ps.hdc, g_szPreviewText, -1, &rect, 0);
  670. SelectObject(ps.hdc, hbrOld);
  671. DeleteObject(hbrNew);
  672. SelectObject(ps.hdc, hfontOld);
  673. EndPaint(hWnd, &ps);
  674. break;
  675. default:
  676. return DefWindowProc(hWnd, wMessage, wParam, lParam);
  677. }
  678. return 0L;
  679. }
  680. /*
  681. * Get the font index for a new font
  682. * If necessary, attempt to create the font.
  683. * Always return a valid FontIndex (even if not correct)
  684. * Family: Find/Create a font with of this Family
  685. * 0 - don't care
  686. * ptszFace: Find/Create a font with this face name.
  687. * NULL or TEXT("") - use DefaultFaceName
  688. * Size: Must match SizeWant or actual Size.
  689. */
  690. int
  691. FindCreateFont(
  692. DWORD Family,
  693. LPTSTR ptszFace,
  694. COORD Size,
  695. LONG Weight,
  696. UINT CodePage)
  697. {
  698. #define NOT_CREATED_NOR_FOUND -1
  699. #define CREATED_BUT_NOT_FOUND -2
  700. int i;
  701. int FontIndex = NOT_CREATED_NOR_FOUND;
  702. BOOL bFontOK;
  703. TCHAR AltFaceName[LF_FACESIZE];
  704. COORD AltFontSize;
  705. BYTE AltFontFamily;
  706. ULONG AltFontIndex = 0;
  707. LPTSTR ptszAltFace = NULL;
  708. BYTE CharSet = CodePageToCharSet(CodePage);
  709. ASSERT(OEMCP != 0);
  710. DBGFONTS(("FindCreateFont Family=%x %ls (%d,%d) %d %d %x\n",
  711. Family, ptszFace, Size.X, Size.Y, Weight, CodePage, CharSet));
  712. if (gfFESystem) {
  713. if (IS_ANY_DBCS_CHARSET(CharSet)) {
  714. if (ptszFace == NULL || *ptszFace == TEXT('\0')) {
  715. ptszFace = DefaultFaceName;
  716. }
  717. if (Size.Y == 0) {
  718. Size = DefaultFontSize;
  719. }
  720. }
  721. else {
  722. MakeAltRasterFont(CodePage, &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
  723. if (ptszFace == NULL || *ptszFace == TEXT('\0')) {
  724. ptszFace = AltFaceName;
  725. }
  726. if (Size.Y == 0) {
  727. Size.X = AltFontSize.X;
  728. Size.Y = AltFontSize.Y;
  729. }
  730. }
  731. }
  732. else {
  733. if (ptszFace == NULL || *ptszFace == TEXT('\0')) {
  734. ptszFace = DefaultFaceName;
  735. }
  736. if (Size.Y == 0) {
  737. Size = DefaultFontSize;
  738. }
  739. }
  740. if (IsAvailableTTFont(ptszFace)) {
  741. ptszAltFace = GetAltFaceName(ptszFace);
  742. }
  743. else {
  744. ptszAltFace = ptszFace;
  745. }
  746. /*
  747. * Try to find the exact font
  748. */
  749. TryFindExactFont:
  750. for (i=0; i < (int)NumberOfFonts; i++) {
  751. /*
  752. * If looking for a particular Family, skip non-matches
  753. */
  754. if ((Family != 0) &&
  755. ((BYTE)Family != FontInfo[i].Family)) {
  756. continue;
  757. }
  758. /*
  759. * Skip non-matching sizes
  760. */
  761. if ((!SIZE_EQUAL(FontInfo[i].SizeWant, Size) &&
  762. !SIZE_EQUAL(FontInfo[i].Size, Size))) {
  763. continue;
  764. }
  765. /*
  766. * Skip non-matching weights
  767. */
  768. if ((Weight != 0) && (Weight != FontInfo[i].Weight)) {
  769. continue;
  770. }
  771. #if defined(FE_SB)
  772. if (!TM_IS_TT_FONT(FontInfo[i].Family) &&
  773. FontInfo[i].tmCharSet != CharSet) {
  774. continue;
  775. }
  776. #endif
  777. /*
  778. * Size (and maybe Family) match.
  779. * If we don't care about the name, or if it matches, use this font.
  780. * Else if name doesn't match and it is a raster font, consider it.
  781. */
  782. if ((ptszFace == NULL) || (ptszFace[0] == TEXT('\0')) ||
  783. (_tcscmp(FontInfo[i].FaceName, ptszFace) == 0) ||
  784. (_tcscmp(FontInfo[i].FaceName, ptszAltFace) == 0)
  785. ) {
  786. FontIndex = i;
  787. goto FoundFont;
  788. } else if (!TM_IS_TT_FONT(FontInfo[i].Family)) {
  789. FontIndex = i;
  790. }
  791. }
  792. if (FontIndex == NOT_CREATED_NOR_FOUND) {
  793. /*
  794. * Didn't find the exact font, so try to create it
  795. */
  796. ULONG ulOldEnumFilter;
  797. ulOldEnumFilter = SetFontEnumeration(0);
  798. SetFontEnumeration(ulOldEnumFilter & ~FE_FILTER_TRUETYPE);
  799. if (Size.Y < 0) {
  800. Size.Y = -Size.Y;
  801. }
  802. bFontOK = DoFontEnum(NULL, ptszFace, &Size.Y, 1);
  803. SetFontEnumeration(ulOldEnumFilter);
  804. if (bFontOK) {
  805. DBGFONTS(("FindCreateFont created font!\n"));
  806. FontIndex = CREATED_BUT_NOT_FOUND;
  807. goto TryFindExactFont;
  808. } else {
  809. DBGFONTS(("FindCreateFont failed to create font!\n"));
  810. }
  811. } else if (FontIndex >= 0) {
  812. // a close Raster Font fit - only the name doesn't match.
  813. goto FoundFont;
  814. }
  815. /*
  816. * Failed to find exact match, even after enumeration, so now try
  817. * to find a font of same family and same size or bigger
  818. */
  819. for (i=0; i < (int)NumberOfFonts; i++) {
  820. #if defined(FE_SB)
  821. if (gfFESystem) {
  822. if ((Family != 0) &&
  823. ((BYTE)Family != FontInfo[i].Family)) {
  824. continue;
  825. }
  826. if (!TM_IS_TT_FONT(FontInfo[i].Family) &&
  827. FontInfo[i].tmCharSet != CharSet) {
  828. continue;
  829. }
  830. }
  831. else {
  832. #endif
  833. if ((BYTE)Family != FontInfo[i].Family) {
  834. continue;
  835. }
  836. #if defined(FE_SB)
  837. }
  838. #endif
  839. if (FontInfo[i].Size.Y >= Size.Y &&
  840. FontInfo[i].Size.X >= Size.X) {
  841. // Same family, size >= desired.
  842. FontIndex = i;
  843. break;
  844. }
  845. }
  846. if (FontIndex < 0) {
  847. DBGFONTS(("FindCreateFont defaults!\n"));
  848. #if defined(FE_SB)
  849. if (gfFESystem) {
  850. if (CodePage == OEMCP) {
  851. FontIndex = DefaultFontIndex;
  852. }
  853. else {
  854. FontIndex = AltFontIndex;
  855. }
  856. }
  857. else {
  858. #endif
  859. FontIndex = DefaultFontIndex;
  860. #if defined(FE_SB)
  861. }
  862. #endif
  863. }
  864. FoundFont:
  865. DBGFONTS(("FindCreateFont returns %x : %ls (%d,%d)\n", FontIndex,
  866. FontInfo[FontIndex].FaceName,
  867. FontInfo[FontIndex].Size.X, FontInfo[FontIndex].Size.Y));
  868. return FontIndex;
  869. #undef NOT_CREATED_NOR_FOUND
  870. #undef CREATED_BUT_NOT_FOUND
  871. }
  872. /*
  873. * SelectCurrentSize - Select the right line of the Size listbox/combobox.
  874. * bLB : Size controls is a listbox (TRUE for RasterFonts)
  875. * FontIndex : Index into FontInfo[] cache
  876. * If < 0 then choose a good font.
  877. * Returns
  878. * FontIndex : Index into FontInfo[] cache
  879. */
  880. int
  881. SelectCurrentSize(HWND hDlg, BOOL bLB, int FontIndex)
  882. {
  883. int iCB;
  884. HWND hWndList;
  885. DBGFONTS(("SelectCurrentSize %lx %s %x\n",
  886. hDlg, bLB ? "Raster" : "TrueType", FontIndex));
  887. hWndList = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
  888. iCB = lcbGETCOUNT(hWndList, bLB);
  889. DBGFONTS((" Count of items in %lx = %lx\n", hWndList, iCB));
  890. if (FontIndex >= 0) {
  891. /*
  892. * look for FontIndex
  893. */
  894. while (iCB > 0) {
  895. iCB--;
  896. if (lcbGETITEMDATA(hWndList, bLB, iCB) == FontIndex) {
  897. lcbSETCURSEL(hWndList, bLB, iCB);
  898. break;
  899. }
  900. }
  901. } else {
  902. /*
  903. * look for a reasonable default size: looking backwards, find
  904. * the first one same height or smaller.
  905. */
  906. DWORD Size;
  907. Size = GetWindowLong(hDlg, GWLP_USERDATA);
  908. #if defined(FE_SB)
  909. ASSERT(OEMCP != 0);
  910. if (gfFESystem && bLB
  911. && (FontInfo[CurrentFontIndex].tmCharSet != LOBYTE(LOWORD(Size)))
  912. )
  913. {
  914. TCHAR AltFaceName[LF_FACESIZE];
  915. COORD AltFontSize;
  916. BYTE AltFontFamily;
  917. ULONG AltFontIndex = 0;
  918. MakeAltRasterFont(gpStateInfo->CodePage, &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
  919. while (iCB > 0) {
  920. iCB--;
  921. if (lcbGETITEMDATA(hWndList, bLB, iCB) == (int)AltFontIndex) {
  922. lcbSETCURSEL(hWndList, bLB, iCB);
  923. break;
  924. }
  925. }
  926. }
  927. else
  928. #endif
  929. while (iCB > 0) {
  930. iCB--;
  931. FontIndex = lcbGETITEMDATA(hWndList, bLB, iCB);
  932. if (FontInfo[FontIndex].Size.Y <= HIWORD(Size)) {
  933. lcbSETCURSEL(hWndList, bLB, iCB);
  934. break;
  935. }
  936. }
  937. }
  938. DBGFONTS(("SelectCurrentSize returns %x\n", FontIndex));
  939. return FontIndex;
  940. }
  941. BOOL
  942. SelectCurrentFont(HWND hDlg, int FontIndex)
  943. {
  944. BOOL bLB;
  945. DBGFONTS(("SelectCurrentFont hDlg=%lx, FontIndex=%x\n", hDlg, FontIndex));
  946. bLB = !TM_IS_TT_FONT(FontInfo[FontIndex].Family);
  947. SendDlgItemMessage(hDlg, IDD_FACENAME, LB_SELECTSTRING, (WPARAM)-1,
  948. bLB ? (LPARAM)tszRasterFonts : (LPARAM)FontInfo[FontIndex].FaceName);
  949. SelectCurrentSize(hDlg, bLB, FontIndex);
  950. return bLB;
  951. }
  952. BOOL
  953. PreviewInit(
  954. HWND hDlg
  955. )
  956. /* PreviewInit
  957. * Prepares the preview code, sizing the window and the dialog to
  958. * make an attractive preview.
  959. * Returns TRUE if Raster Fonts, FALSE if TT Font
  960. */
  961. {
  962. int nFont;
  963. DBGFONTS(("PreviewInit hDlg=%lx\n", hDlg));
  964. /*
  965. * Set the current font
  966. */
  967. nFont = FindCreateFont(gpStateInfo->FontFamily,
  968. gpStateInfo->FaceName,
  969. gpStateInfo->FontSize,
  970. gpStateInfo->FontWeight,
  971. gpStateInfo->CodePage);
  972. DBGPRINT(("Changing Font Number from %d to %d\n",
  973. CurrentFontIndex, nFont));
  974. CurrentFontIndex = nFont;
  975. return SelectCurrentFont(hDlg, nFont);
  976. }
  977. BOOL
  978. PreviewUpdate(
  979. HWND hDlg,
  980. BOOL bLB
  981. )
  982. /*++
  983. Does the preview of the selected font.
  984. --*/
  985. {
  986. PFONT_INFO lpFont;
  987. int FontIndex;
  988. LONG lIndex;
  989. HWND hWnd;
  990. TCHAR tszText[60];
  991. TCHAR tszFace[LF_FACESIZE + CCH_SELECTEDFONT];
  992. HWND hWndList;
  993. DBGFONTS(("PreviewUpdate hDlg=%lx, %s\n", hDlg,
  994. bLB ? "Raster" : "TrueType"));
  995. hWndList = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
  996. /* When we select a font, we do the font preview by setting it into
  997. * the appropriate list box
  998. */
  999. lIndex = lcbGETCURSEL(hWndList, bLB);
  1000. DBGFONTS(("PreviewUpdate GETCURSEL gets %x\n", lIndex));
  1001. if ((lIndex < 0) && !bLB) {
  1002. COORD NewSize;
  1003. lIndex = (LONG)SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETCURSEL, 0, 0L);
  1004. SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETTEXT, lIndex, (LPARAM)tszFace);
  1005. NewSize.X = 0;
  1006. NewSize.Y = (SHORT)GetPointSizeInRange(hDlg, MIN_PIXEL_HEIGHT, MAX_PIXEL_HEIGHT);
  1007. if (NewSize.Y == 0) {
  1008. TCHAR tszBuf[60];
  1009. /*
  1010. * Use tszText, tszBuf to put up an error msg for bad point size
  1011. */
  1012. gbPointSizeError = TRUE;
  1013. LoadString(ghInstance, IDS_FONTSIZE, tszBuf, NELEM(tszBuf));
  1014. wsprintf(tszText, tszBuf, MIN_PIXEL_HEIGHT, MAX_PIXEL_HEIGHT);
  1015. GetWindowText(hDlg, tszBuf, NELEM(tszBuf));
  1016. MessageBoxEx(hDlg, tszText, tszBuf, MB_OK|MB_ICONINFORMATION, 0L);
  1017. SetFocus(hWndList);
  1018. gbPointSizeError = FALSE;
  1019. return FALSE;
  1020. }
  1021. FontIndex = FindCreateFont(FF_MODERN|TMPF_VECTOR|TMPF_TRUETYPE,
  1022. tszFace, NewSize, 0,
  1023. gpStateInfo->CodePage);
  1024. } else {
  1025. FontIndex = lcbGETITEMDATA(hWndList, bLB, lIndex);
  1026. }
  1027. if (FontIndex < 0) {
  1028. FontIndex = DefaultFontIndex;
  1029. }
  1030. /*
  1031. * If we've selected a new font, tell the property sheet we've changed
  1032. */
  1033. if (CurrentFontIndex != (ULONG)FontIndex) {
  1034. CurrentFontIndex = FontIndex;
  1035. }
  1036. lpFont = &FontInfo[FontIndex];
  1037. /* Display the new font */
  1038. _tcscpy(tszFace, tszSelectedFont);
  1039. _tcscat(tszFace, lpFont->FaceName);
  1040. SetDlgItemText(hDlg, IDD_GROUP, tszFace);
  1041. /* Put the font size in the static boxes */
  1042. wsprintf(tszText, TEXT("%u"), lpFont->Size.X);
  1043. hWnd = GetDlgItem(hDlg, IDD_FONTWIDTH);
  1044. SetWindowText(hWnd, tszText);
  1045. InvalidateRect(hWnd, NULL, TRUE);
  1046. wsprintf(tszText, TEXT("%u"), lpFont->Size.Y);
  1047. hWnd = GetDlgItem(hDlg, IDD_FONTHEIGHT);
  1048. SetWindowText(hWnd, tszText);
  1049. InvalidateRect(hWnd, NULL, TRUE);
  1050. /* Force the preview windows to repaint */
  1051. hWnd = GetDlgItem(hDlg, IDD_PREVIEWWINDOW);
  1052. SendMessage(hWnd, CM_PREVIEW_UPDATE, 0, 0);
  1053. hWnd = GetDlgItem(hDlg, IDD_FONTWINDOW);
  1054. InvalidateRect(hWnd, NULL, TRUE);
  1055. DBGFONTS(("Font %x, (%d,%d) %ls\n", FontIndex,
  1056. FontInfo[FontIndex].Size.X,
  1057. FontInfo[FontIndex].Size.Y,
  1058. FontInfo[FontIndex].FaceName));
  1059. return TRUE;
  1060. }