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.

1961 lines
63 KiB

  1. /*******************************************************************************
  2. *
  3. * MODULE : Font.c
  4. *
  5. * DESCRIPTION : Font selection dialog routines and related functions.
  6. *
  7. * HISTORY : 11/13/90 - by L.Raman.
  8. * HISTORY : 4/30/91 - reworked for new super font dialog
  9. *
  10. * Copyright (c) Microsoft Corporation, 1990-
  11. *
  12. * some notes:
  13. *
  14. * under 3.0 sending a CB_SETCURSEL message to an owner draw
  15. * combo wipes out the exit text (in this case that means the
  16. * face and size combos).
  17. *
  18. ******************************************************************************/
  19. #define NOCOMM
  20. #define NOWH
  21. #include <windows.h>
  22. #include "privcomd.h"
  23. #include "font.h"
  24. typedef struct {
  25. HWND hwndFamily;
  26. HWND hwndStyle;
  27. HWND hwndSizes;
  28. HDC hDC;
  29. DWORD dwFlags;
  30. WORD nFontType;
  31. BOOL bFillSize;
  32. BOOL bPrinterFont;
  33. LPCHOOSEFONT lpcf;
  34. } ENUM_FONT_DATA, FAR *LPENUM_FONT_DATA;
  35. #define CBN_MYSELCHANGE (WM_USER + 500)
  36. #define CBN_MYEDITUPDATE (WM_USER + 501)
  37. #define DEF_POINT_SIZE 10
  38. HBITMAP NEAR PASCAL LoadBitmaps(int id);
  39. BOOL FAR PASCAL FormatCharDlgProc(HWND, unsigned, WORD, LONG);
  40. void NEAR PASCAL FreeFonts(HWND hwnd);
  41. BOOL NEAR PASCAL ProcessDlgCtrlCommand(HWND hDlg, LPCHOOSEFONT lpcf, WORD wParam, LONG lParam);
  42. BOOL NEAR PASCAL DrawColorComboItem(LPDRAWITEMSTRUCT lpdis);
  43. BOOL NEAR PASCAL DrawFamilyComboItem(LPDRAWITEMSTRUCT lpdis);
  44. BOOL NEAR PASCAL DrawSizeComboItem(LPDRAWITEMSTRUCT lpdis);
  45. BOOL NEAR PASCAL FillInFont(HWND hDlg, LPCHOOSEFONT lpcf, LPLOGFONT lplf, BOOL bSetBits);
  46. void NEAR PASCAL FillColorCombo(HWND hDlg);
  47. void NEAR PASCAL ComputeSampleTextRectangle(HWND hDlg);
  48. void NEAR PASCAL SelectStyleFromLF(HWND hwnd, LPLOGFONT lplf);
  49. void NEAR PASCAL DrawSampleText(HWND hDlg, LPCHOOSEFONT lpcf, HDC hDC);
  50. int NEAR PASCAL GetPointString(LPSTR buf, HDC hdc, int height);
  51. BOOL NEAR PASCAL GetFontFamily(HWND hDlg, HDC hDC, DWORD dwEnumCode);
  52. BOOL NEAR PASCAL GetFontStylesAndSizes(HWND hDlg, LPCHOOSEFONT lpcf, BOOL bFillSizes);
  53. int NEAR PASCAL CBSetTextFromSel(HWND hwnd);
  54. int NEAR PASCAL CBSetSelFromText(HWND hwnd, LPSTR lpszString);
  55. int NEAR PASCAL CBFindString(HWND hwnd, LPSTR lpszString);
  56. int NEAR PASCAL CBGetTextAndData(HWND hwnd, LPSTR lpszString, int iSize, LPDWORD lpdw);
  57. void NEAR PASCAL InitLF(LPLOGFONT lplf);
  58. #if 0
  59. int NEAR PASCAL atoi(LPSTR sz);
  60. #endif
  61. /* color table used for colors combobox
  62. the order of these values must match the names in sz.src */
  63. DWORD rgbColors[CCHCOLORS] = {
  64. RGB( 0, 0, 0), /* Black */
  65. RGB(128, 0, 0), /* Dark red */
  66. RGB( 0, 128, 0), /* Dark green */
  67. RGB(128, 128, 0), /* Dark yellow */
  68. RGB( 0, 0, 128), /* Dark blue */
  69. RGB(128, 0, 128), /* Dark purple */
  70. RGB( 0, 128, 128), /* Dark aqua */
  71. RGB(128, 128, 128), /* Dark grey */
  72. RGB(192, 192, 192), /* Light grey */
  73. RGB(255, 0, 0), /* Light red */
  74. RGB( 0, 255, 0), /* Light green */
  75. RGB(255, 255, 0), /* Light yellow */
  76. RGB( 0, 0, 255), /* Light blue */
  77. RGB(255, 0, 255), /* Light purple */
  78. RGB( 0, 255, 255), /* Light aqua */
  79. RGB(255, 255, 255), /* White */
  80. };
  81. RECT rcText;
  82. WORD nLastFontType;
  83. HBITMAP hbmFont = NULL;
  84. #define DX_BITMAP 20
  85. #define DY_BITMAP 12
  86. char szRegular[CCHSTYLE];
  87. char szBold[CCHSTYLE];
  88. char szItalic[CCHSTYLE];
  89. char szBoldItalic[CCHSTYLE];
  90. #if 0
  91. char szEnumFonts31[] = "EnumFontFamilies";
  92. char szEnumFonts30[] = "EnumFonts";
  93. #else
  94. #define szEnumFonts30 MAKEINTRESOURCE(70)
  95. #define szEnumFonts31 MAKEINTRESOURCE(330)
  96. #endif
  97. char szGDI[] = "GDI";
  98. char szPtFormat[] = "%d";
  99. UINT (FAR PASCAL *glpfnFontHook)(HWND, UINT, WPARAM, LPARAM) = 0;
  100. void NEAR PASCAL SetStyleSelection(HWND hDlg, LPCHOOSEFONT lpcf, BOOL bInit)
  101. {
  102. if (!(lpcf->Flags & CF_NOSTYLESEL)) {
  103. if (bInit && (lpcf->Flags & CF_USESTYLE))
  104. {
  105. PLOGFONT plf;
  106. short iSel;
  107. iSel = (short)CBSetSelFromText(GetDlgItem(hDlg, cmb2), lpcf->lpszStyle);
  108. if (iSel >= 0)
  109. {
  110. plf = (PLOGFONT)(WORD)SendDlgItemMessage(hDlg, cmb2,
  111. CB_GETITEMDATA, iSel, 0L);
  112. lpcf->lpLogFont->lfWeight = plf->lfWeight;
  113. lpcf->lpLogFont->lfItalic = plf->lfItalic;
  114. }
  115. else
  116. {
  117. lpcf->lpLogFont->lfWeight = FW_NORMAL;
  118. lpcf->lpLogFont->lfItalic = 0;
  119. }
  120. }
  121. else
  122. SelectStyleFromLF(GetDlgItem(hDlg, cmb2), lpcf->lpLogFont);
  123. CBSetTextFromSel(GetDlgItem(hDlg, cmb2));
  124. }
  125. }
  126. void NEAR PASCAL HideDlgItem(HWND hDlg, int id)
  127. {
  128. EnableWindow(GetDlgItem(hDlg, id), FALSE);
  129. ShowWindow(GetDlgItem(hDlg, id), SW_HIDE);
  130. }
  131. // fix the ownerdraw combos to match the heigh of the non owner draw combo
  132. // this only works on 3.1
  133. void NEAR PASCAL FixComboHeights(HWND hDlg)
  134. {
  135. int height;
  136. height = (int)SendDlgItemMessage(hDlg, cmb2, CB_GETITEMHEIGHT, (WPARAM)-1, 0L);
  137. SendDlgItemMessage(hDlg, cmb1, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)height);
  138. SendDlgItemMessage(hDlg, cmb3, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)height);
  139. }
  140. /****************************************************************************
  141. *
  142. * FormatCharDlgProc
  143. *
  144. * PURPOSE : Handles dialog messages for the font picker dialog.
  145. *
  146. * RETURNS : Normal dialog function values.
  147. *
  148. * ASSUMES :
  149. * chx1 - " " "Underline" checkbox
  150. * chx2 - " " "Strikeout" checkbox
  151. * psh4 - " " "Help..." pushbutton
  152. *
  153. * COMMENTS : The CHOOSEFONT struct is accessed via lParam during a
  154. * WM_INITDIALOG, and stored in the window's property list. If
  155. * a hook function has been specified, it is invoked AFTER the
  156. * current function has processed WM_INITDIALOG. For all other
  157. * messages, control is passed directly to the hook function.
  158. * Depending on the latter's return value, the message is also
  159. * processed by this function.
  160. *
  161. ****************************************************************************/
  162. BOOL FAR PASCAL FormatCharDlgProc(HWND hDlg, unsigned wMsg, WORD wParam, LONG lParam)
  163. {
  164. PAINTSTRUCT ps;
  165. TEXTMETRIC tm;
  166. HDC hDC; /* handle to screen DC */
  167. LPCHOOSEFONT lpcf = NULL; /* ptr. to struct. passed to ChooseFont() */
  168. LPCHOOSEFONT *plpcf; /* ptr. to above */
  169. HWND hWndHelp; /* handle to Help... pushbutton */
  170. short nIndex; /* At init, see if color matches */
  171. char szPoints[10];
  172. HDC hdc;
  173. HFONT hFont;
  174. DWORD dw;
  175. WORD wRet;
  176. /* If the CHOOSEFONT. struct has already been accessed and if a hook fn. is
  177. * specified, let it do the processing.
  178. */
  179. plpcf = (LPCHOOSEFONT *)GetProp(hDlg, FONTPROP);
  180. if (plpcf) {
  181. lpcf = (LPCHOOSEFONT)*plpcf++;
  182. if (lpcf->Flags & CF_ENABLEHOOK) {
  183. if ((wRet = (WORD)(*lpcf->lpfnHook)(hDlg, wMsg, wParam, lParam)) != 0)
  184. return wRet;
  185. }
  186. }
  187. else if (glpfnFontHook && (wMsg != WM_INITDIALOG)) {
  188. if ((wRet = (WORD)(* glpfnFontHook)(hDlg, wMsg,wParam,lParam)) != 0) {
  189. return(wRet);
  190. }
  191. }
  192. switch(wMsg){
  193. case WM_INITDIALOG:
  194. if (!LoadString(hinsCur, iszRegular, (LPSTR)szRegular, CCHSTYLE) ||
  195. !LoadString(hinsCur, iszBold, (LPSTR)szBold, CCHSTYLE) ||
  196. !LoadString(hinsCur, iszItalic, (LPSTR)szItalic, CCHSTYLE) ||
  197. !LoadString(hinsCur, iszBoldItalic, (LPSTR)szBoldItalic, CCHSTYLE))
  198. {
  199. dwExtError = CDERR_LOADSTRFAILURE;
  200. EndDialog(hDlg, FALSE);
  201. return FALSE;
  202. }
  203. lpcf = (LPCHOOSEFONT)lParam;
  204. if ((lpcf->Flags & CF_LIMITSIZE) &&
  205. (lpcf->nSizeMax < lpcf->nSizeMin))
  206. {
  207. dwExtError = CFERR_MAXLESSTHANMIN;
  208. EndDialog(hDlg, FALSE);
  209. return FALSE;
  210. }
  211. /* Save the pointer to the CHOOSEFONT struct. in the dialog's
  212. * property list. Also, allocate for a temporary LOGFONT struct.
  213. * to be used for the length of the dlg. session, the contents of
  214. * which will be copied over to the final LOGFONT (pointed to by
  215. * CHOOSEFONT) only if <OK> is selected.
  216. */
  217. plpcf = (LPCHOOSEFONT *)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(LPCHOOSEFONT));
  218. if (!plpcf) {
  219. dwExtError = CDERR_MEMALLOCFAILURE;
  220. EndDialog(hDlg, FALSE);
  221. return FALSE;
  222. }
  223. SetProp(hDlg, FONTPROP, (HANDLE)plpcf);
  224. glpfnFontHook = 0;
  225. lpcf = *(LPCHOOSEFONT FAR *)plpcf = (LPCHOOSEFONT)lParam;
  226. if (!hbmFont)
  227. hbmFont = LoadBitmaps(BMFONT);
  228. if (!(lpcf->Flags & CF_APPLY))
  229. HideDlgItem(hDlg, psh3);
  230. if (!(lpcf->Flags & CF_EFFECTS)) {
  231. HideDlgItem(hDlg, stc4);
  232. HideDlgItem(hDlg, cmb4);
  233. } else {
  234. // fill color list
  235. FillColorCombo(hDlg);
  236. for (nIndex = CCHCOLORS - 1; nIndex > 0; nIndex--) {
  237. dw = SendDlgItemMessage(hDlg, cmb4, CB_GETITEMDATA, nIndex, 0L);
  238. if (lpcf->rgbColors == dw)
  239. break;
  240. }
  241. SendDlgItemMessage(hDlg, cmb4, CB_SETCURSEL, nIndex, 0L);
  242. }
  243. ComputeSampleTextRectangle(hDlg);
  244. FixComboHeights(hDlg);
  245. // init our LOGFONT
  246. if (!(lpcf->Flags & CF_INITTOLOGFONTSTRUCT)) {
  247. InitLF(lpcf->lpLogFont);
  248. #if 0
  249. *lpcf->lpLogFont->lfFaceName = 0;
  250. lpcf->lpLogFont->lfWeight = FW_NORMAL;
  251. lpcf->lpLogFont->lfHeight = 0;
  252. lpcf->lpLogFont->lfItalic = 0;
  253. lpcf->lpLogFont->lfStrikeOut = 0;
  254. lpcf->lpLogFont->lfUnderline = 0;
  255. #endif
  256. }
  257. // init effects
  258. if (!(lpcf->Flags & CF_EFFECTS)) {
  259. HideDlgItem(hDlg, grp1);
  260. HideDlgItem(hDlg, chx1);
  261. HideDlgItem(hDlg, chx2);
  262. } else {
  263. CheckDlgButton(hDlg, chx1, lpcf->lpLogFont->lfStrikeOut);
  264. CheckDlgButton(hDlg, chx2, lpcf->lpLogFont->lfUnderline);
  265. }
  266. nLastFontType = 0;
  267. if (!GetFontFamily(hDlg, lpcf->hDC, lpcf->Flags)) {
  268. dwExtError = CFERR_NOFONTS;
  269. EndDialog(hDlg, FALSE);
  270. RemoveProp(hDlg, FONTPROP);
  271. if (lpcf->Flags & CF_ENABLEHOOK)
  272. glpfnFontHook = lpcf->lpfnHook;
  273. return FALSE;
  274. }
  275. if (!(lpcf->Flags & CF_NOFACESEL) && *lpcf->lpLogFont->lfFaceName) {
  276. CBSetSelFromText(GetDlgItem(hDlg, cmb1), lpcf->lpLogFont->lfFaceName);
  277. CBSetTextFromSel(GetDlgItem(hDlg, cmb1));
  278. }
  279. GetFontStylesAndSizes(hDlg, lpcf, TRUE);
  280. if (!(lpcf->Flags & CF_NOSTYLESEL)) {
  281. SetStyleSelection(hDlg, lpcf, TRUE);
  282. }
  283. if (!(lpcf->Flags & CF_NOSIZESEL) && lpcf->lpLogFont->lfHeight) {
  284. hdc = GetDC(NULL);
  285. GetPointString(szPoints, hdc, lpcf->lpLogFont->lfHeight);
  286. ReleaseDC(NULL, hdc);
  287. CBSetSelFromText(GetDlgItem(hDlg, cmb3), szPoints);
  288. SetDlgItemText(hDlg, cmb3, szPoints);
  289. }
  290. /* Hide the help button if it isn't needed */
  291. if (!(lpcf->Flags & CF_SHOWHELP)) {
  292. ShowWindow (hWndHelp = GetDlgItem(hDlg, pshHelp), SW_HIDE);
  293. EnableWindow (hWndHelp, FALSE);
  294. }
  295. SendDlgItemMessage(hDlg, cmb1, CB_LIMITTEXT, LF_FACESIZE-1, 0L);
  296. SendDlgItemMessage(hDlg, cmb2, CB_LIMITTEXT, LF_FACESIZE-1, 0L);
  297. SendDlgItemMessage(hDlg, cmb3, CB_LIMITTEXT, 4, 0L);
  298. // if hook function has been specified, let it do any additional
  299. // processing of this message.
  300. if (lpcf->Flags & CF_ENABLEHOOK)
  301. return (*lpcf->lpfnHook)(hDlg, wMsg, wParam, lParam);
  302. SetCursor(LoadCursor(NULL, IDC_ARROW));
  303. break;
  304. case WM_PAINT:
  305. if (BeginPaint(hDlg, &ps)) {
  306. DrawSampleText(hDlg, lpcf, ps.hdc);
  307. EndPaint(hDlg, &ps);
  308. }
  309. break;
  310. case WM_MEASUREITEM:
  311. hDC = GetDC(hDlg);
  312. hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
  313. if (hFont)
  314. hFont = SelectObject(hDC, hFont);
  315. GetTextMetrics(hDC, &tm);
  316. if (hFont)
  317. SelectObject(hDC, hFont);
  318. ReleaseDC(hDlg, hDC);
  319. if (((LPMEASUREITEMSTRUCT)lParam)->itemID != -1)
  320. ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = max(tm.tmHeight, DY_BITMAP);
  321. else
  322. // this is for 3.0. since in 3.1 the CB_SETITEMHEIGH
  323. // will fix this. note, this is off by one on 8514
  324. ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = tm.tmHeight + 1;
  325. break;
  326. case WM_DRAWITEM:
  327. #define lpdis ((LPDRAWITEMSTRUCT)lParam)
  328. if (lpdis->itemID == 0xFFFF)
  329. break;
  330. if (lpdis->CtlID == cmb4)
  331. DrawColorComboItem(lpdis);
  332. else if (lpdis->CtlID == cmb1)
  333. DrawFamilyComboItem(lpdis);
  334. else
  335. DrawSizeComboItem(lpdis);
  336. break;
  337. #undef lpdis
  338. case WM_SYSCOLORCHANGE:
  339. DeleteObject(hbmFont);
  340. hbmFont = LoadBitmaps(BMFONT);
  341. break;
  342. case WM_COMMAND:
  343. return ProcessDlgCtrlCommand(hDlg, lpcf, wParam, lParam);
  344. break;
  345. case WM_CHOOSEFONT_GETLOGFONT:
  346. return FillInFont(hDlg, lpcf, (LPLOGFONT)lParam, TRUE);
  347. default:
  348. return FALSE;
  349. }
  350. return TRUE;
  351. }
  352. // given a logfont select the closest match in the style list
  353. void NEAR PASCAL SelectStyleFromLF(HWND hwnd, LPLOGFONT lplf)
  354. {
  355. int i, count, iSel;
  356. LPLOGFONT plf;
  357. int weight_delta, best_weight_delta = 1000;
  358. BOOL bIgnoreItalic;
  359. count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
  360. iSel = 0;
  361. bIgnoreItalic = FALSE;
  362. TryAgain:
  363. for (i = 0; i < count; i++) {
  364. plf = (LPLOGFONT)SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
  365. if (bIgnoreItalic ||
  366. (plf->lfItalic && lplf->lfItalic) ||
  367. (!plf->lfItalic && !lplf->lfItalic)) {
  368. weight_delta = lplf->lfWeight - plf->lfWeight;
  369. if (weight_delta < 0)
  370. weight_delta = -weight_delta;
  371. if (weight_delta < best_weight_delta) {
  372. best_weight_delta = weight_delta;
  373. iSel = i;
  374. }
  375. }
  376. }
  377. if (!bIgnoreItalic && iSel == 0) {
  378. bIgnoreItalic = TRUE;
  379. goto TryAgain;
  380. }
  381. SendMessage(hwnd, CB_SETCURSEL, iSel, 0L);
  382. }
  383. // make the currently selected item the edit text for a combobox
  384. int NEAR PASCAL CBSetTextFromSel(HWND hwnd)
  385. {
  386. int iSel;
  387. char szFace[LF_FACESIZE];
  388. iSel = (int)SendMessage(hwnd, CB_GETCURSEL, 0, 0L);
  389. if (iSel >= 0) {
  390. SendMessage(hwnd, CB_GETLBTEXT, iSel, (LONG)(LPSTR)szFace);
  391. SetWindowText(hwnd, szFace);
  392. }
  393. return iSel;
  394. }
  395. // set the selection based on lpszString. send notification
  396. // messages if bNotify is TRUE
  397. int NEAR PASCAL CBSetSelFromText(HWND hwnd, LPSTR lpszString)
  398. {
  399. int iInd;
  400. iInd = CBFindString(hwnd, lpszString);
  401. if (iInd >= 0) {
  402. SendMessage(hwnd, CB_SETCURSEL, iInd, 0L);
  403. }
  404. return iInd;
  405. }
  406. // return the text and item data for a combo box based on the current
  407. // edit text. if the current edit text does not match anything in the
  408. // listbox return CB_ERR
  409. int NEAR PASCAL CBGetTextAndData(HWND hwnd, LPSTR lpszString, int iSize, LPDWORD lpdw)
  410. {
  411. int iSel;
  412. GetWindowText(hwnd, lpszString, iSize);
  413. iSel = CBFindString(hwnd, lpszString);
  414. if (iSel < 0)
  415. return iSel;
  416. *lpdw = SendMessage(hwnd, CB_GETITEMDATA, iSel, 0L);
  417. return iSel;
  418. }
  419. // do an exact string find and return the index
  420. int NEAR PASCAL CBFindString(HWND hwnd, LPSTR lpszString)
  421. {
  422. int iItem, iCount;
  423. char szFace[LF_FACESIZE];
  424. iCount = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
  425. for (iItem = 0; iItem < iCount; iItem++) {
  426. SendMessage(hwnd, CB_GETLBTEXT, iItem, (LONG)(LPSTR)szFace);
  427. if (!lstrcmpi(szFace, lpszString))
  428. return iItem;
  429. }
  430. return CB_ERR;
  431. }
  432. #define GPS_COMPLAIN 0x0001
  433. #define GPS_SETDEFSIZE 0x0002
  434. // make sure the point size edit field is in range.
  435. //
  436. // returns:
  437. // the point size of the edit field limitted by the min/max size
  438. // 0 if the field is empty
  439. BOOL NEAR PASCAL GetPointSizeInRange(HWND hDlg, LPCHOOSEFONT lpcf, LPINT pts,
  440. WORD wFlags)
  441. {
  442. char szBuffer[90];
  443. char szTitle[90];
  444. int nTmp;
  445. BOOL bOK;
  446. *pts = 0;
  447. if (GetDlgItemText(hDlg, cmb3, szBuffer, sizeof(szBuffer))) {
  448. nTmp = GetDlgItemInt(hDlg, cmb3, &bOK, TRUE);
  449. if (!bOK)
  450. nTmp = 0;
  451. } else if (wFlags & GPS_SETDEFSIZE) {
  452. nTmp = DEF_POINT_SIZE;
  453. bOK = TRUE;
  454. } else {
  455. /* We're just returning with 0 in *pts
  456. */
  457. return(FALSE);
  458. }
  459. /* Check that we got a number in range
  460. */
  461. if (wFlags & GPS_COMPLAIN) {
  462. if ((lpcf->Flags&CF_LIMITSIZE) &&
  463. (!bOK || nTmp>lpcf->nSizeMax || nTmp<lpcf->nSizeMin)) {
  464. bOK = FALSE;
  465. LoadString(hinsCur, iszSizeRange, szTitle, sizeof(szTitle));
  466. wsprintf(szBuffer, szTitle, lpcf->nSizeMin, lpcf->nSizeMax);
  467. } else if (!bOK)
  468. LoadString(hinsCur, iszSizeNumber, szBuffer, sizeof(szBuffer));
  469. if (!bOK) {
  470. GetWindowText(hDlg, szTitle, sizeof(szTitle));
  471. MessageBox(hDlg, szBuffer, szTitle, MB_OK | MB_ICONINFORMATION);
  472. return(FALSE);
  473. }
  474. }
  475. *pts = nTmp;
  476. return(TRUE);
  477. }
  478. /****************************************************************************
  479. *
  480. * ProcessDlgCtrlCommand
  481. *
  482. * PURPOSE : Handles all WM_COMMAND messages for the font picker dialog
  483. *
  484. * ASSUMES : cmb1 - ID of font facename combobox
  485. * cmb2 - " " style
  486. * cmb3 - " " size
  487. * chx1 - " " "Underline" checkbox
  488. * chx2 - " " "Strikeout" checkbox
  489. * stc5 - " " frame around text preview area
  490. * psh4 - " " button that invokes the Help application
  491. * IDOK - " " OK button to end dialog, retaining information
  492. * IDCANCEL" " button to cancel dialog, not doing anything.
  493. *
  494. * RETURNS : TRUE if message is processed succesfully, FALSE otherwise.
  495. *
  496. * COMMENTS : if the OK button is selected, all the font information is
  497. * written into the CHOOSEFONT structure.
  498. *
  499. ****************************************************************************/
  500. BOOL NEAR PASCAL ProcessDlgCtrlCommand(HWND hDlg, LPCHOOSEFONT lpcf, WORD wParam, LONG lParam)
  501. {
  502. int iSel;
  503. char szPoints[10];
  504. char szStyle[LF_FACESIZE];
  505. DWORD dw;
  506. WORD wCmbId;
  507. char szMsg[160], szTitle[160];
  508. switch (wParam) {
  509. case IDABORT:
  510. // this is how a hook can cause the dialog to go away
  511. FreeFonts(GetDlgItem(hDlg, cmb2));
  512. EndDialog(hDlg, LOWORD(lParam));
  513. RemoveProp(hDlg, FONTPROP);
  514. if (lpcf->Flags & CF_ENABLEHOOK)
  515. glpfnFontHook = lpcf->lpfnHook;
  516. break;
  517. case IDOK:
  518. if (!GetPointSizeInRange(hDlg, lpcf, &iSel,
  519. GPS_COMPLAIN|GPS_SETDEFSIZE)) {
  520. PostMessage(hDlg, WM_NEXTDLGCTL, GetDlgItem(hDlg, cmb3), 1L);
  521. break;
  522. }
  523. lpcf->iPointSize = iSel * 10;
  524. FillInFont(hDlg, lpcf, lpcf->lpLogFont, TRUE);
  525. if (lpcf->Flags & CF_FORCEFONTEXIST)
  526. {
  527. if (lpcf->Flags & CF_NOFACESEL)
  528. wCmbId = cmb1;
  529. else if (lpcf->Flags & CF_NOSTYLESEL)
  530. wCmbId = cmb2;
  531. else
  532. wCmbId = NULL;
  533. if (wCmbId) /* Error found */
  534. {
  535. LoadString(hinsCur, (wCmbId == cmb1) ? iszNoFaceSel
  536. : iszNoStyleSel, szMsg, sizeof(szMsg));
  537. GetWindowText(hDlg, szTitle, sizeof(szTitle));
  538. MessageBox(hDlg, szMsg, szTitle, MB_OK|MB_ICONINFORMATION);
  539. PostMessage(hDlg,WM_NEXTDLGCTL,GetDlgItem(hDlg,wCmbId),1L);
  540. break;
  541. }
  542. }
  543. if (lpcf->Flags & CF_EFFECTS) {
  544. // Get currently selected item in color combo box and the 32 bit
  545. // color rgb value associated with it
  546. iSel = (int)SendDlgItemMessage(hDlg, cmb4, CB_GETCURSEL, 0, 0L);
  547. lpcf->rgbColors= (DWORD)SendDlgItemMessage(hDlg, cmb4, CB_GETITEMDATA, iSel, 0L);
  548. }
  549. CBGetTextAndData(GetDlgItem(hDlg, cmb2), szStyle, sizeof(szStyle), &dw);
  550. lpcf->nFontType = HIWORD(dw);
  551. if (lpcf->Flags & CF_USESTYLE)
  552. lstrcpy(lpcf->lpszStyle, szStyle);
  553. // fall through
  554. case IDCANCEL:
  555. FreeFonts(GetDlgItem(hDlg, cmb2));
  556. EndDialog(hDlg, wParam == IDOK);
  557. RemoveProp(hDlg, FONTPROP);
  558. if (lpcf->Flags & CF_ENABLEHOOK)
  559. glpfnFontHook = lpcf->lpfnHook;
  560. break;
  561. case cmb1: // facenames combobox
  562. switch (HIWORD(lParam)) {
  563. case CBN_SELCHANGE:
  564. CBSetTextFromSel(LOWORD(lParam));
  565. FillStyles:
  566. // try to mainting the current point size and style
  567. GetDlgItemText(hDlg, cmb3, szPoints, sizeof(szPoints));
  568. GetFontStylesAndSizes(hDlg, lpcf, FALSE);
  569. SetStyleSelection(hDlg, lpcf, FALSE);
  570. // preserv the point size selection or put it in the
  571. // edit control if it is not in the list for this font
  572. iSel = CBFindString(GetDlgItem(hDlg, cmb3), szPoints);
  573. if (iSel < 0) {
  574. SetDlgItemText(hDlg, cmb3, szPoints);
  575. } else {
  576. SendDlgItemMessage(hDlg, cmb3, CB_SETCURSEL, iSel, 0L);
  577. // 3.0 wipes out the edit text in the above call
  578. if (wWinVer < 0x030A)
  579. CBSetTextFromSel(GetDlgItem(hDlg, cmb3));
  580. }
  581. if (wWinVer < 0x030A)
  582. PostMessage(hDlg, WM_COMMAND, cmb1, MAKELONG(LOWORD(lParam), CBN_MYSELCHANGE));
  583. goto DrawSample;
  584. break;
  585. case CBN_MYSELCHANGE: // for 3.0
  586. CBSetTextFromSel(LOWORD(lParam));
  587. SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, 0xFFFF0000);
  588. break;
  589. case CBN_EDITUPDATE:
  590. PostMessage(hDlg, WM_COMMAND, wParam, MAKELONG(LOWORD(lParam), CBN_MYEDITUPDATE));
  591. break;
  592. // case CBN_EDITCHANGE:
  593. // case CBN_EDITUPDATE:
  594. case CBN_MYEDITUPDATE:
  595. GetWindowText(LOWORD(lParam), szStyle, sizeof(szStyle));
  596. iSel = CBFindString(LOWORD(lParam), szStyle);
  597. if (iSel >= 0) {
  598. SendMessage(LOWORD(lParam), CB_SETCURSEL, iSel, 0L);
  599. // 3.0 wipes out the edit text in the above call
  600. if (wWinVer < 0x030A)
  601. CBSetTextFromSel(LOWORD(lParam));
  602. SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, -1L);
  603. goto FillStyles;
  604. }
  605. break;
  606. }
  607. break;
  608. case cmb3: // point sizes combobox
  609. case cmb2: // styles combobox
  610. switch (HIWORD(lParam)) {
  611. case CBN_EDITUPDATE:
  612. PostMessage(hDlg, WM_COMMAND, wParam, MAKELONG(LOWORD(lParam), CBN_MYEDITUPDATE));
  613. break;
  614. // case CBN_EDITCHANGE:
  615. // case CBN_EDITUPDATE:
  616. case CBN_MYEDITUPDATE:
  617. if (wParam == cmb2) {
  618. GetWindowText(LOWORD(lParam), szStyle, sizeof(szStyle));
  619. iSel = CBFindString(LOWORD(lParam), szStyle);
  620. if (iSel >= 0) {
  621. SendMessage(LOWORD(lParam), CB_SETCURSEL, iSel, 0L);
  622. // 3.0 wipes out the edit text in the above call
  623. if (wWinVer < 0x030A)
  624. CBSetTextFromSel(LOWORD(lParam));
  625. SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, -1L);
  626. goto DrawSample;
  627. }
  628. }
  629. break;
  630. case CBN_SELCHANGE:
  631. iSel = CBSetTextFromSel(LOWORD(lParam));
  632. if (iSel >= 0) {
  633. // make the style selection stick
  634. if (wParam == cmb2) {
  635. PLOGFONT plf = (PLOGFONT)(WORD)SendMessage(LOWORD(lParam), CB_GETITEMDATA, iSel, 0L);
  636. lpcf->lpLogFont->lfWeight = plf->lfWeight;
  637. lpcf->lpLogFont->lfItalic = plf->lfItalic;
  638. }
  639. }
  640. if (wWinVer < 0x030A)
  641. PostMessage(hDlg, WM_COMMAND, wParam, MAKELONG(LOWORD(lParam), CBN_MYSELCHANGE));
  642. goto DrawSample;
  643. case CBN_MYSELCHANGE: // for 3.0
  644. CBSetTextFromSel(LOWORD(lParam));
  645. SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, 0xFFFF0000);
  646. break;
  647. case CBN_KILLFOCUS:
  648. DrawSample:
  649. // force redraw of preview text for any size change
  650. InvalidateRect(hDlg, &rcText, FALSE);
  651. UpdateWindow(hDlg);
  652. }
  653. break;
  654. case cmb4:
  655. if (HIWORD(lParam) != CBN_SELCHANGE)
  656. break;
  657. // fall through
  658. case chx1: // bold
  659. case chx2: // italic
  660. goto DrawSample;
  661. case pshHelp: // help
  662. if (msgHELP && lpcf->hwndOwner)
  663. SendMessage(lpcf->hwndOwner, msgHELP, hDlg, (DWORD) lpcf);
  664. break;
  665. default:
  666. return (FALSE);
  667. }
  668. return TRUE;
  669. }
  670. //
  671. // this returns the best of the 2 font types.
  672. // the values of the font type bits are monotonic except the low
  673. // bit (RASTER_FONTTYPE). so we flip that bit and then can compare
  674. // the words directly.
  675. //
  676. int NEAR PASCAL CmpFontType(WORD ft1, WORD ft2)
  677. {
  678. ft1 &= ~(SCREEN_FONTTYPE | PRINTER_FONTTYPE);
  679. ft2 &= ~(SCREEN_FONTTYPE | PRINTER_FONTTYPE);
  680. ft1 ^= RASTER_FONTTYPE; // flip these so we can compare
  681. ft2 ^= RASTER_FONTTYPE;
  682. return (int)ft1 - (int)ft2;
  683. }
  684. // nFontType bits
  685. //
  686. // SCALABLE DEVICE RASTER
  687. // (TT) (not GDI) (not scalable)
  688. // 0 0 0 vector, ATM screen
  689. // 0 0 1 GDI raster font
  690. // 0 1 0 PS/LJ III, ATM printer, ATI/LaserMaster
  691. // 0 1 1 non scalable device font
  692. // 1 0 x TT screen font
  693. // 1 1 x TT dev font
  694. int FAR PASCAL FontFamilyEnumProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, WORD nFontType, LPENUM_FONT_DATA lpData)
  695. {
  696. int iItem;
  697. WORD nOldType, nNewType;
  698. lptm = lptm;
  699. // bounce non TT fonts
  700. if ((lpData->dwFlags & CF_TTONLY) &&
  701. !(nFontType & TRUETYPE_FONTTYPE))
  702. return TRUE;
  703. // bounce non scalable fonts
  704. if ((lpData->dwFlags & CF_SCALABLEONLY) &&
  705. (nFontType & RASTER_FONTTYPE))
  706. return TRUE;
  707. // bounce non ANSI fonts
  708. if ((lpData->dwFlags & CF_ANSIONLY) &&
  709. (lplf->lfCharSet != ANSI_CHARSET))
  710. return TRUE;
  711. // bounce proportional fonts
  712. if ((lpData->dwFlags & CF_FIXEDPITCHONLY) &&
  713. (lplf->lfPitchAndFamily & VARIABLE_PITCH))
  714. return TRUE;
  715. // bounce vector fonts
  716. if ((lpData->dwFlags & CF_NOVECTORFONTS) &&
  717. (lplf->lfCharSet == OEM_CHARSET))
  718. return TRUE;
  719. if (lpData->bPrinterFont)
  720. nFontType |= PRINTER_FONTTYPE;
  721. else
  722. nFontType |= SCREEN_FONTTYPE;
  723. // test for a name collision
  724. iItem = CBFindString(lpData->hwndFamily, lplf->lfFaceName);
  725. if (iItem >= 0) {
  726. nOldType = (WORD)SendMessage(lpData->hwndFamily, CB_GETITEMDATA, iItem, 0L);
  727. /* If we don't want screen fonts, but do want printer fonts,
  728. * the old font is a screen font and the new font is a
  729. * printer font, take the new font regardless of other flags.
  730. * Note that this means if a printer wants TRUETYPE fonts, it
  731. * should enumerate them. Bug 9675, 12-12-91, Clark Cyr
  732. */
  733. if (!(lpData->dwFlags & CF_SCREENFONTS) &&
  734. (lpData->dwFlags & CF_PRINTERFONTS) &&
  735. (nFontType & PRINTER_FONTTYPE) &&
  736. (nOldType & SCREEN_FONTTYPE) )
  737. {
  738. nOldType = 0; /* for setting nNewType below */
  739. goto SetNewType;
  740. }
  741. if (CmpFontType(nFontType, nOldType) > 0) {
  742. SetNewType:
  743. nNewType = nFontType;
  744. SendMessage(lpData->hwndFamily, CB_INSERTSTRING, iItem, (LONG)(LPSTR)lplf->lfFaceName);
  745. SendMessage(lpData->hwndFamily, CB_DELETESTRING, iItem + 1, 0L);
  746. } else {
  747. nNewType = nOldType;
  748. }
  749. // accumulate the printer/screen ness of these fonts
  750. nNewType |= (nFontType | nOldType) & (SCREEN_FONTTYPE | PRINTER_FONTTYPE);
  751. SendMessage(lpData->hwndFamily, CB_SETITEMDATA, iItem, MAKELONG(nNewType, 0));
  752. return TRUE;
  753. }
  754. iItem = (int)SendMessage(lpData->hwndFamily, CB_ADDSTRING, 0, (LONG)(LPSTR)lplf->lfFaceName);
  755. if (iItem < 0)
  756. return FALSE;
  757. SendMessage(lpData->hwndFamily, CB_SETITEMDATA, iItem, MAKELONG(nFontType, 0));
  758. return TRUE;
  759. }
  760. /****************************************************************************
  761. *
  762. * GetFontFamily
  763. *
  764. * PURPOSE : Fills the screen and/or printer font facenames into the font
  765. * facenames combobox, depending on the CF_?? flags passed in.
  766. *
  767. * ASSUMES : cmb1 - ID of font facename combobox
  768. *
  769. * RETURNS : TRUE if succesful, FALSE otherwise.
  770. *
  771. * COMMENTS : Both screen and printer fonts are listed into the same combo
  772. * box.
  773. *
  774. ****************************************************************************/
  775. BOOL NEAR PASCAL GetFontFamily(HWND hDlg, HDC hDC, DWORD dwEnumCode)
  776. {
  777. ENUM_FONT_DATA data;
  778. HANDLE hMod;
  779. int iItem, iCount;
  780. WORD nFontType;
  781. char szMsg[100], szTitle[40];
  782. WORD (FAR PASCAL *lpEnumFonts)(HDC, LPSTR, FARPROC, VOID FAR *);
  783. hMod = GetModuleHandle(szGDI);
  784. if (wWinVer < 0x030A)
  785. lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts30);
  786. else
  787. lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts31);
  788. if (!lpEnumFonts)
  789. return FALSE;
  790. data.hwndFamily = GetDlgItem(hDlg, cmb1);
  791. data.dwFlags = dwEnumCode;
  792. // this is a bit strage. we have to get all the screen fonts
  793. // so if they ask for the printer fonts we can tell which
  794. // are really printer fonts. that is so we don't list the
  795. // vector and raster fonts as printer device fonts
  796. data.hDC = GetDC(NULL);
  797. data.bPrinterFont = FALSE;
  798. (*lpEnumFonts)(data.hDC, NULL, FontFamilyEnumProc, &data);
  799. ReleaseDC(NULL, data.hDC);
  800. /* list out printer font facenames */
  801. if (dwEnumCode & CF_PRINTERFONTS) {
  802. data.hDC = hDC;
  803. data.bPrinterFont = TRUE;
  804. (*lpEnumFonts)(hDC, NULL, FontFamilyEnumProc, &data);
  805. }
  806. // now we have to remove those screen fonts if they didn't
  807. // ask for them.
  808. if (!(dwEnumCode & CF_SCREENFONTS)) {
  809. iCount = (int)SendMessage(data.hwndFamily, CB_GETCOUNT, 0, 0L);
  810. for (iItem = iCount - 1; iItem >= 0; iItem--) {
  811. nFontType = (WORD)SendMessage(data.hwndFamily, CB_GETITEMDATA, iItem, 0L);
  812. if ((nFontType & (SCREEN_FONTTYPE | PRINTER_FONTTYPE)) == SCREEN_FONTTYPE)
  813. SendMessage(data.hwndFamily, CB_DELETESTRING, iItem, 0L);
  814. }
  815. }
  816. // for WYSIWYG mode we delete all the fonts that don't exist
  817. // on the screen and the printer
  818. if (dwEnumCode & CF_WYSIWYG) {
  819. iCount = (int)SendMessage(data.hwndFamily, CB_GETCOUNT, 0, 0L);
  820. for (iItem = iCount - 1; iItem >= 0; iItem--) {
  821. nFontType = (WORD)SendMessage(data.hwndFamily, CB_GETITEMDATA, iItem, 0L);
  822. if ((nFontType & (SCREEN_FONTTYPE | PRINTER_FONTTYPE)) != (SCREEN_FONTTYPE | PRINTER_FONTTYPE))
  823. SendMessage(data.hwndFamily, CB_DELETESTRING, iItem, 0L);
  824. }
  825. }
  826. if ((int)SendMessage(data.hwndFamily, CB_GETCOUNT, 0, 0L) <= 0) {
  827. LoadString(hinsCur, iszNoFontsTitle, szTitle, sizeof(szTitle));
  828. LoadString(hinsCur, iszNoFontsMsg, szMsg, sizeof(szMsg));
  829. MessageBox(hDlg, szMsg, szTitle, MB_OK | MB_ICONINFORMATION);
  830. return FALSE;
  831. }
  832. return TRUE;
  833. }
  834. void NEAR PASCAL CBAddSize(HWND hwnd, int pts, LPCHOOSEFONT lpcf)
  835. {
  836. int iInd;
  837. char szSize[10];
  838. int count, test_size;
  839. if ((lpcf->Flags & CF_LIMITSIZE) && ((pts > lpcf->nSizeMax) || (pts < lpcf->nSizeMin)))
  840. return;
  841. wsprintf(szSize, szPtFormat, pts);
  842. count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
  843. test_size = -1;
  844. for (iInd = 0; iInd < count; iInd++) {
  845. test_size = (int)SendMessage(hwnd, CB_GETITEMDATA, iInd, 0L);
  846. if (pts <= test_size)
  847. break;
  848. }
  849. if (pts == test_size) /* don't add duplicates */
  850. return;
  851. iInd = (int)SendMessage(hwnd, CB_INSERTSTRING, iInd, (LONG)(LPSTR)szSize);
  852. if (iInd >= 0)
  853. SendMessage(hwnd, CB_SETITEMDATA, iInd, MAKELONG(pts, 0));
  854. }
  855. // sort styles by weight first, then italicness
  856. // returns:
  857. // the index of the place this was inserted
  858. int NEAR PASCAL InsertStyleSorted(HWND hwnd, LPSTR lpszStyle, LPLOGFONT lplf)
  859. {
  860. int count, i;
  861. LPLOGFONT plf;
  862. count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
  863. for (i = 0; i < count; i++) {
  864. plf = (LPLOGFONT)SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
  865. if (lplf->lfWeight < plf->lfWeight) {
  866. break;
  867. } else if (lplf->lfWeight == plf->lfWeight) {
  868. if (lplf->lfItalic && !plf->lfItalic)
  869. i++;
  870. break;
  871. }
  872. }
  873. return (int)SendMessage(hwnd, CB_INSERTSTRING, i, (LONG)lpszStyle);
  874. }
  875. PLOGFONT NEAR PASCAL CBAddStyle(HWND hwnd, LPSTR lpszStyle, WORD nFontType, LPLOGFONT lplf)
  876. {
  877. int iItem;
  878. PLOGFONT plf;
  879. // don't add duplicates
  880. if (CBFindString(hwnd, lpszStyle) >= 0)
  881. return NULL;
  882. iItem = (int)InsertStyleSorted(hwnd, lpszStyle, lplf);
  883. if (iItem < 0)
  884. return NULL;
  885. plf = (PLOGFONT)LocalAlloc(LMEM_FIXED, sizeof(LOGFONT));
  886. if (!plf) {
  887. SendMessage(hwnd, CB_DELETESTRING, iItem, 0L);
  888. return NULL;
  889. }
  890. *plf = *lplf;
  891. SendMessage(hwnd, CB_SETITEMDATA, iItem, MAKELONG(plf, nFontType));
  892. return plf;
  893. }
  894. // generate simulated forms from those that we have
  895. //
  896. // reg -> bold
  897. // reg -> italic
  898. // bold || italic || reg -> bold italic
  899. void NEAR PASCAL FillInMissingStyles(HWND hwnd)
  900. {
  901. PLOGFONT plf, plf_reg, plf_bold, plf_italic;
  902. WORD nFontType;
  903. int i, count;
  904. BOOL bBold, bItalic, bBoldItalic;
  905. DWORD dw;
  906. LOGFONT lf;
  907. bBold = bItalic = bBoldItalic = FALSE;
  908. plf_reg = plf_bold = plf_italic = NULL;
  909. count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
  910. for (i = 0; i < count; i++) {
  911. dw = SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
  912. plf = (PLOGFONT)LOWORD(dw);
  913. nFontType = HIWORD(dw);
  914. if ((nFontType & BOLD_FONTTYPE) && (nFontType & ITALIC_FONTTYPE)) {
  915. bBoldItalic = TRUE;
  916. } else if (nFontType & BOLD_FONTTYPE) {
  917. bBold = TRUE;
  918. plf_bold = plf;
  919. } else if (nFontType & ITALIC_FONTTYPE) {
  920. bItalic = TRUE;
  921. plf_italic = plf;
  922. } else
  923. plf_reg = plf;
  924. }
  925. nFontType |= SIMULATED_FONTTYPE;
  926. if (!bBold && plf_reg) {
  927. lf = *plf_reg;
  928. lf.lfWeight = FW_BOLD;
  929. CBAddStyle(hwnd, szBold, nFontType | BOLD_FONTTYPE, &lf);
  930. }
  931. if (!bItalic && plf_reg) {
  932. lf = *plf_reg;
  933. lf.lfItalic = TRUE;
  934. CBAddStyle(hwnd, szItalic, nFontType | ITALIC_FONTTYPE, &lf);
  935. }
  936. if (!bBoldItalic && (plf_bold || plf_italic || plf_reg)) {
  937. if (plf_italic)
  938. plf = plf_italic;
  939. else if (plf_bold)
  940. plf = plf_bold;
  941. else
  942. plf = plf_reg;
  943. lf = *plf;
  944. lf.lfItalic = TRUE;
  945. lf.lfWeight = FW_BOLD;
  946. CBAddStyle(hwnd, szBoldItalic, nFontType | BOLD_FONTTYPE | ITALIC_FONTTYPE, &lf);
  947. }
  948. }
  949. void NEAR PASCAL FillScalableSizes(HWND hwnd, LPCHOOSEFONT lpcf)
  950. {
  951. CBAddSize(hwnd, 8, lpcf);
  952. CBAddSize(hwnd, 9, lpcf);
  953. CBAddSize(hwnd, 10, lpcf);
  954. CBAddSize(hwnd, 11, lpcf);
  955. CBAddSize(hwnd, 12, lpcf);
  956. CBAddSize(hwnd, 14, lpcf);
  957. CBAddSize(hwnd, 16, lpcf);
  958. CBAddSize(hwnd, 18, lpcf);
  959. CBAddSize(hwnd, 20, lpcf);
  960. CBAddSize(hwnd, 22, lpcf);
  961. CBAddSize(hwnd, 24, lpcf);
  962. CBAddSize(hwnd, 26, lpcf);
  963. CBAddSize(hwnd, 28, lpcf);
  964. CBAddSize(hwnd, 36, lpcf);
  965. CBAddSize(hwnd, 48, lpcf);
  966. CBAddSize(hwnd, 72, lpcf);
  967. }
  968. #define GDI_FONTTYPE_STUFF (RASTER_FONTTYPE | DEVICE_FONTTYPE | TRUETYPE_FONTTYPE)
  969. int FAR PASCAL FontStyleEnumProc(LPLOGFONT lplf, LPNEWTEXTMETRIC lptm, WORD nFontType, LPENUM_FONT_DATA lpData)
  970. {
  971. int height, pts;
  972. char buf[10];
  973. // filter for a font type match (the font type of the selected face
  974. // must be the same as that enumerated)
  975. if (nFontType != (WORD)(GDI_FONTTYPE_STUFF & lpData->nFontType))
  976. return TRUE;
  977. if (!(nFontType & RASTER_FONTTYPE)) {
  978. // vector or TT font
  979. if (lpData->bFillSize &&
  980. (int)SendMessage(lpData->hwndSizes, CB_GETCOUNT, 0, 0L) == 0) {
  981. FillScalableSizes(lpData->hwndSizes, lpData->lpcf);
  982. }
  983. } else {
  984. height = lptm->tmHeight - lptm->tmInternalLeading;
  985. pts = GetPointString(buf, lpData->hDC, height);
  986. // filter devices same size of multiple styles
  987. if (CBFindString(lpData->hwndSizes, buf) < 0)
  988. CBAddSize(lpData->hwndSizes, pts, lpData->lpcf);
  989. }
  990. // keep the printer/screen bits from the family list here too
  991. nFontType |= (lpData->nFontType & (SCREEN_FONTTYPE | PRINTER_FONTTYPE));
  992. if (nFontType & TRUETYPE_FONTTYPE) {
  993. // if (lptm->ntmFlags & NTM_REGULAR)
  994. if (!(lptm->ntmFlags & (NTM_BOLD | NTM_ITALIC)))
  995. nFontType |= REGULAR_FONTTYPE;
  996. if (lptm->ntmFlags & NTM_ITALIC)
  997. nFontType |= ITALIC_FONTTYPE;
  998. if (lptm->ntmFlags & NTM_BOLD)
  999. nFontType |= BOLD_FONTTYPE;
  1000. // after the LOGFONT.lfFaceName there are 2 more names
  1001. // lfFullName[LF_FACESIZE * 2]
  1002. // lfStyle[LF_FACESIZE]
  1003. CBAddStyle(lpData->hwndStyle, lplf->lfFaceName + 3 * LF_FACESIZE, nFontType, lplf);
  1004. } else {
  1005. if ((lplf->lfWeight >= FW_BOLD) && lplf->lfItalic)
  1006. CBAddStyle(lpData->hwndStyle, szBoldItalic, nFontType | BOLD_FONTTYPE | ITALIC_FONTTYPE, lplf);
  1007. else if (lplf->lfWeight >= FW_BOLD)
  1008. CBAddStyle(lpData->hwndStyle, szBold, nFontType | BOLD_FONTTYPE, lplf);
  1009. else if (lplf->lfItalic)
  1010. CBAddStyle(lpData->hwndStyle, szItalic, nFontType | ITALIC_FONTTYPE, lplf);
  1011. else
  1012. CBAddStyle(lpData->hwndStyle, szRegular, nFontType | REGULAR_FONTTYPE, lplf);
  1013. }
  1014. return TRUE;
  1015. }
  1016. void NEAR PASCAL FreeFonts(HWND hwnd)
  1017. {
  1018. DWORD dw;
  1019. int i, count;
  1020. count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
  1021. for (i = 0; i < count; i++) {
  1022. dw = SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
  1023. LocalFree((HANDLE)LOWORD(dw));
  1024. }
  1025. SendMessage(hwnd, CB_RESETCONTENT, 0, 0L);
  1026. }
  1027. // initalize a LOGFONT strucuture to some base generic regular type font
  1028. void NEAR PASCAL InitLF(LPLOGFONT lplf)
  1029. {
  1030. HDC hdc;
  1031. lplf->lfEscapement = 0;
  1032. lplf->lfOrientation = 0;
  1033. lplf->lfCharSet = ANSI_CHARSET;
  1034. lplf->lfOutPrecision = OUT_DEFAULT_PRECIS;
  1035. lplf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
  1036. lplf->lfQuality = DEFAULT_QUALITY;
  1037. lplf->lfPitchAndFamily = DEFAULT_PITCH;
  1038. lplf->lfItalic = 0;
  1039. lplf->lfWeight = FW_NORMAL;
  1040. lplf->lfStrikeOut = 0;
  1041. lplf->lfUnderline = 0;
  1042. lplf->lfWidth = 0; // otherwise we get independant x-y scaling
  1043. lplf->lfFaceName[0] = 0;
  1044. hdc = GetDC(NULL);
  1045. lplf->lfHeight = -MulDiv(DEF_POINT_SIZE, GetDeviceCaps(hdc, LOGPIXELSY), POINTS_PER_INCH);
  1046. ReleaseDC(NULL, hdc);
  1047. }
  1048. /****************************************************************************
  1049. *
  1050. * GetFontStylesAndSizes
  1051. *
  1052. * PURPOSE : Fills the point sizes combo box with the point sizes for the
  1053. * current selection in the facenames combobox.
  1054. *
  1055. * ASSUMES : cmb1 - ID of font facename combobox
  1056. *
  1057. * RETURNS : TRUE if succesful, FALSE otherwise.
  1058. *
  1059. ****************************************************************************/
  1060. BOOL NEAR PASCAL GetFontStylesAndSizes(HWND hDlg, LPCHOOSEFONT lpcf, BOOL bForceSizeFill)
  1061. {
  1062. ENUM_FONT_DATA data;
  1063. char szFace[LF_FACESIZE];
  1064. WORD nFontType;
  1065. int iSel;
  1066. int iMapMode;
  1067. DWORD dwViewportExt, dwWindowExt;
  1068. HANDLE hMod;
  1069. LOGFONT lf;
  1070. WORD (FAR PASCAL *lpEnumFonts)(HDC, LPSTR, FARPROC, VOID FAR *);
  1071. bForceSizeFill = bForceSizeFill;
  1072. hMod = GetModuleHandle(szGDI);
  1073. if (wWinVer < 0x030A)
  1074. lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts30);
  1075. else
  1076. lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts31);
  1077. if (!lpEnumFonts)
  1078. return FALSE;
  1079. FreeFonts(GetDlgItem(hDlg, cmb2));
  1080. data.hwndStyle = GetDlgItem(hDlg, cmb2);
  1081. data.hwndSizes = GetDlgItem(hDlg, cmb3);
  1082. data.dwFlags = lpcf->Flags;
  1083. data.lpcf = lpcf;
  1084. iSel = (int)SendDlgItemMessage(hDlg, cmb1, CB_GETCURSEL, 0, 0L);
  1085. if (iSel < 0) {
  1086. // if we don't have a face name selected we will synthisize
  1087. // the standard font styles...
  1088. InitLF(&lf);
  1089. CBAddStyle(data.hwndStyle, szRegular, REGULAR_FONTTYPE, &lf);
  1090. lf.lfWeight = FW_BOLD;
  1091. CBAddStyle(data.hwndStyle, szBold, BOLD_FONTTYPE, &lf);
  1092. lf.lfWeight = FW_NORMAL;
  1093. lf.lfItalic = TRUE;
  1094. CBAddStyle(data.hwndStyle, szItalic, ITALIC_FONTTYPE, &lf);
  1095. lf.lfWeight = FW_BOLD;
  1096. CBAddStyle(data.hwndStyle, szBoldItalic, BOLD_FONTTYPE | ITALIC_FONTTYPE, &lf);
  1097. FillScalableSizes(data.hwndSizes, lpcf);
  1098. return TRUE;
  1099. }
  1100. nFontType = (WORD)SendDlgItemMessage(hDlg, cmb1, CB_GETITEMDATA, iSel, 0L);
  1101. data.nFontType = nFontType;
  1102. #if 0
  1103. data.bFillSize = bForceSizeFill ||
  1104. (nLastFontType & RASTER_FONTTYPE) != (nFontType & RASTER_FONTTYPE) ||
  1105. (nFontType & RASTER_FONTTYPE);
  1106. /* This does the same thing as above, i.e. if either or both fonts are
  1107. * raster fonts, update the sizes combobox. If they're both non-raster,
  1108. * don't update the combobox.
  1109. */
  1110. data.bFillSize = bForceSizeFill ||
  1111. (nLastFontType & RASTER_FONTTYPE) ||
  1112. (nFontType & RASTER_FONTTYPE) ||
  1113. (SendMessage(data.hwndSizes, CB_GETCOUNT, 0, 0L) <= 0);
  1114. #else
  1115. data.bFillSize = TRUE;
  1116. #endif
  1117. if (data.bFillSize) {
  1118. SendMessage(data.hwndSizes, CB_RESETCONTENT, 0, 0L);
  1119. SendMessage(data.hwndSizes, WM_SETREDRAW, FALSE, 0L);
  1120. }
  1121. SendMessage(data.hwndStyle, WM_SETREDRAW, FALSE, 0L);
  1122. GetDlgItemText(hDlg, cmb1, szFace, sizeof(szFace));
  1123. if (lpcf->Flags & CF_SCREENFONTS) {
  1124. data.hDC = GetDC(NULL);
  1125. data.bPrinterFont = FALSE;
  1126. (*lpEnumFonts)(data.hDC, szFace, FontStyleEnumProc, &data);
  1127. ReleaseDC(NULL, data.hDC);
  1128. }
  1129. if (lpcf->Flags & CF_PRINTERFONTS) {
  1130. /* Bug #10619: Save and restore the DC's mapping mode (and extents if
  1131. * needed) if it's been set by the app to something other than MM_TEXT.
  1132. * 3 January 1992 Clark Cyr
  1133. */
  1134. if ((iMapMode = GetMapMode(lpcf->hDC)) != MM_TEXT)
  1135. {
  1136. if ((iMapMode == MM_ISOTROPIC) || (iMapMode == MM_ANISOTROPIC))
  1137. {
  1138. dwViewportExt = GetViewportExt(lpcf->hDC);
  1139. dwWindowExt = GetWindowExt(lpcf->hDC);
  1140. }
  1141. SetMapMode(lpcf->hDC, MM_TEXT);
  1142. }
  1143. data.hDC = lpcf->hDC;
  1144. data.bPrinterFont = TRUE;
  1145. (*lpEnumFonts)(lpcf->hDC, szFace, FontStyleEnumProc, &data);
  1146. if (iMapMode != MM_TEXT)
  1147. {
  1148. SetMapMode(lpcf->hDC, iMapMode);
  1149. if ((iMapMode == MM_ISOTROPIC) || (iMapMode == MM_ANISOTROPIC))
  1150. {
  1151. SetWindowExt(lpcf->hDC, LOWORD(dwWindowExt),
  1152. HIWORD(dwWindowExt));
  1153. SetViewportExt(lpcf->hDC, LOWORD(dwViewportExt),
  1154. HIWORD(dwViewportExt));
  1155. }
  1156. }
  1157. }
  1158. if (!(lpcf->Flags & CF_NOSIMULATIONS))
  1159. FillInMissingStyles(data.hwndStyle);
  1160. SendMessage(data.hwndStyle, WM_SETREDRAW, TRUE, 0L);
  1161. if (wWinVer < 0x030A)
  1162. InvalidateRect(data.hwndStyle, NULL, TRUE);
  1163. if (data.bFillSize) {
  1164. SendMessage(data.hwndSizes, WM_SETREDRAW, TRUE, 0L);
  1165. if (wWinVer < 0x030A)
  1166. InvalidateRect(data.hwndSizes, NULL, TRUE);
  1167. }
  1168. return TRUE;
  1169. }
  1170. /****************************************************************************
  1171. *
  1172. * FillColorCombo
  1173. *
  1174. * PURPOSE : Adds the color name strings to the colors combobox.
  1175. *
  1176. * ASSUMES : cmb4 - ID of colors combobox
  1177. *
  1178. * COMMENTS : The color rectangles are drawn later in response to
  1179. * WM_DRAWITEM messages
  1180. *
  1181. ****************************************************************************/
  1182. void NEAR PASCAL FillColorCombo(HWND hDlg)
  1183. {
  1184. int iT, item;
  1185. char szT[CCHCOLORNAMEMAX];
  1186. for (iT = 0; iT < CCHCOLORS; ++iT)
  1187. {
  1188. *szT = 0;
  1189. LoadString(hinsCur, iszBlack + iT, szT, sizeof(szT));
  1190. item = (int)SendDlgItemMessage(hDlg, cmb4, CB_INSERTSTRING, iT, (LONG)(LPSTR)szT);
  1191. if (item >= 0)
  1192. SendDlgItemMessage(hDlg, cmb4, CB_SETITEMDATA, item, rgbColors[iT]);
  1193. }
  1194. }
  1195. /****************************************************************************
  1196. *
  1197. * ComputeSampleTextRectangle
  1198. *
  1199. * PURPOSE : Determines the bounding rectangle for the text preview area,
  1200. * and fills in rcText.
  1201. *
  1202. * ASSUMES : stc5 - ID preview text rectangle
  1203. *
  1204. * COMMENTS : The coordinates are calculated w.r.t the dialog.
  1205. *
  1206. ****************************************************************************/
  1207. void NEAR PASCAL ComputeSampleTextRectangle(HWND hDlg)
  1208. {
  1209. GetWindowRect(GetDlgItem (hDlg, stc5), &rcText);
  1210. ScreenToClient(hDlg, (LPPOINT)&rcText.left);
  1211. ScreenToClient(hDlg, (LPPOINT)&rcText.right);
  1212. }
  1213. BOOL NEAR PASCAL DrawSizeComboItem(LPDRAWITEMSTRUCT lpdis)
  1214. {
  1215. HDC hDC;
  1216. DWORD rgbBack, rgbText;
  1217. char szFace[10];
  1218. hDC = lpdis->hDC;
  1219. if (lpdis->itemState & ODS_SELECTED) {
  1220. rgbBack = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
  1221. rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  1222. } else {
  1223. rgbBack = SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  1224. rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  1225. }
  1226. SendMessage(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LONG)(LPSTR)szFace);
  1227. ExtTextOut(hDC, lpdis->rcItem.left + GetSystemMetrics(SM_CXBORDER), lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, szFace, lstrlen(szFace), NULL);
  1228. SetTextColor(hDC, rgbText);
  1229. SetBkColor(hDC, rgbBack);
  1230. return TRUE;
  1231. }
  1232. BOOL NEAR PASCAL DrawFamilyComboItem(LPDRAWITEMSTRUCT lpdis)
  1233. {
  1234. HDC hDC, hdcMem;
  1235. DWORD rgbBack, rgbText;
  1236. char szFace[LF_FACESIZE + 10];
  1237. HBITMAP hOld;
  1238. int dy, x;
  1239. hDC = lpdis->hDC;
  1240. if (lpdis->itemState & ODS_SELECTED) {
  1241. rgbBack = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
  1242. rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  1243. } else {
  1244. rgbBack = SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  1245. rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  1246. }
  1247. // wsprintf(szFace, "%4.4X", LOWORD(lpdis->itemData));
  1248. SendMessage(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LONG)(LPSTR)szFace);
  1249. ExtTextOut(hDC, lpdis->rcItem.left + DX_BITMAP, lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, szFace, lstrlen(szFace), NULL);
  1250. hdcMem = CreateCompatibleDC(hDC);
  1251. if (hdcMem) {
  1252. if (hbmFont) {
  1253. hOld = SelectObject(hdcMem, hbmFont);
  1254. if (lpdis->itemData & TRUETYPE_FONTTYPE)
  1255. x = 0;
  1256. else if ((lpdis->itemData & (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) == (PRINTER_FONTTYPE | DEVICE_FONTTYPE))
  1257. // this may be a screen and printer font but
  1258. // we will call it a printer font here
  1259. x = DX_BITMAP;
  1260. else
  1261. goto SkipBlt;
  1262. dy = ((lpdis->rcItem.bottom - lpdis->rcItem.top) - DY_BITMAP) / 2;
  1263. BitBlt(hDC, lpdis->rcItem.left, lpdis->rcItem.top + dy, DX_BITMAP, DY_BITMAP, hdcMem,
  1264. x, lpdis->itemState & ODS_SELECTED ? DY_BITMAP : 0, SRCCOPY);
  1265. SkipBlt:
  1266. SelectObject(hdcMem, hOld);
  1267. }
  1268. DeleteDC(hdcMem);
  1269. }
  1270. SetTextColor(hDC, rgbText);
  1271. SetBkColor(hDC, rgbBack);
  1272. return TRUE;
  1273. }
  1274. /****************************************************************************
  1275. *
  1276. * DrawColorComboItem
  1277. *
  1278. * PURPOSE : Called by main dialog fn. in response to a WM_DRAWITEM
  1279. * message, computes and draws the color combo items.
  1280. *
  1281. * RETURNS : TRUE if succesful, FALSE otherwise.
  1282. *
  1283. * COMMENTS : All color name strings have already loaded and filled into
  1284. * combobox.
  1285. *
  1286. ****************************************************************************/
  1287. BOOL NEAR PASCAL DrawColorComboItem(LPDRAWITEMSTRUCT lpdis)
  1288. {
  1289. HDC hDC;
  1290. HBRUSH hbr;
  1291. WORD dx, dy;
  1292. RECT rc;
  1293. char szColor[CCHCOLORNAMEMAX];
  1294. DWORD rgbBack, rgbText, dw;
  1295. hDC = lpdis->hDC;
  1296. if (lpdis->itemState & ODS_SELECTED) {
  1297. rgbBack = SetBkColor(hDC, GetSysColor (COLOR_HIGHLIGHT));
  1298. rgbText = SetTextColor(hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
  1299. } else {
  1300. rgbBack = SetBkColor(hDC, GetSysColor (COLOR_WINDOW));
  1301. rgbText = SetTextColor(hDC, GetSysColor (COLOR_WINDOWTEXT));
  1302. }
  1303. ExtTextOut(hDC, lpdis->rcItem.left, lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, NULL, 0, NULL);
  1304. /* compute coordinates of color rectangle and draw it */
  1305. dx = (WORD)GetSystemMetrics(SM_CXBORDER);
  1306. dy = (WORD)GetSystemMetrics(SM_CYBORDER);
  1307. rc.top = lpdis->rcItem.top + dy;
  1308. rc.bottom = lpdis->rcItem.bottom - dy;
  1309. rc.left = lpdis->rcItem.left + dx;
  1310. rc.right = rc.left + 2 * (rc.bottom - rc.top);
  1311. if (wWinVer < 0x030A)
  1312. dw = SendMessage(lpdis->hwndItem, CB_GETITEMDATA, lpdis->itemID, 0L);
  1313. else
  1314. dw = lpdis->itemData;
  1315. hbr = CreateSolidBrush(dw);
  1316. if (!hbr)
  1317. return FALSE;
  1318. hbr = SelectObject (hDC, hbr);
  1319. Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
  1320. DeleteObject(SelectObject(hDC, hbr));
  1321. /* shift the color text right by the width of the color rectangle */
  1322. *szColor = 0;
  1323. SendMessage(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LONG)(LPSTR)szColor);
  1324. TextOut(hDC, 2 * dx + rc.right, lpdis->rcItem.top, szColor, lstrlen(szColor));
  1325. SetTextColor(hDC, rgbText);
  1326. SetBkColor(hDC, rgbBack);
  1327. return TRUE;
  1328. }
  1329. /****************************************************************************
  1330. *
  1331. * DrawSampleText
  1332. *
  1333. * PURPOSE : To display the sample text with the given attributes
  1334. *
  1335. * COMMENTS : Assumes rcText holds the coordinates of the area within the
  1336. * frame (relative to dialog client) which text should be drawn in
  1337. *
  1338. ****************************************************************************/
  1339. void NEAR PASCAL DrawSampleText(HWND hDlg, LPCHOOSEFONT lpcf, HDC hDC)
  1340. {
  1341. DWORD rgbText;
  1342. DWORD rgbBack;
  1343. int iItem;
  1344. HFONT hFont, hTemp;
  1345. char szSample[50];
  1346. LOGFONT lf;
  1347. int len, x, y, dx, dy;
  1348. TEXTMETRIC tm;
  1349. BOOL bCompleteFont;
  1350. bCompleteFont = FillInFont(hDlg, lpcf, &lf, FALSE);
  1351. hFont = CreateFontIndirect(&lf);
  1352. if (!hFont)
  1353. return;
  1354. hTemp = SelectObject(hDC, hFont);
  1355. rgbBack = SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  1356. if (lpcf->Flags & CF_EFFECTS) {
  1357. iItem = (int)SendDlgItemMessage(hDlg, cmb4, CB_GETCURSEL, 0, 0L);
  1358. if (iItem != CB_ERR)
  1359. rgbText = SendDlgItemMessage(hDlg, cmb4, CB_GETITEMDATA, iItem, 0L);
  1360. else
  1361. goto GetWindowTextColor;
  1362. }
  1363. else
  1364. {
  1365. GetWindowTextColor:
  1366. rgbText = GetSysColor(COLOR_WINDOWTEXT);
  1367. }
  1368. rgbText = SetTextColor(hDC, rgbText);
  1369. if (bCompleteFont)
  1370. GetDlgItemText(hDlg, stc5, szSample, sizeof(szSample));
  1371. else
  1372. szSample[0] = 0;
  1373. GetTextMetrics(hDC, &tm);
  1374. len = lstrlen(szSample);
  1375. dx = (int)GetTextExtent(hDC, szSample, len);
  1376. dy = tm.tmAscent - tm.tmInternalLeading;
  1377. if ((dx >= (rcText.right - rcText.left)) || (dx <= 0))
  1378. x = rcText.left;
  1379. else
  1380. x = rcText.left + ((rcText.right - rcText.left) - (int)dx) / 2;
  1381. y = min(rcText.bottom, rcText.bottom - ((rcText.bottom - rcText.top) - (int)dy) / 2);
  1382. ExtTextOut(hDC, x, y - (tm.tmAscent), ETO_OPAQUE | ETO_CLIPPED, &rcText, szSample, len, NULL);
  1383. SetBkColor(hDC, rgbBack);
  1384. SetTextColor(hDC, rgbText);
  1385. if (hTemp)
  1386. DeleteObject(SelectObject(hDC, hTemp));
  1387. }
  1388. // fill in the LOGFONT strucuture based on the current selection
  1389. //
  1390. // in:
  1391. // bSetBits if TRUE the Flags fields in the lpcf are set to
  1392. // indicate what parts (face, style, size) are not
  1393. // selected
  1394. // out:
  1395. // lplf filled in LOGFONT
  1396. //
  1397. // returns:
  1398. // TRUE if there was an unambigious selection
  1399. // (the LOGFONT is filled as per the enumeration in)
  1400. // FALSE there was not a complete selection
  1401. // (fields set in the LOGFONT with default values)
  1402. BOOL NEAR PASCAL FillInFont(HWND hDlg, LPCHOOSEFONT lpcf, LPLOGFONT lplf, BOOL bSetBits)
  1403. {
  1404. HDC hdc;
  1405. int iSel, id, pts;
  1406. DWORD dw;
  1407. WORD nFontType;
  1408. PLOGFONT plf;
  1409. char szStyle[LF_FACESIZE];
  1410. char szMessage[128];
  1411. BOOL bFontComplete = TRUE;
  1412. InitLF(lplf);
  1413. GetDlgItemText(hDlg, cmb1, lplf->lfFaceName, sizeof(lplf->lfFaceName));
  1414. if (CBFindString(GetDlgItem(hDlg, cmb1), lplf->lfFaceName) >= 0) {
  1415. if (bSetBits)
  1416. lpcf->Flags &= ~CF_NOFACESEL;
  1417. } else {
  1418. bFontComplete = FALSE;
  1419. if (bSetBits)
  1420. lpcf->Flags |= CF_NOFACESEL;
  1421. }
  1422. iSel = CBGetTextAndData(GetDlgItem(hDlg, cmb2), szStyle, sizeof(szStyle), &dw);
  1423. if (iSel >= 0) {
  1424. nFontType = HIWORD(dw);
  1425. plf = (PLOGFONT)LOWORD(dw);
  1426. *lplf = *plf; // copy the LOGFONT
  1427. lplf->lfWidth = 0; // 1:1 x-y scaling
  1428. if (bSetBits)
  1429. lpcf->Flags &= ~CF_NOSTYLESEL;
  1430. } else {
  1431. bFontComplete = FALSE;
  1432. if (bSetBits)
  1433. lpcf->Flags |= CF_NOSTYLESEL;
  1434. nFontType = 0;
  1435. }
  1436. // now make sure the size is in range; pts will be 0 if not
  1437. GetPointSizeInRange(hDlg, lpcf, &pts, 0);
  1438. hdc = GetDC(NULL);
  1439. if (pts) {
  1440. lplf->lfHeight = -MulDiv(pts, GetDeviceCaps(hdc, LOGPIXELSY), POINTS_PER_INCH);
  1441. if (bSetBits)
  1442. lpcf->Flags &= ~CF_NOSIZESEL;
  1443. } else {
  1444. lplf->lfHeight = -MulDiv(DEF_POINT_SIZE, GetDeviceCaps(hdc, LOGPIXELSY), POINTS_PER_INCH);
  1445. bFontComplete = FALSE;
  1446. if (bSetBits)
  1447. lpcf->Flags |= CF_NOSIZESEL;
  1448. }
  1449. ReleaseDC(NULL, hdc);
  1450. // and the attributes we control
  1451. lplf->lfStrikeOut = (BYTE)IsDlgButtonChecked(hDlg, chx1);
  1452. lplf->lfUnderline = (BYTE)IsDlgButtonChecked(hDlg, chx2);
  1453. if (nFontType != nLastFontType) {
  1454. if (lpcf->Flags & CF_PRINTERFONTS) {
  1455. if (nFontType & SIMULATED_FONTTYPE) {
  1456. id = iszSynth;
  1457. } else if (nFontType & TRUETYPE_FONTTYPE) {
  1458. id = iszTrueType;
  1459. } else if ((nFontType & (PRINTER_FONTTYPE | SCREEN_FONTTYPE)) == SCREEN_FONTTYPE) {
  1460. id = iszGDIFont;
  1461. } else if ((nFontType & (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) == (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) {
  1462. // may be both screen and printer (ATM) but we'll just
  1463. // call this a printer font
  1464. id = iszPrinterFont;
  1465. } else {
  1466. szMessage[0] = 0;
  1467. goto SetText;
  1468. }
  1469. LoadString(hinsCur, id, szMessage, sizeof(szMessage));
  1470. SetText:
  1471. SetDlgItemText(hDlg, stc6, szMessage);
  1472. }
  1473. }
  1474. nLastFontType = nFontType;
  1475. return bFontComplete;
  1476. }
  1477. /****************************************************************************
  1478. *
  1479. * TermFont
  1480. *
  1481. * PURPOSE : To release any data required by functions in this module
  1482. * Called from WEP on exit from DLL
  1483. *
  1484. ****************************************************************************/
  1485. void FAR PASCAL TermFont(void)
  1486. {
  1487. if (hbmFont)
  1488. DeleteObject(hbmFont);
  1489. }
  1490. /****************************************************************************
  1491. *
  1492. * GetPointString
  1493. *
  1494. * PURPOSE : Converts font height into a string of digits repr. pointsize
  1495. *
  1496. * RETURNS : size in points and fills in buffer with string
  1497. *
  1498. ****************************************************************************/
  1499. int NEAR PASCAL GetPointString(LPSTR buf, HDC hDC, int height)
  1500. {
  1501. int pts;
  1502. pts = MulDiv((height < 0) ? -height : height, 72, GetDeviceCaps(hDC, LOGPIXELSY));
  1503. wsprintf(buf, szPtFormat, pts);
  1504. return pts;
  1505. }
  1506. //
  1507. // BOOL FAR PASCAL LoadBitmaps()
  1508. //
  1509. // this routine loads DIB bitmaps, and "fixes up" their color tables
  1510. // so that we get the desired result for the device we are on.
  1511. //
  1512. // this routine requires:
  1513. // the DIB is a 16 color DIB authored with the standard windows colors
  1514. // bright blue (00 00 FF) is converted to the background color!
  1515. // light grey (C0 C0 C0) is replaced with the button face color
  1516. // dark grey (80 80 80) is replaced with the button shadow color
  1517. //
  1518. // this means you can't have any of these colors in your bitmap
  1519. //
  1520. #define BACKGROUND 0x000000FF // bright blue
  1521. #define BACKGROUNDSEL 0x00FF00FF // bright blue
  1522. #define BUTTONFACE 0x00C0C0C0 // bright grey
  1523. #define BUTTONSHADOW 0x00808080 // dark grey
  1524. DWORD NEAR PASCAL FlipColor(DWORD rgb)
  1525. {
  1526. return RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb));
  1527. }
  1528. HBITMAP NEAR PASCAL LoadBitmaps(int id)
  1529. {
  1530. HDC hdc;
  1531. HANDLE h;
  1532. DWORD FAR *p;
  1533. LPSTR lpBits;
  1534. HANDLE hRes;
  1535. LPBITMAPINFOHEADER lpBitmapInfo;
  1536. int numcolors;
  1537. DWORD rgbSelected;
  1538. DWORD rgbUnselected;
  1539. HBITMAP hbm;
  1540. rgbSelected = FlipColor(GetSysColor(COLOR_HIGHLIGHT));
  1541. rgbUnselected = FlipColor(GetSysColor(COLOR_WINDOW));
  1542. h = FindResource(hinsCur, MAKEINTRESOURCE(id), RT_BITMAP);
  1543. hRes = LoadResource(hinsCur, h);
  1544. /* Lock the bitmap and get a pointer to the color table. */
  1545. lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
  1546. if (!lpBitmapInfo)
  1547. return FALSE;
  1548. p = (DWORD FAR *)((LPSTR)(lpBitmapInfo) + lpBitmapInfo->biSize);
  1549. /* Search for the Solid Blue entry and replace it with the current
  1550. * background RGB.
  1551. */
  1552. numcolors = 16;
  1553. while (numcolors-- > 0) {
  1554. if (*p == BACKGROUND)
  1555. *p = rgbUnselected;
  1556. else if (*p == BACKGROUNDSEL)
  1557. *p = rgbSelected;
  1558. #if 0
  1559. else if (*p == BUTTONFACE)
  1560. *p = FlipColor(GetSysColor(COLOR_BTNFACE));
  1561. else if (*p == BUTTONSHADOW)
  1562. *p = FlipColor(GetSysColor(COLOR_BTNSHADOW));
  1563. #endif
  1564. p++;
  1565. }
  1566. UnlockResource(hRes);
  1567. /* Now create the DIB. */
  1568. lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
  1569. /* First skip over the header structure */
  1570. lpBits = (LPSTR)(lpBitmapInfo + 1);
  1571. /* Skip the color table entries, if any */
  1572. lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
  1573. /* Create a color bitmap compatible with the display device */
  1574. hdc = GetDC(NULL);
  1575. hbm = CreateDIBitmap(hdc, lpBitmapInfo, (DWORD)CBM_INIT, lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS);
  1576. ReleaseDC(NULL, hdc);
  1577. MySetObjectOwner(hbm);
  1578. GlobalUnlock(hRes);
  1579. FreeResource(hRes);
  1580. return hbm;
  1581. }
  1582. #if 0
  1583. #define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
  1584. int NEAR PASCAL atoi(LPSTR sz)
  1585. {
  1586. int n = 0;
  1587. BOOL bNeg = FALSE;
  1588. if (*sz == '-') {
  1589. bNeg = TRUE;
  1590. sz++;
  1591. }
  1592. while (ISDIGIT(*sz)) {
  1593. n *= 10;
  1594. n += *sz - '0';
  1595. sz++;
  1596. }
  1597. return bNeg ? -n : n;
  1598. }
  1599. #endif