Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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