|
|
/***
** ** Module: T1Instal ** ** Description: ** This is the Win32 DLL (t1instal.dll) interface to the ** font converter. All window specific code is located in ** this module and the error hadler module (errors.c). ** ** Author: Michael Jansson ** Created: 12/18/93 ** ***/
/***** INCLUDES */
#include "windows.h"
#include <string.h>
#include <time.h>
#include <limits.h>
#include <ctype.h>
#undef IN
#include "titott.h"
#include "types.h"
#include "t1local.h"
#include "t1instal.h"
#include "fileio.h"
#include "safemem.h"
#include "t1msg.h"
#undef UNICODE
/* The CopyrightCheck/MAYBEOK case always succeeds for now. */ #define MAYBEOK SUCCESS
/***** LOCAL TYPES */ struct callFrame { const void (STDCALL *Progress)(short, void*); void *arg; int last; int done; };
static short lastCP = FALSE; static char lastVendor[256] = "Unknown.";
/***** CONSTANTS */ #define MIN_PROGRESS 3
#define DELIMITERS " ,"
#define COPYSIGN 169
#define TRUE 1
#define FALSE 0
#define DFFACE 139
#define DFDRIVERINFO 101
#define VERSTR "Converter: Windows Type 1 Installer V1.0d.\n" \
"Font: V"
const char version[] = "\n$VER: 1.0d\n";
#ifndef NOANSIWINMAC
const char *winmac[] = { "A", "AE", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "B", "C", "Cacute", "Ccaron", "Ccedilla", "D", "Delta", "E", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Eth", "F", "G", "Gbreve", "H", "I", "Iacute", "Icircumflex", "Idieresis", "Idot", "Igrave", "J", "K", "L", "Lslash", "M", "N", "Ntilde", "O", "OE", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Oslash", "Otilde", "P", "Q", "R", "S", "Scaron", "Scedilla", "T", "Thorn", "U", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "V", "W", "X", "Y", "Yacute", "Ydieresis", "Z", "a", "aacute", "acircumflex", "acute", "adieresis", "ae", "agrave", "ampersand", "approxequal", "aring", "asciicircum", "asciitilde", "asterisk", "at", "atilde", "b", "backslash", "bar", "braceleft", "braceright", "bracketleft", "bracketright", "breve", "brokenbar", "bullet", "c", "cacute", "caron", "ccaron", "ccedilla", "cedilla", "cent", "circumflex", "colon", "comma", "copyright", "currency", "d", "dagger", "daggerdbl", "degree", "dieresis", "divide", "dmacron", "dollar", "dotaccent", "dotlessi", "e", "eacute", "ecircumflex", "edieresis", "egrave", "eight", "ellipsis", "emdash", "endash", "equal", "eth", "exclam", "exclamdown", "f", "fi", "five", "fl", "florin", "four", "fraction", "franc", "g", "gbreve", "germandbls", "grave", "greater", "greaterequal", "guillemotleft", "guillemotright", "guilsinglleft", "guilsinglright", "h", "hungerumlaut", "hyphen", "i", "iacute", "icircumflex", "idieresis", "igrave", "infinity", "integral", "j", "k", "l", "less", "lessequal", "logicalnot", "lozenge", "lslash", "m", "macron", "middot", "minus", "mu", "multiply", "n", "nbspace", "nine", "notequal", "ntilde", "numbersign", "o", "oacute", "ocircumflex", "odieresis", "oe", "ogonek", "ograve", "ohm", "one", "onehalf", "onequarter", "onesuperior", "ordfeminine", "ordmasculine", "oslash", "otilde", "overscore", "p", "paragraph", "parenleft", "parenright", "partialdiff", "percent", "period", "periodcentered", "perthousand", "pi", "plus", "plusminus", "product", "q", "question", "questiondown", "quotedbl", "quotedblbase", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "quotesinglbase", "quotesingle", "r", "radical", "registered", "ring", "s", "scaron", "scedilla", "section", "semicolon", "seven", "sfthyphen", "six", "slash", "space", "sterling", "summation", "t", "thorn", "three", "threequarters", "threesuperior", "tilde", "trademark", "two", "twosuperior", "u", "uacute", "ucircumflex", "udieresis", "ugrave", "underscore", "v", "w", "x", "y", "yacute", "ydieresis", "yen", "z", "zero" };
#define GLYPHFILTER &win
const struct GlyphFilter win = { sizeof(winmac) / sizeof(winmac[0]), winmac };
#else
#define GLYPHFILER (struct GlyphFilter *)0
#endif /* NOANSIWINMAC */
/***** PROTOTYPES */ extern int __cdecl sprintf(char *, const char *, ...);
/***** MACROS */
#define ReadLittleEndianDword(file,dw) { \
dw = (DWORD)io_ReadOneByte(file) ; \ dw |= (DWORD)io_ReadOneByte(file) << 8; \ dw |= (DWORD)io_ReadOneByte(file) << 16; \ dw |= (DWORD)io_ReadOneByte(file) << 24; \ } #ifndef try
#define try __try
#define except __except
#endif
/***** GLOBALS */ HANDLE hInst;
/***** STATIC FUNCTIONS */
/***
** Function: Decrypt ** ** Description: ** Decrypt a byte. ***/ static DWORD CSum(char *str) { DWORD sum = 0;
while (*str) sum += *str++;
return sum; }
/***
** Function: Decrypt ** ** Description: ** Decrypt a byte. ***/ static char *Encrypt(char *str, char *out) { const USHORT c1 = 52845; const USHORT c2 = 22719; UBYTE cipher; USHORT r = 8366; int i; for (i=0; i<(int)strlen(str); i++) { cipher = (UBYTE)(str[i] ^ (r>>8)); r = (USHORT)((cipher + r) * c1 + c2); out[i] = (char)((cipher & 0x3f) + ' ');
/* Unmap 'bad' characters, that the Registry DB doesn't like. */ if (out[i]=='=' || out[i]==' ' || out[i]=='@' || out[i]=='"') out[i] = 'M'; } out[i] = '\0';
return out; }
static char *stristr(char *src, char *word) { int len = strlen(word); char *tmp = src;
while (*src) { if (!_strnicmp(src, word, len)) break; src++; }
return src; }
/***
** Function: GetCompany ** ** Description: ** Extract the company name out of a copyright string. ***/ char *GetCompany(char *buf) { char *company = NULL; int done = FALSE; UBYTE *token; UBYTE *tmp1; UBYTE *tmp2; UBYTE *tmp3; UBYTE *tmp4; int i;
token = buf;
while (token && !done) {
/* Locate the start of the copyright string. */ tmp1 = stristr(token, "copyright"); tmp2 = stristr(token, "(c)"); tmp3 = stristr(token, " c "); if ((tmp4 = strchr(token, COPYSIGN))==NULL) tmp4 = &token[strlen(token)]; if (*tmp1==0 && *tmp2==0 && *tmp3==0 && *tmp4==0) { token = NULL; break; } else if (tmp1<tmp2 && tmp1<tmp3 && tmp1<tmp4) token = tmp1; else if (tmp2<tmp3 && tmp2<tmp4) token = tmp2; else if (tmp3<tmp4) token = tmp3; else token = tmp4;
/* Skip the leading copyright strings/character. */ if (token[0]==COPYSIGN && token[1]!='\0') { token += 2; } else if (!_strnicmp(token, "copyright", strlen("copyright"))) { token += strlen("copyright"); } else { token += strlen("(c)"); }
/* Skip blanks. */ while(*token && isspace(*token) || *token==',') token++;
/* Another copyright word? */ if (!_strnicmp((char*)token, "(c)", strlen("(c)")) || !_strnicmp((char*)token, "copyright", strlen("copyright")) || token[0]==COPYSIGN) continue;
/* Skip the years. */ company = token; if (isdigit(token[0])) { while (isdigit(*company) || isspace(*company) || ispunct(*company) || (*company)=='-') company++;
if (*company=='\0') break;
/* Skip strings like "by", up to the beginning of a name that */ /* starts with an upper case letter. */ while (*company && (company[0]<'A' || company[0]>'Z')) company++;
done = TRUE; } else { continue; } }
/* Did we find it? */ if (company) { while (*company && isspace(*company)) company++;
if (*company=='\0') { company=NULL; } else {
/* Terminate the company name. */ if ((token = (UBYTE*)strchr(company, '.'))!=NULL) {
/* Period as an initial delimiter, e.g. James, A. B. ?*/ if (token[-1]>='A' && token[-1]<='Z') { if (strchr((char*)&token[1], '.')) token = (UBYTE*)strchr((char*)&token[1], '.');
/* Check for "James A. Bently, " */ else if (strchr((char*)&token[1], ',')) { token = (UBYTE*)strchr((char*)&token[1], ','); token[0] = '.'; } } token[1] = '\0'; } else { /* Name ending with a ';'? */ if ((token = (UBYTE*)strrchr(company, ';'))) { *token = '\0'; } }
/* Truncate some common strings. */ tmp1 = stristr(company, "all rights reserved"); *tmp1 = '\0';
/* Remove trailing punctuation character. */ for (i=strlen(company)-1; i>0 && (ispunct(company[i]) || isspace(company[i])); i--) { company[i] = 0; } } }
return company; }
/**** FUNCTIONS */
/***
** Function: ConvertAnyway ** ** Description: ** Ask the user if it is ok to convert. ***/ static errcode ConvertAnyway(const char *vendor, const char *facename) { char tmp[256]; char msg[1024]; errcode answer;
if (vendor==NULL || strlen(vendor)==0) { LoadString(hInst, IDS_RECOGNIZE1, tmp, sizeof(tmp)); sprintf(msg, tmp, facename); } else { LoadString(hInst, IDS_RECOGNIZE2, tmp, sizeof(tmp)); sprintf(msg, tmp, facename, vendor); } LoadString(hInst, IDS_MAINMSG, tmp, sizeof(tmp)); strcat(msg, tmp); LoadString(hInst, IDS_CAPTION, tmp, sizeof(tmp)); answer = (errcode)MessageBox(NULL, msg, tmp, QUERY); SetLastError(0);
return answer; }
/***
** Function: CheckCopyright ** ** Description: ** This is the callback function that verifies that ** the converted font is copyrighted by a company who ** has agreed to having their fonts converted by ** this software. These companies are registered in the ** registry data base. ***/
static errcode CheckCopyright(const char *facename, const char *copyright, const char *notice) { #ifdef NOCOPYRIGHTS
return SKIP; #else
HKEY key; char tmp[256]; char *company = NULL; char buf[1024]; int done = FALSE; short result = FAILURE;
/* Access the REG data base. */ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SUBKEY_TYPE1COPYRIGHTS, 0, KEY_QUERY_VALUE, &key)==ERROR_SUCCESS) {
/* Look for the company name in the /notice string. */ if (notice && notice[0]) { strcpy(buf, notice); company = GetCompany(buf); }
/* Look in the /copyright string if the company name was not found. */ if (company==NULL && copyright && copyright[0]) { strcpy(buf, copyright); company = GetCompany(buf); }
#ifdef SHOWCOPYRIGHTS
LogError(MSG_INFO, MSG_Copyright, company); Encrypt(company, tmp); sprintf(&tmp[strlen(tmp)], "(%d)\n", CSum(tmp)); LogError(MSG_INFO, MSG_Encoding, tmp); #else
/* Did not find a company name? */ if (company==NULL && ((notice==NULL || notice[0]=='\0'|| strstr(notice, "Copyright")==NULL) && (copyright==NULL || copyright[0]=='\0' || strstr(copyright, "Copyright")==NULL))) {
/* No known copyright. */ LogError(MSG_WARNING, MSG_NOCOPYRIGHT, NULL); result = MAYBEOK;
/* Strange copyright format? */ } else if (company==NULL || company[0]=='\0') { if (notice || notice[0]) LogError(MSG_WARNING, MSG_BADFORMAT, notice); else LogError(MSG_WARNING, MSG_BADFORMAT, copyright);
result = MAYBEOK;
/* Found copyright! */ } else { DWORD size; DWORD csum;
size = 4; if (RegQueryValueEx(key, Encrypt(company, tmp), NULL, NULL, (LPBYTE)&csum, &size)==ERROR_SUCCESS) { /* A positive match -> ok to convert. */ if (CSum(tmp)==csum) { LogError(MSG_INFO, MSG_COPYRIGHT, company); result = SUCCESS; } else { LogError(MSG_ERROR, MSG_BADCOPYRIGHT, company); result = SKIP; } } else { LogError(MSG_WARNING, MSG_BADCOPYRIGHT, company); result = MAYBEOK; } } #endif
RegCloseKey(key);
/* Give the user the final word. */ if (result==FAILURE) { if (ConvertAnyway(company, facename)==TRUE) result = SUCCESS; }
/* No copyright key in the registry? */ } else { LogError(MSG_ERROR, MSG_NODB, NULL); result = FAILURE; }
return result; #endif
}
/***
** Function: NTCheckCopyright ** ** Description: ** This is the callback function that verifies that ** the converted font is copyrighted by a company who ** has agreed to having their fonts converted by ** this software. These companies are registered in the ** registry data base. ***/ static errcode NTCheckCopyright(const char *facename, const char *copyright, const char *notice) { HKEY key; char tmp[256]; char *company = NULL; char buf[1024]; int done = FALSE; short result = FAILURE;
/* Access the REG data base. */ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SUBKEY_TYPE1COPYRIGHTS, 0, KEY_QUERY_VALUE, &key)==ERROR_SUCCESS) {
/* Look for the company name in the /notice string. */ if (notice && notice[0]) { strcpy(buf, notice); company = GetCompany(buf); }
/* Look in the /copyright string if the company name was not found. */ if (company==NULL && copyright && copyright[0]) { strcpy(buf, copyright); company = GetCompany(buf); }
/* Did not find a company name? */ if (company==NULL && ((notice==NULL || notice[0]=='\0'|| strstr(notice, "Copyright")==NULL) && (copyright==NULL || copyright[0]=='\0' || strstr(copyright, "Copyright")==NULL))) {
/* No known copyright. */ result = MAYBE;
/* Strange copyright format? */ } else if (company==NULL || company[0]=='\0') { result = MAYBE;
/* Found copyright! */ } else { DWORD size; DWORD csum;
/* remember for future use. */ strncpy(lastVendor, company, 256); lastVendor[MIN(255, strlen(company))] = '\0';
size = 4; if (RegQueryValueEx(key, Encrypt(company, tmp), NULL, NULL, (LPBYTE)&csum, &size)==ERROR_SUCCESS) { /* A positive match -> ok to convert. */ if (CSum(tmp)==csum) { result = SUCCESS; } else { result = FAILURE; } } else { result = MAYBE; } }
RegCloseKey(key);
/* No copyright key in the registry? */ } else { result = FAILURE; }
lastCP = result;
return FAILURE; }
/***
** Function: _Progress ** ** Description: ** This is the internal progress callback function that ** computes an percentage-done number, based on the ** number of converted glyphs. ***/ static void _Progress(short type, void *generic, void *arg) { struct callFrame *f = arg;
/* Processing glyphs or wrapping up? */ if (type==0 || type==1) f->done++; else f->done = MIN(sizeof(winmac)/sizeof(winmac[0]), f->done+10); if ((f->done-f->last)>MIN_PROGRESS) { f->Progress((short)(f->done*100/(sizeof(winmac)/sizeof(winmac[0]))), f->arg); f->last = f->done; } UNREFERENCED_PARAMETER(type); UNREFERENCED_PARAMETER(generic); SetLastError(0L); } static BOOL ReadStringFromOffset(struct ioFile *file, const DWORD dwOffset, char *pszString, int cLen, BOOL bStrip) { BOOL result = TRUE; DWORD offset;
/* Get offset to string. */ io_FileSeek(file, dwOffset);
/* Read the offset. */
ReadLittleEndianDword(file, offset);
/* Get the string. */ (void)io_FileSeek(file, offset); if (io_FileError(file) != SUCCESS) { result = FALSE; } else { int i;
i=0; while (io_FileError(file)==SUCCESS && i<cLen) { pszString[i] = (UBYTE)io_ReadOneByte(file); if (pszString[i]=='\0') break;
/* Replace all dashes with spaces. */ if (bStrip && pszString[i]=='-') pszString[i]=' '; i++; } }
return TRUE; }
/**** FUNCTIONS */
/***
** Function: ConvertTypeFaceA ** ** Description: ** Convert a T1 font into a TT font file. This is the ** simplified interface used by the Win32 DLL, with the ** ANSI interface. ***/ short STDCALL ConvertTypefaceAInternal(const char *type1, const char *metrics, const char *truetype, const void (STDCALL *Progress)(short, void*), void *arg) { struct callFrame f; struct callProgress p; struct T1Arg t1Arg; struct TTArg ttArg; short status;
/* Check parameters. */ if (type1==NULL || metrics==NULL) return FAILURE;
/* Set up arguments to ConvertTypefaceA() */ t1Arg.filter = GLYPHFILTER; t1Arg.upem = (short)2048; t1Arg.name = (char *)type1; t1Arg.metrics = (char *)metrics; ttArg.precision = (short)50; ttArg.name = (char *)truetype; ttArg.tag = VERSTR;
/* Use progress gauge */ if (Progress) { LogError(MSG_INFO, MSG_STARTING, type1);
f.Progress = Progress; f.done = 0; f.last = 0; f.arg = arg; p.arg = &f; p.cb = _Progress; status = ConvertT1toTT(&ttArg, &t1Arg, CheckCopyright, &p); Progress(100, arg); } else { status = ConvertT1toTT(&ttArg, &t1Arg, CheckCopyright, NULL); }
return status; }
short STDCALL ConvertTypefaceA(const char *type1, const char *metrics, const char *truetype, const void (STDCALL *Progress)(short, void*), void *arg) {
short bRet;
try { bRet = ConvertTypefaceAInternal(type1, metrics, truetype, Progress, arg); } except (EXCEPTION_EXECUTE_HANDLER) { #if 0
ASSERTGDI( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR, "ttfd!ttfdSemLoadFontFile, strange exception code\n" ); #endif
bRet = BADINPUTFILE;
}
return bRet; }
short STDCALL FindPfb ( char *pszPFM, char *achPFB );
/***
** Function: CheckPfmA ** ** Description: ** This function determines if there is a pfm/pfb pair of ** files that makes up an Adobe Type 1 font, and determins ** the descriptive face name of 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 ** FVS_INVALID_ARG ** FVS_FILE_IO_ERR ** FVS_BAD_VERSION ***/
short STDCALL CheckPfmA( char *pszPFM, DWORD cjDesc, char *pszDesc, DWORD cjPFB, char *pszPFB ) { struct ioFile *file; char szDriver[MAX_PATH]; short result = FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK); short ver;
char achPFB[MAX_PATH];
char *psz_PFB; DWORD cjPFB1;
if (pszPFB) { psz_PFB = pszPFB; cjPFB1 = cjPFB; } else { psz_PFB = (char *)achPFB; cjPFB1 = MAX_PATH; }
/* Check parameter. */ if (pszPFM==NULL || ((strlen(pszPFM)+3) >= cjPFB1)) return FVS_MAKE_CODE(FVS_INVALID_ARG, FVS_FILE_UNK);
// check if pfb file exists and find the path to it:
result = FindPfb(pszPFM, psz_PFB); if (FVS_STATUS(result) != FVS_SUCCESS) return result;
/****
* Locate the pszDescriptive name of the font. */
if ((file = io_OpenFile(pszPFM, READONLY))==NULL) return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFM);
(void)io_ReadOneByte(file); /* Skip the revision number. */ ver = (short)io_ReadOneByte(file);
if (ver > 3) { /* ERROR - unsupported format */ result = FVS_MAKE_CODE(FVS_BAD_VERSION, FVS_FILE_PFM); } else {
/* Read the driver name. */ if (!ReadStringFromOffset(file, DFDRIVERINFO, szDriver, sizeof(szDriver), FALSE)) { result = FVS_MAKE_CODE(FVS_FILE_IO_ERR, FVS_FILE_PFM); } /* Is it "PostScript" ? */ else if (_stricmp(szDriver, "PostScript")) { result = FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM); } /* Only get description if asked to do so. */ else if (pszDesc && !ReadStringFromOffset(file, DFFACE, pszDesc, cjDesc, TRUE)) { result = FVS_MAKE_CODE(FVS_FILE_IO_ERR, FVS_FILE_PFM); } }
(void)io_CloseFile(file);
return result; }
/***
** Function: DllMain ** ** Description: ** Main function of the DLL. Use to cache the module handle, ** which is needed to pop-up messages and peek in the registry. ***/ BOOL WINAPI DllMain(PVOID hmod, ULONG ulReason, PCONTEXT pctx OPTIONAL) { if (ulReason == DLL_PROCESS_ATTACH) { hInst = hmod; DisableThreadLibraryCalls(hInst); }
UNREFERENCED_PARAMETER(pctx);
return TRUE; }
/***
** Function: CheckCopyrightsA ** ** Description: ** This function verifies that it is ok to convert the font. This is ** done by faking an installation. ***/ short STDCALL CheckCopyrightAInternal(const char *szPFB, const DWORD wSize, char *szVendor) { struct T1Arg t1Arg; struct TTArg ttArg; /* Set up arguments to ConvertTypefaceA() */ t1Arg.metrics = NULL; t1Arg.upem = (short)2048; t1Arg.filter = GLYPHFILTER; t1Arg.name = szPFB; ttArg.precision = (short)200; ttArg.tag = NULL; ttArg.name = "NIL:"; lastCP = FAILURE; strcpy(lastVendor, ""); (void)ConvertT1toTT(&ttArg, &t1Arg, NTCheckCopyright, NULL); strncpy(szVendor, lastVendor, wSize); szVendor[MIN(wSize, strlen(lastVendor))] = '\0'; return lastCP; }
short STDCALL CheckCopyrightA(const char *szPFB, const DWORD wSize, char *szVendor) { short iRet;
try { iRet = CheckCopyrightAInternal(szPFB,wSize,szVendor); } except (EXCEPTION_EXECUTE_HANDLER) { iRet = BADINPUTFILE; } return iRet;
}
/******************************Public*Routine******************************\
* * short STDCALL CheckInfA ( * * If pfm and inf files are in the same directory only pfm is recognized * and inf file is ignored. * * History: * 27-Apr-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 * FVS_FILE_BUILD_ERR * FVS_FILE_EXISTS * FVS_INSUFFICIENT_BUF * \**************************************************************************/
short CreatePFM(char *pszINF, char *pszAFM, char *pszPFM); BOOL bGetDescFromInf(char * pszINF, DWORD cjDesc, char *pszDesc);
BOOL bFileExists(char *pszFile) { HFILE hf;
if ((hf = _lopen(pszFile, OF_READ)) != -1) { _lclose(hf); return TRUE; }
return FALSE; }
short STDCALL CheckInfA ( char *pszINF, DWORD cjDesc, char *pszDesc, DWORD cjPFM, char *pszPFM, DWORD cjPFB, char *pszPFB, BOOL *pbCreatedPFM, char *pszFontPath ) { char achPFM[MAX_PATH]; char achPFB[MAX_PATH]; char achAFM[MAX_PATH];
DWORD cjKey; char *pszParent = NULL; // points to the where parent dir of the inf file is
char *pszBare = NULL; // "bare" .inf name, initialization essential
short result = FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK); BOOL bAfmExists = FALSE; BOOL bPfbExists = FALSE;
//
// This is a real hack use of pbCreatedPFM.
// It's the best solution with the time we have.
//
BOOL bCheckForExistingPFM = *pbCreatedPFM;
*pbCreatedPFM = FALSE;
// example:
// if pszINF -> "c:\psfonts\fontinfo\foo_____.inf"
// then pszParent -> "fontinfo\foo_____.inf"
cjKey = strlen(pszINF) + 1;
if (cjKey < 5) // 5 = strlen(".pfm") + 1;
return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF);
// check if a pfm file exists in the SAME directory.
// Use the buffer on the stack to produce the path for the pfm file:
strcpy(achPFM, pszINF); strcpy(&achPFM[cjKey - 5],".PFM");
// try to open pfm file to check if it exists:
if (bCheckForExistingPFM && bFileExists(achPFM)) { // we found the pfm file, therefore we do not report this .inf file.
return FVS_MAKE_CODE(FVS_FILE_EXISTS, FVS_FILE_PFM); }
// pfm file is NOT found, go on to check if .afm and .pfb files exists:
// We will first check if .afm and .pfb files exists in the same dir as .inf
strcpy(achAFM, pszINF); strcpy(&achAFM[cjKey - 5],".AFM");
strcpy(achPFB, pszINF); strcpy(&achPFB[cjKey - 5],".PFB");
bAfmExists = bFileExists(achAFM); bPfbExists = bFileExists(achPFB);
if (!bAfmExists || !bPfbExists) { // we did not find the .afm and .pfb files in the same dir as .inf
// we will check two more directories for the .afm and .pfb files
// 1) the parent directory of the .inf file for .pfb file
// 2) the afm subdirectory of the .inf parent directory for .afm file
//
// This is meant to handle the standard configuration of files produced
// on user's hard drive by unlocking fonts from Adobe's CD or from a
// previous installation of atm manager on this machine.
// This configuration is as follows:
// c:\psfonts\ *.pfb files are here
// c:\psfonts\afm *.afm files are here
// c:\psfonts\fontinfo *.inf files are here
// c:\psfonts\pfm *.pfm files that are created on the fly
// are PUT here by atm.
// We will instead put the files in windows\system dir where all other
// fonts are, it may not be possible to write pmf files on the media
// from where we are installing fonts
pszBare = &pszINF[cjKey - 5]; for ( ; pszBare > pszINF; pszBare--) { if ((*pszBare == '\\') || (*pszBare == ':')) { pszBare++; // found it
break; } }
// check if full path to .inf file was passed in or a bare
// name itself was passed in to look for .inf file in the current dir
if ((pszBare > pszINF) && (pszBare[-1] == '\\')) { // skip '\\' and search backwards for another '\\':
for (pszParent = &pszBare[-2]; pszParent > pszINF; pszParent--) { if ((*pszParent == '\\') || (*pszParent == ':')) { pszParent++; // found it
break; } }
// create .pfb file name in the .inf parent directory:
strcpy(&achPFB[pszParent - pszINF], pszBare); strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
// create .afm file name in the afm subdirectory of the .inf
// parent directory:
strcpy(&achAFM[pszParent - pszINF], "afm\\"); strcpy(&achAFM[pszParent - pszINF + 4], pszBare); strcpy(&achAFM[strlen(achAFM) - 4], ".AFM");
} else if (pszBare == pszINF) { // bare name was passed in, to check for the inf file in the "." dir:
strcpy(achPFB, "..\\"); strcpy(&achPFB[3], pszBare); // 3 == strlen("..\\")
strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
strcpy(achAFM, "..\\afm\\"); strcpy(&achAFM[7], pszBare); // 7 == strlen("..\\afm\\")
strcpy(&achAFM[strlen(achAFM) - 4], ".AFM"); } else { return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK); }
// check again if we can find the files, if not fail.
if (!bAfmExists && !bFileExists(achAFM)) return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_AFM); if (!bPfbExists && !bFileExists(achPFB)) return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFB); }
// now we have paths to .inf .afm and .pfb files. Now let us see
// what the caller wants from us:
if (pszDesc) { // we need to return description string in the buffer supplied
if (!bGetDescFromInf(pszINF, (DWORD)cjDesc, pszDesc)) return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF); }
// copy pfb file path out if requested
if (pszPFB) { if ((strlen(achPFB) + 1) < cjPFB) strcpy(pszPFB,achPFB); else return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK); }
// the caller wants a pfm file created from inf,afm files
// For now and probably for ever we will put this file in
// the %windir%\system, or %windir%\fonts for the secure system.
if (pszPFM) { UINT cjSystemDir; char *pszAppendHere; // append "bare" name here
// copy the first directory of the font path into the buffer provided
// It is expected that this routine will get something like
// "c:\foo" pointing to font path
strcpy(achPFM,pszFontPath); pszAppendHere = &achPFM[strlen(pszFontPath) - 1];
if (*pszAppendHere != '\\') { pszAppendHere++; *pszAppendHere = '\\'; } pszAppendHere++;
// find bare name of the .inf file if we do not have already:
if (!pszBare) { pszBare = &pszINF[cjKey - 5]; for ( ; pszBare > pszINF; pszBare--) { if ((*pszBare == '\\') || (*pszBare == ':')) { pszBare++; // found it
break; } } }
// append Bare name to the %windir%system\ path
strcpy(pszAppendHere, pszBare);
// finally change .inf extension to .pfm extension
strcpy(&pszAppendHere[strlen(pszAppendHere) - 4], ".PFM");
// copy out:
strcpy(pszPFM, achPFM); result = CreatePFM(pszINF, achAFM, pszPFM); *pbCreatedPFM = (FVS_STATUS(result) == FVS_SUCCESS);
if (!(*pbCreatedPFM)) return result; }
return FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK); }
/******************************Public*Routine******************************\
* * short STDCALL CheckType1AInternal * * Effects: See if we are going to report this as a valid type 1 font * * Warnings: * * History: * 29-Apr-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 * FVS_FILE_BUILD_ERR * FVS_INVALID_ARG * FVS_FILE_IO_ERR * FVS_BAD_VERSION * FVS_FILE_EXISTS * FVS_INSUFFICIENT_BUF * \**************************************************************************/
short STDCALL CheckType1AInternal ( char *pszKeyFile, DWORD cjDesc, char *pszDesc, DWORD cjPFM, char *pszPFM, DWORD cjPFB, char *pszPFB, BOOL *pbCreatedPFM, char *pszFontPath
) { DWORD cjKey;
*pbCreatedPFM = FALSE; // initialization is essential.
cjKey = strlen(pszKeyFile) + 1;
if (cjKey < 5) // 5 = strlen(".pfm") + 1;
return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK);
if (!_strcmpi(&pszKeyFile[cjKey - 5], ".PFM")) { // copy out pfm string when asked to do so:
if (pszPFM && (cjKey < cjPFM)) { if (cjKey < cjPFM) strcpy(pszPFM, pszKeyFile); else return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK); }
return CheckPfmA( pszKeyFile, cjDesc, pszDesc, cjPFB, pszPFB ); } else if (!_strcmpi(&pszKeyFile[cjKey - 5], ".INF")) { return CheckInfA ( pszKeyFile, cjDesc, pszDesc, cjPFM, pszPFM, cjPFB, pszPFB, pbCreatedPFM, pszFontPath ); } else { // this font is not our friend
return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK); } }
/******************************Public*Routine******************************\
* * CheckType1WithStatusA, try / except wrapper * * Effects: * * Warnings: * * 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 * FVS_FILE_BUILD_ERR * FVS_INVALID_ARG * FVS_FILE_IO_ERR * FVS_BAD_VERSION * FVS_FILE_EXISTS * FVS_INSUFFICIENT_BUF * FVS_EXCEPTION * \**************************************************************************/
short STDCALL CheckType1WithStatusA ( char *pszKeyFile, DWORD cjDesc, char *pszDesc, DWORD cjPFM, char *pszPFM, DWORD cjPFB, char *pszPFB, BOOL *pbCreatedPFM, char *pszFontPath ) { short status; try { status = CheckType1AInternal ( pszKeyFile, cjDesc, pszDesc, cjPFM, pszPFM, cjPFB, pszPFB, pbCreatedPFM, pszFontPath); } except (EXCEPTION_EXECUTE_HANDLER) { status = FVS_MAKE_CODE(FVS_EXCEPTION, FVS_FILE_UNK); }
return status; }
/******************************Public*Routine******************************\
* * CheckType1A, try / except wrapper * * Effects: * * Warnings: * * History: * 14-Jun-1994 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL STDCALL CheckType1A ( char *pszKeyFile, DWORD cjDesc, char *pszDesc, DWORD cjPFM, char *pszPFM, DWORD cjPFB, char *pszPFB, BOOL *pbCreatedPFM, char *pszFontPath ) { short status = CheckType1WithStatusA(pszKeyFile, cjDesc, pszDesc, cjPFM, pszPFM, cjPFB, pszPFB, pbCreatedPFM, pszFontPath);
return (FVS_STATUS(status) == FVS_SUCCESS); }
/******************************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 * \**************************************************************************/
short STDCALL FindPfb ( char *pszPFM, char *achPFB ) { DWORD cjKey; char *pszParent = NULL; // points to the where parent dir of the inf file is
char *pszBare = NULL; // "bare" .inf name, initialization essential
// example:
// if pszPFM -> "c:\psfonts\pfm\foo_____.pfm"
// then pszParent -> "pfm\foo_____.pfm"
cjKey = strlen(pszPFM) + 1;
if (cjKey < 5) // 5 = strlen(".pfm") + 1;
return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM);
// go on to check if .pfb file exists:
// We will first check .pfb file exists in the same dir as .pfm
strcpy(achPFB, pszPFM); strcpy(&achPFB[cjKey - 5],".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 == '\\') || (*pszBare == ':')) { 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] == '\\')) { // skip '\\' and search backwards for another '\\':
for (pszParent = &pszBare[-2]; pszParent > pszPFM; pszParent--) { if ((*pszParent == '\\') || (*pszParent == ':')) { pszParent++; // found it
break; } }
// create .pfb file name in the .pfm parent directory:
strcpy(&achPFB[pszParent - pszPFM], pszBare); strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
} else if (pszBare == pszPFM) { // bare name was passed in, to check for the inf file in the "." dir:
strcpy(achPFB, "..\\"); strcpy(&achPFB[3], pszBare); // 3 == strlen("..\\")
strcpy(&achPFB[strlen(achPFB) - 4], ".PFB"); } else { return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM); // We should never get here.
}
// check again if we can find the file, if not fail.
if (!bFileExists(achPFB)) { return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFB); } }
// now we have paths to .pfb file in the buffer provided by the caller.
return FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK); }
|