Leaked source code of windows server 2003
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.

1738 lines
42 KiB

  1. /***
  2. **
  3. ** Module: T1Instal
  4. **
  5. ** Description:
  6. ** This is the Win32 DLL (t1instal.dll) interface to the
  7. ** font converter. All window specific code is located in
  8. ** this module and the error hadler module (errors.c).
  9. **
  10. ** Author: Michael Jansson
  11. ** Created: 12/18/93
  12. **
  13. ***/
  14. /***** INCLUDES */
  15. #include "windows.h"
  16. #include <string.h>
  17. #include <time.h>
  18. #include <limits.h>
  19. #include <ctype.h>
  20. #define STRSAFE_NO_DEPRECATE
  21. #include <strsafe.h>
  22. #undef IN
  23. #include "titott.h"
  24. #include "types.h"
  25. #include "t1local.h"
  26. #include "t1instal.h"
  27. #include "fileio.h"
  28. #include "safemem.h"
  29. #include "t1msg.h"
  30. #undef UNICODE
  31. /* The CopyrightCheck/MAYBEOK case always succeeds for now. */
  32. #define MAYBEOK SUCCESS
  33. /***** LOCAL TYPES */
  34. struct callFrame {
  35. const void (STDCALL *Progress)(short, void*);
  36. void *arg;
  37. int last;
  38. int done;
  39. };
  40. static short lastCP = FALSE;
  41. static char lastVendor[256] = "Unknown.";
  42. /***** CONSTANTS */
  43. #define MIN_PROGRESS 3
  44. #define DELIMITERS " ,"
  45. #define COPYSIGN 169
  46. #define TRUE 1
  47. #define FALSE 0
  48. #define DFFACE 139
  49. #define DFDRIVERINFO 101
  50. #define VERSTR "Converter: Windows Type 1 Installer V1.0d.\n" \
  51. "Font: V"
  52. const char version[] = "\n$VER: 1.0d\n";
  53. #ifndef NOANSIWINMAC
  54. const char *winmac[] = {
  55. "A",
  56. "AE",
  57. "Aacute",
  58. "Acircumflex",
  59. "Adieresis",
  60. "Agrave",
  61. "Aring",
  62. "Atilde",
  63. "B",
  64. "C",
  65. "Cacute",
  66. "Ccaron",
  67. "Ccedilla",
  68. "D",
  69. "Delta",
  70. "E",
  71. "Eacute",
  72. "Ecircumflex",
  73. "Edieresis",
  74. "Egrave",
  75. "Eth",
  76. "F",
  77. "G",
  78. "Gbreve",
  79. "H",
  80. "I",
  81. "Iacute",
  82. "Icircumflex",
  83. "Idieresis",
  84. "Idot",
  85. "Igrave",
  86. "J",
  87. "K",
  88. "L",
  89. "Lslash",
  90. "M",
  91. "N",
  92. "Ntilde",
  93. "O",
  94. "OE",
  95. "Oacute",
  96. "Ocircumflex",
  97. "Odieresis",
  98. "Ograve",
  99. "Oslash",
  100. "Otilde",
  101. "P",
  102. "Q",
  103. "R",
  104. "S",
  105. "Scaron",
  106. "Scedilla",
  107. "T",
  108. "Thorn",
  109. "U",
  110. "Uacute",
  111. "Ucircumflex",
  112. "Udieresis",
  113. "Ugrave",
  114. "V",
  115. "W",
  116. "X",
  117. "Y",
  118. "Yacute",
  119. "Ydieresis",
  120. "Z",
  121. "a",
  122. "aacute",
  123. "acircumflex",
  124. "acute",
  125. "adieresis",
  126. "ae",
  127. "agrave",
  128. "ampersand",
  129. "approxequal",
  130. "aring",
  131. "asciicircum",
  132. "asciitilde",
  133. "asterisk",
  134. "at",
  135. "atilde",
  136. "b",
  137. "backslash",
  138. "bar",
  139. "braceleft",
  140. "braceright",
  141. "bracketleft",
  142. "bracketright",
  143. "breve",
  144. "brokenbar",
  145. "bullet",
  146. "c",
  147. "cacute",
  148. "caron",
  149. "ccaron",
  150. "ccedilla",
  151. "cedilla",
  152. "cent",
  153. "circumflex",
  154. "colon",
  155. "comma",
  156. "copyright",
  157. "currency",
  158. "d",
  159. "dagger",
  160. "daggerdbl",
  161. "degree",
  162. "dieresis",
  163. "divide",
  164. "dmacron",
  165. "dollar",
  166. "dotaccent",
  167. "dotlessi",
  168. "e",
  169. "eacute",
  170. "ecircumflex",
  171. "edieresis",
  172. "egrave",
  173. "eight",
  174. "ellipsis",
  175. "emdash",
  176. "endash",
  177. "equal",
  178. "eth",
  179. "exclam",
  180. "exclamdown",
  181. "f",
  182. "fi",
  183. "five",
  184. "fl",
  185. "florin",
  186. "four",
  187. "fraction",
  188. "franc",
  189. "g",
  190. "gbreve",
  191. "germandbls",
  192. "grave",
  193. "greater",
  194. "greaterequal",
  195. "guillemotleft",
  196. "guillemotright",
  197. "guilsinglleft",
  198. "guilsinglright",
  199. "h",
  200. "hungerumlaut",
  201. "hyphen",
  202. "i",
  203. "iacute",
  204. "icircumflex",
  205. "idieresis",
  206. "igrave",
  207. "infinity",
  208. "integral",
  209. "j",
  210. "k",
  211. "l",
  212. "less",
  213. "lessequal",
  214. "logicalnot",
  215. "lozenge",
  216. "lslash",
  217. "m",
  218. "macron",
  219. "middot",
  220. "minus",
  221. "mu",
  222. "multiply",
  223. "n",
  224. "nbspace",
  225. "nine",
  226. "notequal",
  227. "ntilde",
  228. "numbersign",
  229. "o",
  230. "oacute",
  231. "ocircumflex",
  232. "odieresis",
  233. "oe",
  234. "ogonek",
  235. "ograve",
  236. "ohm",
  237. "one",
  238. "onehalf",
  239. "onequarter",
  240. "onesuperior",
  241. "ordfeminine",
  242. "ordmasculine",
  243. "oslash",
  244. "otilde",
  245. "overscore",
  246. "p",
  247. "paragraph",
  248. "parenleft",
  249. "parenright",
  250. "partialdiff",
  251. "percent",
  252. "period",
  253. "periodcentered",
  254. "perthousand",
  255. "pi",
  256. "plus",
  257. "plusminus",
  258. "product",
  259. "q",
  260. "question",
  261. "questiondown",
  262. "quotedbl",
  263. "quotedblbase",
  264. "quotedblleft",
  265. "quotedblright",
  266. "quoteleft",
  267. "quoteright",
  268. "quotesinglbase",
  269. "quotesingle",
  270. "r",
  271. "radical",
  272. "registered",
  273. "ring",
  274. "s",
  275. "scaron",
  276. "scedilla",
  277. "section",
  278. "semicolon",
  279. "seven",
  280. "sfthyphen",
  281. "six",
  282. "slash",
  283. "space",
  284. "sterling",
  285. "summation",
  286. "t",
  287. "thorn",
  288. "three",
  289. "threequarters",
  290. "threesuperior",
  291. "tilde",
  292. "trademark",
  293. "two",
  294. "twosuperior",
  295. "u",
  296. "uacute",
  297. "ucircumflex",
  298. "udieresis",
  299. "ugrave",
  300. "underscore",
  301. "v",
  302. "w",
  303. "x",
  304. "y",
  305. "yacute",
  306. "ydieresis",
  307. "yen",
  308. "z",
  309. "zero"
  310. };
  311. #define GLYPHFILTER &win
  312. const struct GlyphFilter win = {
  313. sizeof(winmac) / sizeof(winmac[0]),
  314. winmac
  315. };
  316. #else
  317. #define GLYPHFILTER (struct GlyphFilter *)0
  318. #endif /* NOANSIWINMAC */
  319. /***** MACROS */
  320. #define ReadLittleEndianDword(file,dw) { \
  321. dw = (DWORD)io_ReadOneByte(file) ; \
  322. dw |= (DWORD)io_ReadOneByte(file) << 8; \
  323. dw |= (DWORD)io_ReadOneByte(file) << 16; \
  324. dw |= (DWORD)io_ReadOneByte(file) << 24; \
  325. }
  326. #ifndef try
  327. #define try __try
  328. #define except __except
  329. #endif
  330. /***** GLOBALS */
  331. HMODULE ModuleInstance(
  332. void
  333. )
  334. {
  335. static HMODULE hInst = NULL;
  336. if (NULL == hInst)
  337. hInst = GetModuleHandle(TEXT("fontext.dll"));
  338. return hInst;
  339. }
  340. /***** STATIC FUNCTIONS */
  341. /***
  342. ** Function: Decrypt
  343. **
  344. ** Description:
  345. ** Decrypt a byte.
  346. ***/
  347. static DWORD CSum(char *str)
  348. {
  349. DWORD sum = 0;
  350. while (*str)
  351. sum += *str++;
  352. return sum;
  353. }
  354. /***
  355. ** Function: Decrypt
  356. **
  357. ** Description:
  358. ** Decrypt a byte.
  359. ***/
  360. static char *Encrypt(char *str, char *out, unsigned long cbOut)
  361. {
  362. const USHORT c1 = 52845;
  363. const USHORT c2 = 22719;
  364. UBYTE cipher;
  365. USHORT r = 8366;
  366. int i;
  367. for (i=0; i<(int)strlen(str) && i<(int)cbOut; i++) {
  368. cipher = (UBYTE)(str[i] ^ (r>>8));
  369. r = (USHORT)((cipher + r) * c1 + c2);
  370. out[i] = (char)((cipher & 0x3f) + ' ');
  371. /* Unmap 'bad' characters, that the Registry DB doesn't like. */
  372. if (out[i]=='=' || out[i]==' ' || out[i]=='@' || out[i]=='"')
  373. out[i] = 'M';
  374. }
  375. out[i] = '\0';
  376. return out;
  377. }
  378. static char *stristr(char *src, char *word)
  379. {
  380. size_t len = strlen(word);
  381. char *tmp = src;
  382. while (*src) {
  383. if (!_strnicmp(src, word, len))
  384. break;
  385. src++;
  386. }
  387. return src;
  388. }
  389. /***
  390. ** Function: GetCompany
  391. **
  392. ** Description:
  393. ** Extract the company name out of a copyright string.
  394. ***/
  395. char *GetCompany(char *buf)
  396. {
  397. char *company = NULL;
  398. int done = FALSE;
  399. UBYTE *token;
  400. UBYTE *tmp1;
  401. UBYTE *tmp2;
  402. UBYTE *tmp3;
  403. UBYTE *tmp4;
  404. int i;
  405. token = buf;
  406. while (token && !done) {
  407. /* Locate the start of the copyright string. */
  408. tmp1 = stristr(token, "copyright");
  409. tmp2 = stristr(token, "(c)");
  410. tmp3 = stristr(token, " c ");
  411. if ((tmp4 = strchr(token, COPYSIGN))==NULL)
  412. tmp4 = &token[strlen(token)];
  413. if (*tmp1==0 && *tmp2==0 && *tmp3==0 && *tmp4==0) {
  414. token = NULL;
  415. break;
  416. } else if (tmp1<tmp2 && tmp1<tmp3 && tmp1<tmp4)
  417. token = tmp1;
  418. else if (tmp2<tmp3 && tmp2<tmp4)
  419. token = tmp2;
  420. else if (tmp3<tmp4)
  421. token = tmp3;
  422. else
  423. token = tmp4;
  424. /* Skip the leading copyright strings/character. */
  425. if (token[0]==COPYSIGN && token[1]!='\0') {
  426. token += 2;
  427. } else if (!_strnicmp(token, "copyright", strlen("copyright"))) {
  428. token += strlen("copyright");
  429. } else {
  430. token += strlen("(c)");
  431. }
  432. /* Skip blanks. */
  433. while(*token && isspace(*token) || *token==',')
  434. token++;
  435. /* Another copyright word? */
  436. if (!_strnicmp((char*)token, "(c)", strlen("(c)")) ||
  437. !_strnicmp((char*)token, "copyright", strlen("copyright")) ||
  438. token[0]==COPYSIGN)
  439. continue;
  440. /* Skip the years. */
  441. company = token;
  442. if (isdigit(token[0])) {
  443. while (isdigit(*company) || isspace(*company) ||
  444. ispunct(*company) || (*company)=='-')
  445. company++;
  446. if (*company=='\0')
  447. break;
  448. /* Skip strings like "by", up to the beginning of a name that */
  449. /* starts with an upper case letter. */
  450. while (*company && (company[0]<'A' || company[0]>'Z'))
  451. company++;
  452. done = TRUE;
  453. } else {
  454. continue;
  455. }
  456. }
  457. /* Did we find it? */
  458. if (company) {
  459. while (*company && isspace(*company))
  460. company++;
  461. if (*company=='\0') {
  462. company=NULL;
  463. } else {
  464. /* Terminate the company name. */
  465. if ((token = (UBYTE*)strchr(company, '.'))!=NULL) {
  466. /* Period as an initial delimiter, e.g. James, A. B. ?*/
  467. if (token[-1]>='A' && token[-1]<='Z') {
  468. if (strchr((char*)&token[1], '.'))
  469. token = (UBYTE*)strchr((char*)&token[1], '.');
  470. /* Check for "James A. Bently, " */
  471. else if (strchr((char*)&token[1], ',')) {
  472. token = (UBYTE*)strchr((char*)&token[1], ',');
  473. token[0] = '.';
  474. }
  475. }
  476. token[1] = '\0';
  477. } else {
  478. /* Name ending with a ';'? */
  479. if ((token = (UBYTE*)strrchr(company, ';'))) {
  480. *token = '\0';
  481. }
  482. }
  483. /* Truncate some common strings. */
  484. tmp1 = stristr(company, "all rights reserved");
  485. *tmp1 = '\0';
  486. /* Remove trailing punctuation character. */
  487. for (i=(int)strlen(company)-1; i>0 &&
  488. (ispunct(company[i]) || isspace(company[i])); i--) {
  489. company[i] = 0;
  490. }
  491. }
  492. }
  493. return company;
  494. }
  495. /**** FUNCTIONS */
  496. /***
  497. ** Function: ConvertAnyway
  498. **
  499. ** Description:
  500. ** Ask the user if it is ok to convert.
  501. ***/
  502. static errcode ConvertAnyway(const char *vendor, const char *facename)
  503. {
  504. char tmp[256];
  505. char msg[1024];
  506. errcode answer;
  507. HMODULE hInst = ModuleInstance();
  508. if (vendor==NULL || strlen(vendor)==0) {
  509. LoadString(hInst, IDS_RECOGNIZE1, tmp, sizeof(tmp));
  510. StringCchPrintfA(msg, sizeof(msg), tmp, facename);
  511. } else {
  512. LoadString(hInst, IDS_RECOGNIZE2, tmp, sizeof(tmp));
  513. StringCchPrintfA(msg, sizeof(msg), tmp, facename, vendor);
  514. }
  515. LoadString(hInst, IDS_MAINMSG, tmp, sizeof(tmp));
  516. StringCchCatA(msg, sizeof(msg), tmp);
  517. LoadString(hInst, IDS_CAPTION, tmp, sizeof(tmp));
  518. answer = (errcode)MessageBox(NULL, msg, tmp, QUERY);
  519. SetLastError(0);
  520. return answer;
  521. }
  522. /***
  523. ** Function: CheckCopyright
  524. **
  525. ** Description:
  526. ** This is the callback function that verifies that
  527. ** the converted font is copyrighted by a company who
  528. ** has agreed to having their fonts converted by
  529. ** this software. These companies are registered in the
  530. ** registry data base.
  531. ***/
  532. static errcode CheckCopyright(const char *facename,
  533. const char *copyright,
  534. const char *notice)
  535. {
  536. #ifdef NOCOPYRIGHTS
  537. return SKIP;
  538. #else
  539. HKEY key;
  540. char tmp[256];
  541. char *company = NULL;
  542. char buf[1024];
  543. int done = FALSE;
  544. short result = FAILURE;
  545. /* Access the REG data base. */
  546. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SUBKEY_TYPE1COPYRIGHTS, 0,
  547. KEY_QUERY_VALUE, &key)==ERROR_SUCCESS) {
  548. /* Look for the company name in the /notice string. */
  549. if (notice && notice[0]) {
  550. strncpy(buf, notice, sizeof(buf));
  551. buf[sizeof(buf)-1] = '\0';
  552. company = GetCompany(buf);
  553. }
  554. /* Look in the /copyright string if the company name was not found. */
  555. if (company==NULL && copyright && copyright[0]) {
  556. strncpy(buf, copyright, sizeof(buf));
  557. buf[sizeof(buf)-1] = '\0';
  558. company = GetCompany(buf);
  559. }
  560. #ifdef SHOWCOPYRIGHTS
  561. LogError(MSG_INFO, MSG_Copyright, company);
  562. Encrypt(company, tmp, sizeof(tmp)-1);
  563. sprintf(&tmp[strlen(tmp)], "(%d)\n", CSum(tmp));
  564. LogError(MSG_INFO, MSG_Encoding, tmp);
  565. #else
  566. /* Did not find a company name? */
  567. if (company==NULL &&
  568. ((notice==NULL || notice[0]=='\0'||
  569. strstr(notice, "Copyright")==NULL) &&
  570. (copyright==NULL || copyright[0]=='\0' ||
  571. strstr(copyright, "Copyright")==NULL))) {
  572. /* No known copyright. */
  573. LogError(MSG_WARNING, MSG_NOCOPYRIGHT, NULL);
  574. result = MAYBEOK;
  575. /* Strange copyright format? */
  576. } else if (company==NULL || company[0]=='\0') {
  577. if (notice && notice[0])
  578. LogError(MSG_WARNING, MSG_BADFORMAT, notice);
  579. else
  580. LogError(MSG_WARNING, MSG_BADFORMAT, copyright);
  581. result = MAYBEOK;
  582. /* Found copyright! */
  583. } else {
  584. DWORD size;
  585. DWORD csum;
  586. size = 4;
  587. if (RegQueryValueEx(key, Encrypt(company, tmp, sizeof(tmp)-1), NULL, NULL,
  588. (LPBYTE)&csum, &size)==ERROR_SUCCESS) {
  589. /* A positive match -> ok to convert. */
  590. if (CSum(tmp)==csum) {
  591. LogError(MSG_INFO, MSG_COPYRIGHT, company);
  592. result = SUCCESS;
  593. } else {
  594. LogError(MSG_ERROR, MSG_BADCOPYRIGHT, company);
  595. result = SKIP;
  596. }
  597. } else {
  598. LogError(MSG_WARNING, MSG_BADCOPYRIGHT, company);
  599. result = MAYBEOK;
  600. }
  601. }
  602. #endif
  603. RegCloseKey(key);
  604. /* Give the user the final word. */
  605. if (result==FAILURE) {
  606. if (ConvertAnyway(company, facename)==TRUE)
  607. result = SUCCESS;
  608. }
  609. /* No copyright key in the registry? */
  610. } else {
  611. LogError(MSG_ERROR, MSG_NODB, NULL);
  612. result = FAILURE;
  613. }
  614. return result;
  615. #endif
  616. }
  617. /***
  618. ** Function: NTCheckCopyright
  619. **
  620. ** Description:
  621. ** This is the callback function that verifies that
  622. ** the converted font is copyrighted by a company who
  623. ** has agreed to having their fonts converted by
  624. ** this software. These companies are registered in the
  625. ** registry data base.
  626. ***/
  627. static errcode NTCheckCopyright(const char *facename,
  628. const char *copyright,
  629. const char *notice)
  630. {
  631. HKEY key;
  632. char tmp[256];
  633. char *company = NULL;
  634. char buf[1024];
  635. int done = FALSE;
  636. short result = FAILURE;
  637. /* Access the REG data base. */
  638. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SUBKEY_TYPE1COPYRIGHTS, 0,
  639. KEY_QUERY_VALUE, &key)==ERROR_SUCCESS) {
  640. /* Look for the company name in the /notice string. */
  641. if (notice && notice[0]) {
  642. strncpy(buf, notice, sizeof(buf));
  643. buf[sizeof(buf)-1] = '\0';
  644. company = GetCompany(buf);
  645. }
  646. /* Look in the /copyright string if the company name was not found. */
  647. if (company==NULL && copyright && copyright[0]) {
  648. strncpy(buf, copyright, sizeof(buf));
  649. buf[sizeof(buf)-1] = '\0';
  650. company = GetCompany(buf);
  651. }
  652. /* Did not find a company name? */
  653. if (company==NULL &&
  654. ((notice==NULL || notice[0]=='\0'||
  655. strstr(notice, "Copyright")==NULL) &&
  656. (copyright==NULL || copyright[0]=='\0' ||
  657. strstr(copyright, "Copyright")==NULL))) {
  658. /* No known copyright. */
  659. result = MAYBE;
  660. /* Strange copyright format? */
  661. } else if (company==NULL || company[0]=='\0') {
  662. result = MAYBE;
  663. /* Found copyright! */
  664. } else {
  665. DWORD size;
  666. DWORD csum;
  667. /* remember for future use. */
  668. strncpy(lastVendor, company, 256);
  669. lastVendor[MIN(255, strlen(company))] = '\0';
  670. size = 4;
  671. if (RegQueryValueEx(key, Encrypt(company, tmp, sizeof(tmp)-1), NULL, NULL,
  672. (LPBYTE)&csum, &size)==ERROR_SUCCESS) {
  673. /* A positive match -> ok to convert. */
  674. if (CSum(tmp)==csum) {
  675. result = SUCCESS;
  676. } else {
  677. result = FAILURE;
  678. }
  679. } else {
  680. result = MAYBE;
  681. }
  682. }
  683. RegCloseKey(key);
  684. /* No copyright key in the registry? */
  685. } else {
  686. result = FAILURE;
  687. }
  688. lastCP = result;
  689. return FAILURE;
  690. }
  691. /***
  692. ** Function: _Progress
  693. **
  694. ** Description:
  695. ** This is the internal progress callback function that
  696. ** computes an percentage-done number, based on the
  697. ** number of converted glyphs.
  698. ***/
  699. static void _Progress(short type, void *generic, void *arg)
  700. {
  701. struct callFrame *f = arg;
  702. /* Processing glyphs or wrapping up? */
  703. if (type==0 || type==1)
  704. f->done++;
  705. else
  706. f->done = MIN(sizeof(winmac)/sizeof(winmac[0]), f->done+10);
  707. if ((f->done-f->last)>MIN_PROGRESS) {
  708. f->Progress((short)(f->done*100/(sizeof(winmac)/sizeof(winmac[0]))),
  709. f->arg);
  710. f->last = f->done;
  711. }
  712. UNREFERENCED_PARAMETER(type);
  713. UNREFERENCED_PARAMETER(generic);
  714. SetLastError(0L);
  715. }
  716. static BOOL ReadStringFromOffset(struct ioFile *file,
  717. const DWORD dwOffset,
  718. char *pszString,
  719. int cLen,
  720. BOOL bStrip)
  721. {
  722. BOOL result = TRUE;
  723. DWORD offset;
  724. /* Get offset to string. */
  725. io_FileSeek(file, dwOffset);
  726. /* Read the offset. */
  727. ReadLittleEndianDword(file, offset);
  728. /* Get the string. */
  729. (void)io_FileSeek(file, offset);
  730. if (io_FileError(file) != SUCCESS) {
  731. result = FALSE;
  732. } else {
  733. int i;
  734. i=0;
  735. while (io_FileError(file)==SUCCESS && i<cLen) {
  736. pszString[i] = (UBYTE)io_ReadOneByte(file);
  737. if (pszString[i]=='\0')
  738. break;
  739. /* Replace all dashes with spaces. */
  740. if (bStrip && pszString[i]=='-')
  741. pszString[i]=' ';
  742. i++;
  743. }
  744. /* If it was truncated, we need to NULL terminate it */
  745. if (i==cLen && cLen>0)
  746. pszString[cLen-1] = '\0';
  747. }
  748. return result;
  749. }
  750. /**** FUNCTIONS */
  751. /***
  752. ** Function: ConvertTypeFaceA
  753. **
  754. ** Description:
  755. ** Convert a T1 font into a TT font file. This is the
  756. ** simplified interface used by the Win32 DLL, with the
  757. ** ANSI interface.
  758. ***/
  759. short STDCALL ConvertTypefaceAInternal(const char *type1,
  760. const char *metrics,
  761. const char *truetype,
  762. const void (STDCALL *Progress)(short, void*),
  763. void *arg)
  764. {
  765. struct callFrame f;
  766. struct callProgress p;
  767. struct T1Arg t1Arg;
  768. struct TTArg ttArg;
  769. short status;
  770. /* Check parameters. */
  771. if (type1==NULL || metrics==NULL)
  772. return FAILURE;
  773. /* Set up arguments to ConvertTypefaceA() */
  774. t1Arg.filter = GLYPHFILTER;
  775. t1Arg.upem = (short)2048;
  776. t1Arg.name = (char *)type1;
  777. t1Arg.metrics = (char *)metrics;
  778. ttArg.precision = (short)50;
  779. ttArg.name = (char *)truetype;
  780. ttArg.tag = VERSTR;
  781. /* Use progress gauge */
  782. if (Progress) {
  783. LogError(MSG_INFO, MSG_STARTING, type1);
  784. f.Progress = Progress;
  785. f.done = 0;
  786. f.last = 0;
  787. f.arg = arg;
  788. p.arg = &f;
  789. p.cb = _Progress;
  790. status = ConvertT1toTT(&ttArg, &t1Arg, CheckCopyright, &p);
  791. Progress(100, arg);
  792. } else {
  793. status = ConvertT1toTT(&ttArg, &t1Arg, CheckCopyright, NULL);
  794. }
  795. return status;
  796. }
  797. short STDCALL ConvertTypefaceA(char *type1,
  798. char *metrics,
  799. char *truetype,
  800. void (STDCALL *Progress)(short, void*),
  801. void *arg)
  802. {
  803. short bRet;
  804. try
  805. {
  806. bRet = ConvertTypefaceAInternal(type1,
  807. metrics,
  808. truetype,
  809. Progress,
  810. arg);
  811. }
  812. except (EXCEPTION_EXECUTE_HANDLER)
  813. {
  814. #if 0
  815. ASSERTGDI(
  816. GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR,
  817. "ttfd!ttfdSemLoadFontFile, strange exception code\n"
  818. );
  819. #endif
  820. bRet = BADINPUTFILE;
  821. }
  822. return bRet;
  823. }
  824. short STDCALL FindPfb (
  825. char *pszPFM,
  826. char *achPFB,
  827. DWORD cbPFB
  828. );
  829. /***
  830. ** Function: CheckPfmA
  831. **
  832. ** Description:
  833. ** This function determines if there is a pfm/pfb pair of
  834. ** files that makes up an Adobe Type 1 font, and determins
  835. ** the descriptive face name of it.
  836. **
  837. ** Returns: 16-bit encoded value indicating error and type of file where
  838. ** error occurred. (see fvscodes.h) for definitions.
  839. ** The following table lists the "status" portion of the codes
  840. ** returned.
  841. **
  842. ** FVS_SUCCESS
  843. ** FVS_INVALID_FONTFILE
  844. ** FVS_FILE_OPEN_ERR
  845. ** FVS_INVALID_ARG
  846. ** FVS_FILE_IO_ERR
  847. ** FVS_BAD_VERSION
  848. ***/
  849. short STDCALL CheckPfmA(
  850. char *pszPFM,
  851. DWORD cjDesc,
  852. char *pszDesc,
  853. DWORD cjPFB,
  854. char *pszPFB
  855. )
  856. {
  857. struct ioFile *file;
  858. char szDriver[MAX_PATH];
  859. short result = FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  860. short ver;
  861. char achPFB[MAX_PATH];
  862. char *psz_PFB;
  863. DWORD cjPFB1;
  864. if (pszPFB)
  865. {
  866. psz_PFB = pszPFB;
  867. cjPFB1 = cjPFB;
  868. }
  869. else
  870. {
  871. psz_PFB = (char *)achPFB;
  872. cjPFB1 = MAX_PATH;
  873. }
  874. /* Check parameter. */
  875. if (pszPFM==NULL || ((strlen(pszPFM)+3) >= cjPFB1))
  876. return FVS_MAKE_CODE(FVS_INVALID_ARG, FVS_FILE_UNK);
  877. // check if pfb file exists and find the path to it:
  878. result = FindPfb(pszPFM, psz_PFB, cjPFB1);
  879. if (FVS_STATUS(result) != FVS_SUCCESS)
  880. return result;
  881. /****
  882. * Locate the pszDescriptive name of the font.
  883. */
  884. if ((file = io_OpenFile(pszPFM, READONLY))==NULL)
  885. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFM);
  886. (void)io_ReadOneByte(file); /* Skip the revision number. */
  887. ver = (short)io_ReadOneByte(file);
  888. if (ver > 3) {
  889. /* ERROR - unsupported format */
  890. result = FVS_MAKE_CODE(FVS_BAD_VERSION, FVS_FILE_PFM);
  891. } else {
  892. /* Read the driver name. */
  893. if (!ReadStringFromOffset(file, DFDRIVERINFO, szDriver,
  894. sizeof(szDriver), FALSE))
  895. {
  896. result = FVS_MAKE_CODE(FVS_FILE_IO_ERR, FVS_FILE_PFM);
  897. }
  898. /* Is it "PostScript" ? */
  899. else if (_stricmp(szDriver, "PostScript"))
  900. {
  901. result = FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM);
  902. }
  903. /* Only get description if asked to do so. */
  904. else if (pszDesc && !ReadStringFromOffset(file, DFFACE, pszDesc, cjDesc, TRUE))
  905. {
  906. result = FVS_MAKE_CODE(FVS_FILE_IO_ERR, FVS_FILE_PFM);
  907. }
  908. }
  909. (void)io_CloseFile(file);
  910. return result;
  911. }
  912. /***
  913. ** Function: CheckCopyrightsA
  914. **
  915. ** Description:
  916. ** This function verifies that it is ok to convert the font. This is
  917. ** done by faking an installation.
  918. ***/
  919. short STDCALL CheckCopyrightAInternal(char *szPFB,
  920. DWORD wSize,
  921. char *szVendor)
  922. {
  923. struct T1Arg t1Arg;
  924. struct TTArg ttArg;
  925. /* Set up arguments to ConvertTypefaceA() */
  926. t1Arg.metrics = NULL;
  927. t1Arg.upem = (short)2048;
  928. t1Arg.filter = GLYPHFILTER;
  929. t1Arg.name = szPFB;
  930. ttArg.precision = (short)200;
  931. ttArg.tag = NULL;
  932. ttArg.name = "NIL:";
  933. lastCP = FAILURE;
  934. strcpy(lastVendor, "");
  935. (void)ConvertT1toTT(&ttArg, &t1Arg, NTCheckCopyright, NULL);
  936. if (szVendor && wSize)
  937. {
  938. strncpy(szVendor, lastVendor, wSize);
  939. szVendor[MIN(wSize-1, strlen(lastVendor))] = '\0';
  940. }
  941. return lastCP;
  942. }
  943. short STDCALL CheckCopyrightA(char *szPFB,
  944. DWORD wSize,
  945. char *szVendor)
  946. {
  947. short iRet;
  948. try
  949. {
  950. iRet = CheckCopyrightAInternal(szPFB,wSize,szVendor);
  951. }
  952. except (EXCEPTION_EXECUTE_HANDLER)
  953. {
  954. iRet = BADINPUTFILE;
  955. }
  956. return iRet;
  957. }
  958. /******************************Public*Routine******************************\
  959. *
  960. * short STDCALL CheckInfA (
  961. *
  962. * If pfm and inf files are in the same directory only pfm is recognized
  963. * and inf file is ignored.
  964. *
  965. * History:
  966. * 27-Apr-1994 -by- Bodin Dresevic [BodinD]
  967. * Wrote it.
  968. *
  969. * Returns: 16-bit encoded value indicating error and type of file where
  970. * error occurred. (see fvscodes.h) for definitions.
  971. * The following table lists the "status" portion of the codes
  972. * returned.
  973. *
  974. * FVS_SUCCESS
  975. * FVS_INVALID_FONTFILE
  976. * FVS_FILE_OPEN_ERR
  977. * FVS_FILE_BUILD_ERR
  978. * FVS_FILE_EXISTS
  979. * FVS_INSUFFICIENT_BUF
  980. *
  981. \**************************************************************************/
  982. short CreatePFM(char *pszINF, char *pszAFM, char *pszPFM);
  983. BOOL bGetDescFromInf(char * pszINF, DWORD cjDesc, char *pszDesc);
  984. BOOL bFileExists(char *pszFile)
  985. {
  986. HFILE hf;
  987. if ((hf = _lopen(pszFile, OF_READ)) != -1)
  988. {
  989. _lclose(hf);
  990. return TRUE;
  991. }
  992. return FALSE;
  993. }
  994. short STDCALL CheckInfA (
  995. char *pszINF,
  996. DWORD cjDesc,
  997. char *pszDesc,
  998. DWORD cjPFM,
  999. char *pszPFM,
  1000. DWORD cjPFB,
  1001. char *pszPFB,
  1002. BOOL *pbCreatedPFM,
  1003. char *pszFontPath
  1004. )
  1005. {
  1006. char achPFM[MAX_PATH];
  1007. char achPFB[MAX_PATH];
  1008. char achAFM[MAX_PATH];
  1009. DWORD cjKey;
  1010. char *pszParent = NULL; // points to the where parent dir of the inf file is
  1011. char *pszBare = NULL; // "bare" .inf name, initialization essential
  1012. short result = FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  1013. BOOL bAfmExists = FALSE;
  1014. BOOL bPfbExists = FALSE;
  1015. //
  1016. // This is a real hack use of pbCreatedPFM.
  1017. // It's the best solution with the time we have.
  1018. //
  1019. BOOL bCheckForExistingPFM = *pbCreatedPFM;
  1020. *pbCreatedPFM = FALSE;
  1021. // example:
  1022. // if pszINF -> "c:\psfonts\fontinfo\foo_____.inf"
  1023. // then pszParent -> "fontinfo\foo_____.inf"
  1024. cjKey = (DWORD)strlen(pszINF) + 1;
  1025. if (cjKey < 5) // 5 = strlen(".pfm") + 1;
  1026. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF);
  1027. // Need to check that it is not too long.
  1028. // Below we do a "strcpy(achAFM, "..\\afm\\")", so need to have space
  1029. // for 7 extra bytes in our buffers.
  1030. if (cjKey > (sizeof(achPFM)-7))
  1031. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF);
  1032. // check if a pfm file exists in the SAME directory.
  1033. // Use the buffer on the stack to produce the path for the pfm file:
  1034. strcpy(achPFM, pszINF);
  1035. strcpy(&achPFM[cjKey - 5],".PFM");
  1036. // try to open pfm file to check if it exists:
  1037. if (bCheckForExistingPFM && bFileExists(achPFM))
  1038. {
  1039. // we found the pfm file, therefore we do not report this .inf file.
  1040. return FVS_MAKE_CODE(FVS_FILE_EXISTS, FVS_FILE_PFM);
  1041. }
  1042. // pfm file is NOT found, go on to check if .afm and .pfb files exists:
  1043. // We will first check if .afm and .pfb files exists in the same dir as .inf
  1044. strcpy(achAFM, pszINF);
  1045. strcpy(&achAFM[cjKey - 5],".AFM");
  1046. strcpy(achPFB, pszINF);
  1047. strcpy(&achPFB[cjKey - 5],".PFB");
  1048. bAfmExists = bFileExists(achAFM);
  1049. bPfbExists = bFileExists(achPFB);
  1050. if (!bAfmExists || !bPfbExists)
  1051. {
  1052. // we did not find the .afm and .pfb files in the same dir as .inf
  1053. // we will check two more directories for the .afm and .pfb files
  1054. // 1) the parent directory of the .inf file for .pfb file
  1055. // 2) the afm subdirectory of the .inf parent directory for .afm file
  1056. //
  1057. // This is meant to handle the standard configuration of files produced
  1058. // on user's hard drive by unlocking fonts from Adobe's CD or from a
  1059. // previous installation of atm manager on this machine.
  1060. // This configuration is as follows:
  1061. // c:\psfonts\ *.pfb files are here
  1062. // c:\psfonts\afm *.afm files are here
  1063. // c:\psfonts\fontinfo *.inf files are here
  1064. // c:\psfonts\pfm *.pfm files that are created on the fly
  1065. // are PUT here by atm.
  1066. // We will instead put the files in windows\system dir where all other
  1067. // fonts are, it may not be possible to write pmf files on the media
  1068. // from where we are installing fonts
  1069. pszBare = &pszINF[cjKey - 5];
  1070. for ( ; pszBare > pszINF; pszBare--)
  1071. {
  1072. if ((*pszBare == '\\') || (*pszBare == ':'))
  1073. {
  1074. pszBare++; // found it
  1075. break;
  1076. }
  1077. }
  1078. // check if full path to .inf file was passed in or a bare
  1079. // name itself was passed in to look for .inf file in the current dir
  1080. if ((pszBare > pszINF) && (pszBare[-1] == '\\'))
  1081. {
  1082. // skip '\\' and search backwards for another '\\':
  1083. for (pszParent = &pszBare[-2]; pszParent > pszINF; pszParent--)
  1084. {
  1085. if ((*pszParent == '\\') || (*pszParent == ':'))
  1086. {
  1087. pszParent++; // found it
  1088. break;
  1089. }
  1090. }
  1091. // create .pfb file name in the .inf parent directory:
  1092. strcpy(&achPFB[pszParent - pszINF], pszBare);
  1093. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1094. // create .afm file name in the afm subdirectory of the .inf
  1095. // parent directory:
  1096. strcpy(&achAFM[pszParent - pszINF], "afm\\");
  1097. strcpy(&achAFM[pszParent - pszINF + 4], pszBare);
  1098. strcpy(&achAFM[strlen(achAFM) - 4], ".AFM");
  1099. }
  1100. else if (pszBare == pszINF)
  1101. {
  1102. // bare name was passed in, to check for the inf file in the "." dir:
  1103. strcpy(achPFB, "..\\");
  1104. strcpy(&achPFB[3], pszBare); // 3 == strlen("..\\")
  1105. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1106. strcpy(achAFM, "..\\afm\\");
  1107. strcpy(&achAFM[7], pszBare); // 7 == strlen("..\\afm\\")
  1108. strcpy(&achAFM[strlen(achAFM) - 4], ".AFM");
  1109. }
  1110. else
  1111. {
  1112. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK);
  1113. }
  1114. // check again if we can find the files, if not fail.
  1115. if (!bAfmExists && !bFileExists(achAFM))
  1116. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_AFM);
  1117. if (!bPfbExists && !bFileExists(achPFB))
  1118. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFB);
  1119. }
  1120. // now we have paths to .inf .afm and .pfb files. Now let us see
  1121. // what the caller wants from us:
  1122. if (pszDesc)
  1123. {
  1124. // we need to return description string in the buffer supplied
  1125. if (!bGetDescFromInf(pszINF, (DWORD)cjDesc, pszDesc))
  1126. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF);
  1127. }
  1128. // copy pfb file path out if requested
  1129. if (pszPFB)
  1130. {
  1131. if ((strlen(achPFB) + 1) < cjPFB)
  1132. strcpy(pszPFB,achPFB);
  1133. else
  1134. return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK);
  1135. }
  1136. // the caller wants a pfm file created from inf,afm files
  1137. // For now and probably for ever we will put this file in
  1138. // the %windir%\system, or %windir%\fonts for the secure system.
  1139. if (pszPFM && pszFontPath && *pszFontPath)
  1140. {
  1141. char *pszAppendHere; // append "bare" name here
  1142. // copy the first directory of the font path into the buffer provided
  1143. // It is expected that this routine will get something like
  1144. // "c:\foo" pointing to font path
  1145. strncpy(achPFM,pszFontPath,sizeof(achPFM));
  1146. achPFM[sizeof(achPFM)-1] = '\0';
  1147. pszAppendHere = &achPFM[strlen(pszFontPath) - 1];
  1148. if (*pszAppendHere != '\\')
  1149. {
  1150. pszAppendHere++;
  1151. *pszAppendHere = '\\';
  1152. }
  1153. pszAppendHere++;
  1154. // Check buffer bounds
  1155. if (pszAppendHere >= &achPFM[sizeof(achPFM)-1])
  1156. return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK);
  1157. // find bare name of the .inf file if we do not have already:
  1158. if (!pszBare)
  1159. {
  1160. pszBare = &pszINF[cjKey - 5];
  1161. for ( ; pszBare > pszINF; pszBare--)
  1162. {
  1163. if ((*pszBare == '\\') || (*pszBare == ':'))
  1164. {
  1165. pszBare++; // found it
  1166. break;
  1167. }
  1168. }
  1169. }
  1170. // append Bare name to the %windir%system\ path
  1171. // Check buffer bounds
  1172. if ((pszAppendHere+strlen(pszBare)) >= &achPFM[sizeof(achPFM)-1])
  1173. return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK);
  1174. strcpy(pszAppendHere, pszBare);
  1175. // finally change .inf extension to .pfm extension
  1176. strcpy(&pszAppendHere[strlen(pszAppendHere) - 4], ".PFM");
  1177. // copy out:
  1178. strncpy(pszPFM, achPFM, cjPFM);
  1179. pszPFM[cjPFM-1] = '\0';
  1180. result = CreatePFM(pszINF, achAFM, pszPFM);
  1181. *pbCreatedPFM = (FVS_STATUS(result) == FVS_SUCCESS);
  1182. if (!(*pbCreatedPFM))
  1183. return result;
  1184. }
  1185. return FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  1186. }
  1187. /******************************Public*Routine******************************\
  1188. *
  1189. * short STDCALL CheckType1AInternal
  1190. *
  1191. * Effects: See if we are going to report this as a valid type 1 font
  1192. *
  1193. * Warnings:
  1194. *
  1195. * History:
  1196. * 29-Apr-1994 -by- Bodin Dresevic [BodinD]
  1197. * Wrote it.
  1198. *
  1199. * Returns: 16-bit encoded value indicating error and type of file where
  1200. * error occurred. (see fvscodes.h) for definitions.
  1201. * The following table lists the "status" portion of the codes
  1202. * returned.
  1203. *
  1204. * FVS_SUCCESS
  1205. * FVS_INVALID_FONTFILE
  1206. * FVS_FILE_OPEN_ERR
  1207. * FVS_FILE_BUILD_ERR
  1208. * FVS_INVALID_ARG
  1209. * FVS_FILE_IO_ERR
  1210. * FVS_BAD_VERSION
  1211. * FVS_FILE_EXISTS
  1212. * FVS_INSUFFICIENT_BUF
  1213. *
  1214. \**************************************************************************/
  1215. short STDCALL CheckType1AInternal (
  1216. char *pszKeyFile,
  1217. DWORD cjDesc,
  1218. char *pszDesc,
  1219. DWORD cjPFM,
  1220. char *pszPFM,
  1221. DWORD cjPFB,
  1222. char *pszPFB,
  1223. BOOL *pbCreatedPFM,
  1224. char *pszFontPath
  1225. )
  1226. {
  1227. DWORD cjKey;
  1228. // Validate indata
  1229. if (pszKeyFile==NULL || pbCreatedPFM==NULL)
  1230. return FVS_MAKE_CODE(FVS_INVALID_ARG, FVS_FILE_UNK);
  1231. *pbCreatedPFM = FALSE; // initialization is essential.
  1232. cjKey = (DWORD)strlen(pszKeyFile) + 1;
  1233. if (cjKey < 5) // 5 = strlen(".pfm") + 1;
  1234. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK);
  1235. if (!_strcmpi(&pszKeyFile[cjKey - 5], ".PFM"))
  1236. {
  1237. // copy out pfm string when asked to do so:
  1238. if (pszPFM && (cjKey < cjPFM))
  1239. {
  1240. if (cjKey < cjPFM)
  1241. strcpy(pszPFM, pszKeyFile);
  1242. else
  1243. return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK);
  1244. }
  1245. return CheckPfmA(
  1246. pszKeyFile,
  1247. cjDesc,
  1248. pszDesc,
  1249. cjPFB,
  1250. pszPFB
  1251. );
  1252. }
  1253. else if (!_strcmpi(&pszKeyFile[cjKey - 5], ".INF"))
  1254. {
  1255. return CheckInfA (
  1256. pszKeyFile,
  1257. cjDesc,
  1258. pszDesc,
  1259. cjPFM,
  1260. pszPFM,
  1261. cjPFB,
  1262. pszPFB,
  1263. pbCreatedPFM,
  1264. pszFontPath
  1265. );
  1266. }
  1267. else
  1268. {
  1269. // this font is not our friend
  1270. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK);
  1271. }
  1272. }
  1273. /******************************Public*Routine******************************\
  1274. *
  1275. * CheckType1WithStatusA, try / except wrapper
  1276. *
  1277. * Effects:
  1278. *
  1279. * Warnings:
  1280. *
  1281. * History:
  1282. * 14-Jun-1994 -by- Bodin Dresevic [BodinD]
  1283. * Wrote it.
  1284. *
  1285. * Returns: 16-bit encoded value indicating error and type of file where
  1286. * error occurred. (see fvscodes.h) for definitions.
  1287. * The following table lists the "status" portion of the codes
  1288. * returned.
  1289. *
  1290. * FVS_SUCCESS
  1291. * FVS_INVALID_FONTFILE
  1292. * FVS_FILE_OPEN_ERR
  1293. * FVS_FILE_BUILD_ERR
  1294. * FVS_INVALID_ARG
  1295. * FVS_FILE_IO_ERR
  1296. * FVS_BAD_VERSION
  1297. * FVS_FILE_EXISTS
  1298. * FVS_INSUFFICIENT_BUF
  1299. * FVS_EXCEPTION
  1300. *
  1301. \**************************************************************************/
  1302. short STDCALL CheckType1WithStatusA (
  1303. char *pszKeyFile,
  1304. DWORD cjDesc,
  1305. char *pszDesc,
  1306. DWORD cjPFM,
  1307. char *pszPFM,
  1308. DWORD cjPFB,
  1309. char *pszPFB,
  1310. BOOL *pbCreatedPFM,
  1311. char *pszFontPath
  1312. )
  1313. {
  1314. short status;
  1315. try
  1316. {
  1317. status = CheckType1AInternal (
  1318. pszKeyFile,
  1319. cjDesc,
  1320. pszDesc,
  1321. cjPFM,
  1322. pszPFM,
  1323. cjPFB,
  1324. pszPFB,
  1325. pbCreatedPFM,
  1326. pszFontPath);
  1327. }
  1328. except (EXCEPTION_EXECUTE_HANDLER)
  1329. {
  1330. status = FVS_MAKE_CODE(FVS_EXCEPTION, FVS_FILE_UNK);
  1331. }
  1332. return status;
  1333. }
  1334. /******************************Public*Routine******************************\
  1335. *
  1336. * CheckType1A, try / except wrapper
  1337. *
  1338. * Effects:
  1339. *
  1340. * Warnings:
  1341. *
  1342. * History:
  1343. * 14-Jun-1994 -by- Bodin Dresevic [BodinD]
  1344. * Wrote it.
  1345. \**************************************************************************/
  1346. BOOL STDCALL CheckType1A (
  1347. char *pszKeyFile,
  1348. DWORD cjDesc,
  1349. char *pszDesc,
  1350. DWORD cjPFM,
  1351. char *pszPFM,
  1352. DWORD cjPFB,
  1353. char *pszPFB,
  1354. BOOL *pbCreatedPFM,
  1355. char *pszFontPath
  1356. )
  1357. {
  1358. short status = CheckType1WithStatusA(pszKeyFile,
  1359. cjDesc,
  1360. pszDesc,
  1361. cjPFM,
  1362. pszPFM,
  1363. cjPFB,
  1364. pszPFB,
  1365. pbCreatedPFM,
  1366. pszFontPath);
  1367. return (FVS_STATUS(status) == FVS_SUCCESS);
  1368. }
  1369. /******************************Public*Routine******************************\
  1370. *
  1371. * FindPfb, given pfm file, see if pfb file exists in the same dir or in the
  1372. * parent directory of the pfm file
  1373. *
  1374. * History:
  1375. * 14-Jun-1994 -by- Bodin Dresevic [BodinD]
  1376. * Wrote it.
  1377. *
  1378. * Returns: 16-bit encoded value indicating error and type of file where
  1379. * error occurred. (see fvscodes.h) for definitions.
  1380. * The following table lists the "status" portion of the codes
  1381. * returned.
  1382. *
  1383. * FVS_SUCCESS
  1384. * FVS_INVALID_FONTFILE
  1385. * FVS_FILE_OPEN_ERR
  1386. *
  1387. \**************************************************************************/
  1388. short STDCALL FindPfb (
  1389. char *pszPFM,
  1390. char *achPFB,
  1391. DWORD cbPFB
  1392. )
  1393. {
  1394. DWORD cjKey;
  1395. char *pszParent = NULL; // points to the where parent dir of the inf file is
  1396. char *pszBare = NULL; // "bare" .inf name, initialization essential
  1397. // example:
  1398. // if pszPFM -> "c:\psfonts\pfm\foo_____.pfm"
  1399. // then pszParent -> "pfm\foo_____.pfm"
  1400. cjKey = (DWORD)strlen(pszPFM) + 1;
  1401. if (cjKey < 5 || cjKey > cbPFB-3) // 5 = strlen(".pfm") + 1; 3 = strlen("..\\") below
  1402. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM);
  1403. // go on to check if .pfb file exists:
  1404. // We will first check .pfb file exists in the same dir as .pfm
  1405. strcpy(achPFB, pszPFM);
  1406. strcpy(&achPFB[cjKey - 5],".PFB");
  1407. if (!bFileExists(achPFB))
  1408. {
  1409. // we did not find the .pfb file in the same dir as .pfm
  1410. // Now check the parent directory of the .pfm file
  1411. pszBare = &pszPFM[cjKey - 5];
  1412. for ( ; pszBare > pszPFM; pszBare--)
  1413. {
  1414. if ((*pszBare == '\\') || (*pszBare == ':'))
  1415. {
  1416. pszBare++; // found it
  1417. break;
  1418. }
  1419. }
  1420. // check if full path to .pfm was passed in or a bare
  1421. // name itself was passed in to look for .pfm file in the current dir
  1422. if ((pszBare > pszPFM) && (pszBare[-1] == '\\'))
  1423. {
  1424. // skip '\\' and search backwards for another '\\':
  1425. for (pszParent = &pszBare[-2]; pszParent > pszPFM; pszParent--)
  1426. {
  1427. if ((*pszParent == '\\') || (*pszParent == ':'))
  1428. {
  1429. pszParent++; // found it
  1430. break;
  1431. }
  1432. }
  1433. // create .pfb file name in the .pfm parent directory:
  1434. strcpy(&achPFB[pszParent - pszPFM], pszBare);
  1435. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1436. }
  1437. else if (pszBare == pszPFM)
  1438. {
  1439. // bare name was passed in, to check for the inf file in the "." dir:
  1440. strcpy(achPFB, "..\\");
  1441. strcpy(&achPFB[3], pszBare); // 3 == strlen("..\\")
  1442. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1443. }
  1444. else
  1445. {
  1446. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM); // We should never get here.
  1447. }
  1448. // check again if we can find the file, if not fail.
  1449. if (!bFileExists(achPFB))
  1450. {
  1451. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFB);
  1452. }
  1453. }
  1454. // now we have paths to .pfb file in the buffer provided by the caller.
  1455. return FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  1456. }