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.

1114 lines
33 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 "shellprv.h"
  12. #pragma hdrstop
  13. #include "lnkcon.h"
  14. HBITMAP g_hbmTT = NULL; // handle of TT logo bitmap
  15. BITMAP g_bmTT; // attributes of TT source bitmap
  16. int g_dyFacelistItem = 0;
  17. /* ----- Prototypes ----- */
  18. int FontListCreate(
  19. CONSOLEPROP_DATA * pcpd,
  20. HWND hDlg,
  21. LPTSTR ptszTTFace,
  22. BOOL bNewFaceList
  23. );
  24. BOOL ConsolePreviewUpdate(
  25. CONSOLEPROP_DATA * pcpd,
  26. HWND hDlg,
  27. BOOL bLB
  28. );
  29. int SelectCurrentSize(
  30. CONSOLEPROP_DATA * pcpd,
  31. HWND hDlg,
  32. BOOL bLB,
  33. int FontIndex);
  34. BOOL ConsolePreviewInit(
  35. CONSOLEPROP_DATA * pcpd,
  36. HWND hDlg,
  37. BOOL* pfRaster);
  38. VOID ConsoleDrawItemFontList(
  39. CONSOLEPROP_DATA * pcpd,
  40. const LPDRAWITEMSTRUCT lpdis);
  41. /* ----- Globals ----- */
  42. const TCHAR g_szPreviewText[] = \
  43. TEXT("C:\\WINDOWS> dir \n") \
  44. TEXT("SYSTEM <DIR> 10-01-99 5:00a\n") \
  45. TEXT("SYSTEM32 <DIR> 10-01-99 5:00a\n") \
  46. TEXT("README TXT 26926 10-01-99 5:00a\n") \
  47. TEXT("WINDOWS BMP 46080 10-01-99 5:00a\n") \
  48. TEXT("NOTEPAD EXE 337232 10-01-99 5:00a\n") \
  49. TEXT("CLOCK AVI 39594 10-01-99 5:00p\n") \
  50. TEXT("WIN INI 7005 10-01-99 5:00a\n");
  51. // Context-sensitive help ids
  52. const static DWORD rgdwHelpFont[] = {
  53. IDC_CNSL_PREVIEWLABEL, IDH_DOS_FONT_WINDOW_PREVIEW,
  54. IDC_CNSL_PREVIEWWINDOW, IDH_DOS_FONT_WINDOW_PREVIEW,
  55. IDC_CNSL_STATIC, IDH_CONSOLE_FONT_FONT,
  56. IDC_CNSL_FACENAME, IDH_CONSOLE_FONT_FONT,
  57. IDC_CNSL_FONTSIZE, IDH_DOS_FONT_SIZE,
  58. IDC_CNSL_PIXELSLIST, IDH_DOS_FONT_SIZE,
  59. IDC_CNSL_POINTSLIST, IDH_DOS_FONT_SIZE,
  60. IDC_CNSL_BOLDFONT, IDH_CONSOLE_FONT_BOLD_FONTS,
  61. IDC_CNSL_GROUP, IDH_DOS_FONT_FONT_PREVIEW,
  62. IDC_CNSL_STATIC2, IDH_DOS_FONT_FONT_PREVIEW,
  63. IDC_CNSL_STATIC3, IDH_DOS_FONT_FONT_PREVIEW,
  64. IDC_CNSL_STATIC4, IDH_DOS_FONT_FONT_PREVIEW,
  65. IDC_CNSL_FONTWIDTH, IDH_DOS_FONT_FONT_PREVIEW,
  66. IDC_CNSL_FONTHEIGHT, IDH_DOS_FONT_FONT_PREVIEW,
  67. IDC_CNSL_FONTWINDOW, IDH_DOS_FONT_FONT_PREVIEW,
  68. 0, 0
  69. };
  70. // selelct font based on the current code page
  71. BOOL
  72. SelectCurrentFont(
  73. CONSOLEPROP_DATA * pcpd,
  74. HWND hDlg,
  75. int FontIndex
  76. );
  77. // Globals strings loaded from resource
  78. TCHAR tszSelectedFont[CCH_SELECTEDFONT+1];
  79. TCHAR tszRasterFonts[CCH_RASTERFONTS+1];
  80. BOOL
  81. CALLBACK
  82. _FontDlgProc(
  83. HWND hDlg,
  84. UINT wMsg,
  85. WPARAM wParam,
  86. LPARAM lParam
  87. )
  88. /*++
  89. Dialog proc for the font selection dialog box.
  90. Returns the near offset into the far table of LOGFONT structures.
  91. --*/
  92. {
  93. HWND hWndFocus;
  94. HWND hWndList;
  95. int FontIndex;
  96. BOOL bLB;
  97. TEXTMETRIC tm;
  98. HDC hDC;
  99. LINKDATA * pld = (LINKDATA *)GetWindowLongPtr(hDlg, DWLP_USER);
  100. switch (wMsg) {
  101. case WM_INITDIALOG:
  102. pld = (LINKDATA *)((PROPSHEETPAGE *)lParam)->lParam;
  103. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pld);
  104. pld->cpd.bFontInit = FALSE;
  105. SendDlgItemMessage(hDlg, IDC_CNSL_PREVIEWWINDOW, CM_PREVIEW_INIT, 0, (LPARAM)&pld->cpd );
  106. SendDlgItemMessage(hDlg, IDC_CNSL_PREVIEWWINDOW, CM_PREVIEW_UPDATE, 0, 0 );
  107. /*
  108. * Load the font description strings
  109. */
  110. LoadString(HINST_THISDLL, IDS_CNSL_RASTERFONT,
  111. tszRasterFonts, NELEM(tszRasterFonts));
  112. ASSERT(lstrlen(tszRasterFonts) < CCH_RASTERFONTS);
  113. LoadString(g_hinst, IDS_CNSL_SELECTEDFONT,
  114. tszSelectedFont, NELEM(tszSelectedFont));
  115. ASSERT(lstrlen(tszSelectedFont) < CCH_SELECTEDFONT);
  116. /* Save current font size as dialog window's user data */
  117. if (IsFarEastCP(pld->cpd.uOEMCP))
  118. {
  119. // Assigning different value when we run on FarEast codepage
  120. pld->cpd.FontLong =
  121. MAKELONG(pld->cpd.FontInfo[pld->cpd.CurrentFontIndex].tmCharSet,
  122. pld->cpd.FontInfo[pld->cpd.CurrentFontIndex].Size.Y);
  123. }
  124. else
  125. {
  126. pld->cpd.FontLong =
  127. MAKELONG(pld->cpd.FontInfo[pld->cpd.CurrentFontIndex].Size.X,
  128. pld->cpd.FontInfo[pld->cpd.CurrentFontIndex].Size.Y);
  129. }
  130. /* Create the list of suitable fonts */
  131. pld->cpd.gbEnumerateFaces = TRUE;
  132. bLB = !TM_IS_TT_FONT(pld->cpd.lpConsole->uFontFamily);
  133. pld->cpd.gbBold = IS_BOLD(pld->cpd.lpConsole->uFontWeight);
  134. CheckDlgButton(hDlg, IDC_CNSL_BOLDFONT, pld->cpd.gbBold);
  135. FontListCreate(&pld->cpd, hDlg, bLB ? NULL : pld->cpd.lpFaceName, TRUE);
  136. /* Initialize the preview window - selects current face & size too */
  137. if (ConsolePreviewInit(&pld->cpd, hDlg, &bLB))
  138. {
  139. ConsolePreviewUpdate(&pld->cpd, hDlg, bLB);
  140. /* Make sure the list box has the focus */
  141. hWndList = GetDlgItem(hDlg, bLB ? IDC_CNSL_PIXELSLIST : IDC_CNSL_POINTSLIST);
  142. SetFocus(hWndList);
  143. pld->cpd.bFontInit = TRUE;
  144. }
  145. else
  146. {
  147. EndDialog(hDlg, IDCANCEL);
  148. }
  149. break;
  150. case WM_FONTCHANGE:
  151. pld->cpd.gbEnumerateFaces = TRUE;
  152. bLB = !TM_IS_TT_FONT(pld->cpd.lpConsole->uFontFamily);
  153. FontListCreate(&pld->cpd, hDlg, NULL, TRUE);
  154. FontIndex = FindCreateFont(&pld->cpd,
  155. pld->cpd.lpConsole->uFontFamily,
  156. pld->cpd.lpFaceName,
  157. pld->cpd.lpConsole->dwFontSize,
  158. pld->cpd.lpConsole->uFontWeight);
  159. SelectCurrentSize(&pld->cpd, hDlg, bLB, FontIndex);
  160. return TRUE;
  161. case WM_PAINT:
  162. // fChangeCodePage can be TRUE only on FE codepage
  163. if (pld->cpd.fChangeCodePage)
  164. {
  165. pld->cpd.fChangeCodePage = FALSE;
  166. /* Create the list of suitable fonts */
  167. bLB = !TM_IS_TT_FONT(pld->cpd.lpConsole->uFontFamily);
  168. FontIndex = FontListCreate(&pld->cpd, hDlg, !bLB ? NULL : pld->cpd.lpFaceName, TRUE);
  169. FontIndex = FontListCreate(&pld->cpd, hDlg, bLB ? NULL : pld->cpd.lpFaceName, TRUE);
  170. pld->cpd.CurrentFontIndex = FontIndex;
  171. FontIndex = SelectCurrentSize(&pld->cpd, hDlg, bLB, FontIndex);
  172. SelectCurrentFont(&pld->cpd, hDlg, FontIndex);
  173. ConsolePreviewUpdate(&pld->cpd, hDlg, bLB);
  174. }
  175. break;
  176. case WM_HELP: /* F1 or title-bar help button */
  177. WinHelp( (HWND) ((LPHELPINFO) lParam)->hItemHandle,
  178. NULL,
  179. HELP_WM_HELP,
  180. (ULONG_PTR) (LPVOID) &rgdwHelpFont[0]
  181. );
  182. break;
  183. case WM_CONTEXTMENU: /* right mouse click */
  184. WinHelp( (HWND) wParam,
  185. NULL,
  186. HELP_CONTEXTMENU,
  187. (ULONG_PTR) (LPTSTR) &rgdwHelpFont[0]
  188. );
  189. break;
  190. case WM_COMMAND:
  191. switch (LOWORD(wParam))
  192. {
  193. case IDC_CNSL_BOLDFONT:
  194. pld->cpd.gbBold = IsDlgButtonChecked(hDlg, IDC_CNSL_BOLDFONT);
  195. pld->cpd.bConDirty = TRUE;
  196. goto RedoFontListAndPreview;
  197. case IDC_CNSL_FACENAME:
  198. switch (HIWORD(wParam))
  199. {
  200. case LBN_SELCHANGE:
  201. RedoFontListAndPreview:
  202. if (pld->cpd.bFontInit)
  203. PropSheet_Changed( GetParent( hDlg ), hDlg );
  204. {
  205. TCHAR atchNewFace[LF_FACESIZE];
  206. LRESULT l;
  207. l = SendDlgItemMessage(hDlg, IDC_CNSL_FACENAME, LB_GETCURSEL, 0, 0L);
  208. bLB = (BOOL) SendDlgItemMessage(hDlg, IDC_CNSL_FACENAME, LB_GETITEMDATA, l, 0L);
  209. if (!bLB) {
  210. SendDlgItemMessage(hDlg, IDC_CNSL_FACENAME, LB_GETTEXT, l, (LPARAM)atchNewFace);
  211. }
  212. FontIndex = FontListCreate(&pld->cpd, hDlg, bLB ? NULL : atchNewFace, FALSE);
  213. FontIndex = SelectCurrentSize(&pld->cpd, hDlg, bLB, FontIndex);
  214. ConsolePreviewUpdate(&pld->cpd, hDlg, bLB);
  215. pld->cpd.bConDirty = TRUE;
  216. return TRUE;
  217. }
  218. }
  219. break;
  220. case IDC_CNSL_POINTSLIST:
  221. switch (HIWORD(wParam)) {
  222. case CBN_SELCHANGE:
  223. if (pld->cpd.bFontInit)
  224. PropSheet_Changed( GetParent( hDlg ), hDlg );
  225. ConsolePreviewUpdate(&pld->cpd, hDlg, FALSE);
  226. pld->cpd.bConDirty = TRUE;
  227. return TRUE;
  228. case CBN_KILLFOCUS:
  229. if (!pld->cpd.gbPointSizeError) {
  230. hWndFocus = GetFocus();
  231. if (hWndFocus != NULL && IsChild(hDlg, hWndFocus) &&
  232. hWndFocus != GetDlgItem(hDlg, IDCANCEL)) {
  233. ConsolePreviewUpdate(&pld->cpd, hDlg, FALSE);
  234. }
  235. }
  236. return TRUE;
  237. default:
  238. break;
  239. }
  240. break;
  241. case IDC_CNSL_PIXELSLIST:
  242. switch (HIWORD(wParam)) {
  243. case LBN_SELCHANGE:
  244. if (pld->cpd.bFontInit)
  245. PropSheet_Changed( GetParent( hDlg ), hDlg );
  246. ConsolePreviewUpdate(&pld->cpd, hDlg, TRUE);
  247. pld->cpd.bConDirty = TRUE;
  248. return TRUE;
  249. default:
  250. break;
  251. }
  252. break;
  253. default:
  254. break;
  255. }
  256. break;
  257. case WM_NOTIFY:
  258. switch (((LPNMHDR)lParam)->code)
  259. {
  260. case PSN_APPLY:
  261. // Write out the state values and exit.
  262. if (FAILED(SaveLink(pld)))
  263. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  264. break;
  265. case PSN_KILLACTIVE:
  266. //
  267. // If the TT combo box is visible, update selection
  268. //
  269. hWndList = GetDlgItem(hDlg, IDC_CNSL_POINTSLIST);
  270. if (hWndList != NULL && IsWindowVisible(hWndList)) {
  271. if (!ConsolePreviewUpdate(&pld->cpd, hDlg, FALSE)) {
  272. SetDlgMsgResult(hDlg, PSN_KILLACTIVE, TRUE);
  273. return TRUE;
  274. }
  275. SetDlgMsgResult(hDlg, PSN_KILLACTIVE, FALSE);
  276. }
  277. FontIndex = pld->cpd.CurrentFontIndex;
  278. if (pld->cpd.FontInfo[FontIndex].SizeWant.Y == 0) {
  279. // Raster Font, so save actual size
  280. pld->cpd.lpConsole->dwFontSize = pld->cpd.FontInfo[FontIndex].Size;
  281. } else {
  282. // TT Font, so save desired size
  283. pld->cpd.lpConsole->dwFontSize = pld->cpd.FontInfo[FontIndex].SizeWant;
  284. }
  285. pld->cpd.lpConsole->uFontWeight = pld->cpd.FontInfo[FontIndex].Weight;
  286. pld->cpd.lpConsole->uFontFamily = pld->cpd.FontInfo[FontIndex].Family;
  287. lstrcpy(pld->cpd.lpFaceName, pld->cpd.FontInfo[FontIndex].FaceName);
  288. return TRUE;
  289. }
  290. break;
  291. /*
  292. * For WM_MEASUREITEM and WM_DRAWITEM, since there is only one
  293. * owner-draw item (combobox) in the entire dialog box, we don't have
  294. * to do a GetDlgItem to figure out who he is.
  295. */
  296. case WM_MEASUREITEM:
  297. /*
  298. * Load the TrueType logo bitmap
  299. */
  300. if (g_hbmTT == NULL)
  301. {
  302. g_hbmTT = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_TRUETYPE));
  303. if (g_hbmTT)
  304. {
  305. if (!GetObject(g_hbmTT, sizeof(BITMAP), &g_bmTT))
  306. {
  307. DeleteObject(g_hbmTT);
  308. g_hbmTT = NULL;
  309. }
  310. }
  311. }
  312. /*
  313. * Compute the height of face name listbox entries
  314. */
  315. if (g_dyFacelistItem == 0) {
  316. HFONT hFont;
  317. hDC = GetDC(hDlg);
  318. if (hDC)
  319. {
  320. hFont = GetWindowFont(hDlg);
  321. if (hFont) {
  322. hFont = SelectObject(hDC, hFont);
  323. }
  324. GetTextMetrics(hDC, &tm);
  325. if (hFont) {
  326. SelectObject(hDC, hFont);
  327. }
  328. ReleaseDC(hDlg, hDC);
  329. g_dyFacelistItem = max(tm.tmHeight, g_bmTT.bmHeight);
  330. }
  331. else
  332. {
  333. // We just failed GetDC: Low memory - we might look corrupted here, but its
  334. // better than using a null DC or bad textmetrics structure. Prefix 98166
  335. g_dyFacelistItem = g_bmTT.bmHeight;
  336. }
  337. }
  338. ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = g_dyFacelistItem;
  339. return TRUE;
  340. case WM_DRAWITEM:
  341. ConsoleDrawItemFontList(&pld->cpd, (LPDRAWITEMSTRUCT)lParam);
  342. return TRUE;
  343. case WM_DESTROY:
  344. /*
  345. * Delete the TrueType logo bitmap
  346. */
  347. if (g_hbmTT != NULL) {
  348. DeleteObject(g_hbmTT);
  349. g_hbmTT = NULL;
  350. }
  351. return TRUE;
  352. default:
  353. break;
  354. }
  355. return FALSE;
  356. }
  357. int
  358. FontListCreate(
  359. CONSOLEPROP_DATA * pcpd,
  360. HWND hDlg,
  361. LPTSTR ptszTTFace,
  362. BOOL bNewFaceList
  363. )
  364. /*++
  365. Initializes the font list by enumerating all fonts and picking the
  366. proper ones for our list.
  367. Returns
  368. FontIndex of selected font (LB_ERR if none)
  369. --*/
  370. {
  371. TCHAR tszText[80];
  372. LONG lListIndex;
  373. ULONG i;
  374. HWND hWndShow; // List or Combo box
  375. HWND hWndHide; // Combo or List box
  376. HWND hWndFaceCombo;
  377. BOOL bLB;
  378. int LastShowX = 0;
  379. int LastShowY = 0;
  380. int nSameSize = 0;
  381. UINT CodePage = pcpd->lpFEConsole->uCodePage;
  382. BOOL fDbcsCharSet = IS_ANY_DBCS_CHARSET( CodePageToCharSet( CodePage ) );
  383. BOOL fFESystem = IsFarEastCP(pcpd->uOEMCP);
  384. BOOL fFindTTFont = FALSE;
  385. LPTSTR ptszAltTTFace = NULL;
  386. DWORD dwExStyle = 0L;
  387. bLB = ((ptszTTFace == NULL) || (ptszTTFace[0] == TEXT('\0')));
  388. if (! bLB) {
  389. if (IsAvailableTTFont(pcpd, ptszTTFace)) {
  390. ptszAltTTFace = GetAltFaceName(pcpd, ptszTTFace);
  391. }
  392. else {
  393. ptszAltTTFace = ptszTTFace;
  394. }
  395. }
  396. /*
  397. * This only enumerates face names if necessary, and
  398. * it only enumerates font sizes if necessary
  399. */
  400. if (STATUS_SUCCESS != EnumerateFonts(pcpd, bLB ? EF_OEMFONT : EF_TTFONT))
  401. {
  402. return LB_ERR;
  403. }
  404. /* init the TTFaceNames */
  405. if (bNewFaceList) {
  406. FACENODE *panFace;
  407. hWndFaceCombo = GetDlgItem(hDlg, IDC_CNSL_FACENAME);
  408. SendMessage(hWndFaceCombo, LB_RESETCONTENT, 0, 0);
  409. lListIndex = (LONG) SendMessage(hWndFaceCombo, LB_ADDSTRING, 0, (LPARAM)tszRasterFonts);
  410. SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, TRUE);
  411. for (panFace = pcpd->gpFaceNames; panFace; panFace = panFace->pNext) {
  412. if ((panFace->dwFlag & (EF_TTFONT|EF_NEW)) != (EF_TTFONT|EF_NEW)) {
  413. continue;
  414. }
  415. if (!fDbcsCharSet && (panFace->dwFlag & EF_DBCSFONT)) {
  416. continue;
  417. }
  418. if ( ( fDbcsCharSet && IsAvailableTTFontCP(pcpd, panFace->atch, CodePage)) ||
  419. ( !fDbcsCharSet && IsAvailableTTFontCP(pcpd, panFace->atch, 0)))
  420. {
  421. if ( !bLB &&
  422. (lstrcmp(ptszTTFace, panFace->atch) == 0 ||
  423. lstrcmp(ptszAltTTFace, panFace->atch) == 0)
  424. )
  425. fFindTTFont = TRUE;
  426. lListIndex = (LONG) SendMessage(hWndFaceCombo, LB_ADDSTRING, 0,
  427. (LPARAM)panFace->atch);
  428. SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, FALSE);
  429. }
  430. }
  431. if (! bLB && ! fFindTTFont)
  432. {
  433. for (panFace = pcpd->gpFaceNames; panFace; panFace = panFace->pNext) {
  434. if ((panFace->dwFlag & (EF_TTFONT|EF_NEW)) != (EF_TTFONT|EF_NEW)) {
  435. continue;
  436. }
  437. if ( !fDbcsCharSet && (panFace->dwFlag & EF_DBCSFONT)) {
  438. continue;
  439. }
  440. if ( ( fDbcsCharSet && IsAvailableTTFontCP(pcpd, panFace->atch, CodePage)) ||
  441. (! fDbcsCharSet && IsAvailableTTFontCP(pcpd, panFace->atch, 0))
  442. )
  443. {
  444. if (lstrcmp(ptszTTFace, panFace->atch) != 0)
  445. {
  446. lstrcpy(ptszTTFace, panFace->atch);
  447. break;
  448. }
  449. }
  450. }
  451. }
  452. } // bNewFaceList == TRUE
  453. hWndShow = GetDlgItem(hDlg, IDC_CNSL_BOLDFONT);
  454. // Disable bold font if that will be GDI simulated
  455. if ( fDbcsCharSet && IsDisableBoldTTFont(pcpd, ptszTTFace) )
  456. {
  457. EnableWindow(hWndShow, FALSE);
  458. pcpd->gbBold = FALSE;
  459. CheckDlgButton(hDlg, IDC_CNSL_BOLDFONT, FALSE);
  460. }
  461. else
  462. {
  463. CheckDlgButton(hDlg, IDC_CNSL_BOLDFONT, (bLB || !pcpd->gbBold) ? FALSE : TRUE);
  464. EnableWindow(hWndShow, bLB ? FALSE : TRUE);
  465. }
  466. hWndHide = GetDlgItem(hDlg, bLB ? IDC_CNSL_POINTSLIST : IDC_CNSL_PIXELSLIST);
  467. ShowWindow(hWndHide, SW_HIDE);
  468. EnableWindow(hWndHide, FALSE);
  469. hWndShow = GetDlgItem(hDlg, bLB ? IDC_CNSL_PIXELSLIST : IDC_CNSL_POINTSLIST);
  470. // hStockFont = GetStockObject(SYSTEM_FIXED_FONT);
  471. // SendMessage(hWndShow, WM_SETFONT, (DWORD)hStockFont, FALSE);
  472. ShowWindow(hWndShow, SW_SHOW);
  473. EnableWindow(hWndShow, TRUE);
  474. if (bNewFaceList)
  475. {
  476. lcbRESETCONTENT(hWndShow, bLB);
  477. }
  478. dwExStyle = GetWindowLong(hWndShow, GWL_EXSTYLE);
  479. if(dwExStyle & RTL_MIRRORED_WINDOW)
  480. {
  481. // if mirrored RTL Reading means LTR !!
  482. SetWindowBits(hWndShow, GWL_EXSTYLE, WS_EX_RTLREADING, WS_EX_RTLREADING);
  483. }
  484. /* Initialize hWndShow list/combo box */
  485. for (i=0;i<pcpd->NumberOfFonts;i++) {
  486. int ShowX, ShowY;
  487. if (!bLB == !TM_IS_TT_FONT(pcpd->FontInfo[i].Family)) {
  488. continue;
  489. }
  490. if (fDbcsCharSet) {
  491. if (! IS_ANY_DBCS_CHARSET(pcpd->FontInfo[i].tmCharSet)) {
  492. continue;
  493. }
  494. }
  495. else {
  496. if (IS_ANY_DBCS_CHARSET(pcpd->FontInfo[i].tmCharSet)) {
  497. continue;
  498. }
  499. }
  500. if (!bLB) {
  501. if (lstrcmp(pcpd->FontInfo[i].FaceName, ptszTTFace) != 0 &&
  502. lstrcmp(pcpd->FontInfo[i].FaceName, ptszAltTTFace) != 0) {
  503. /*
  504. * A TrueType font, but not the one we're interested in,
  505. * so don't add it to the list of point sizes.
  506. */
  507. continue;
  508. }
  509. if (pcpd->gbBold != IS_BOLD(pcpd->FontInfo[i].Weight)) {
  510. continue;
  511. }
  512. }
  513. if (pcpd->FontInfo[i].SizeWant.X > 0) {
  514. ShowX = pcpd->FontInfo[i].SizeWant.X;
  515. } else {
  516. ShowX = pcpd->FontInfo[i].Size.X;
  517. }
  518. if (pcpd->FontInfo[i].SizeWant.Y > 0) {
  519. ShowY = pcpd->FontInfo[i].SizeWant.Y;
  520. } else {
  521. ShowY = pcpd->FontInfo[i].Size.Y;
  522. }
  523. /*
  524. * Add the size description string to the end of the right list
  525. */
  526. if (TM_IS_TT_FONT(pcpd->FontInfo[i].Family)) {
  527. // point size
  528. wsprintf(tszText, TEXT("%2d"), pcpd->FontInfo[i].SizeWant.Y);
  529. } else {
  530. // pixel size
  531. if ((LastShowX == ShowX) && (LastShowY == ShowY)) {
  532. nSameSize++;
  533. } else {
  534. LastShowX = ShowX;
  535. LastShowY = ShowY;
  536. nSameSize = 0;
  537. }
  538. /*
  539. * The number nSameSize is appended to the string to distinguish
  540. * between Raster fonts of the same size. It is not intended to
  541. * be visible and exists off the edge of the list
  542. */
  543. if(((dwExStyle & WS_EX_RIGHT) && !(dwExStyle & RTL_MIRRORED_WINDOW))
  544. || (!(dwExStyle & WS_EX_RIGHT) && (dwExStyle & RTL_MIRRORED_WINDOW))) {
  545. // flip it so that the hidden part be at the far left
  546. wsprintf(tszText, TEXT("#%d %2d x %2d"),
  547. nSameSize, ShowX, ShowY);
  548. } else {
  549. wsprintf(tszText, TEXT("%2d x %2d #%d"),
  550. ShowX, ShowY, nSameSize);
  551. }
  552. }
  553. lListIndex = (LONG) lcbFINDSTRINGEXACT(hWndShow, bLB, tszText);
  554. if (lListIndex == LB_ERR) {
  555. lListIndex = (LONG) lcbADDSTRING(hWndShow, bLB, tszText);
  556. }
  557. lcbSETITEMDATA(hWndShow, bLB, (DWORD)lListIndex, i);
  558. }
  559. /*
  560. * Get the FontIndex from the currently selected item.
  561. * (i will be LB_ERR if no currently selected item).
  562. */
  563. lListIndex = (LONG) lcbGETCURSEL(hWndShow, bLB);
  564. i = (int) lcbGETITEMDATA(hWndShow, bLB, lListIndex);
  565. return i;
  566. }
  567. /** ConsoleDrawItemFontList
  568. *
  569. * Answer the WM_DRAWITEM message sent from the font list box or
  570. * facename list box.
  571. *
  572. * Entry:
  573. * lpdis -> DRAWITEMSTRUCT describing object to be drawn
  574. *
  575. * Returns:
  576. * None.
  577. *
  578. * The object is drawn.
  579. */
  580. VOID WINAPI
  581. ConsoleDrawItemFontList(CONSOLEPROP_DATA * pcpd, const LPDRAWITEMSTRUCT lpdis)
  582. {
  583. HDC hDC, hdcMem;
  584. DWORD rgbBack, rgbText, rgbFill;
  585. TCHAR tszFace[LF_FACESIZE];
  586. HBITMAP hOld;
  587. int dy;
  588. HBRUSH hbrFill;
  589. HWND hWndItem;
  590. BOOL bLB;
  591. int dxttbmp;
  592. if ((int)lpdis->itemID < 0)
  593. return;
  594. hDC = lpdis->hDC;
  595. if (lpdis->itemAction & ODA_FOCUS) {
  596. if (lpdis->itemState & ODS_SELECTED) {
  597. DrawFocusRect(hDC, &lpdis->rcItem);
  598. }
  599. } else {
  600. if (lpdis->itemState & ODS_SELECTED) {
  601. rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  602. rgbBack = SetBkColor(hDC, rgbFill = GetSysColor(COLOR_HIGHLIGHT));
  603. } else {
  604. rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  605. rgbBack = SetBkColor(hDC, rgbFill = GetSysColor(COLOR_WINDOW));
  606. }
  607. // draw selection background
  608. hbrFill = CreateSolidBrush(rgbFill);
  609. if (hbrFill) {
  610. FillRect(hDC, &lpdis->rcItem, hbrFill);
  611. DeleteObject(hbrFill);
  612. }
  613. // get the string
  614. if (IsWindow(hWndItem = lpdis->hwndItem) == FALSE) {
  615. return;
  616. }
  617. SendMessage(hWndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)tszFace);
  618. bLB = (BOOL) SendMessage(hWndItem, LB_GETITEMDATA, lpdis->itemID, 0L);
  619. dxttbmp = bLB ? 0 : g_bmTT.bmWidth;
  620. // draw the text
  621. TabbedTextOut(hDC, lpdis->rcItem.left + dxttbmp,
  622. lpdis->rcItem.top, tszFace,
  623. lstrlen(tszFace), 0, NULL, dxttbmp);
  624. // and the TT bitmap if needed
  625. if (!bLB) {
  626. hdcMem = CreateCompatibleDC(hDC);
  627. if (hdcMem) {
  628. hOld = SelectObject(hdcMem, g_hbmTT);
  629. dy = ((lpdis->rcItem.bottom - lpdis->rcItem.top) - g_bmTT.bmHeight) / 2;
  630. BitBlt(hDC, lpdis->rcItem.left, lpdis->rcItem.top + dy,
  631. dxttbmp, g_dyFacelistItem, hdcMem,
  632. 0, 0, SRCINVERT);
  633. if (hOld)
  634. SelectObject(hdcMem, hOld);
  635. DeleteDC(hdcMem);
  636. }
  637. }
  638. SetTextColor(hDC, rgbText);
  639. SetBkColor(hDC, rgbBack);
  640. if (lpdis->itemState & ODS_FOCUS) {
  641. DrawFocusRect(hDC, &lpdis->rcItem);
  642. }
  643. }
  644. }
  645. UINT
  646. GetPointSizeInRange(
  647. HWND hDlg,
  648. INT Min,
  649. INT Max)
  650. /*++
  651. Routine Description:
  652. Get a size from the Point Size ComboBox edit field
  653. Return Value:
  654. Point Size - of the edit field limited by Min/Max size
  655. 0 - if the field is empty or invalid
  656. --*/
  657. {
  658. TCHAR szBuf[90];
  659. int nTmp = 0;
  660. BOOL bOK;
  661. if (GetDlgItemText(hDlg, IDC_CNSL_POINTSLIST, szBuf, NELEM(szBuf))) {
  662. nTmp = GetDlgItemInt(hDlg, IDC_CNSL_POINTSLIST, &bOK, TRUE);
  663. if (bOK && nTmp >= Min && nTmp <= Max) {
  664. return nTmp;
  665. }
  666. }
  667. return 0;
  668. }
  669. /* ----- Preview routines ----- */
  670. LRESULT
  671. _FontPreviewWndProc(
  672. HWND hWnd,
  673. UINT wMessage,
  674. WPARAM wParam,
  675. LPARAM lParam
  676. )
  677. /* FontPreviewWndProc
  678. * Handles the font preview window
  679. */
  680. {
  681. PAINTSTRUCT ps;
  682. RECT rect;
  683. HBRUSH hbrClient;
  684. HBRUSH hbrOld;
  685. COLORREF rgbText;
  686. COLORREF rgbBk;
  687. CONSOLEPROP_DATA * pcpd = (CONSOLEPROP_DATA *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
  688. switch (wMessage) {
  689. case WM_CREATE:
  690. pcpd = (CONSOLEPROP_DATA *)((LPCREATESTRUCT)lParam)->lpCreateParams;
  691. SetWindowLongPtr( hWnd, GWLP_USERDATA, (LPARAM)pcpd );
  692. break;
  693. case WM_PAINT:
  694. BeginPaint(hWnd, &ps);
  695. /* Draw the font sample */
  696. rgbText = GetNearestColor(ps.hdc, ScreenTextColor(pcpd));
  697. rgbBk = GetNearestColor(ps.hdc, ScreenBkColor(pcpd));
  698. SelectObject(ps.hdc, pcpd->FontInfo[pcpd->CurrentFontIndex].hFont);
  699. SetTextColor(ps.hdc, rgbText);
  700. SetBkColor(ps.hdc, rgbBk);
  701. GetClientRect(hWnd, &rect);
  702. InflateRect(&rect, -2, -2);
  703. hbrClient = CreateSolidBrush(rgbBk);
  704. if (hbrClient)
  705. hbrOld = SelectObject(ps.hdc, hbrClient);
  706. PatBlt(ps.hdc, rect.left, rect.top,
  707. rect.right - rect.left, rect.bottom - rect.top,
  708. PATCOPY);
  709. DrawText(ps.hdc, g_szPreviewText, -1, &rect, 0);
  710. if (hbrClient)
  711. {
  712. SelectObject(ps.hdc, hbrOld);
  713. DeleteObject(hbrClient);
  714. }
  715. EndPaint(hWnd, &ps);
  716. break;
  717. default:
  718. return DefWindowProc(hWnd, wMessage, wParam, lParam);
  719. }
  720. return 0L;
  721. }
  722. /*
  723. * SelectCurrentSize - Select the right line of the Size listbox/combobox.
  724. * bLB : Size controls is a listbox (TRUE for RasterFonts)
  725. * FontIndex : Index into FontInfo[] cache
  726. * If < 0 then choose a good font.
  727. * Returns
  728. * FontIndex : Index into FontInfo[] cache
  729. */
  730. int
  731. SelectCurrentSize(CONSOLEPROP_DATA * pcpd, HWND hDlg, BOOL bLB, int FontIndex)
  732. {
  733. int iCB;
  734. HWND hWndList;
  735. hWndList = GetDlgItem(hDlg, bLB ? IDC_CNSL_PIXELSLIST : IDC_CNSL_POINTSLIST);
  736. iCB = (int) lcbGETCOUNT(hWndList, bLB);
  737. if (FontIndex >= 0) {
  738. /*
  739. * look for FontIndex
  740. */
  741. while (iCB > 0) {
  742. iCB--;
  743. if (lcbGETITEMDATA(hWndList, bLB, iCB) == FontIndex) {
  744. lcbSETCURSEL(hWndList, bLB, iCB);
  745. break;
  746. }
  747. }
  748. } else {
  749. /*
  750. * look for a reasonable default size: looking backwards, find
  751. * the first one same height or smaller.
  752. */
  753. DWORD Size;
  754. Size = pcpd->FontLong;
  755. if (IsFarEastCP(pcpd->uOEMCP) & bLB
  756. && (pcpd->FontInfo[pcpd->CurrentFontIndex].tmCharSet != LOBYTE(LOWORD(Size)))
  757. )
  758. {
  759. TCHAR AltFaceName[LF_FACESIZE];
  760. COORD AltFontSize;
  761. BYTE AltFontFamily;
  762. ULONG AltFontIndex = 0;
  763. MakeAltRasterFont(pcpd, pcpd->lpFEConsole->uCodePage, &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
  764. while(iCB > 0) {
  765. iCB--;
  766. if (lcbGETITEMDATA(hWndList, bLB, iCB) == (int)AltFontIndex) {
  767. lcbSETCURSEL(hWndList, bLB, iCB);
  768. break;
  769. }
  770. }
  771. }
  772. else
  773. {
  774. while (iCB > 0) {
  775. iCB--;
  776. FontIndex = (ULONG) lcbGETITEMDATA(hWndList, bLB, iCB);
  777. if (pcpd->FontInfo[FontIndex].Size.Y <= HIWORD(Size)) {
  778. lcbSETCURSEL(hWndList, bLB, iCB);
  779. break;
  780. }
  781. }
  782. }
  783. }
  784. return FontIndex;
  785. }
  786. BOOL
  787. SelectCurrentFont(CONSOLEPROP_DATA * pcpd, HWND hDlg, int FontIndex)
  788. {
  789. BOOL bLB;
  790. bLB = !TM_IS_TT_FONT(pcpd->FontInfo[FontIndex].Family);
  791. SendDlgItemMessage(hDlg, IDC_CNSL_FACENAME, LB_SELECTSTRING, (DWORD)-1,
  792. bLB ? (LPARAM)tszRasterFonts : (LPARAM)(pcpd->FontInfo[FontIndex].FaceName));
  793. SelectCurrentSize(pcpd, hDlg, bLB, FontIndex);
  794. return bLB;
  795. }
  796. BOOL
  797. ConsolePreviewInit(
  798. CONSOLEPROP_DATA * pcpd,
  799. HWND hDlg,
  800. BOOL* pfRaster
  801. )
  802. /* PreviewInit
  803. * Prepares the preview code, sizing the window and the dialog to
  804. * make an attractive preview.
  805. * *pfRaster is TRUE if Raster Fonts, FALSE if TT Font
  806. * Returns FALSE on critical failure, TRUE otherwise
  807. */
  808. {
  809. HDC hDC;
  810. TEXTMETRIC tm;
  811. RECT rectLabel;
  812. RECT rectGroup;
  813. int nFont;
  814. SHORT xChar;
  815. SHORT yChar;
  816. /* Get the system char size */
  817. hDC = GetDC(hDlg);
  818. if (!hDC)
  819. {
  820. // Out of memory; just close the dialog - better than crashing: Prefix 98162
  821. return FALSE;
  822. }
  823. GetTextMetrics(hDC, &tm);
  824. ReleaseDC(hDlg, hDC);
  825. xChar = (SHORT) (tm.tmAveCharWidth);
  826. yChar = (SHORT) (tm.tmHeight + tm.tmExternalLeading);
  827. /* Compute the size of the font preview */
  828. GetWindowRect(GetDlgItem(hDlg, IDC_CNSL_GROUP), &rectGroup);
  829. MapWindowRect(HWND_DESKTOP, hDlg, &rectGroup);
  830. rectGroup.bottom -= rectGroup.top;
  831. GetWindowRect(GetDlgItem(hDlg, IDC_CNSL_STATIC2), &rectLabel);
  832. MapWindowRect(HWND_DESKTOP, hDlg, &rectLabel);
  833. /* Create the font preview */
  834. CreateWindowEx(0L, TEXT("WOACnslFontPreview"), NULL,
  835. WS_CHILD | WS_VISIBLE,
  836. rectGroup.left + xChar, rectGroup.top + 3 * yChar / 2,
  837. rectLabel.left - rectGroup.left - 2 * xChar,
  838. rectGroup.bottom - 2 * yChar,
  839. hDlg, (HMENU)IDC_CNSL_FONTWINDOW, g_hinst, (LPVOID)pcpd);
  840. /*
  841. * Set the current font
  842. */
  843. nFont = FindCreateFont(pcpd,
  844. pcpd->lpConsole->uFontFamily,
  845. pcpd->lpFaceName,
  846. pcpd->lpConsole->dwFontSize,
  847. pcpd->lpConsole->uFontWeight);
  848. pcpd->CurrentFontIndex = nFont;
  849. *pfRaster = SelectCurrentFont(pcpd, hDlg, nFont);
  850. return TRUE;
  851. }
  852. BOOL
  853. ConsolePreviewUpdate(
  854. CONSOLEPROP_DATA * pcpd,
  855. HWND hDlg,
  856. BOOL bLB
  857. )
  858. /*++
  859. Does the preview of the selected font.
  860. --*/
  861. {
  862. FONT_INFO *lpFont;
  863. int FontIndex;
  864. LONG lIndex;
  865. HWND hWnd;
  866. TCHAR tszText[60];
  867. TCHAR tszFace[LF_FACESIZE + CCH_SELECTEDFONT];
  868. HWND hWndList;
  869. hWndList = GetDlgItem(hDlg, bLB ? IDC_CNSL_PIXELSLIST : IDC_CNSL_POINTSLIST);
  870. /* When we select a font, we do the font preview by setting it into
  871. * the appropriate list box
  872. */
  873. lIndex = (LONG) lcbGETCURSEL(hWndList, bLB);
  874. if ((lIndex < 0) && !bLB) {
  875. COORD NewSize;
  876. lIndex = (LONG) SendDlgItemMessage(hDlg, IDC_CNSL_FACENAME, LB_GETCURSEL, 0, 0L);
  877. SendDlgItemMessage(hDlg, IDC_CNSL_FACENAME, LB_GETTEXT, lIndex, (LPARAM)tszFace);
  878. NewSize.X = 0;
  879. NewSize.Y = (SHORT) GetPointSizeInRange(hDlg, MIN_PIXEL_HEIGHT, MAX_PIXEL_HEIGHT);
  880. if (NewSize.Y == 0) {
  881. TCHAR tszBuf[60];
  882. /*
  883. * Use tszText, tszBuf to put up an error msg for bad point size
  884. */
  885. pcpd->gbPointSizeError = TRUE;
  886. GetWindowText(hDlg, tszBuf, NELEM(tszBuf));
  887. ShellMessageBox(HINST_THISDLL, hDlg, MAKEINTRESOURCE(IDS_CNSL_FONTSIZE),
  888. tszBuf, MB_OK|MB_ICONINFORMATION,
  889. MIN_PIXEL_HEIGHT, MAX_PIXEL_HEIGHT);
  890. SetFocus(hWndList);
  891. pcpd->gbPointSizeError = FALSE;
  892. return FALSE;
  893. }
  894. FontIndex = FindCreateFont(pcpd,
  895. FF_MODERN|TMPF_VECTOR|TMPF_TRUETYPE,
  896. tszFace, NewSize, 0);
  897. } else {
  898. FontIndex = (int) lcbGETITEMDATA(hWndList, bLB, lIndex);
  899. }
  900. if (FontIndex < 0) {
  901. FontIndex = pcpd->DefaultFontIndex;
  902. }
  903. /*
  904. * If we've selected a new font, tell the property sheet we've changed
  905. */
  906. if (pcpd->CurrentFontIndex != (ULONG)FontIndex) {
  907. pcpd->CurrentFontIndex = FontIndex;
  908. }
  909. lpFont = &pcpd->FontInfo[FontIndex];
  910. /* Display the new font */
  911. lstrcpy(tszFace, tszSelectedFont);
  912. lstrcat(tszFace, lpFont->FaceName);
  913. SetDlgItemText(hDlg, IDC_CNSL_GROUP, tszFace);
  914. /* Put the font size in the static boxes */
  915. wsprintf(tszText, TEXT("%u"), lpFont->Size.X);
  916. hWnd = GetDlgItem(hDlg, IDC_CNSL_FONTWIDTH);
  917. SetWindowText(hWnd, tszText);
  918. InvalidateRect(hWnd, NULL, TRUE);
  919. wsprintf(tszText, TEXT("%u"), lpFont->Size.Y);
  920. hWnd = GetDlgItem(hDlg, IDC_CNSL_FONTHEIGHT);
  921. SetWindowText(hWnd, tszText);
  922. InvalidateRect(hWnd, NULL, TRUE);
  923. /* Force the preview windows to repaint */
  924. hWnd = GetDlgItem(hDlg, IDC_CNSL_PREVIEWWINDOW);
  925. SendMessage(hWnd, CM_PREVIEW_UPDATE, 0, 0);
  926. hWnd = GetDlgItem(hDlg, IDC_CNSL_FONTWINDOW);
  927. InvalidateRect(hWnd, NULL, TRUE);
  928. return TRUE;
  929. }