/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/ /* loadfont.c - MW font support code */ #define NOWINMESSAGES #define NOVIRTUALKEYCODES #define NOSYSMETRICS #define NOMENUS #define NOWINSTYLES #define NOCTLMGR #define NOCLIPBOARD #include #include "mw.h" #include "propdefs.h" #include "macro.h" #define NOUAC #include "cmddefs.h" #include "wwdefs.h" #include "fontdefs.h" #include "docdefs.h" #ifdef DBCS #include "dbcs.h" #include "kanji.h" #endif extern HDC vhMDC; extern HDC vhDCPrinter; extern struct CHP vchpNormal; extern int vifceMac; extern union FCID vfcidScreen; extern union FCID vfcidPrint; extern struct FCE rgfce[ifceMax]; extern struct FCE *vpfceMru; extern struct FCE *vpfceScreen; extern struct FCE *vpfcePrint; extern struct FMI vfmiScreen; extern struct FMI vfmiPrint; #ifdef SYSENDMARK extern struct FMI vfmiSysScreen; #endif /* KANJI */ extern int dxpLogInch; extern int dypLogInch; extern int dxaPrPage; extern int dyaPrPage; extern int dxpPrPage; extern int dypPrPage; extern int ypSubSuperPr; extern BOOL vfPrinterValid; #ifdef DEBUG BOOL NEAR DogoneTrashTest(HDC hdc, struct FCE *pfce, BOOL fPrint); #endif NEAR LoadFcid(union FCID *, struct CHP *); void NEAR SelectWriteFont(int, HFONT *); struct FCE * (PfceFcidScan(union FCID *)); struct FCE * (PfceLruGet(void)); #ifdef SMFONT void NEAR FillWidthTable(HDC, int [], TEXTMETRIC *); #endif /* SMFONT */ #ifdef JAPAN // added 11 Jun. 1992 by Hiraisi void fnCheckWriting( LPLOGFONT ); #endif LoadFont( doc, pchp, mdFont ) /* loads the font specified in pchp for this doc. mdFont tells us how the font will be used (printer, screen, screen modulo printer,... */ int doc; register struct CHP *pchp; int mdFont; { register int wFcid; struct CHP *pchpT; union FCID fcid; Assert(doc != docNil); pchpT = pchp; if (pchp == NULL) pchp = &vchpNormal; fcid.strFcid.hps = pchp->hps; fcid.strFcid.ftc = pchp->ftc; fcid.strFcid.doc = doc; #ifdef ENABLE wFcid = pchp->psWidth; wFcid |= bitPrintFcid; if (pchp->fItalic) wFcid |= bitItalicFcid; if (pchp->fBold) wFcid |= bitBoldFcid; if (pchp->fUline) wFcid |= bitUlineFcid; if (pchp->fFixedPitch) wFcid |= bitFixedPitchFcid; fcid.strFcid.wFcid = wFcid; #else /* Super-nitpick-optimization (but worth it because LoadFont can take 10% of display refresh time): bits being cleared is more common than set, and a "jump not taken" plus an "or di, xxxx" is 8 cycles, vs the above "jump taken" which is 16 */ wFcid = pchp->psWidth + bitPrintFcid + bitItalicFcid + bitBoldFcid + bitUlineFcid + bitFixedPitchFcid; if (!pchp->fItalic) wFcid &= ~bitItalicFcid; if (!pchp->fBold) wFcid &= ~bitBoldFcid; if (!pchp->fUline) wFcid &= ~bitUlineFcid; if (!pchp->fFixedPitch) wFcid &= ~bitFixedPitchFcid; fcid.strFcid.wFcid = wFcid; #endif switch (mdFont) { /* fall throughs are intentional! */ default: break; case mdFontChk: /* sets font as constrained by printer avail */ case mdFontPrint: /* like mdFontScreen, but for the printer */ /* don't want to jam the chp props back */ pchpT = NULL; case mdFontJam: /* like mdFontChk, but jams props into chp */ /* get printer font loaded */ LoadFcid(&fcid, pchpT); if (mdFont == mdFontPrint) /* don't need screen font */ return; case mdFontScreen: /* sets font for random screen chars */ /* get screen font loaded */ fcid.strFcid.wFcid &= ~bitPrintFcid; LoadFcid(&fcid, (struct CHP *)NULL); } } NEAR LoadFcid(pfcid, pchp) /* loads described font and associates it with the appropriate dc's */ union FCID *pfcid; struct CHP *pchp; { register struct FCE *pfce; int fPrint; int fTouchAndGo; int fGetMetrics; int fNewFont; struct FFN **hffnSave; LOGFONT lf; #ifdef SYSENDMARK fPrint = pfcid->strFcid.wFcid & bitPrintFcid; /* Since this ftc came from CHP, we have lost the first 2 bits. */ if (pfcid->strFcid.ftc == (bitFtcChp & ftcSystem)) { /* If vpfceScreen == NULL already, the standard system font has already been selected. So, save some time here. */ if (vpfceScreen != NULL) { /* Gives you the standard system font for the screen. */ ResetFont(FALSE); } bltbyte(&vfmiSysScreen, &vfmiScreen, sizeof(struct FMI)); #if defined(KANJI) && defined(DFONT) /* CommSz("System Font!\r\n"); */ KTS(); #endif return; } else if (fPrint) #else if ((fPrint = pfcid->strFcid.wFcid & bitPrintFcid)) #endif /* if-else-def KANJI */ { if (pfcid->lFcid == vfcidPrint.lFcid) { pfce = vpfcePrint; fTouchAndGo = TRUE; goto EstablishFont; } } else { if (pfcid->lFcid == vfcidScreen.lFcid) { pfce = vpfceScreen; fTouchAndGo = TRUE; goto EstablishFont; } } /* failed at the "trivial" comparisons - look through list */ fTouchAndGo = FALSE; pfce = vpfceMru; do { if (pfce->fcidRequest.lFcid == pfcid->lFcid) { /* found a match */ fGetMetrics = FALSE; goto EstablishFont; } pfce = pfce->pfceNext; } while (pfce != vpfceMru); /* failed at the "easy" search - look for name text & property match */ fGetMetrics = TRUE; if (fNewFont = (pfce = PfceFcidScan(pfcid)) == NULL) { /* this font isn't in our list - we have to create it */ int wFcid = pfcid->strFcid.wFcid; int dyaHeight; int cwAlloc; int ich; struct FFN **hffnT; struct FFN **MpFcidHffn(); pfce = PfceLruGet(); /* disposes of a font to make room */ bltbc(&lf, 0, sizeof(LOGFONT)); dyaHeight = pfcid->strFcid.hps * (czaPoint / 2); if (fPrint) { lf.lfHeight = -MultDiv(dyaHeight, dypPrPage, dyaPrPage); } else { /* In the Z version we have tried the idea of using a positive value for selection based on cell height rather than character height because of weirdness with the Courier screen font -- but it seemed to mess too many things up (like make all other fonts a bit too small and it didn't always make Courier work right). I believe Win Word *is* using this trick but only when selecting Courier fonts. It seems to me like there has got to be a different cause of this anamoly. ..pault 9/22/89 */ lf.lfHeight = -MultDiv(dyaHeight, dypLogInch, czaInch); if (wFcid & grpbitPsWidthFcid) { // Sync Win3.0 //T-HIROYN #ifdef JAPAN #ifdef KKBUGFIX // added by Hiraisi (BUG#1980) lf.lfWidth = 0; #else lf.lfWidth = MultDiv((wFcid & grpbitPsWidthFcid) * czaPoint, dxpLogInch, czaInch); #endif #else //lf.lfWidth = MultDiv((wFcid & grpbitPsWidthFcid) * czaPoint, //dxpLogInch, czaInch); lf.lfWidth = 0; #endif } } if (wFcid & bitItalicFcid) { lf.lfItalic = 1; } if (wFcid & bitUlineFcid) { lf.lfUnderline = 1; } lf.lfWeight = wFcid & bitBoldFcid ? FW_BOLD : FW_NORMAL; hffnSave = MpFcidHffn(pfcid); #ifdef JAPAN // When we need system font, we want rather variable pitch than fixed, // since fixed pitch system font is probably same as terminal font. // So we specify VARIABLE_PITCH especialy for system font. { extern char szSystem[]; extern char szAtSystem[]; if( WCompSz(szSystem,(*hffnSave)->szFfn) == 0 || WCompSz(szAtSystem,(*hffnSave)->szFfn) == 0 )// Add '@'systemfont lf.lfPitchAndFamily = (*hffnSave)->ffid | VARIABLE_PITCH ; else lf.lfPitchAndFamily = ((*hffnSave)->ffid) | ((wFcid & bitPrintFcid) ? DEFAULT_PITCH : ((wFcid & bitFixedPitchFcid) ? FIXED_PITCH : VARIABLE_PITCH)); } #else lf.lfPitchAndFamily = ((*hffnSave)->ffid) | ((wFcid & bitPrintFcid) ? DEFAULT_PITCH : ((wFcid & bitFixedPitchFcid) ? FIXED_PITCH : VARIABLE_PITCH)); #endif #if defined(NEWFONTENUM) && !defined(KANJI) lf.lfCharSet = (*hffnSave)->chs; /* pass the character set that enumfonts told us this fontname was associated with ..pault */ #else /*T-HIROYN from 3.0 loadfont.c*/ #if defined(NEWFONTENUM) && defined(JAPAN) lf.lfCharSet = (*hffnSave)->chs; /* pass the character set that enumfonts told us this fontname was associated with ..pault */ #endif /* NEWFONTENUM and JAPAN */ #endif ich = 0; if ((*hffnSave)->szFfn[0] == chGhost) { ich++; } bltszLimit(&(*hffnSave)->szFfn[ich], lf.lfFaceName, LF_FACESIZE); #ifdef KOREA if ( (*hffnSave)->szFfn[ich] > 0xA0 || ( (*hffnSave)->szFfn[ich]=='@' && (*hffnSave)->szFfn[ich+1] > 0xA0 ) || ( WCompSz(lf.lfFaceName,"terminal")==0 ) || ( WCompSz(lf.lfFaceName,"@terminal")==0 ) || ( WCompSz(lf.lfFaceName,"system")==0 ) || ( WCompSz(lf.lfFaceName,"@system")==0 ) ) lf.lfCharSet = HANGEUL_CHARSET; #endif #if defined(DFONT) || defined (PRDRVTEST) { char rgch[100]; wsprintf(rgch, "Creating %s font: %s,\t\th %d, w %d, charset %d\n\r", (LPSTR)(fPrint ? "prt" : "scr"), (LPSTR)lf.lfFaceName, lf.lfHeight, lf.lfWidth, (int)(lf.lfCharSet)); CommSz(rgch); CommSzNum(" Requested weight: ", lf.lfWeight); CommSzNum(" Requested italics: ", lf.lfItalic); CommSzNum(" Requested underline: ", lf.lfUnderline); CommSzNum(" Requested family: ", lf.lfPitchAndFamily >> 4); CommSzNum(" Requested pitch: ", lf.lfPitchAndFamily & 3); } #endif /* DFONT */ #ifdef JAPAN // added 11 Jun. 1992 by Hiraisi { extern BOOL fPrinting; // Specifies printing doc. // PrintDoc function had set this flag. extern BOOL fWriting; // Specifies printing direction. // TRUE vertically or FALSE horizontally. // This flag had been set in the PRINT DIALOG. if( fPrinting && fWriting ) fnCheckWriting( (LPLOGFONT)&lf ); } #endif if ((pfce->hfont = CreateFontIndirect((LPLOGFONT)&lf)) == NULL) { pfce->hfont = GetStockObject( fPrint && vfPrinterValid ? DEVICE_DEFAULT_FONT : SYSTEM_FONT ); Assert( pfce->hfont ); /* if the above fails, I don't know what we can do */ WinFailure(); /* report the failure so we give the user notice for weird behavior to follow */ } #ifdef DFONT CommSzNum("Font handle: ", pfce->hfont); #endif /* DFONT */ pfce->fcidRequest = *pfcid; cwAlloc = CwFromCch(CbFfn(CchSz((*hffnSave)->szFfn))); if (FNoHeap(hffnT = (struct FFN **)HAllocate(cwAlloc))) { FreePfce(pfce); return; } else { blt((*hffnSave), (*hffnT), cwAlloc); } pfce->hffn = hffnT; } EstablishFont: if ((pfce != vpfceMru) && (pfce != vpfceMru->pfceNext)) { /* make this the mru font cache entry */ /* Only do it if pfce is not already one of the first 2 mru fonts */ /* since we generally ask for the things in groups of 2 */ /* pull it out of its current place */ pfce->pfceNext->pfcePrev = pfce->pfcePrev; pfce->pfcePrev->pfceNext = pfce->pfceNext; /* insert it at mru position */ pfce->pfceNext = vpfceMru; pfce->pfcePrev = vpfceMru->pfcePrev; pfce->pfceNext->pfcePrev = pfce; pfce->pfcePrev->pfceNext = pfce; vpfceMru = pfce; #ifndef JAPAN // added by Hiraisi(BUG#4645/WIN31) #ifndef DISCARDABLE_FONTS /* KLUDGE ALERT: To accomodate Windows inability to make synthesized fonts discardable, we will now throw out the third font in the LRU chain if it is taller than 16 points. (Ain't this a doozey...) */ { register struct FCE *pfceThird = vpfceMru->pfceNext->pfceNext; if (pfceThird->fcidRequest.lFcid != fcidNil && #ifdef OLD pfceThird->fcidActual.strFcid.hps > 32) #else pfceThird->fcidActual.strFcid.hps > 48) #endif /* if-else-def OLD */ { /* Free this particular font. */ FreePfce(pfceThird); } } #endif /* not DISCARDABLE_FONTS */ #endif // not JAPAN } if (!fTouchAndGo) { /* we have this font in our cache, but we need to select it */ SelectWriteFont(fPrint, &pfce->hfont); /** I wish I knew why this is needed, but I don't want to spend more time on it. For some reason the font width table (pfce->rgdxp) is getting either trashed or is simply incorrect when first obtained. I suspect it is a GDI bug because it only happens the first time you use certain fonts (at least in Write) during a given session of Windows. The DogoneTrashTest detects the problem and fixes it. It is slow though, unfortunately. (7.25.91) v-dougk. **/ #ifdef DEBUG if (!fGetMetrics) DogoneTrashTest(fPrint ? vhDCPrinter : vhMDC, pfce, fPrint); #endif if (fGetMetrics) { register union FCID *pfcidT = &pfce->fcidActual; HDC hDCMetrics = fPrint ? vhDCPrinter : vhMDC; TEXTMETRIC tm; Assert(hDCMetrics); if (hDCMetrics == NULL) return; GetTextMetrics(hDCMetrics, (LPTEXTMETRIC)&tm); if (fNewFont) { /* We need all of the metrics for this guy. */ CHAR szFace[LF_FACESIZE]; int wFcid; int dypHeight; int dxpch; #if defined(DFONT) || defined(PRDRVTEST) { char rgch[100]; GetTextFace(hDCMetrics, LF_FACESIZE, (LPSTR)szFace); wsprintf(rgch, " Actual fname: %s,\t\th %d, w %d, charset %d\n\r", (LPSTR)szFace, tm.tmHeight-tm.tmInternalLeading, tm.tmAveCharWidth, (int)(tm.tmCharSet)); CommSz(rgch); } CommSzNum(" Actual width: ", tm.tmAveCharWidth); CommSzNum(" Actual leading: ", tm.tmInternalLeading + tm.tmExternalLeading); CommSzNum(" Actual weight: ", tm.tmWeight); CommSzNum(" Actual italics: ", tm.tmItalic); CommSzNum(" Actual underline: ", tm.tmUnderlined); CommSzNum(" Actual font family: ", tm.tmPitchAndFamily >> 4); CommSzNum(" Actual pitch: ", tm.tmPitchAndFamily & 1); #endif /* DFONT */ SetTextJustification(hDCMetrics, 0, 0); pfce->fmi.dxpOverhang = tm.tmOverhang; #if defined(KOREA) if ((tm.tmPitchAndFamily & 1) == 0) pfce->fmi.dxpSpace = tm.tmAveCharWidth; else #endif pfce->fmi.dxpSpace = LOWORD(GetTextExtent(hDCMetrics, (LPSTR)" ", 1)) - tm.tmOverhang; #ifdef PRDRVTEST { /* Just so no printers or printer driver manufacturers get funky on us! ..pault */ int dxpSpace = pfce->fmi.dxpSpace + tm.tmOverhang; CommSzNum(" GetTextExtent(space) ", LOWORD(GetTextExtent(hDCMetrics, (LPSTR)" ", 1))); if (dxpSpace < 1 || dxpSpace > tm.tmMaxCharWidth+tm.tmOverhang) { pfce->fmi.dxpSpace = tm.tmAveCharWidth; CommSzNum(" ...resetting to ",pfce->fmi.dxpSpace); } } #endif pfce->fmi.dypAscent = tm.tmAscent; pfce->fmi.dypDescent = tm.tmDescent; pfce->fmi.dypBaseline = tm.tmAscent; pfce->fmi.dypLeading = tm.tmExternalLeading; #ifdef DBCS pfce->fmi.dypIntLeading = tm.tmInternalLeading; //#ifdef KOREA // if (tm.tmPitchAndFamily & 1) /* Is variable pitch ? */ // pfce->fmi.dxpDBCS = dxpNil; // else //#endif { #if defined(TAIWAN) || defined(KOREA) || defined(PRC) //fix Italic display error, for Bug# 3362, MSTC - pisuih, 3/4/93 CHAR rgchT[cchDBCS << 1]; int dxpOverhang; #else CHAR rgchT[cchDBCS]; #endif //TAIWAN int dxpDBCS; rgchT[0] = rgchT[1] = bKanji1Min; dxpDBCS = LOWORD(GetTextExtent(hDCMetrics, (LPSTR) rgchT, cchDBCS)); #if defined(TAIWAN) || defined(KOREA) || defined(PRC) //fix Italic display error, for Bug# 3362, MSTC - pisuih, 3/4/93 rgchT[2] = rgchT[3] = bKanji1Min; dxpOverhang = (dxpDBCS << 1) - LOWORD( GetTextExtent( hDCMetrics, (LPSTR) rgchT, cchDBCS << 1 )); //for compatible with SBCS's overhang dxpDBCS += (pfce->fmi.dxpOverhang - dxpOverhang); #endif //TAIWAN pfce->fmi.dxpDBCS = #if defined(JAPAN) || defined(KOREA) || defined(PRC) //Win3.1 BYTE-->WORD pfce->fmi.dxpDBCS = (WORD) ((0 <= dxpDBCS && dxpDBCS < dxpNil) ? dxpDBCS : dxpNil); #elif TAIWAN //Win3.1 BYTE-->WORD pfce->fmi.dxpDBCS = (WORD) ((0 <= dxpDBCS && dxpDBCS < dxpNil) ? dxpDBCS : dxpNil); #else pfce->fmi.dxpDBCS = (BYTE) ((0 <= dxpDBCS && dxpDBCS < dxpNil) ? dxpDBCS : dxpNil); #endif } #endif #ifdef SMFONT FillWidthTable(hDCMetrics, pfce->rgdxp, &tm); #ifdef DEBUG if (DogoneTrashTest(hDCMetrics, pfce, fPrint)) OutputDebugString("That was an immediate check\n\r"); #endif #else /* not SMFONT */ /* Fill the width table. If this is a fixed font and the width fits in a byte, then go ahead and fill the width table with the width; otherwise, put dxpNil in the table. */ dxpch = (tm.tmPitchAndFamily & 1 || tm.tmAveCharWidth >= dxpNil) ? dxpNil : tm.tmAveCharWidth; bltc(pfce->rgdxp, dxpch, chFmiMax - chFmiMin); #endif /* SMFONT */ if ((*hffnSave)->ffid == FF_DONTCARE && (tm.tmPitchAndFamily & grpbitFamily) != FF_DONTCARE) { /* Hey! maybe we've discovered a family for this orphan font? */ GetTextFace(hDCMetrics, LF_FACESIZE, (LPSTR)szFace); if (WCompSz((*hffnSave)->szFfn, szFace) == 0) { /* name matches - jam family in */ (*hffnSave)->ffid = tm.tmPitchAndFamily & grpbitFamily; } } /* jam back the properties we found */ dypHeight = tm.tmHeight - tm.tmInternalLeading; if (fPrint) { /* Save the height of this font. */ pfcidT->strFcid.hps = umin((MultDiv(dypHeight, dyaPrPage, dypPrPage) + (czaPoint / 4)) / (czaPoint / 2), 0xff); #ifdef APLLW /* Save the width of this font if it is a fixed pitch device font. */ wFcid = ((tm.tmPitchAndFamily & 0x09) == 0x08) ? #else /* Save the width of this font if it is a device font. */ #ifdef KOREA /* give width info for all (like excel) to select DuBae shape */ wFcid = (1==1) ? #else wFcid = (tm.tmPitchAndFamily & 0x08) ? #endif #endif /* if-else-def APLLW */ umin((MultDiv(tm.tmAveCharWidth, dxaPrPage, dxpPrPage) + (czaPoint / 2)) / czaPoint, psWidthMax) : 0; wFcid |= bitPrintFcid; } else { pfcidT->strFcid.hps = umin((MultDiv(dypHeight, czaInch, dypLogInch) + (czaPoint / 4)) / (czaPoint / 2), 0xff); wFcid = 0; } if (tm.tmWeight > (FW_NORMAL + FW_BOLD) / 2) { wFcid |= bitBoldFcid; } if (tm.tmItalic) { wFcid |= bitItalicFcid; } if (tm.tmUnderlined) { wFcid |= bitUlineFcid; } if ((tm.tmPitchAndFamily & bitPitch) == 0) { wFcid |= bitFixedPitchFcid; } pfcidT->strFcid.wFcid = wFcid; } /* Set the document and the font code. */ pfcidT->strFcid.doc = pfce->fcidRequest.strFcid.doc; if (fPrint) { CHAR rgb[ibFfnMax]; struct FFN *pffn = (struct FFN *)&rgb[0]; /* Get the font code for this font. */ GetTextFace(vhDCPrinter, LF_FACESIZE, (LPSTR)pffn->szFfn); if (WCompSz(pffn->szFfn, (*pfce->hffn)->szFfn) == 0) { /* The face name is the same as what we requested; so, the font code should be the same. */ pfcidT->strFcid.ftc = pfce->fcidRequest.strFcid.ftc; } else { /* Well, we've got to go hunting for the font code. */ int ftc; pffn->ffid = tm.tmPitchAndFamily & grpbitFamily; #ifdef NEWFONTENUM pffn->chs = tm.tmCharSet; #endif ftc = FtcScanDocFfn(pfcidT->strFcid.doc, pffn); if (ftc == ftcNil) { /* Make the first character of the face name a sentinal to mark that this font was not requested by the user. */ bltszLimit(pffn->szFfn, &pffn->szFfn[1], LF_FACESIZE); pffn->szFfn[0] = chGhost; ftc = FtcChkDocFfn(pfcidT->strFcid.doc, pffn); } pfcidT->strFcid.ftc = ftc; } } else { pfcidT->strFcid.ftc = pfce->fcidRequest.strFcid.ftc; } } if (fPrint) { vpfcePrint = pfce; vfcidPrint = pfce->fcidRequest; bltbyte(&pfce->fmi, &vfmiPrint, sizeof(struct FMI)); } else { vpfceScreen = pfce; vfcidScreen = pfce->fcidRequest; bltbyte(&pfce->fmi, &vfmiScreen, sizeof(struct FMI)); } } if (pfce->fcidRequest.lFcid != pfce->fcidActual.lFcid) { /* all's not as we asked for - feed properties back to caller */ pfcid->lFcid = pfce->fcidActual.lFcid; if (pchp != NULL) { /* JamChpFcid(pchp, pfcid) bring in line for speed */ register struct CHP *pchpT = pchp; int wFcid = pfcid->strFcid.wFcid; pchpT->ftc = pfcid->strFcid.ftc; pchpT->hps = pfcid->strFcid.hps; pchpT->psWidth = wFcid & grpbitPsWidthFcid; pchpT->fBold = pchpT->fItalic = pchpT->fUline = pchpT->fFixedPitch = FALSE; if (wFcid & bitBoldFcid) { pchpT->fBold = TRUE; } if (wFcid & bitItalicFcid) { pchpT->fItalic = TRUE; } if (wFcid & bitUlineFcid) { pchpT->fUline = TRUE; } if (wFcid & bitFixedPitchFcid) { pchpT->fFixedPitch = TRUE; } } } } void NEAR SelectWriteFont(fPrint, phfont) int fPrint; HFONT *phfont; { extern HWND hParentWw; extern int wwMac; extern struct WWD rgwwd[]; if (fPrint) { #ifdef DFONT CommSzNum("Selecting printer font: ", *phfont); #endif /* DFONT */ /* The printer DC should be valid. */ if (vhDCPrinter == NULL) { /* This case can occur from ResetFont when closing */ return; } else { /* Establish the font with the printer DC. */ if (SelectObject(vhDCPrinter, *phfont) == NULL) { if (SelectObject(vhDCPrinter, GetStockObject(vfPrinterValid ? DEVICE_DEFAULT_FONT : SYSTEM_FONT)) == NULL) { if (vfPrinterValid) { /* This is a real printer DC; delete it. */ DeleteDC(vhDCPrinter); } else { /* This is really the screen DC; it must be released. */ ReleaseDC(hParentWw, vhDCPrinter); } vhDCPrinter = NULL; } WinFailure(); if (vhDCPrinter == NULL) { GetPrinterDC(FALSE); } return; } } } else { /* Establish it with screen and memory DC's. */ register int ww; register struct WWD *pwwd; #ifdef DFONT CommSzNum("Selecting screen font: ", *phfont); #endif /* DFONT */ /* The current memory DC had best be active. */ if (vhMDC == NULL) { /* this case occurs from ResetFont when Write is closed */ return; } else { /* Select the font into the memory DC. */ if (SelectObject(vhMDC, *phfont) == NULL) { Assert(*phfont != GetStockObject(SYSTEM_FONT)); *phfont = GetStockObject(SYSTEM_FONT); Assert( *phfont ); #ifdef DEBUG Assert( SelectObject( vhMDC, *phfont ) ); #else /* not DEBUG */ SelectObject(vhMDC, *phfont ); #endif /* not DEBUG */ WinFailure(); } } /* Select the font into all of the window DC's. */ for (ww = 0, pwwd = &rgwwd[0]; ww < wwMac; ww++, pwwd++) { if (pwwd->hDC != NULL) { if (SelectObject(pwwd->hDC, *phfont) == NULL) { HFONT hSysFont = GetStockObject(SYSTEM_FONT); int wwT; struct WWD *pwwdT; #ifdef DEBUG Assert(*phfont != hSysFont); Assert(SelectObject(vhMDC, hSysFont) != NULL); #else /* not DEBUG */ SelectObject(vhMDC, hSysFont); #endif /* not DEBUG */ *phfont = hSysFont; for (wwT = 0, pwwdT = &rgwwd[0]; wwT <= ww; wwT++, pwwdT++) { if (pwwdT->hDC != NULL) { #ifdef DEBUG Assert(SelectObject(pwwdT->hDC, hSysFont) != NULL); #else /* not DEBUG */ SelectObject(pwwdT->hDC, hSysFont); #endif /* not DEBUG */ } } WinFailure(); } } } } } ResetFont(fPrint) BOOL fPrint; { /* This routine sets to NULL the currently selected printer or screen font, depending on the value of fPrint. */ extern HFONT vhfSystem; HFONT hfont; #ifdef DFONT CommSzSz("Resetting the ", (fPrint ? "printer font." : "screen font.")); #endif /* DEBUG */ #ifdef JAPAN /* T-YOSHIO win 3.1 */ hfont = GetStockObject(fPrint && vfPrinterValid ? DEVICE_DEFAULT_FONT : ANSI_VAR_FONT); #else hfont = GetStockObject(fPrint && vfPrinterValid ? DEVICE_DEFAULT_FONT : SYSTEM_FONT); #endif SelectWriteFont( fPrint, &hfont ); if (fPrint) { vpfcePrint = NULL; vfcidPrint.lFcid = fcidNil; } else { vpfceScreen = NULL; vfcidScreen.lFcid = fcidNil; } } BOOL OurGetCharWidth(hdc, chFirst, chLast, lpw) HDC hdc; CHAR chFirst, chLast; LPINT lpw; { int i; BYTE b; for (i = chFirst; i <= chLast; i++) { /*T-HIROYN from 3.0 loadfont.c */ #ifdef DBCS /* KenjiK '90-11-26 */ if(IsDBCSLeadByte(i)) { *(lpw++) = dxpNil; } else { b = i; *(lpw++) = LOWORD(GetTextExtent(hdc, (LPSTR)&b, 1)); } } #else b = i; *(lpw++) = LOWORD(GetTextExtent(hdc, (LPSTR)&b, 1)); } #endif return(fTrue); } #ifdef SMFONT /* Note: we put widths in here that represent true char widths, not considering bold/italics Overhang. This is because of the following formula for string widths: strwidth = overhang + summation [ (gettextextent_or_getcharwidth - overhang) ] ..pault 9/22/89 */ void NEAR FillWidthTable(hdc, rgdxp, ptm) HDC hdc; int rgdxp[]; TEXTMETRIC *ptm; { int rgWidth[chFmiMax - chFmiMin]; if ((ptm->tmPitchAndFamily & 1) == 0) { #ifdef PRDRVTEST CommSzNum(" * Fixed pitch font! tmAveCharWidth==",ptm->tmMaxCharWidth); #endif #if defined(DBCS) && !defined(KOREA) /* was in JAPAN */ bltc(rgdxp, (WORD)dxpNil, chFmiMax - chFmiMin); #else bltc(rgdxp, (WORD)ptm->tmAveCharWidth, chFmiMax - chFmiMin); #endif } /* Attempt to get the width table from the DC. */ else { int *pdxpMax = &rgdxp[chFmiMax - chFmiMin]; register int *pWidth; register int *pdxp; int dxpOverhang = ptm->tmOverhang; #ifdef DBCS /* was in JAPAN; KenjiK '90-11-26 */ //92.10.26 T-HIROYN //Win3.1J if(OurGetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth)) if( (GetDeviceCaps(hdc, DRIVERVERSION) > 0x300) ? GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth) : OurGetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth) ) #else if (GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgWidth)) #endif { #if defined(JAPAN) || defined(KOREA) // added by Hiraisi (BUG#2690) int ch = chFmiMin; #endif #ifdef PRDRVTEST CommSz(" * GetCharWidth() supported\n\r"); #endif /* Remove the overhang factor from individual char widths (see formula for widths of character strings above) */ for (pWidth = &rgWidth[0], pdxp = &rgdxp[0]; pdxp != pdxpMax; pWidth++, pdxp++) { #ifdef DBCS /* was in JAPAN */ #if defined(JAPAN) || defined(KOREA) // added by Hiraisi (BUG#2690) if(!IsDBCSLeadByte(ch++)) { #endif if(*pWidth == dxpNil) /*T-HIROYN *pdxp = (CHAR)dxpNil;*/ *pdxp = dxpNil; else *pdxp = (*pWidth - dxpOverhang); #if defined(JAPAN) || defined(KOREA) // added by Hiraisi (BUG#2690) } else *pdxp = dxpNil; #endif #else *pdxp = (*pWidth - dxpOverhang); #endif } } else { /* There is no easy way, put dxpNil in the table. It looks like each char has a bogus width but FormatLine will make individual calls to GetTextExtent() and replace the dxpNil on an as-needed basis ..pault */ #ifdef PRDRVTEST CommSz(" * GetCharWidth() not supported!\n\r"); #endif bltc(rgdxp, (WORD)dxpNil, chFmiMax - chFmiMin); } } #ifdef PRDRVTEST /* Take a quick look through to see if this printer is returning any char widths that seem odd -- report those! This should end my searching for WRITE problems which are really caused by bad printer-driver return values! */ { BOOL fReported = fFalse; int rgch[cchMaxSz]; int i,w; BYTE b; for (i = chFmiMin; i < chFmiMax; i++) { b = i; w = LOWORD(GetTextExtent(hdc, (LPSTR)&b, 1)); if (w < 1) { wsprintf(rgch," GetTextExtent(ascii %d) return value %d is invalid\n\r",b,(int)w); CommSz(rgch); if (!fReported) { CommSz(""); fReported = fTrue; } } else if (w > (ptm->tmMaxCharWidth + ptm->tmOverhang)) { wsprintf(rgch," GetTextExtent(ascii %d) return value %d exceeds tmMaxCharWidth %d\n\r", b,(int)w,(int)(ptm->tmMaxCharWidth + ptm->tmOverhang)); CommSz(rgch); if (!fReported) { CommSz(""); fReported = fTrue; } } else if ((rgdxp[i] != dxpNil) && (rgdxp[i] > (ptm->tmMaxCharWidth + ptm->tmOverhang))) { wsprintf(rgch," GetCharWidth(ascii %d) return value %d questionable, exceeds tmMaxCW %d\n\r", b, (int)(rgdxp[i]), (int)(ptm->tmMaxCharWidth + ptm->tmOverhang)); CommSz(rgch); if (!fReported) { CommSz(""); fReported = fTrue; } } } } #endif /* PRDRVTEST */ } #endif /* SMFONT */ #ifdef DEBUG BOOL NEAR DogoneTrashTest(HDC hdc, struct FCE *pfce, BOOL fPrint) { #if 1 int i,width; int *pdxpMax = pfce->rgdxp + chFmiMax - chFmiMin; int dxpOverhang = pfce->fmi.dxpOverhang; register int *rgdxp; int rgdxpNew[chFmiMax - chFmiMin]; register int *dxpNew; return 0; for (i=chFmiMin, rgdxp = pfce->rgdxp; i < chFmiMax; rgdxp++, ++i) { width = LOWORD(GetTextExtent(hdc,&i,1)); if (*rgdxp != (width - dxpOverhang)) { #ifdef DEBUG { char msg[120]; wsprintf(msg,"widths have changed! Getting new width. (%s)\n\r", (LPSTR)(fPrint ? "PrinterDc" : "ScreenDC")); OutputDebugString(msg); } #endif GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgdxpNew); for (dxpNew = rgdxpNew, rgdxp = pfce->rgdxp; rgdxp != pdxpMax; dxpNew++, rgdxp++) *rgdxp = (*dxpNew - dxpOverhang); return TRUE; } } #else int rgdxpNew[chFmiMax - chFmiMin]; int *pdxpMax = pfce->rgdxp + chFmiMax - chFmiMin; int dxpOverhang = pfce->fmi.dxpOverhang; register int *dxpNew; register int *rgdxp; if (GetCharWidth(hdc, chFmiMin, chFmiMax - 1, (LPINT)rgdxpNew)) { /* Remove the overhang factor from individual char widths (see formula for widths of character strings above) */ for (dxpNew = rgdxpNew, rgdxp = pfce->rgdxp; rgdxp != pdxpMax; dxpNew++, rgdxp++) { if (*rgdxp != (*dxpNew - dxpOverhang)) { #ifdef DEBUG { char msg[120]; wsprintf(msg,"widths have changed! Getting new width. (%s)\n\r", (LPSTR)(fPrint ? "PrinterDc" : "ScreenDC")); OutputDebugString(msg); } #endif for (dxpNew = rgdxpNew, rgdxp = pfce->rgdxp; rgdxp != pdxpMax; dxpNew++, rgdxp++) *rgdxp = (*dxpNew - dxpOverhang); return TRUE; } } } #endif return FALSE; } #endif #ifdef JAPAN // added 11 Jun. 1992 by Hiraisi int FAR PASCAL _export fnFontHook( lf, tm, nType, lpData ) LPLOGFONT lf; LPTEXTMETRIC tm; short nType; LPSTR lpData; { if( lf->lfFaceName[0] == '@' && lf->lfEscapement == 0 ){ /* @facename is found */ return( FALSE ); } return( TRUE ); } void fnCheckWriting( LPLOGFONT lf ) { extern HANDLE hMmwModInstance; FARPROC lpfnFontHook; char cFaceName[LF_FACESIZE+1] = "@"; lstrcat( (LPSTR)cFaceName, lf->lfFaceName ); lpfnFontHook = MakeProcInstance(fnFontHook, hMmwModInstance); if( !EnumFonts( vhDCPrinter, cFaceName, lpfnFontHook, NULL ) ) lstrcpy( (LPSTR)lf->lfFaceName, (LPSTR)cFaceName ); FreeProcInstance( lpfnFontHook ); } #endif