Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1631 lines
48 KiB

/****************************************************************************\
*
* PROGRAM: fontview.c
*
* PURPOSE: Loads and displays fonts from the given filename
*
* COMMENTS:
*
* HISTORY:
* 02-Oct-1995 JonPa Created It
*
\****************************************************************************/
#include <windows.h> /* required for all Windows applications */
#include <commdlg.h>
#ifdef WINNT
# include <wingdip.h> /* prototype for GetFontRsourceInfo */
#endif
#include "fontdefs.h" /* specific to this program */
#include "fvmsg.h"
#include "fvrc.h"
#include "ttdefs.h"
HANDLE hInst; /* current instance */
HWND ghwndView = NULL;
HWND ghwndFrame = NULL;
BOOL gfPrint = FALSE;
TCHAR gszFontPath[2 * MAX_PATH];
LPTSTR gpszSampleText;
LPTSTR gpszSampleAlph[3];
FFTYPE gfftFontType;
LOGFONT glfTimes;
DISPTEXT gdtDisplay;
HBRUSH ghbr3DFace;
HBRUSH ghbr3DShadow;
int gyScroll = 0; // Vertical scroll offset in pels
int gcyLine = 0;
int gcxMinWinSize = CX_MIN_WINSIZE;
int gcyMinWinSize = CY_MIN_WINSIZE;
int apts[] = { 12, 18, 24, 36, 48, 60, 72 };
#define C_POINTS_LIST (sizeof(apts) / sizeof(apts[0]))
#define CPTS_BTN_AREA 28
int gcyBtnArea = CPTS_BTN_AREA;
BTNREC gabtCmdBtns[] = {
{ 6, 6, 36, 16, IDB_DONE, NULL, MSG_DONE, NULL },
{ -6, 6, 36, 16, IDB_PRINT, NULL, MSG_PRINT, NULL }
};
#define C_BUTTONS (sizeof(gabtCmdBtns) / sizeof(gabtCmdBtns[0]))
/****************************************************************************
*
* FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
*
* PURPOSE: calls initialization function, processes message loop
*
*
\****************************************************************************/
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpstrCmdLine,
int nCmdShow
)
{
int i, iCpts;
MSG msg;
HACCEL hAccel;
/*
* Parse the Command Line
*
* Use GetCommandLine() here (instead of lpstrCmdLine) so the
* command string will be in Unicode on NT
*/
FillMemory( &gdtDisplay, sizeof(gdtDisplay), 0 );
if (!ParseCommand( GetCommandLine(), gszFontPath, &gfPrint ) ||
(gfftFontType = LoadFontFile( gszFontPath, &gdtDisplay )) == FFT_BAD_FILE) {
// Bad font file, inform user, and exit
FmtMessageBox( NULL, MSG_APP_TITLE, NULL, MB_OK | MB_ICONSTOP,
FALSE, MSG_BADFILENAME, gszFontPath );
ExitProcess(1);
}
/*
* Now finish initializing the display structure
*/
gpszSampleAlph[0] = FmtSprintf(MSG_SAMPLEALPH_0);
gpszSampleAlph[1] = FmtSprintf(MSG_SAMPLEALPH_1);
gpszSampleAlph[2] = FmtSprintf(MSG_SAMPLEALPH_2);
// find next line on display
for( i = 0; i < CLINES_DISPLAY; i++ ) {
if (gdtDisplay.atlDsp[i].dtyp == DTP_UNUSED)
break;
}
// fill in sample alphabet
gdtDisplay.atlDsp[i].pszText = gpszSampleAlph[0];
gdtDisplay.atlDsp[i].cchText = lstrlen(gpszSampleAlph[0]);
gdtDisplay.atlDsp[i].dtyp = DTP_SHRINKTEXT;
gdtDisplay.atlDsp[i].cptsSize = CPTS_SAMPLE_ALPHA;
i++;
gdtDisplay.atlDsp[i] = gdtDisplay.atlDsp[i-1];
gdtDisplay.atlDsp[i].pszText = gpszSampleAlph[1];
gdtDisplay.atlDsp[i].cchText = lstrlen(gpszSampleAlph[1]);
i++;
gdtDisplay.atlDsp[i] = gdtDisplay.atlDsp[i-1];
gdtDisplay.atlDsp[i].pszText = gpszSampleAlph[2];
gdtDisplay.atlDsp[i].cchText = lstrlen(gpszSampleAlph[2]);
gdtDisplay.atlDsp[i].fLineUnder = TRUE;
// now fill in sample Sentences
iCpts = 0;
gpszSampleText = FmtSprintf(MSG_SAMPLETEXT);
for( i += 1; i < CLINES_DISPLAY && iCpts < C_POINTS_LIST; i++ ) {
if (gdtDisplay.atlDsp[i].dtyp == DTP_UNUSED) {
gdtDisplay.atlDsp[i].pszText = gpszSampleText;
gdtDisplay.atlDsp[i].cchText = lstrlen(gpszSampleText);
gdtDisplay.atlDsp[i].dtyp = DTP_TEXTOUT;
gdtDisplay.atlDsp[i].cptsSize = apts[iCpts++];
}
}
/*
* Init the title font LOGFONT, and other variables
*/
InitGlobals();
if (!hPrevInstance) {
if (!InitApplication(hInstance)) {
msg.wParam = FALSE;
goto ExitProg;
}
}
/* Perform initializations that apply to a specific instance */
if (!InitInstance(hInstance, nCmdShow, gdtDisplay.atlDsp[0].pszText)) {
msg.wParam = FALSE;
goto ExitProg;
}
/* Acquire and dispatch messages until a WM_QUIT message is received. */
hAccel = LoadAccelerators(hInstance, TEXT("fviewAccel"));
while (GetMessage(&msg, NULL, 0L, 0L)) {
if (!TranslateAccelerator(ghwndView, hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
ExitProg:
for ( i = 0; i < C_BUTTONS; i++ )
FmtFree( gabtCmdBtns[i].pszText );
RemoveFontResource( gszFontPath );
return (msg.wParam);
}
/****************************************************************************
*
* FUNCTION: InitApplication(HANDLE)
*
* PURPOSE: Initializes window data and registers window class
*
* COMMENTS:
*
* This function is called at initialization time only if no other
* instances of the application are running. This function performs
* initialization tasks that can be done once for any number of running
* instances.
*
* In this case, we initialize a window class by filling out a data
* structure of type WNDCLASS and calling the Windows RegisterClass()
* function. Since all instances of this application use the same window
* class, we only need to do this when the first instance is initialized.
*
*
\****************************************************************************/
BOOL InitApplication(HANDLE hInstance) /* current instance */
{
WNDCLASS wc;
BOOL fRet = FALSE;
/* Fill in window class structure with parameters that describe the */
/* main window. */
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)FrameWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance; /* Application that owns the class. */
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = ghbr3DFace;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("FontViewWClass");
/* Register the window class and return success/failure code. */
if (RegisterClass(&wc)) {
/* Fill in window class structure with parameters that describe the */
/* main window. */
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)ViewWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance; /* Application that owns the class. */
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("FontDisplayClass");
fRet = RegisterClass(&wc);
}
return fRet;
}
/****************************************************************************
*
* FUNCTION: InitInstance(HANDLE, int)
*
* PURPOSE: Saves instance handle and creates main window
*
* COMMENTS:
*
* This function is called at initialization time for every instance of
* this application. This function performs initialization tasks that
* cannot be shared by multiple instances.
*
* In this case, we save the instance handle in a static variable and
* create and display the main program window.
*
\****************************************************************************/
BOOL InitInstance( HANDLE hInstance, int nCmdShow, LPTSTR pszTitle)
{
/* Save the instance handle in static variable, which will be used in */
/* many subsequence calls from this application to Windows. */
hInst = hInstance;
/* Create a main window for this application instance. */
ghwndFrame = CreateWindow( TEXT("FontViewWClass"), pszTitle,
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );
/* If window could not be created, return "failure" */
if (!ghwndFrame)
return (FALSE);
return (TRUE); /* Returns the value from PostQuitMessage */
}
/****************************************************************************
*
* FUNCTION: InitLogFont
*
\****************************************************************************/
void InitGlobals( void ) {
TCHAR szTimesNewRoman[LF_FACESIZE];
INT cyDPI,i, cxFiller, cxMaxTxt, cxTxt, cxMax;
HDC hdc;
HFONT hfOld;
RECT rc;
FillMemory( &glfTimes, sizeof(glfTimes), 0 );
glfTimes.lfCharSet = DEFAULT_CHARSET;
glfTimes.lfOutPrecision = OUT_DEFAULT_PRECIS;
glfTimes.lfClipPrecision = CLIP_DEFAULT_PRECIS;
glfTimes.lfQuality = DEFAULT_QUALITY;
glfTimes.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
if (LoadString(hInst, IDS_TIMESNEWROMAN, szTimesNewRoman, sizeof(szTimesNewRoman)))
lstrcpy(glfTimes.lfFaceName, szTimesNewRoman);
else
lstrcpy(glfTimes.lfFaceName, TEXT("Times New Roman"));
hdc = CreateCompatibleDC(NULL);
cyDPI = GetDeviceCaps(hdc, LOGPIXELSY );
hfOld = SelectObject( hdc, GetStockObject(ANSI_VAR_FONT));
// Find out size of padding around text
SetRect(&rc, 0, 0, 0, 0 );
DrawText(hdc, TEXT("####"), -1, &rc, DT_CALCRECT | DT_CENTER);
cxFiller = rc.right - rc.left;
gcyBtnArea = MulDiv( gcyBtnArea, cyDPI, C_PTS_PER_INCH );
cxMax = cxMaxTxt = 0;
for( i = 0; i < C_BUTTONS; i++ ) {
gabtCmdBtns[i].x = MulDiv( gabtCmdBtns[i].x, cyDPI, C_PTS_PER_INCH );
gabtCmdBtns[i].y = MulDiv( gabtCmdBtns[i].y, cyDPI, C_PTS_PER_INCH );
gabtCmdBtns[i].cx = MulDiv( gabtCmdBtns[i].cx, cyDPI, C_PTS_PER_INCH );
gabtCmdBtns[i].cy = MulDiv( gabtCmdBtns[i].cy, cyDPI, C_PTS_PER_INCH );
if (gabtCmdBtns[i].cx > cxMax)
cxMax = gabtCmdBtns[i].cx;
gabtCmdBtns[i].pszText = FmtSprintf( gabtCmdBtns[i].idText );
SetRect(&rc, 0, 0, 0, 0 );
DrawText(hdc, gabtCmdBtns[i].pszText, -1, &rc, DT_CALCRECT | DT_CENTER);
cxTxt = rc.right - rc.left + cxFiller;
if (cxMaxTxt < cxTxt) {
cxMaxTxt = cxTxt;
}
}
//
// Make sure buttons are big enough for text! (So localizer's won't have
// to change code.
//
if (cxMax < cxMaxTxt) {
for( i = 0; i < C_BUTTONS; i++ ) {
gabtCmdBtns[i].cx = gabtCmdBtns[i].cx * cxMaxTxt / cxMax;
}
}
//
// Make sure buttons don't overlap
//
i = C_BUTTONS - 1;
cxMax = gabtCmdBtns[0].x + gabtCmdBtns[0].cx + gabtCmdBtns[0].x + gabtCmdBtns[i].cx + (-gabtCmdBtns[i].x) +
(2 * GetSystemMetrics(SM_CXSIZEFRAME));
if (cxMax > gcxMinWinSize)
gcxMinWinSize = cxMax;
SelectObject(hdc, hfOld);
DeleteDC(hdc);
gcyLine = MulDiv( CPTS_INFO_SIZE, cyDPI, C_PTS_PER_INCH );
ghbr3DFace = GetSysColorBrush(COLOR_3DFACE);
ghbr3DShadow = GetSysColorBrush(COLOR_3DSHADOW);
}
/****************************************************************************
*
* FUNCTION: SkipWhiteSpace
*
\****************************************************************************/
LPTSTR SkipWhiteSpace( LPTSTR psz ) {
while( *psz == TEXT(' ') || *psz == TEXT('\t') || *psz == TEXT('\n') ) {
psz = CharNext( psz );
}
return psz;
}
/****************************************************************************
*
* FUNCTION: CloneString
*
\****************************************************************************/
LPTSTR CloneString(LPTSTR psz) {
int cch;
LPTSTR pszRet;
cch = (lstrlen( psz ) + 1) * sizeof(TCHAR);
pszRet = AllocMem(cch);
lstrcpy( pszRet, psz );
return pszRet;
}
/****************************************************************************
*
* FUNCTION: GetFileSizeFromName(pszFontPath)
*
\****************************************************************************/
DWORD GetFileSizeFromName( LPCTSTR pszPath ) {
HANDLE hfile;
DWORD cb = 0;
hfile = CreateFile( pszPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if (hfile != INVALID_HANDLE_VALUE) {
cb = GetFileSize( hfile, NULL );
CloseHandle(hfile);
}
return cb;
}
BOOL bFindPfb (
TCHAR *pszPFM,
TCHAR *achPFB
);
/****************************************************************************
*
* FUNCTION: ParseCommand
*
\****************************************************************************/
BOOL ParseCommand( LPTSTR lpstrCmdLine, LPTSTR pszFontPath, BOOL *pfPrint ) {
LPTSTR psz;
BOOL fInQuote = FALSE;
DWORD cwc;
TCHAR achPfmPfb[2*MAX_PATH];
//
// Skip program name
//
for( psz = SkipWhiteSpace(lpstrCmdLine);
*psz != TEXT('\0') && (fInQuote || *psz != TEXT(' ')); psz = CharNext(psz) ) {
if (*psz == TEXT('\"')) {
fInQuote = !fInQuote;
}
}
if (*psz == TEXT('\0')) {
*pszFontPath = TEXT('\0');
return FALSE;
}
psz = SkipWhiteSpace(psz);
//
// Check for "/p"
//
if (psz[0] == TEXT('/') && (psz[1] == TEXT('p') || psz[1] == TEXT('P'))) {
*pfPrint = TRUE;
psz += 2; // DBCS OK since we already verified that the
// chars were '/' and 'p', they can't be lead bytes
} else
*pfPrint = FALSE;
psz = SkipWhiteSpace(psz);
cwc = lstrlen(psz) + 1;
if ((cwc >= 5) && !lstrcmpi(&psz[cwc - 5], TEXT(".PFM")))
{
lstrcpy(achPfmPfb, psz);
if (bFindPfb(achPfmPfb, &achPfmPfb[cwc]))
{
// go and concatenate:
achPfmPfb[cwc-1] = TEXT('|');
psz = achPfmPfb;
}
}
lstrcpy( pszFontPath, psz );
return *psz != TEXT('\0');
}
/****************************************************************************
*
* FUNCTION: GetGDILangID
*
* REVIEW! I believe this is how GDI determines the LangID, verify on
* international builds.
*
\****************************************************************************/
WORD GetGDILangID() {
return (WORD)GetSystemDefaultLangID();
}
/****************************************************************************
*
* FUNCTION: GetAlignedTTName
*
* NOTE: This function returns an allocated string that must be freed
* after use.
*
* This function allocs a buffer to recopy the string into incase we are
* running on a RISC machine with NT. Since the string will be UNICODE
* (ie. each char is a WORD), those strings must be aligned on WORD
* boundaries. Unfortunatly, TrueType files do not neccesarily align
* the embedded unicode strings. Furthur more, on NT we can not simply
* return a pointer to the data stored in the input buffer, since the
* 'Unicode' strings stored in the TTF file are stored in Motorola (big
* endian) format, and we need the unicode chars in Intel (little endian)
* format. Last but not least, we need the returned string to be null terminated
* so we need to either alloc the buffer for that case anyway.
*
\****************************************************************************/
#ifdef UNICODE
void ConvertTTStrToWinZStr( LPWSTR pwsz, LPVOID pvTTS, int cbMW ) {
int i, cch;
LPMWORD lpmw = pvTTS;
cch = cbMW / sizeof(MWORD);
for( i = 0; i < cch; i++ ) {
*pwsz++ = MWORD2INT(*lpmw);
lpmw++;
}
*pwsz = L'\0';
}
#else
#pragma error("write ANSI code for this" )
Since apparently TTF files ONLY have Unicode strings, (or MacANSI)
we need to:
1. Convert Motorola format Unicode to Intel format unicode
2. Alloc a buffer for the ANSI string
3. Call WideCharToMultiByte to covert the string to ANSI
#endif
LPTSTR GetAlignedTTName( PBYTE pbTTData, int idName ) {
PTTNAMEREC ptnr;
PTTNAMETBL ptnt;
int cNameRec,i;
LPTSTR psz;
ptnt = (PTTNAMETBL)pbTTData;
cNameRec = MWORD2INT(ptnt->mwcNameRec);
//
// Look For Microsoft Platform ID's
//
for( i = 0; i < cNameRec; i++ ) {
LPVOID pvTTStr;
ptnr = &(ptnt->anrNames[i]);
if (MWORD2INT(ptnr->mwidPlatform) != TTID_PLATFORM_MS ||
MWORD2INT(ptnr->mwidName) != idName ||
MWORD2INT(ptnr->mwidLang) != GetGDILangID()) {
continue;
}
pvTTStr = (LPVOID)(pbTTData + MWORD2INT(ptnt->mwoffStrings) + MWORD2INT(ptnr->mwoffString));
psz = AllocMem(MWORD2INT(ptnr->mwcbString) + sizeof(TEXT('\0')));
ConvertTTStrToWinZStr( psz, pvTTStr, MWORD2INT(ptnr->mwcbString) );
return psz;
}
//
// Didn't find MS Platform, try Macintosh
//
for( i = 0; i < cNameRec; i++ ) {
int cch;
LPSTR pszMacStr;
ptnr = &(ptnt->anrNames[i]);
if (MWORD2INT(ptnr->mwidPlatform) != TTID_PLATFORM_MAC ||
MWORD2INT(ptnr->mwidName) != idName) {
continue;
}
pszMacStr = (LPVOID)(pbTTData + MWORD2INT(ptnt->mwoffStrings) + MWORD2INT(ptnr->mwoffString));
cch = MultiByteToWideChar(CP_MACCP, 0, pszMacStr, MWORD2INT(ptnr->mwcbString), NULL, 0);
if (cch == 0)
continue;
cch += 1; // for null
psz = AllocMem(cch * sizeof(TCHAR));
if (psz == NULL)
continue;
cch = MultiByteToWideChar(CP_MACCP, 0, pszMacStr, MWORD2INT(ptnr->mwcbString), psz, cch);
if (cch == 0) {
FreeMem(psz);
continue;
}
return psz;
}
return NULL;
}
/****************************************************************************
*
* FUNCTION: LoadFontFile
*
\****************************************************************************/
#ifndef WINNT
FFTYPE LoadFontFile( LPCTSTR pszFontPath, PDISPTEXT pdtSmpl ) {
HANDLE hfile;
FFTYPE fft;
LPTSTR pszFName;
/*
* Open the file
*/
hfile = CreateFile( pszFontPath, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if (hfile == INVALID_HANDLE_VALUE)
return FFT_BAD_FILE;
/*
* Now determine the file type
*/
fDone = FALSE;
for(fft = FFT_TRUETYPE; !fDone && fft < FFT_BAD_FILE; fft++ ) {
fDone = (afnGetFaceName[fft])( hfile, PTXTLN ptlList );
}
CloseHandle( hfile );
/*
* if type is not bad
* addfontresource( filename )
*/
if ( fft != FFT_BAD_FILE )
AddFontResource( pszFontPath );
return fft;
}
#else
FFTYPE LoadFontFile( LPCTSTR pszFontPath, PDISPTEXT pdtSmpl ) {
int cFonts;
FFTYPE fft = FFT_BAD_FILE;
cFonts = AddFontResource( pszFontPath );
if (cFonts != 0) {
LPLOGFONT lplf;
DWORD cb;
BOOL fIsTT;
cb = sizeof(LOGFONT) * cFonts;
lplf = AllocMem(cb);
if (GetFontResourceInfoW( (LPTSTR)pszFontPath, &cb, lplf, GFRI_LOGFONTS )) {
HDC hdc;
HFONT hf, hfOld;
hf = CreateFontIndirect(lplf);
hdc = CreateCompatibleDC(NULL);
hfOld = SelectObject(hdc, hf);
cb = GetFontData(hdc, TT_TBL_NAME, 0, NULL, 0);
fIsTT = (cb != 0 && cb != GDI_ERROR);
fft = fIsTT ? FFT_TRUETYPE : FFT_BITMAP;
if (fIsTT) {
int i;
LPBYTE lpTTData;
LPTSTR pszTmp;
lpTTData = AllocMem(cb);
GetFontData(hdc, TT_TBL_NAME, 0, lpTTData, cb);
i = 0;
//
// Title String
//
pdtSmpl->atlDsp[i].dtyp = DTP_SHRINKDRAW;
pdtSmpl->atlDsp[i].cptsSize = CPTS_TITLE_SIZE;
pdtSmpl->atlDsp[i].fLineUnder = TRUE;
pszTmp = GetAlignedTTName( lpTTData, TTID_NAME_FULLFONTNM );
if (pszTmp != NULL) {
pdtSmpl->atlDsp[i].pszText = FmtSprintf(MSG_PTRUETYPEP, pszTmp);
pdtSmpl->atlDsp[i].cchText = lstrlen(pdtSmpl->atlDsp[i].pszText);
FreeMem(pszTmp);
} else {
pdtSmpl->atlDsp[i].pszText = CloneString(lplf->lfFaceName);
pdtSmpl->atlDsp[i].cchText = lstrlen(pdtSmpl->atlDsp[0].pszText);
}
i++;
pdtSmpl->atlDsp[i] = pdtSmpl->atlDsp[i-1];
//
// Typeface Name:
//
pdtSmpl->atlDsp[i].cptsSize = CPTS_INFO_SIZE;
pdtSmpl->atlDsp[i].dtyp = DTP_NORMALDRAW;
pdtSmpl->atlDsp[i].fLineUnder = FALSE;
pszTmp = GetAlignedTTName( lpTTData, TTID_NAME_FONTFAMILY );
if (pszTmp != NULL) {
pdtSmpl->atlDsp[i].pszText = FmtSprintf(MSG_TYPEFACENAME, pszTmp);
pdtSmpl->atlDsp[i].cchText = lstrlen(pdtSmpl->atlDsp[i].pszText);
FreeMem(pszTmp);
i++;
pdtSmpl->atlDsp[i] = pdtSmpl->atlDsp[i-1];
}
//
// File size:
//
pdtSmpl->atlDsp[i].pszText = FmtSprintf(MSG_FILESIZE,
ROUND_UP_DIV(GetFileSizeFromName(pszFontPath), CB_ONE_K));
pdtSmpl->atlDsp[i].cchText = lstrlen(pdtSmpl->atlDsp[i].pszText);
//
// Version:
//
pszTmp = GetAlignedTTName( lpTTData, TTID_NAME_VERSIONSTR );
if (pszTmp != NULL) {
i++;
pdtSmpl->atlDsp[i] = pdtSmpl->atlDsp[i-1];
pdtSmpl->atlDsp[i].pszText = FmtSprintf(MSG_VERSION, pszTmp);
pdtSmpl->atlDsp[i].cchText = lstrlen(pdtSmpl->atlDsp[i].pszText);
FreeMem( pszTmp );
}
//
// Copyright string
//
pszTmp = GetAlignedTTName( lpTTData, TTID_NAME_COPYRIGHT );
if (pszTmp != NULL) {
i++;
pdtSmpl->atlDsp[i] = pdtSmpl->atlDsp[i-1];
pdtSmpl->atlDsp[i].cptsSize = CPTS_COPYRIGHT_SIZE;
pdtSmpl->atlDsp[i].dtyp = DTP_WRAPDRAW;
pdtSmpl->atlDsp[i].pszText = FmtSprintf(MSG_COPYRIGHT, pszTmp);
pdtSmpl->atlDsp[i].cchText = lstrlen(pdtSmpl->atlDsp[i].pszText);
FreeMem( pszTmp );
}
pdtSmpl->atlDsp[i].fLineUnder = TRUE;
} else {
//
// Title String (Non TrueType case)
//
pdtSmpl->atlDsp[0].dtyp = DTP_SHRINKDRAW;
pdtSmpl->atlDsp[0].cptsSize = CPTS_TITLE_SIZE;
pdtSmpl->atlDsp[0].fLineUnder = TRUE;
pdtSmpl->atlDsp[0].pszText = CloneString(lplf->lfFaceName);
pdtSmpl->atlDsp[0].cchText = lstrlen(pdtSmpl->atlDsp[0].pszText);
// Use Default quality, so we can see GDI scaling of Bitmap Fonts
lplf->lfQuality = DEFAULT_QUALITY;
lplf->lfWidth = 0;
}
SelectObject(hdc, hfOld);
DeleteObject(hf);
DeleteDC(hdc);
pdtSmpl->lfTestFont = *lplf;
}
FreeMem(lplf);
}
return fft;
}
#endif
/****************************************************************************
*
* FUNCTION: DrawFontSample
*
* Parameters:
*
* lprcPage Size of the page in pels. A page is either a printed
* sheet (on a printer) or the Window.
*
* cyOffset Offset into the virtual sample text. Used to "scroll" the
* window up and down. Positive number means start further
* down in the virtual sample text as the top line in the
* lprcPage.
*
* lprcPaint Rectangle to draw. It is in the same coord space as
* lprcPage. Used to optimize window repaints, and to
* support banding to printers.
*
*
\****************************************************************************/
int DrawFontSample( HDC hdc, LPRECT lprcPage, int cyOffset, LPRECT lprcPaint, BOOL fReallyDraw ) {
int cyDPI;
HFONT hfOld, hfText, hfTimes;
LOGFONT lfTmp;
int yBaseline = -cyOffset;
int taOld,i;
TCHAR szNumber[10];
int cyShkTxt = -1, cptsShkTxt = -1;
SIZE sz;
int cxPage;
DPRINT((DBTX("PAINTING")));
cyDPI = GetDeviceCaps(hdc, LOGPIXELSY );
taOld = SetTextAlign(hdc, TA_BASELINE);
glfTimes.lfHeight = MulDiv( -CPTS_COPYRIGHT_SIZE, cyDPI, C_PTS_PER_INCH );
hfTimes = CreateFontIndirect(&glfTimes);
// Get hfOld for later
hfOld = SelectObject(hdc, hfTimes);
//
// Find the longest shrinktext line so we can make sure they will fit
// on the screen
//
cxPage = lprcPage->right - lprcPage->left;
for( i = 0; i < CLINES_DISPLAY && gdtDisplay.atlDsp[i].dtyp != DTP_UNUSED; i++ ) {
PTXTLN ptlCurrent = &(gdtDisplay.atlDsp[i]);
if (ptlCurrent->dtyp == DTP_SHRINKTEXT) {
lfTmp = gdtDisplay.lfTestFont;
if (cptsShkTxt == -1)
cptsShkTxt = ptlCurrent->cptsSize;
cyShkTxt = MulDiv( -cptsShkTxt, cyDPI, C_PTS_PER_INCH );
lfTmp.lfHeight = cyShkTxt;
hfText = CreateFontIndirect( &lfTmp );
SelectObject(hdc, hfText);
GetTextExtentPoint32(hdc, ptlCurrent->pszText, ptlCurrent->cchText, &sz );
SelectObject(hdc, hfOld);
DeleteObject(hfText);
// Make sure shrink lines are not too long
if (sz.cx > cxPage) {
DPRINT((DBTX(">>>Old lfH:%d sz.cx:%d cxPage:%d"), lfTmp.lfHeight, sz.cx, cxPage));
cptsShkTxt = cptsShkTxt * cxPage / sz.cx;
cyShkTxt = MulDiv( -cptsShkTxt, cyDPI, C_PTS_PER_INCH );
DPRINT((DBTX(">>>New lfH:%d"),lfTmp.lfHeight));
}
}
}
//
// Paint the screen/page
//
for( i = 0; i < CLINES_DISPLAY && gdtDisplay.atlDsp[i].dtyp != DTP_UNUSED; i++ ) {
TEXTMETRIC tm;
PTXTLN ptlCurrent = &(gdtDisplay.atlDsp[i]);
// Create and select the font for this line
if (ptlCurrent->dtyp == DTP_TEXTOUT || ptlCurrent->dtyp == DTP_SHRINKTEXT )
lfTmp = gdtDisplay.lfTestFont;
else
lfTmp = glfTimes;
if (ptlCurrent->dtyp == DTP_SHRINKTEXT) {
DPRINT((DBTX("PAINT:Creating ShrinkText Font:%s height:%d"), lfTmp.lfFaceName, lfTmp.lfHeight ));
lfTmp.lfHeight = cyShkTxt;
}
else
lfTmp.lfHeight = MulDiv( -ptlCurrent->cptsSize, cyDPI, C_PTS_PER_INCH );
hfText = CreateFontIndirect( &lfTmp );
SelectObject(hdc, hfText);
// Get size characteristics for this line in the selected font
if (ptlCurrent->dtyp == DTP_SHRINKDRAW) {
GetTextExtentPoint32(hdc, ptlCurrent->pszText, ptlCurrent->cchText, &sz );
// Make sure shrink lines are not too long
if (sz.cx > cxPage) {
SelectObject(hdc, hfOld);
DeleteObject(hfText);
DPRINT((DBTX("===Old lfH:%d sz.cx:%d cxPage:%d"), lfTmp.lfHeight, sz.cx, cxPage));
lfTmp.lfHeight = MulDiv( -ptlCurrent->cptsSize * cxPage / sz.cx, cyDPI, C_PTS_PER_INCH );
DPRINT((DBTX("===New lfH:%d"),lfTmp.lfHeight));
hfText = CreateFontIndirect( &lfTmp );
SelectObject(hdc, hfText);
}
}
GetTextMetrics(hdc, &tm);
yBaseline += (tm.tmAscent + tm.tmExternalLeading);
DPRINT((DBTX("tmH:%d tmA:%d tmD:%d tmIL:%d tmEL:%d"), tm.tmHeight, tm.tmAscent, tm.tmDescent, tm.tmInternalLeading, tm.tmExternalLeading));
// Draw the text
switch(ptlCurrent->dtyp) {
case DTP_NORMALDRAW:
case DTP_SHRINKDRAW:
case DTP_SHRINKTEXT:
if (fReallyDraw) {
ExtTextOut(hdc, lprcPage->left, yBaseline, ETO_CLIPPED, lprcPaint,
ptlCurrent->pszText, ptlCurrent->cchText, NULL);
}
//
// Bob says "This looks nice!" (Adding a little extra white space before the underline)
//
if (ptlCurrent->fLineUnder)
yBaseline += tm.tmDescent;
break;
case DTP_WRAPDRAW: {
RECT rc;
int cy;
yBaseline += tm.tmDescent;
SetRect(&rc, lprcPage->left, yBaseline - tm.tmHeight, lprcPage->right, yBaseline );
DPRINT((DBTX("**** Org RC:(%d, %d, %d, %d) tmH:%d"), rc.left, rc.top, rc.right, rc.bottom, tm.tmHeight));
cy = DrawText(hdc, ptlCurrent->pszText, ptlCurrent->cchText, &rc,
DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
DPRINT((DBTX("**** Cmp RC:(%d, %d, %d, %d) cy:%d"), rc.left, rc.top, rc.right, rc.bottom, cy));
if( cy > tm.tmHeight )
yBaseline = rc.bottom = rc.top + cy;
if (fReallyDraw) {
SetTextAlign(hdc, taOld);
DrawText(hdc, ptlCurrent->pszText, ptlCurrent->cchText, &rc, DT_NOPREFIX | DT_WORDBREAK);
SetTextAlign(hdc, TA_BASELINE);
}
break;
}
case DTP_TEXTOUT:
if (fReallyDraw) {
SIZE szNum;
int cchNum;
SelectObject(hdc, hfTimes );
wsprintf( szNumber, TEXT("%d"), ptlCurrent->cptsSize );
cchNum = lstrlen(szNumber);
ExtTextOut(hdc, lprcPage->left, yBaseline, ETO_CLIPPED, lprcPaint, szNumber, cchNum, NULL);
GetTextExtentPoint32(hdc, szNumber, cchNum, &szNum);
SelectObject(hdc, hfText);
ExtTextOut(hdc, lprcPage->left + szNum.cx * 2, yBaseline, ETO_CLIPPED, lprcPaint,
ptlCurrent->pszText, ptlCurrent->cchText, NULL);
}
break;
}
yBaseline += tm.tmDescent;
if (fReallyDraw && ptlCurrent->fLineUnder) {
MoveToEx( hdc, lprcPage->left, yBaseline, NULL);
LineTo( hdc, lprcPage->right, yBaseline );
// Leave space for the line we just drew
yBaseline += 1;
}
SelectObject( hdc, hfOld );
DeleteObject( hfText );
}
SelectObject(hdc, hfOld);
SetTextAlign(hdc, taOld);
DeleteObject(hfTimes);
return yBaseline;
}
/****************************************************************************
*
* FUNCTION: PaintSampleWindow
*
\****************************************************************************/
void PaintSampleWindow( HWND hwnd, HDC hdc, PAINTSTRUCT *pps ) {
RECT rcClient;
GetClientRect(hwnd, &rcClient);
DrawFontSample( hdc, &rcClient, gyScroll, &(pps->rcPaint), TRUE );
}
/****************************************************************************
*
* FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE: Processes messages
*
* MESSAGES:
*
* WM_COMMAND - application menu (About dialog box)
* WM_DESTROY - destroy window
*
* COMMENTS:
*
* To process the IDM_ABOUT message, call MakeProcInstance() to get the
* current instance address of the About() function. Then call Dialog
* box which will create the box according to the information in your
* fontview.rc file and turn control over to the About() function. When
* it returns, free the intance address.
*
\****************************************************************************/
LONG APIENTRY FrameWndProc(
HWND hwnd, /* window handle */
UINT message, /* type of message */
UINT wParam, /* additional information */
LONG lParam) /* additional information */
{
static SIZE szWindow = {0, 0};
switch (message) {
case WM_PAINT: {
HDC hdc;
RECT rc;
PAINTSTRUCT ps;
int x;
hdc = BeginPaint(hwnd, &ps);
// get the window rect
GetClientRect(hwnd, &rc);
// extend only down by gcyBtnArea
rc.bottom = rc.top + gcyBtnArea;
// Fill rect with button face color (handled by class background brush)
// FillRect(hdc, &rc, ghbr3DFace);
// Fill small rect at bottom with edge color
rc.top = rc.bottom - 2;
FillRect(hdc, &rc, ghbr3DShadow);
ReleaseDC(hwnd, hdc);
EndPaint(hwnd, &ps);
break;
}
case WM_CREATE: {
HDC hdc;
RECT rc;
int i;
GetClientRect(hwnd, &rc);
szWindow.cx = rc.right - rc.left;
szWindow.cy = rc.bottom - rc.top;
for( i = 0; i < C_BUTTONS; i++ ) {
int x = gabtCmdBtns[i].x;
HWND hwndBtn;
if (x < 0)
x = szWindow.cx + x - gabtCmdBtns[i].cx;
gabtCmdBtns[i].hwnd = hwndBtn = CreateWindow( TEXT("button"),
gabtCmdBtns[i].pszText, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
x, gabtCmdBtns[i].y,
gabtCmdBtns[i].cx, gabtCmdBtns[i].cy,
hwnd, (HMENU)gabtCmdBtns[i].id,
hInst, NULL);
if (hwndBtn != NULL) {
SendMessage(hwndBtn, WM_SETFONT, (WPARAM)GetStockObject(ANSI_VAR_FONT), MAKELPARAM(TRUE, 0));
}
}
ghwndView = CreateWindow( TEXT("FontDisplayClass"), NULL, WS_CHILD | WS_VSCROLL | WS_VISIBLE,
0, gcyBtnArea, szWindow.cx, szWindow.cy - gcyBtnArea, hwnd, 0, hInst, NULL );
break;
}
case WM_GETMINMAXINFO: {
LPMINMAXINFO lpmmi = (LPMINMAXINFO) lParam;
lpmmi->ptMinTrackSize.x = gcxMinWinSize;
lpmmi->ptMinTrackSize.y = gcyMinWinSize;
break;
}
case WM_SIZE: {
int cxNew, cyNew;
HDC hdc;
RECT rc;
SCROLLINFO sci;
cxNew = LOWORD(lParam);
cyNew = HIWORD(lParam);
if (cyNew != szWindow.cy || cxNew != szWindow.cx) {
int i;
for( i = 0; i < C_BUTTONS; i++ ) {
int x = gabtCmdBtns[i].x;
if (x < 0) {
SetWindowPos(gabtCmdBtns[i].hwnd, NULL, cxNew + x - gabtCmdBtns[i].cx, gabtCmdBtns[i].y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
}
}
szWindow.cx = cxNew;
szWindow.cy = cyNew;
SetWindowPos(ghwndView, NULL, 0, gcyBtnArea, szWindow.cx, szWindow.cy - gcyBtnArea,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
}
break;
}
case WM_COMMAND: /* message: command from application menu */
if (LOWORD(wParam) != IDB_DONE)
return SendMessage(ghwndView, message, wParam, lParam);
PostMessage(ghwndFrame, WM_CLOSE, 0, 0);
break;
case WM_DESTROY: {
int i;
DestroyWindow(ghwndView);
for( i = 0; i < C_BUTTONS; i++ ) {
DestroyWindow(gabtCmdBtns[i].hwnd);
}
PostQuitMessage(0);
break;
}
default: /* Passes it on if unproccessed */
return (DefWindowProc(hwnd, message, wParam, lParam));
}
return (0L);
}
/****************************************************************************
*
* FUNCTION: ViewWndProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE: Processes messages
*
* MESSAGES:
*
* WM_COMMAND - application menu (About dialog box)
* WM_DESTROY - destroy window
*
* COMMENTS:
*
* To process the IDM_ABOUT message, call MakeProcInstance() to get the
* current instance address of the About() function. Then call Dialog
* box which will create the box according to the information in your
* fontview.rc file and turn control over to the About() function. When
* it returns, free the intance address.
*
\****************************************************************************/
LONG APIENTRY ViewWndProc(
HWND hwnd, /* window handle */
UINT message, /* type of message */
UINT wParam, /* additional information */
LONG lParam) /* additional information */
{
static SIZE szWindow = {0, 0};
static int cyVirtPage = 0;
switch (message) {
case WM_CREATE: {
HDC hdc;
RECT rc;
SCROLLINFO sci;
int i;
GetClientRect(hwnd, &rc);
szWindow.cx = rc.right - rc.left;
szWindow.cy = rc.bottom - rc.top;
hdc = CreateCompatibleDC(NULL);
cyVirtPage = DrawFontSample(hdc, &rc, 0, NULL, FALSE);
DeleteDC(hdc);
gyScroll = 0;
sci.cbSize = sizeof(sci);
sci.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
sci.nMin = 0;
sci.nMax = cyVirtPage;
sci.nPage = szWindow.cy;
sci.nPos = gyScroll;
SetScrollInfo(hwnd, SB_VERT, &sci, TRUE );
if (gfPrint)
PostMessage(hwnd, WM_COMMAND, IDB_PRINT, 0);
break;
}
case WM_SIZE: {
int cxNew, cyNew;
HDC hdc;
RECT rc;
SCROLLINFO sci;
cxNew = LOWORD(lParam);
cyNew = HIWORD(lParam);
if (cyNew != szWindow.cy || cxNew != szWindow.cx) {
int i;
szWindow.cx = cxNew;
szWindow.cy = cyNew;
hdc = CreateCompatibleDC(NULL);
SetRect(&rc, 0, 0, szWindow.cx, szWindow.cy);
cyVirtPage = DrawFontSample(hdc, &rc, 0, NULL, FALSE);
DeleteDC(hdc);
if (cyVirtPage <= cyNew) {
// Disable the scrollbar
gyScroll = 0;
}
if (cyVirtPage > szWindow.cy && gyScroll > cyVirtPage - szWindow.cy)
gyScroll = cyVirtPage - szWindow.cy;
sci.cbSize = sizeof(sci);
sci.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
sci.nMin = 0;
sci.nMax = cyVirtPage;
sci.nPage = cyNew;
sci.nPos = gyScroll;
SetScrollInfo(hwnd, SB_VERT, &sci, TRUE );
}
break;
}
case WM_VSCROLL: {
int iCode = (int)LOWORD(wParam);
int yPos = (int)HIWORD(wParam);
int yNewScroll = gyScroll;
switch( iCode ) {
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
if (yPos != yNewScroll)
yNewScroll = yPos;
break;
case SB_LINEUP:
yNewScroll -= gcyLine;
break;
case SB_PAGEUP:
yNewScroll -= szWindow.cy;
break;
case SB_LINEDOWN:
yNewScroll += gcyLine;
break;
case SB_PAGEDOWN:
yNewScroll += szWindow.cy;
break;
case SB_TOP:
yNewScroll = 0;
break;
case SB_BOTTOM:
yNewScroll = cyVirtPage;
break;
}
if (yNewScroll < 0)
yNewScroll = 0;
if (yNewScroll > cyVirtPage - szWindow.cy)
yNewScroll = cyVirtPage - szWindow.cy;
if (gyScroll != yNewScroll) {
SCROLLINFO sci;
int dyScroll;
dyScroll = gyScroll - yNewScroll;
if (ABS(dyScroll) < szWindow.cy) {
ScrollWindowEx(hwnd, 0, dyScroll, NULL, NULL, NULL, NULL, SW_ERASE | SW_INVALIDATE);
} else
InvalidateRect(hwnd, NULL, TRUE);
gyScroll = yNewScroll;
sci.cbSize = sizeof(sci);
sci.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
sci.nMin = 0;
sci.nMax = cyVirtPage;
sci.nPage = szWindow.cy;
sci.nPos = gyScroll;
SetScrollInfo(hwnd, SB_VERT, &sci, TRUE );
}
break;
}
case WM_COMMAND: /* message: command from application menu */
if( !DoCommand( hwnd, wParam, lParam ) )
return (DefWindowProc(hwnd, message, wParam, lParam));
break;
case WM_PAINT: {
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint( hwnd, &ps );
PaintSampleWindow( hwnd, hdc, &ps );
EndPaint( hwnd, &ps );
break;
}
default: /* Passes it on if unproccessed */
return (DefWindowProc(hwnd, message, wParam, lParam));
}
return (0L);
}
/*********************************************\
*
* PRINT DLGS
*
*
\*********************************************/
HDC PromptForPrinter(HWND hwnd, HINSTANCE hInst, int *pcCopies ) {
PRINTDLG pd;
FillMemory(&pd, sizeof(pd), 0);
pd.lStructSize = sizeof(pd);
pd.hwndOwner = hwnd;
pd.Flags = PD_RETURNDC | PD_NOSELECTION;
pd.nCopies = 1;
pd.hInstance = hInst;
if (PrintDlg(&pd)) {
*pcCopies = pd.nCopies;
return pd.hDC;
} else
return NULL;
}
/****************************************************************************\
*
* FUNCTION: PrintSampleWindow(hwnd)
*
* Prompts for a printer and then draws the sample text to the printer
*
\****************************************************************************/
void PrintSampleWindow(HWND hwnd) {
HDC hdc;
DOCINFO di;
int cxDPI, cyDPI, iPage, cCopies;
RECT rcPage;
HCURSOR hcur;
hdc = PromptForPrinter(hwnd, hInst, &cCopies);
if (hdc == NULL)
return;
hcur = SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)));
cyDPI = GetDeviceCaps(hdc, LOGPIXELSY );
cxDPI = GetDeviceCaps(hdc, LOGPIXELSX );
/*
* Set a one inch margine around the page
*/
SetRect(&rcPage, 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES));
rcPage.left += cxDPI;
rcPage.right -= cxDPI;
di.cbSize = sizeof(di);
di.lpszDocName = gdtDisplay.atlDsp[0].pszText;
di.lpszOutput = NULL;
di.lpszDatatype = NULL;
di.fwType = 0;
StartDoc(hdc, &di);
for( iPage = 0; iPage < cCopies; iPage++ ) {
StartPage(hdc);
DrawFontSample( hdc, &rcPage, -cyDPI, &rcPage, TRUE );
EndPage(hdc);
}
EndDoc(hdc);
DeleteDC(hdc);
SetCursor(hcur);
}
/****************************************************************************\
*
* FUNCTION: DoCommand(HWND, unsigned, WORD, LONG)
*
* PURPOSE: Processes messages for "About" dialog box
*
* MESSAGES:
*
* WM_INITDIALOG - initialize dialog box
* WM_COMMAND - Input received
*
* COMMENTS:
*
* No initialization is needed for this particular dialog box, but TRUE
* must be returned to Windows.
*
* Wait for user to click on "Ok" button, then close the dialog box.
*
\****************************************************************************/
BOOL DoCommand( HWND hWnd, UINT wParam, LONG lParam )
{
DLGPROC lpProcAbout; /* pointer to the "About" function */
switch(LOWORD(wParam)){
case IDB_PRINT: {
PrintSampleWindow(hWnd);
break;
}
case IDB_DONE: {
PostMessage(ghwndFrame, WM_CLOSE, 0, 0);
break;
}
default: {
return FALSE;
}
}
return TRUE;
}
BOOL bFileExists(TCHAR*pszFile)
{
HANDLE hf;
if ((hf = CreateFile(pszFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) != INVALID_HANDLE_VALUE)
{
CloseHandle(hf);
return TRUE;
}
return FALSE;
}
/******************************Public*Routine******************************\
*
* FindPfb, given pfm file, see if pfb file exists in the same dir or in the
* parent directory of the pfm file
*
* History:
* 14-Jun-1994 -by- Bodin Dresevic [BodinD]
* Wrote it.
*
* Returns: 16-bit encoded value indicating error and type of file where
* error occurred. (see fvscodes.h) for definitions.
* The following table lists the "status" portion of the codes
* returned.
*
* FVS_SUCCESS
* FVS_INVALID_FONTFILE
* FVS_FILE_OPEN_ERR
*
\**************************************************************************/
BOOL bFindPfb (
TCHAR *pszPFM,
TCHAR *achPFB
)
{
DWORD cjKey;
TCHAR *pszParent = NULL; // points to the where parent dir of the inf file is
TCHAR *pszBare = NULL; // "bare" .inf name, initialization essential
// example:
// if pszPFM -> "c:\psfonts\pfm\foo_____.pfm"
// then pszParent -> "pfm\foo_____.pfm"
cjKey = lstrlen(pszPFM) + 1;
if (cjKey < 5) // 5 = lstrlen(".pfm") + 1;
return FALSE;
// go on to check if .pfb file exists:
// We will first check .pfb file exists in the same dir as .pfm
lstrcpy(achPFB, pszPFM);
lstrcpy(&achPFB[cjKey - 5],TEXT(".PFB"));
if (!bFileExists(achPFB))
{
// we did not find the .pfb file in the same dir as .pfm
// Now check the parent directory of the .pfm file
pszBare = &pszPFM[cjKey - 5];
for ( ; pszBare > pszPFM; pszBare--)
{
if ((*pszBare == TEXT('\\')) || (*pszBare == TEXT(':')))
{
pszBare++; // found it
break;
}
}
// check if full path to .pfm was passed in or a bare
// name itself was passed in to look for .pfm file in the current dir
if ((pszBare > pszPFM) && (pszBare[-1] == TEXT('\\')))
{
// skip '\\' and search backwards for another '\\':
for (pszParent = &pszBare[-2]; pszParent > pszPFM; pszParent--)
{
if ((*pszParent == TEXT('\\')) || (*pszParent == TEXT(':')))
{
pszParent++; // found it
break;
}
}
// create .pfb file name in the .pfm parent directory:
lstrcpy(&achPFB[pszParent - pszPFM], pszBare);
lstrcpy(&achPFB[lstrlen(achPFB) - 4], TEXT(".PFB"));
}
else if (pszBare == pszPFM)
{
// bare name was passed in, to check for the inf file in the "." dir:
lstrcpy(achPFB, TEXT("..\\"));
lstrcpy(&achPFB[3], pszBare); // 3 == lstrlen("..\\")
lstrcpy(&achPFB[lstrlen(achPFB) - 4], TEXT(".PFB"));
}
else
{
return FALSE;
}
// check again if we can find the file, if not fail.
if (!bFileExists(achPFB))
{
return FALSE;
}
}
// now we have paths to .pfb file in the buffer provided by the caller.
return TRUE;
}