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

/************************************************************/
/* 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 <windows.h>
#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