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.

1195 lines
38 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. /* loadfont.c - MW font support code */
  5. #define NOWINMESSAGES
  6. #define NOVIRTUALKEYCODES
  7. #define NOSYSMETRICS
  8. #define NOMENUS
  9. #define NOWINSTYLES
  10. #define NOCTLMGR
  11. #define NOCLIPBOARD
  12. #include <windows.h>
  13. #include "mw.h"
  14. #include "propdefs.h"
  15. #include "macro.h"
  16. #define NOUAC
  17. #include "cmddefs.h"
  18. #include "wwdefs.h"
  19. #include "fontdefs.h"
  20. #include "docdefs.h"
  21. #ifdef DBCS
  22. #include "dbcs.h"
  23. #include "kanji.h"
  24. #endif
  25. extern HDC vhMDC;
  26. extern HDC vhDCPrinter;
  27. extern struct CHP vchpNormal;
  28. extern int vifceMac;
  29. extern union FCID vfcidScreen;
  30. extern union FCID vfcidPrint;
  31. extern struct FCE rgfce[ifceMax];
  32. extern struct FCE *vpfceMru;
  33. extern struct FCE *vpfceScreen;
  34. extern struct FCE *vpfcePrint;
  35. extern struct FMI vfmiScreen;
  36. extern struct FMI vfmiPrint;
  37. #ifdef SYSENDMARK
  38. extern struct FMI vfmiSysScreen;
  39. #endif /* KANJI */
  40. extern int dxpLogInch;
  41. extern int dypLogInch;
  42. extern int dxaPrPage;
  43. extern int dyaPrPage;
  44. extern int dxpPrPage;
  45. extern int dypPrPage;
  46. extern int ypSubSuperPr;
  47. extern BOOL vfPrinterValid;
  48. #ifdef DEBUG
  49. BOOL NEAR DogoneTrashTest(HDC hdc, struct FCE *pfce, BOOL fPrint);
  50. #endif
  51. NEAR LoadFcid(union FCID *, struct CHP *);
  52. void NEAR SelectWriteFont(int, HFONT *);
  53. struct FCE * (PfceFcidScan(union FCID *));
  54. struct FCE * (PfceLruGet(void));
  55. #ifdef SMFONT
  56. void NEAR FillWidthTable(HDC, int [], TEXTMETRIC *);
  57. #endif /* SMFONT */
  58. #ifdef JAPAN // added 11 Jun. 1992 by Hiraisi
  59. void fnCheckWriting( LPLOGFONT );
  60. #endif
  61. LoadFont( doc, pchp, mdFont )
  62. /* loads the font specified in pchp for this doc. mdFont tells us how the
  63. font will be used (printer, screen, screen modulo printer,... */
  64. int doc;
  65. register struct CHP *pchp;
  66. int mdFont;
  67. {
  68. register int wFcid;
  69. struct CHP *pchpT;
  70. union FCID fcid;
  71. Assert(doc != docNil);
  72. pchpT = pchp;
  73. if (pchp == NULL)
  74. pchp = &vchpNormal;
  75. fcid.strFcid.hps = pchp->hps;
  76. fcid.strFcid.ftc = pchp->ftc;
  77. fcid.strFcid.doc = doc;
  78. #ifdef ENABLE
  79. wFcid = pchp->psWidth;
  80. wFcid |= bitPrintFcid;
  81. if (pchp->fItalic)
  82. wFcid |= bitItalicFcid;
  83. if (pchp->fBold)
  84. wFcid |= bitBoldFcid;
  85. if (pchp->fUline)
  86. wFcid |= bitUlineFcid;
  87. if (pchp->fFixedPitch)
  88. wFcid |= bitFixedPitchFcid;
  89. fcid.strFcid.wFcid = wFcid;
  90. #else
  91. /* Super-nitpick-optimization (but worth it because LoadFont can take
  92. 10% of display refresh time): bits being cleared is more
  93. common than set, and a "jump not taken" plus an "or di, xxxx" is 8
  94. cycles, vs the above "jump taken" which is 16 */
  95. wFcid = pchp->psWidth + bitPrintFcid + bitItalicFcid + bitBoldFcid +
  96. bitUlineFcid + bitFixedPitchFcid;
  97. if (!pchp->fItalic)
  98. wFcid &= ~bitItalicFcid;
  99. if (!pchp->fBold)
  100. wFcid &= ~bitBoldFcid;
  101. if (!pchp->fUline)
  102. wFcid &= ~bitUlineFcid;
  103. if (!pchp->fFixedPitch)
  104. wFcid &= ~bitFixedPitchFcid;
  105. fcid.strFcid.wFcid = wFcid;
  106. #endif
  107. switch (mdFont)
  108. {
  109. /* fall throughs are intentional! */
  110. default:
  111. break;
  112. case mdFontChk: /* sets font as constrained by printer avail */
  113. case mdFontPrint: /* like mdFontScreen, but for the printer */
  114. /* don't want to jam the chp props back */
  115. pchpT = NULL;
  116. case mdFontJam: /* like mdFontChk, but jams props into chp */
  117. /* get printer font loaded */
  118. LoadFcid(&fcid, pchpT);
  119. if (mdFont == mdFontPrint)
  120. /* don't need screen font */
  121. return;
  122. case mdFontScreen: /* sets font for random screen chars */
  123. /* get screen font loaded */
  124. fcid.strFcid.wFcid &= ~bitPrintFcid;
  125. LoadFcid(&fcid, (struct CHP *)NULL);
  126. }
  127. }
  128. NEAR LoadFcid(pfcid, pchp)
  129. /* loads described font and associates it with the appropriate dc's */
  130. union FCID *pfcid;
  131. struct CHP *pchp;
  132. {
  133. register struct FCE *pfce;
  134. int fPrint;
  135. int fTouchAndGo;
  136. int fGetMetrics;
  137. int fNewFont;
  138. struct FFN **hffnSave;
  139. LOGFONT lf;
  140. #ifdef SYSENDMARK
  141. fPrint = pfcid->strFcid.wFcid & bitPrintFcid;
  142. /* Since this ftc came from CHP, we have lost the first 2 bits. */
  143. if (pfcid->strFcid.ftc == (bitFtcChp & ftcSystem)) {
  144. /* If vpfceScreen == NULL already, the standard system font
  145. has already been selected. So, save some time here. */
  146. if (vpfceScreen != NULL) {
  147. /* Gives you the standard system font for the screen. */
  148. ResetFont(FALSE);
  149. }
  150. bltbyte(&vfmiSysScreen, &vfmiScreen, sizeof(struct FMI));
  151. #if defined(KANJI) && defined(DFONT)
  152. /* CommSz("System Font!\r\n"); */
  153. KTS();
  154. #endif
  155. return;
  156. }
  157. else if (fPrint)
  158. #else
  159. if ((fPrint = pfcid->strFcid.wFcid & bitPrintFcid))
  160. #endif /* if-else-def KANJI */
  161. {
  162. if (pfcid->lFcid == vfcidPrint.lFcid)
  163. {
  164. pfce = vpfcePrint;
  165. fTouchAndGo = TRUE;
  166. goto EstablishFont;
  167. }
  168. }
  169. else
  170. {
  171. if (pfcid->lFcid == vfcidScreen.lFcid)
  172. {
  173. pfce = vpfceScreen;
  174. fTouchAndGo = TRUE;
  175. goto EstablishFont;
  176. }
  177. }
  178. /* failed at the "trivial" comparisons - look through list */
  179. fTouchAndGo = FALSE;
  180. pfce = vpfceMru;
  181. do
  182. {
  183. if (pfce->fcidRequest.lFcid == pfcid->lFcid)
  184. {
  185. /* found a match */
  186. fGetMetrics = FALSE;
  187. goto EstablishFont;
  188. }
  189. pfce = pfce->pfceNext;
  190. }
  191. while (pfce != vpfceMru);
  192. /* failed at the "easy" search - look for name text & property match */
  193. fGetMetrics = TRUE;
  194. if (fNewFont = (pfce = PfceFcidScan(pfcid)) == NULL)
  195. {
  196. /* this font isn't in our list - we have to create it */
  197. int wFcid = pfcid->strFcid.wFcid;
  198. int dyaHeight;
  199. int cwAlloc;
  200. int ich;
  201. struct FFN **hffnT;
  202. struct FFN **MpFcidHffn();
  203. pfce = PfceLruGet(); /* disposes of a font to make room */
  204. bltbc(&lf, 0, sizeof(LOGFONT));
  205. dyaHeight = pfcid->strFcid.hps * (czaPoint / 2);
  206. if (fPrint)
  207. {
  208. lf.lfHeight = -MultDiv(dyaHeight, dypPrPage, dyaPrPage);
  209. }
  210. else
  211. {
  212. /* In the Z version we have tried the idea of using a
  213. positive value for selection based on cell height
  214. rather than character height because of weirdness
  215. with the Courier screen font -- but it seemed to
  216. mess too many things up (like make all other fonts
  217. a bit too small and it didn't always make Courier
  218. work right). I believe Win Word *is* using this
  219. trick but only when selecting Courier fonts. It
  220. seems to me like there has got to be a different
  221. cause of this anamoly. ..pault 9/22/89 */
  222. lf.lfHeight = -MultDiv(dyaHeight, dypLogInch, czaInch);
  223. if (wFcid & grpbitPsWidthFcid)
  224. {
  225. // Sync Win3.0 //T-HIROYN
  226. #ifdef JAPAN
  227. #ifdef KKBUGFIX // added by Hiraisi (BUG#1980)
  228. lf.lfWidth = 0;
  229. #else
  230. lf.lfWidth = MultDiv((wFcid & grpbitPsWidthFcid) * czaPoint,
  231. dxpLogInch, czaInch);
  232. #endif
  233. #else
  234. //lf.lfWidth = MultDiv((wFcid & grpbitPsWidthFcid) * czaPoint,
  235. //dxpLogInch, czaInch);
  236. lf.lfWidth = 0;
  237. #endif
  238. }
  239. }
  240. if (wFcid & bitItalicFcid)
  241. {
  242. lf.lfItalic = 1;
  243. }
  244. if (wFcid & bitUlineFcid)
  245. {
  246. lf.lfUnderline = 1;
  247. }
  248. lf.lfWeight = wFcid & bitBoldFcid ? FW_BOLD : FW_NORMAL;
  249. hffnSave = MpFcidHffn(pfcid);
  250. #ifdef JAPAN
  251. // When we need system font, we want rather variable pitch than fixed,
  252. // since fixed pitch system font is probably same as terminal font.
  253. // So we specify VARIABLE_PITCH especialy for system font.
  254. {
  255. extern char szSystem[];
  256. extern char szAtSystem[];
  257. if( WCompSz(szSystem,(*hffnSave)->szFfn) == 0
  258. || WCompSz(szAtSystem,(*hffnSave)->szFfn) == 0 )// Add '@'systemfont
  259. lf.lfPitchAndFamily = (*hffnSave)->ffid | VARIABLE_PITCH ;
  260. else
  261. lf.lfPitchAndFamily
  262. = ((*hffnSave)->ffid) | ((wFcid & bitPrintFcid) ?
  263. DEFAULT_PITCH : ((wFcid & bitFixedPitchFcid) ? FIXED_PITCH :
  264. VARIABLE_PITCH));
  265. }
  266. #else
  267. lf.lfPitchAndFamily = ((*hffnSave)->ffid) | ((wFcid & bitPrintFcid) ?
  268. DEFAULT_PITCH : ((wFcid & bitFixedPitchFcid) ? FIXED_PITCH :
  269. VARIABLE_PITCH));
  270. #endif
  271. #if defined(NEWFONTENUM) && !defined(KANJI)
  272. lf.lfCharSet = (*hffnSave)->chs; /* pass the character set that
  273. enumfonts told us this fontname
  274. was associated with ..pault */
  275. #else
  276. /*T-HIROYN from 3.0 loadfont.c*/
  277. #if defined(NEWFONTENUM) && defined(JAPAN)
  278. lf.lfCharSet = (*hffnSave)->chs; /* pass the character set that
  279. enumfonts told us this fontname
  280. was associated with ..pault */
  281. #endif /* NEWFONTENUM and JAPAN */
  282. #endif
  283. ich = 0;
  284. if ((*hffnSave)->szFfn[0] == chGhost)
  285. {
  286. ich++;
  287. }
  288. bltszLimit(&(*hffnSave)->szFfn[ich], lf.lfFaceName, LF_FACESIZE);
  289. #ifdef KOREA
  290. if ( (*hffnSave)->szFfn[ich] > 0xA0 ||
  291. ( (*hffnSave)->szFfn[ich]=='@' && (*hffnSave)->szFfn[ich+1] > 0xA0 ) ||
  292. ( WCompSz(lf.lfFaceName,"terminal")==0 ) ||
  293. ( WCompSz(lf.lfFaceName,"@terminal")==0 ) ||
  294. ( WCompSz(lf.lfFaceName,"system")==0 ) ||
  295. ( WCompSz(lf.lfFaceName,"@system")==0 ) )
  296. lf.lfCharSet = HANGEUL_CHARSET;
  297. #endif
  298. #if defined(DFONT) || defined (PRDRVTEST)
  299. {
  300. char rgch[100];
  301. wsprintf(rgch, "Creating %s font: %s,\t\th %d, w %d, charset %d\n\r",
  302. (LPSTR)(fPrint ? "prt" : "scr"), (LPSTR)lf.lfFaceName,
  303. lf.lfHeight, lf.lfWidth, (int)(lf.lfCharSet));
  304. CommSz(rgch);
  305. CommSzNum(" Requested weight: ", lf.lfWeight);
  306. CommSzNum(" Requested italics: ", lf.lfItalic);
  307. CommSzNum(" Requested underline: ", lf.lfUnderline);
  308. CommSzNum(" Requested family: ", lf.lfPitchAndFamily >> 4);
  309. CommSzNum(" Requested pitch: ", lf.lfPitchAndFamily & 3);
  310. }
  311. #endif /* DFONT */
  312. #ifdef JAPAN // added 11 Jun. 1992 by Hiraisi
  313. {
  314. extern BOOL fPrinting; // Specifies printing doc.
  315. // PrintDoc function had set this flag.
  316. extern BOOL fWriting; // Specifies printing direction.
  317. // TRUE vertically or FALSE horizontally.
  318. // This flag had been set in the PRINT DIALOG.
  319. if( fPrinting && fWriting )
  320. fnCheckWriting( (LPLOGFONT)&lf );
  321. }
  322. #endif
  323. if ((pfce->hfont = CreateFontIndirect((LPLOGFONT)&lf)) == NULL)
  324. {
  325. pfce->hfont = GetStockObject( fPrint && vfPrinterValid ?
  326. DEVICE_DEFAULT_FONT : SYSTEM_FONT );
  327. Assert( pfce->hfont );
  328. /* if the above fails, I don't know what we can do */
  329. WinFailure(); /* report the failure so we give the user notice
  330. for weird behavior to follow */
  331. }
  332. #ifdef DFONT
  333. CommSzNum("Font handle: ", pfce->hfont);
  334. #endif /* DFONT */
  335. pfce->fcidRequest = *pfcid;
  336. cwAlloc = CwFromCch(CbFfn(CchSz((*hffnSave)->szFfn)));
  337. if (FNoHeap(hffnT = (struct FFN **)HAllocate(cwAlloc)))
  338. {
  339. FreePfce(pfce);
  340. return;
  341. }
  342. else
  343. {
  344. blt((*hffnSave), (*hffnT), cwAlloc);
  345. }
  346. pfce->hffn = hffnT;
  347. }
  348. EstablishFont:
  349. if ((pfce != vpfceMru) && (pfce != vpfceMru->pfceNext))
  350. {
  351. /* make this the mru font cache entry */
  352. /* Only do it if pfce is not already one of the first 2 mru fonts */
  353. /* since we generally ask for the things in groups of 2 */
  354. /* pull it out of its current place */
  355. pfce->pfceNext->pfcePrev = pfce->pfcePrev;
  356. pfce->pfcePrev->pfceNext = pfce->pfceNext;
  357. /* insert it at mru position */
  358. pfce->pfceNext = vpfceMru;
  359. pfce->pfcePrev = vpfceMru->pfcePrev;
  360. pfce->pfceNext->pfcePrev = pfce;
  361. pfce->pfcePrev->pfceNext = pfce;
  362. vpfceMru = pfce;
  363. #ifndef JAPAN // added by Hiraisi(BUG#4645/WIN31)
  364. #ifndef DISCARDABLE_FONTS
  365. /* KLUDGE ALERT: To accomodate Windows inability to make synthesized
  366. fonts discardable, we will now throw out the third font in the LRU chain
  367. if it is taller than 16 points. (Ain't this a doozey...) */
  368. {
  369. register struct FCE *pfceThird = vpfceMru->pfceNext->pfceNext;
  370. if (pfceThird->fcidRequest.lFcid != fcidNil &&
  371. #ifdef OLD
  372. pfceThird->fcidActual.strFcid.hps > 32)
  373. #else
  374. pfceThird->fcidActual.strFcid.hps > 48)
  375. #endif /* if-else-def OLD */
  376. {
  377. /* Free this particular font. */
  378. FreePfce(pfceThird);
  379. }
  380. }
  381. #endif /* not DISCARDABLE_FONTS */
  382. #endif // not JAPAN
  383. }
  384. if (!fTouchAndGo)
  385. {
  386. /* we have this font in our cache, but we need to select it */
  387. SelectWriteFont(fPrint, &pfce->hfont);
  388. /**
  389. I wish I knew why this is needed, but I don't want to spend
  390. more time on it. For some reason the font width table
  391. (pfce->rgdxp) is getting either trashed or is simply
  392. incorrect when first obtained. I suspect it is a GDI bug
  393. because it only happens the first time you use certain fonts
  394. (at least in Write) during a given session of Windows.
  395. The DogoneTrashTest detects the problem and fixes it.
  396. It is slow though, unfortunately.
  397. (7.25.91) v-dougk.
  398. **/
  399. #ifdef DEBUG
  400. if (!fGetMetrics)
  401. DogoneTrashTest(fPrint ? vhDCPrinter : vhMDC, pfce, fPrint);
  402. #endif
  403. if (fGetMetrics)
  404. {
  405. register union FCID *pfcidT = &pfce->fcidActual;
  406. HDC hDCMetrics = fPrint ? vhDCPrinter : vhMDC;
  407. TEXTMETRIC tm;
  408. Assert(hDCMetrics);
  409. if (hDCMetrics == NULL)
  410. return;
  411. GetTextMetrics(hDCMetrics, (LPTEXTMETRIC)&tm);
  412. if (fNewFont)
  413. {
  414. /* We need all of the metrics for this guy. */
  415. CHAR szFace[LF_FACESIZE];
  416. int wFcid;
  417. int dypHeight;
  418. int dxpch;
  419. #if defined(DFONT) || defined(PRDRVTEST)
  420. {
  421. char rgch[100];
  422. GetTextFace(hDCMetrics, LF_FACESIZE, (LPSTR)szFace);
  423. wsprintf(rgch, " Actual fname: %s,\t\th %d, w %d, charset %d\n\r",
  424. (LPSTR)szFace, tm.tmHeight-tm.tmInternalLeading,
  425. tm.tmAveCharWidth, (int)(tm.tmCharSet));
  426. CommSz(rgch);
  427. }
  428. CommSzNum(" Actual width: ", tm.tmAveCharWidth);
  429. CommSzNum(" Actual leading: ", tm.tmInternalLeading +
  430. tm.tmExternalLeading);
  431. CommSzNum(" Actual weight: ", tm.tmWeight);
  432. CommSzNum(" Actual italics: ", tm.tmItalic);
  433. CommSzNum(" Actual underline: ", tm.tmUnderlined);
  434. CommSzNum(" Actual font family: ", tm.tmPitchAndFamily >>
  435. 4);
  436. CommSzNum(" Actual pitch: ", tm.tmPitchAndFamily & 1);
  437. #endif /* DFONT */
  438. SetTextJustification(hDCMetrics, 0, 0);
  439. pfce->fmi.dxpOverhang = tm.tmOverhang;
  440. #if defined(KOREA)
  441. if ((tm.tmPitchAndFamily & 1) == 0)
  442. pfce->fmi.dxpSpace = tm.tmAveCharWidth;
  443. else
  444. #endif
  445. pfce->fmi.dxpSpace = LOWORD(GetTextExtent(hDCMetrics,
  446. (LPSTR)" ", 1)) - tm.tmOverhang;
  447. #ifdef PRDRVTEST
  448. {
  449. /* Just so no printers or printer driver manufacturers
  450. get funky on us! ..pault */
  451. int dxpSpace = pfce->fmi.dxpSpace + tm.tmOverhang;
  452. CommSzNum(" GetTextExtent(space) ", LOWORD(GetTextExtent(hDCMetrics, (LPSTR)" ", 1)));
  453. if (dxpSpace < 1 || dxpSpace > tm.tmMaxCharWidth+tm.tmOverhang)
  454. {
  455. pfce->fmi.dxpSpace = tm.tmAveCharWidth;
  456. CommSzNum(" ...resetting to ",pfce->fmi.dxpSpace);
  457. }
  458. }
  459. #endif
  460. pfce->fmi.dypAscent = tm.tmAscent;
  461. pfce->fmi.dypDescent = tm.tmDescent;
  462. pfce->fmi.dypBaseline = tm.tmAscent;
  463. pfce->fmi.dypLeading = tm.tmExternalLeading;
  464. #ifdef DBCS
  465. pfce->fmi.dypIntLeading = tm.tmInternalLeading;
  466. //#ifdef KOREA
  467. // if (tm.tmPitchAndFamily & 1) /* Is variable pitch ? */
  468. // pfce->fmi.dxpDBCS = dxpNil;
  469. // else
  470. //#endif
  471. {
  472. #if defined(TAIWAN) || defined(KOREA) || defined(PRC) //fix Italic display error, for Bug# 3362, MSTC - pisuih, 3/4/93
  473. CHAR rgchT[cchDBCS << 1];
  474. int dxpOverhang;
  475. #else
  476. CHAR rgchT[cchDBCS];
  477. #endif //TAIWAN
  478. int dxpDBCS;
  479. rgchT[0] = rgchT[1] = bKanji1Min;
  480. dxpDBCS = LOWORD(GetTextExtent(hDCMetrics,
  481. (LPSTR) rgchT, cchDBCS));
  482. #if defined(TAIWAN) || defined(KOREA) || defined(PRC) //fix Italic display error, for Bug# 3362, MSTC - pisuih, 3/4/93
  483. rgchT[2] = rgchT[3] = bKanji1Min;
  484. dxpOverhang = (dxpDBCS << 1) - LOWORD( GetTextExtent(
  485. hDCMetrics, (LPSTR) rgchT, cchDBCS << 1 ));
  486. //for compatible with SBCS's overhang
  487. dxpDBCS += (pfce->fmi.dxpOverhang - dxpOverhang);
  488. #endif //TAIWAN
  489. pfce->fmi.dxpDBCS =
  490. #if defined(JAPAN) || defined(KOREA) || defined(PRC) //Win3.1 BYTE-->WORD
  491. pfce->fmi.dxpDBCS =
  492. (WORD) ((0 <= dxpDBCS && dxpDBCS < dxpNil) ? dxpDBCS : dxpNil);
  493. #elif TAIWAN //Win3.1 BYTE-->WORD
  494. pfce->fmi.dxpDBCS =
  495. (WORD) ((0 <= dxpDBCS && dxpDBCS < dxpNil) ? dxpDBCS : dxpNil);
  496. #else
  497. pfce->fmi.dxpDBCS =
  498. (BYTE) ((0 <= dxpDBCS && dxpDBCS < dxpNil) ? dxpDBCS : dxpNil);
  499. #endif
  500. }
  501. #endif
  502. #ifdef SMFONT
  503. FillWidthTable(hDCMetrics, pfce->rgdxp, &tm);
  504. #ifdef DEBUG
  505. if (DogoneTrashTest(hDCMetrics, pfce, fPrint))
  506. OutputDebugString("That was an immediate check\n\r");
  507. #endif
  508. #else /* not SMFONT */
  509. /* Fill the width table. If this is a fixed font and the width
  510. fits in a byte, then go ahead and fill the width table with the
  511. width; otherwise, put dxpNil in the table. */
  512. dxpch = (tm.tmPitchAndFamily & 1 || tm.tmAveCharWidth >= dxpNil)
  513. ? dxpNil : tm.tmAveCharWidth;
  514. bltc(pfce->rgdxp, dxpch, chFmiMax - chFmiMin);
  515. #endif /* SMFONT */
  516. if ((*hffnSave)->ffid == FF_DONTCARE && (tm.tmPitchAndFamily &
  517. grpbitFamily) != FF_DONTCARE)
  518. {
  519. /* Hey! maybe we've discovered a family for this orphan
  520. font? */
  521. GetTextFace(hDCMetrics, LF_FACESIZE, (LPSTR)szFace);
  522. if (WCompSz((*hffnSave)->szFfn, szFace) == 0)
  523. {
  524. /* name matches - jam family in */
  525. (*hffnSave)->ffid = tm.tmPitchAndFamily & grpbitFamily;
  526. }
  527. }
  528. /* jam back the properties we found */
  529. dypHeight = tm.tmHeight - tm.tmInternalLeading;
  530. if (fPrint)
  531. {
  532. /* Save the height of this font. */
  533. pfcidT->strFcid.hps = umin((MultDiv(dypHeight, dyaPrPage,
  534. dypPrPage) + (czaPoint / 4)) / (czaPoint / 2), 0xff);
  535. #ifdef APLLW
  536. /* Save the width of this font if it is a fixed pitch
  537. device font. */
  538. wFcid = ((tm.tmPitchAndFamily & 0x09) == 0x08) ?
  539. #else
  540. /* Save the width of this font if it is a device font. */
  541. #ifdef KOREA /* give width info for all (like excel) to select DuBae shape */
  542. wFcid = (1==1) ?
  543. #else
  544. wFcid = (tm.tmPitchAndFamily & 0x08) ?
  545. #endif
  546. #endif /* if-else-def APLLW */
  547. umin((MultDiv(tm.tmAveCharWidth, dxaPrPage, dxpPrPage) +
  548. (czaPoint / 2)) / czaPoint, psWidthMax) : 0;
  549. wFcid |= bitPrintFcid;
  550. }
  551. else
  552. {
  553. pfcidT->strFcid.hps = umin((MultDiv(dypHeight, czaInch,
  554. dypLogInch) + (czaPoint / 4)) / (czaPoint / 2), 0xff);
  555. wFcid = 0;
  556. }
  557. if (tm.tmWeight > (FW_NORMAL + FW_BOLD) / 2)
  558. {
  559. wFcid |= bitBoldFcid;
  560. }
  561. if (tm.tmItalic)
  562. {
  563. wFcid |= bitItalicFcid;
  564. }
  565. if (tm.tmUnderlined)
  566. {
  567. wFcid |= bitUlineFcid;
  568. }
  569. if ((tm.tmPitchAndFamily & bitPitch) == 0)
  570. {
  571. wFcid |= bitFixedPitchFcid;
  572. }
  573. pfcidT->strFcid.wFcid = wFcid;
  574. }
  575. /* Set the document and the font code. */
  576. pfcidT->strFcid.doc = pfce->fcidRequest.strFcid.doc;
  577. if (fPrint)
  578. {
  579. CHAR rgb[ibFfnMax];
  580. struct FFN *pffn = (struct FFN *)&rgb[0];
  581. /* Get the font code for this font. */
  582. GetTextFace(vhDCPrinter, LF_FACESIZE, (LPSTR)pffn->szFfn);
  583. if (WCompSz(pffn->szFfn, (*pfce->hffn)->szFfn) == 0)
  584. {
  585. /* The face name is the same as what we requested; so, the
  586. font code should be the same. */
  587. pfcidT->strFcid.ftc = pfce->fcidRequest.strFcid.ftc;
  588. }
  589. else
  590. {
  591. /* Well, we've got to go hunting for the font code. */
  592. int ftc;
  593. pffn->ffid = tm.tmPitchAndFamily & grpbitFamily;
  594. #ifdef NEWFONTENUM
  595. pffn->chs = tm.tmCharSet;
  596. #endif
  597. ftc = FtcScanDocFfn(pfcidT->strFcid.doc, pffn);
  598. if (ftc == ftcNil)
  599. {
  600. /* Make the first character of the face name a sentinal
  601. to mark that this font was not requested by the user. */
  602. bltszLimit(pffn->szFfn, &pffn->szFfn[1], LF_FACESIZE);
  603. pffn->szFfn[0] = chGhost;
  604. ftc = FtcChkDocFfn(pfcidT->strFcid.doc, pffn);
  605. }
  606. pfcidT->strFcid.ftc = ftc;
  607. }
  608. }
  609. else
  610. {
  611. pfcidT->strFcid.ftc = pfce->fcidRequest.strFcid.ftc;
  612. }
  613. }
  614. if (fPrint)
  615. {
  616. vpfcePrint = pfce;
  617. vfcidPrint = pfce->fcidRequest;
  618. bltbyte(&pfce->fmi, &vfmiPrint, sizeof(struct FMI));
  619. }
  620. else
  621. {
  622. vpfceScreen = pfce;
  623. vfcidScreen = pfce->fcidRequest;
  624. bltbyte(&pfce->fmi, &vfmiScreen, sizeof(struct FMI));
  625. }
  626. }
  627. if (pfce->fcidRequest.lFcid != pfce->fcidActual.lFcid)
  628. {
  629. /* all's not as we asked for - feed properties back to caller */
  630. pfcid->lFcid = pfce->fcidActual.lFcid;
  631. if (pchp != NULL)
  632. { /* JamChpFcid(pchp, pfcid) bring in line for speed */
  633. register struct CHP *pchpT = pchp;
  634. int wFcid = pfcid->strFcid.wFcid;
  635. pchpT->ftc = pfcid->strFcid.ftc;
  636. pchpT->hps = pfcid->strFcid.hps;
  637. pchpT->psWidth = wFcid & grpbitPsWidthFcid;
  638. pchpT->fBold = pchpT->fItalic = pchpT->fUline = pchpT->fFixedPitch =
  639. FALSE;
  640. if (wFcid & bitBoldFcid)
  641. {
  642. pchpT->fBold = TRUE;
  643. }
  644. if (wFcid & bitItalicFcid)
  645. {
  646. pchpT->fItalic = TRUE;
  647. }
  648. if (wFcid & bitUlineFcid)
  649. {
  650. pchpT->fUline = TRUE;
  651. }
  652. if (wFcid & bitFixedPitchFcid)
  653. {
  654. pchpT->fFixedPitch = TRUE;
  655. }
  656. }
  657. }
  658. }
  659. void NEAR SelectWriteFont(fPrint, phfont)
  660. int fPrint;
  661. HFONT *phfont;
  662. {
  663. extern HWND hParentWw;
  664. extern int wwMac;
  665. extern struct WWD rgwwd[];
  666. if (fPrint)
  667. {
  668. #ifdef DFONT
  669. CommSzNum("Selecting printer font: ", *phfont);
  670. #endif /* DFONT */
  671. /* The printer DC should be valid. */
  672. if (vhDCPrinter == NULL)
  673. {
  674. /* This case can occur from ResetFont when closing */
  675. return;
  676. }
  677. else
  678. {
  679. /* Establish the font with the printer DC. */
  680. if (SelectObject(vhDCPrinter, *phfont) == NULL)
  681. {
  682. if (SelectObject(vhDCPrinter, GetStockObject(vfPrinterValid ?
  683. DEVICE_DEFAULT_FONT : SYSTEM_FONT)) == NULL)
  684. {
  685. if (vfPrinterValid)
  686. {
  687. /* This is a real printer DC; delete it. */
  688. DeleteDC(vhDCPrinter);
  689. }
  690. else
  691. {
  692. /* This is really the screen DC; it must be released. */
  693. ReleaseDC(hParentWw, vhDCPrinter);
  694. }
  695. vhDCPrinter = NULL;
  696. }
  697. WinFailure();
  698. if (vhDCPrinter == NULL)
  699. {
  700. GetPrinterDC(FALSE);
  701. }
  702. return;
  703. }
  704. }
  705. }
  706. else
  707. {
  708. /* Establish it with screen and memory DC's. */
  709. register int ww;
  710. register struct WWD *pwwd;
  711. #ifdef DFONT
  712. CommSzNum("Selecting screen font: ", *phfont);
  713. #endif /* DFONT */
  714. /* The current memory DC had best be active. */
  715. if (vhMDC == NULL)
  716. {
  717. /* this case occurs from ResetFont when Write is closed */
  718. return;
  719. }
  720. else
  721. {
  722. /* Select the font into the memory DC. */
  723. if (SelectObject(vhMDC, *phfont) == NULL)
  724. {
  725. Assert(*phfont != GetStockObject(SYSTEM_FONT));
  726. *phfont = GetStockObject(SYSTEM_FONT);
  727. Assert( *phfont );
  728. #ifdef DEBUG
  729. Assert( SelectObject( vhMDC, *phfont ) );
  730. #else /* not DEBUG */
  731. SelectObject(vhMDC, *phfont );
  732. #endif /* not DEBUG */
  733. WinFailure();
  734. }
  735. }
  736. /* Select the font into all of the window DC's. */
  737. for (ww = 0, pwwd = &rgwwd[0]; ww < wwMac; ww++, pwwd++)
  738. {
  739. if (pwwd->hDC != NULL)
  740. {
  741. if (SelectObject(pwwd->hDC, *phfont) == NULL)
  742. {
  743. HFONT hSysFont = GetStockObject(SYSTEM_FONT);
  744. int wwT;
  745. struct WWD *pwwdT;
  746. #ifdef DEBUG
  747. Assert(*phfont != hSysFont);
  748. Assert(SelectObject(vhMDC, hSysFont) != NULL);
  749. #else /* not DEBUG */
  750. SelectObject(vhMDC, hSysFont);
  751. #endif /* not DEBUG */
  752. *phfont = hSysFont;
  753. for (wwT = 0, pwwdT = &rgwwd[0]; wwT <= ww; wwT++, pwwdT++)
  754. {
  755. if (pwwdT->hDC != NULL)
  756. {
  757. #ifdef DEBUG
  758. Assert(SelectObject(pwwdT->hDC, hSysFont) != NULL);
  759. #else /* not DEBUG */
  760. SelectObject(pwwdT->hDC, hSysFont);
  761. #endif /* not DEBUG */
  762. }
  763. }
  764. WinFailure();
  765. }
  766. }
  767. }
  768. }
  769. }
  770. ResetFont(fPrint)
  771. BOOL fPrint;
  772. {
  773. /* This routine sets to NULL the currently selected printer or screen font,
  774. depending on the value of fPrint. */
  775. extern HFONT vhfSystem;
  776. HFONT hfont;
  777. #ifdef DFONT
  778. CommSzSz("Resetting the ", (fPrint ? "printer font." : "screen font."));
  779. #endif /* DEBUG */
  780. #ifdef JAPAN /* T-YOSHIO win 3.1 */
  781. hfont = GetStockObject(fPrint && vfPrinterValid ?
  782. DEVICE_DEFAULT_FONT : ANSI_VAR_FONT);
  783. #else
  784. hfont = GetStockObject(fPrint && vfPrinterValid ?
  785. DEVICE_DEFAULT_FONT : SYSTEM_FONT);
  786. #endif
  787. SelectWriteFont( fPrint, &hfont );
  788. if (fPrint)
  789. {
  790. vpfcePrint = NULL;
  791. vfcidPrint.lFcid = fcidNil;
  792. }
  793. else
  794. {
  795. vpfceScreen = NULL;
  796. vfcidScreen.lFcid = fcidNil;
  797. }
  798. }
  799. BOOL OurGetCharWidth(hdc, chFirst, chLast, lpw)
  800. HDC hdc;
  801. CHAR chFirst, chLast;
  802. LPINT lpw;
  803. {
  804. int i;
  805. BYTE b;
  806. for (i = chFirst; i <= chLast; i++)
  807. {
  808. /*T-HIROYN from 3.0 loadfont.c */
  809. #ifdef DBCS /* KenjiK '90-11-26 */
  810. if(IsDBCSLeadByte(i))
  811. {
  812. *(lpw++) = dxpNil;
  813. }
  814. else
  815. {
  816. b = i;
  817. *(lpw++) = LOWORD(GetTextExtent(hdc, (LPSTR)&b, 1));
  818. }
  819. }
  820. #else
  821. b = i;
  822. *(lpw++) = LOWORD(GetTextExtent(hdc, (LPSTR)&b, 1));
  823. }
  824. #endif
  825. return(fTrue);
  826. }
  827. #ifdef SMFONT
  828. /* Note: we put widths in here that represent true char widths,
  829. not considering bold/italics Overhang. This is because of the
  830. following formula for string widths:
  831. strwidth = overhang +
  832. summation [ (gettextextent_or_getcharwidth - overhang) ]
  833. ..pault 9/22/89 */
  834. void NEAR FillWidthTable(hdc, rgdxp, ptm)
  835. HDC hdc;
  836. int rgdxp[];
  837. TEXTMETRIC *ptm;
  838. {
  839. int rgWidth[chFmiMax - chFmiMin];
  840. if ((ptm->tmPitchAndFamily & 1) == 0)
  841. {
  842. #ifdef PRDRVTEST
  843. CommSzNum(" * Fixed pitch font! tmAveCharWidth==",ptm->tmMaxCharWidth);
  844. #endif
  845. #if defined(DBCS) && !defined(KOREA) /* was in JAPAN */
  846. bltc(rgdxp, (WORD)dxpNil, chFmiMax - chFmiMin);
  847. #else
  848. bltc(rgdxp, (WORD)ptm->tmAveCharWidth, chFmiMax - chFmiMin);
  849. #endif
  850. }
  851. /* Attempt to get the width table from the DC. */
  852. else
  853. {
  854. int *pdxpMax = &rgdxp[chFmiMax - chFmiMin];
  855. register int *pWidth;
  856. register int *pdxp;
  857. int dxpOverhang = ptm->tmOverhang;
  858. #ifdef DBCS /* was in JAPAN; KenjiK '90-11-26 */
  859. //92.10.26 T-HIROYN
  860. //Win3.1J if(OurGetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth))
  861. if( (GetDeviceCaps(hdc, DRIVERVERSION) > 0x300) ?
  862. GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth) :
  863. OurGetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth) )
  864. #else
  865. if (GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth))
  866. #endif
  867. {
  868. #if defined(JAPAN) || defined(KOREA) // added by Hiraisi (BUG#2690)
  869. int ch = chFmiMin;
  870. #endif
  871. #ifdef PRDRVTEST
  872. CommSz(" * GetCharWidth() supported\n\r");
  873. #endif
  874. /* Remove the overhang factor from individual char widths
  875. (see formula for widths of character strings above) */
  876. for (pWidth = &rgWidth[0], pdxp = &rgdxp[0];
  877. pdxp != pdxpMax; pWidth++, pdxp++)
  878. {
  879. #ifdef DBCS /* was in JAPAN */
  880. #if defined(JAPAN) || defined(KOREA) // added by Hiraisi (BUG#2690)
  881. if(!IsDBCSLeadByte(ch++))
  882. {
  883. #endif
  884. if(*pWidth == dxpNil)
  885. /*T-HIROYN *pdxp = (CHAR)dxpNil;*/
  886. *pdxp = dxpNil;
  887. else
  888. *pdxp = (*pWidth - dxpOverhang);
  889. #if defined(JAPAN) || defined(KOREA) // added by Hiraisi (BUG#2690)
  890. }
  891. else
  892. *pdxp = dxpNil;
  893. #endif
  894. #else
  895. *pdxp = (*pWidth - dxpOverhang);
  896. #endif
  897. }
  898. }
  899. else
  900. {
  901. /* There is no easy way, put dxpNil in the table. It looks like each
  902. char has a bogus width but FormatLine will make individual calls to
  903. GetTextExtent() and replace the dxpNil on an as-needed basis ..pault */
  904. #ifdef PRDRVTEST
  905. CommSz(" * GetCharWidth() not supported!\n\r");
  906. #endif
  907. bltc(rgdxp, (WORD)dxpNil, chFmiMax - chFmiMin);
  908. }
  909. }
  910. #ifdef PRDRVTEST
  911. /* Take a quick look through to see if this printer is returning any
  912. char widths that seem odd -- report those! This should
  913. end my searching for WRITE problems which are really caused by bad
  914. printer-driver return values! */
  915. {
  916. BOOL fReported = fFalse;
  917. int rgch[cchMaxSz];
  918. int i,w;
  919. BYTE b;
  920. for (i = chFmiMin; i < chFmiMax; i++)
  921. {
  922. b = i;
  923. w = LOWORD(GetTextExtent(hdc, (LPSTR)&b, 1));
  924. if (w < 1)
  925. {
  926. wsprintf(rgch," GetTextExtent(ascii %d) return value %d is invalid\n\r",b,(int)w);
  927. CommSz(rgch);
  928. if (!fReported)
  929. {
  930. CommSz("");
  931. fReported = fTrue;
  932. }
  933. }
  934. else if (w > (ptm->tmMaxCharWidth + ptm->tmOverhang))
  935. {
  936. wsprintf(rgch," GetTextExtent(ascii %d) return value %d exceeds tmMaxCharWidth %d\n\r",
  937. b,(int)w,(int)(ptm->tmMaxCharWidth + ptm->tmOverhang));
  938. CommSz(rgch);
  939. if (!fReported)
  940. {
  941. CommSz("");
  942. fReported = fTrue;
  943. }
  944. }
  945. else if ((rgdxp[i] != dxpNil) && (rgdxp[i] > (ptm->tmMaxCharWidth + ptm->tmOverhang)))
  946. {
  947. wsprintf(rgch," GetCharWidth(ascii %d) return value %d questionable, exceeds tmMaxCW %d\n\r",
  948. b, (int)(rgdxp[i]), (int)(ptm->tmMaxCharWidth + ptm->tmOverhang));
  949. CommSz(rgch);
  950. if (!fReported)
  951. {
  952. CommSz("");
  953. fReported = fTrue;
  954. }
  955. }
  956. }
  957. }
  958. #endif /* PRDRVTEST */
  959. }
  960. #endif /* SMFONT */
  961. #ifdef DEBUG
  962. BOOL NEAR DogoneTrashTest(HDC hdc, struct FCE *pfce, BOOL fPrint)
  963. {
  964. #if 1
  965. int i,width;
  966. int *pdxpMax = pfce->rgdxp + chFmiMax - chFmiMin;
  967. int dxpOverhang = pfce->fmi.dxpOverhang;
  968. register int *rgdxp;
  969. int rgdxpNew[chFmiMax - chFmiMin];
  970. register int *dxpNew;
  971. return 0;
  972. for (i=chFmiMin,
  973. rgdxp = pfce->rgdxp;
  974. i < chFmiMax; rgdxp++, ++i)
  975. {
  976. width = LOWORD(GetTextExtent(hdc,&i,1));
  977. if (*rgdxp != (width - dxpOverhang))
  978. {
  979. #ifdef DEBUG
  980. {
  981. char msg[120];
  982. wsprintf(msg,"widths have changed! Getting new width. (%s)\n\r",
  983. (LPSTR)(fPrint ? "PrinterDc" : "ScreenDC"));
  984. OutputDebugString(msg);
  985. }
  986. #endif
  987. GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgdxpNew);
  988. for (dxpNew = rgdxpNew,
  989. rgdxp = pfce->rgdxp;
  990. rgdxp != pdxpMax; dxpNew++, rgdxp++)
  991. *rgdxp = (*dxpNew - dxpOverhang);
  992. return TRUE;
  993. }
  994. }
  995. #else
  996. int rgdxpNew[chFmiMax - chFmiMin];
  997. int *pdxpMax = pfce->rgdxp + chFmiMax - chFmiMin;
  998. int dxpOverhang = pfce->fmi.dxpOverhang;
  999. register int *dxpNew;
  1000. register int *rgdxp;
  1001. if (GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgdxpNew))
  1002. {
  1003. /* Remove the overhang factor from individual char widths
  1004. (see formula for widths of character strings above) */
  1005. for (dxpNew = rgdxpNew,
  1006. rgdxp = pfce->rgdxp;
  1007. rgdxp != pdxpMax; dxpNew++, rgdxp++)
  1008. {
  1009. if (*rgdxp != (*dxpNew - dxpOverhang))
  1010. {
  1011. #ifdef DEBUG
  1012. {
  1013. char msg[120];
  1014. wsprintf(msg,"widths have changed! Getting new width. (%s)\n\r",
  1015. (LPSTR)(fPrint ? "PrinterDc" : "ScreenDC"));
  1016. OutputDebugString(msg);
  1017. }
  1018. #endif
  1019. for (dxpNew = rgdxpNew,
  1020. rgdxp = pfce->rgdxp;
  1021. rgdxp != pdxpMax; dxpNew++, rgdxp++)
  1022. *rgdxp = (*dxpNew - dxpOverhang);
  1023. return TRUE;
  1024. }
  1025. }
  1026. }
  1027. #endif
  1028. return FALSE;
  1029. }
  1030. #endif
  1031. #ifdef JAPAN // added 11 Jun. 1992 by Hiraisi
  1032. int FAR PASCAL _export fnFontHook( lf, tm, nType, lpData )
  1033. LPLOGFONT lf;
  1034. LPTEXTMETRIC tm;
  1035. short nType;
  1036. LPSTR lpData;
  1037. {
  1038. if( lf->lfFaceName[0] == '@' &&
  1039. lf->lfEscapement == 0 ){ /* @facename is found */
  1040. return( FALSE );
  1041. }
  1042. return( TRUE );
  1043. }
  1044. void fnCheckWriting( LPLOGFONT lf )
  1045. {
  1046. extern HANDLE hMmwModInstance;
  1047. FARPROC lpfnFontHook;
  1048. char cFaceName[LF_FACESIZE+1] = "@";
  1049. lstrcat( (LPSTR)cFaceName, lf->lfFaceName );
  1050. lpfnFontHook = MakeProcInstance(fnFontHook, hMmwModInstance);
  1051. if( !EnumFonts( vhDCPrinter, cFaceName, lpfnFontHook, NULL ) )
  1052. lstrcpy( (LPSTR)lf->lfFaceName, (LPSTR)cFaceName );
  1053. FreeProcInstance( lpfnFontHook );
  1054. }
  1055. #endif