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.

1709 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. 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)
  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++) {
  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. int 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=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. sprintf(msg, tmp, facename);
  511. } else {
  512. LoadString(hInst, IDS_RECOGNIZE2, tmp, sizeof(tmp));
  513. sprintf(msg, tmp, facename, vendor);
  514. }
  515. LoadString(hInst, IDS_MAINMSG, tmp, sizeof(tmp));
  516. strcat(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. strcpy(buf, notice);
  551. company = GetCompany(buf);
  552. }
  553. /* Look in the /copyright string if the company name was not found. */
  554. if (company==NULL && copyright && copyright[0]) {
  555. strcpy(buf, copyright);
  556. company = GetCompany(buf);
  557. }
  558. #ifdef SHOWCOPYRIGHTS
  559. LogError(MSG_INFO, MSG_Copyright, company);
  560. Encrypt(company, tmp);
  561. sprintf(&tmp[strlen(tmp)], "(%d)\n", CSum(tmp));
  562. LogError(MSG_INFO, MSG_Encoding, tmp);
  563. #else
  564. /* Did not find a company name? */
  565. if (company==NULL &&
  566. ((notice==NULL || notice[0]=='\0'||
  567. strstr(notice, "Copyright")==NULL) &&
  568. (copyright==NULL || copyright[0]=='\0' ||
  569. strstr(copyright, "Copyright")==NULL))) {
  570. /* No known copyright. */
  571. LogError(MSG_WARNING, MSG_NOCOPYRIGHT, NULL);
  572. result = MAYBEOK;
  573. /* Strange copyright format? */
  574. } else if (company==NULL || company[0]=='\0') {
  575. if (notice || notice[0])
  576. LogError(MSG_WARNING, MSG_BADFORMAT, notice);
  577. else
  578. LogError(MSG_WARNING, MSG_BADFORMAT, copyright);
  579. result = MAYBEOK;
  580. /* Found copyright! */
  581. } else {
  582. DWORD size;
  583. DWORD csum;
  584. size = 4;
  585. if (RegQueryValueEx(key, Encrypt(company, tmp), NULL, NULL,
  586. (LPBYTE)&csum, &size)==ERROR_SUCCESS) {
  587. /* A positive match -> ok to convert. */
  588. if (CSum(tmp)==csum) {
  589. LogError(MSG_INFO, MSG_COPYRIGHT, company);
  590. result = SUCCESS;
  591. } else {
  592. LogError(MSG_ERROR, MSG_BADCOPYRIGHT, company);
  593. result = SKIP;
  594. }
  595. } else {
  596. LogError(MSG_WARNING, MSG_BADCOPYRIGHT, company);
  597. result = MAYBEOK;
  598. }
  599. }
  600. #endif
  601. RegCloseKey(key);
  602. /* Give the user the final word. */
  603. if (result==FAILURE) {
  604. if (ConvertAnyway(company, facename)==TRUE)
  605. result = SUCCESS;
  606. }
  607. /* No copyright key in the registry? */
  608. } else {
  609. LogError(MSG_ERROR, MSG_NODB, NULL);
  610. result = FAILURE;
  611. }
  612. return result;
  613. #endif
  614. }
  615. /***
  616. ** Function: NTCheckCopyright
  617. **
  618. ** Description:
  619. ** This is the callback function that verifies that
  620. ** the converted font is copyrighted by a company who
  621. ** has agreed to having their fonts converted by
  622. ** this software. These companies are registered in the
  623. ** registry data base.
  624. ***/
  625. static errcode NTCheckCopyright(const char *facename,
  626. const char *copyright,
  627. const char *notice)
  628. {
  629. HKEY key;
  630. char tmp[256];
  631. char *company = NULL;
  632. char buf[1024];
  633. int done = FALSE;
  634. short result = FAILURE;
  635. /* Access the REG data base. */
  636. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SUBKEY_TYPE1COPYRIGHTS, 0,
  637. KEY_QUERY_VALUE, &key)==ERROR_SUCCESS) {
  638. /* Look for the company name in the /notice string. */
  639. if (notice && notice[0]) {
  640. strcpy(buf, notice);
  641. company = GetCompany(buf);
  642. }
  643. /* Look in the /copyright string if the company name was not found. */
  644. if (company==NULL && copyright && copyright[0]) {
  645. strcpy(buf, copyright);
  646. company = GetCompany(buf);
  647. }
  648. /* Did not find a company name? */
  649. if (company==NULL &&
  650. ((notice==NULL || notice[0]=='\0'||
  651. strstr(notice, "Copyright")==NULL) &&
  652. (copyright==NULL || copyright[0]=='\0' ||
  653. strstr(copyright, "Copyright")==NULL))) {
  654. /* No known copyright. */
  655. result = MAYBE;
  656. /* Strange copyright format? */
  657. } else if (company==NULL || company[0]=='\0') {
  658. result = MAYBE;
  659. /* Found copyright! */
  660. } else {
  661. DWORD size;
  662. DWORD csum;
  663. /* remember for future use. */
  664. strncpy(lastVendor, company, 256);
  665. lastVendor[MIN(255, strlen(company))] = '\0';
  666. size = 4;
  667. if (RegQueryValueEx(key, Encrypt(company, tmp), NULL, NULL,
  668. (LPBYTE)&csum, &size)==ERROR_SUCCESS) {
  669. /* A positive match -> ok to convert. */
  670. if (CSum(tmp)==csum) {
  671. result = SUCCESS;
  672. } else {
  673. result = FAILURE;
  674. }
  675. } else {
  676. result = MAYBE;
  677. }
  678. }
  679. RegCloseKey(key);
  680. /* No copyright key in the registry? */
  681. } else {
  682. result = FAILURE;
  683. }
  684. lastCP = result;
  685. return FAILURE;
  686. }
  687. /***
  688. ** Function: _Progress
  689. **
  690. ** Description:
  691. ** This is the internal progress callback function that
  692. ** computes an percentage-done number, based on the
  693. ** number of converted glyphs.
  694. ***/
  695. static void _Progress(short type, void *generic, void *arg)
  696. {
  697. struct callFrame *f = arg;
  698. /* Processing glyphs or wrapping up? */
  699. if (type==0 || type==1)
  700. f->done++;
  701. else
  702. f->done = MIN(sizeof(winmac)/sizeof(winmac[0]), f->done+10);
  703. if ((f->done-f->last)>MIN_PROGRESS) {
  704. f->Progress((short)(f->done*100/(sizeof(winmac)/sizeof(winmac[0]))),
  705. f->arg);
  706. f->last = f->done;
  707. }
  708. UNREFERENCED_PARAMETER(type);
  709. UNREFERENCED_PARAMETER(generic);
  710. SetLastError(0L);
  711. }
  712. static BOOL ReadStringFromOffset(struct ioFile *file,
  713. const DWORD dwOffset,
  714. char *pszString,
  715. int cLen,
  716. BOOL bStrip)
  717. {
  718. BOOL result = TRUE;
  719. DWORD offset;
  720. /* Get offset to string. */
  721. io_FileSeek(file, dwOffset);
  722. /* Read the offset. */
  723. ReadLittleEndianDword(file, offset);
  724. /* Get the string. */
  725. (void)io_FileSeek(file, offset);
  726. if (io_FileError(file) != SUCCESS) {
  727. result = FALSE;
  728. } else {
  729. int i;
  730. i=0;
  731. while (io_FileError(file)==SUCCESS && i<cLen) {
  732. pszString[i] = (UBYTE)io_ReadOneByte(file);
  733. if (pszString[i]=='\0')
  734. break;
  735. /* Replace all dashes with spaces. */
  736. if (bStrip && pszString[i]=='-')
  737. pszString[i]=' ';
  738. i++;
  739. }
  740. }
  741. return TRUE;
  742. }
  743. /**** FUNCTIONS */
  744. /***
  745. ** Function: ConvertTypeFaceA
  746. **
  747. ** Description:
  748. ** Convert a T1 font into a TT font file. This is the
  749. ** simplified interface used by the Win32 DLL, with the
  750. ** ANSI interface.
  751. ***/
  752. short STDCALL ConvertTypefaceAInternal(const char *type1,
  753. const char *metrics,
  754. const char *truetype,
  755. const void (STDCALL *Progress)(short, void*),
  756. void *arg)
  757. {
  758. struct callFrame f;
  759. struct callProgress p;
  760. struct T1Arg t1Arg;
  761. struct TTArg ttArg;
  762. short status;
  763. /* Check parameters. */
  764. if (type1==NULL || metrics==NULL)
  765. return FAILURE;
  766. /* Set up arguments to ConvertTypefaceA() */
  767. t1Arg.filter = GLYPHFILTER;
  768. t1Arg.upem = (short)2048;
  769. t1Arg.name = (char *)type1;
  770. t1Arg.metrics = (char *)metrics;
  771. ttArg.precision = (short)50;
  772. ttArg.name = (char *)truetype;
  773. ttArg.tag = VERSTR;
  774. /* Use progress gauge */
  775. if (Progress) {
  776. LogError(MSG_INFO, MSG_STARTING, type1);
  777. f.Progress = Progress;
  778. f.done = 0;
  779. f.last = 0;
  780. f.arg = arg;
  781. p.arg = &f;
  782. p.cb = _Progress;
  783. status = ConvertT1toTT(&ttArg, &t1Arg, CheckCopyright, &p);
  784. Progress(100, arg);
  785. } else {
  786. status = ConvertT1toTT(&ttArg, &t1Arg, CheckCopyright, NULL);
  787. }
  788. return status;
  789. }
  790. short STDCALL ConvertTypefaceA(char *type1,
  791. char *metrics,
  792. char *truetype,
  793. void (STDCALL *Progress)(short, void*),
  794. void *arg)
  795. {
  796. short bRet;
  797. try
  798. {
  799. bRet = ConvertTypefaceAInternal(type1,
  800. metrics,
  801. truetype,
  802. Progress,
  803. arg);
  804. }
  805. except (EXCEPTION_EXECUTE_HANDLER)
  806. {
  807. #if 0
  808. ASSERTGDI(
  809. GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR,
  810. "ttfd!ttfdSemLoadFontFile, strange exception code\n"
  811. );
  812. #endif
  813. bRet = BADINPUTFILE;
  814. }
  815. return bRet;
  816. }
  817. short STDCALL FindPfb (
  818. char *pszPFM,
  819. char *achPFB
  820. );
  821. /***
  822. ** Function: CheckPfmA
  823. **
  824. ** Description:
  825. ** This function determines if there is a pfm/pfb pair of
  826. ** files that makes up an Adobe Type 1 font, and determins
  827. ** the descriptive face name of it.
  828. **
  829. ** Returns: 16-bit encoded value indicating error and type of file where
  830. ** error occurred. (see fvscodes.h) for definitions.
  831. ** The following table lists the "status" portion of the codes
  832. ** returned.
  833. **
  834. ** FVS_SUCCESS
  835. ** FVS_INVALID_FONTFILE
  836. ** FVS_FILE_OPEN_ERR
  837. ** FVS_INVALID_ARG
  838. ** FVS_FILE_IO_ERR
  839. ** FVS_BAD_VERSION
  840. ***/
  841. short STDCALL CheckPfmA(
  842. char *pszPFM,
  843. DWORD cjDesc,
  844. char *pszDesc,
  845. DWORD cjPFB,
  846. char *pszPFB
  847. )
  848. {
  849. struct ioFile *file;
  850. char szDriver[MAX_PATH];
  851. short result = FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  852. short ver;
  853. char achPFB[MAX_PATH];
  854. char *psz_PFB;
  855. DWORD cjPFB1;
  856. if (pszPFB)
  857. {
  858. psz_PFB = pszPFB;
  859. cjPFB1 = cjPFB;
  860. }
  861. else
  862. {
  863. psz_PFB = (char *)achPFB;
  864. cjPFB1 = MAX_PATH;
  865. }
  866. /* Check parameter. */
  867. if (pszPFM==NULL || ((strlen(pszPFM)+3) >= cjPFB1))
  868. return FVS_MAKE_CODE(FVS_INVALID_ARG, FVS_FILE_UNK);
  869. // check if pfb file exists and find the path to it:
  870. result = FindPfb(pszPFM, psz_PFB);
  871. if (FVS_STATUS(result) != FVS_SUCCESS)
  872. return result;
  873. /****
  874. * Locate the pszDescriptive name of the font.
  875. */
  876. if ((file = io_OpenFile(pszPFM, READONLY))==NULL)
  877. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFM);
  878. (void)io_ReadOneByte(file); /* Skip the revision number. */
  879. ver = (short)io_ReadOneByte(file);
  880. if (ver > 3) {
  881. /* ERROR - unsupported format */
  882. result = FVS_MAKE_CODE(FVS_BAD_VERSION, FVS_FILE_PFM);
  883. } else {
  884. /* Read the driver name. */
  885. if (!ReadStringFromOffset(file, DFDRIVERINFO, szDriver,
  886. sizeof(szDriver), FALSE))
  887. {
  888. result = FVS_MAKE_CODE(FVS_FILE_IO_ERR, FVS_FILE_PFM);
  889. }
  890. /* Is it "PostScript" ? */
  891. else if (_stricmp(szDriver, "PostScript"))
  892. {
  893. result = FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM);
  894. }
  895. /* Only get description if asked to do so. */
  896. else if (pszDesc && !ReadStringFromOffset(file, DFFACE, pszDesc, cjDesc, TRUE))
  897. {
  898. result = FVS_MAKE_CODE(FVS_FILE_IO_ERR, FVS_FILE_PFM);
  899. }
  900. }
  901. (void)io_CloseFile(file);
  902. return result;
  903. }
  904. /***
  905. ** Function: CheckCopyrightsA
  906. **
  907. ** Description:
  908. ** This function verifies that it is ok to convert the font. This is
  909. ** done by faking an installation.
  910. ***/
  911. short STDCALL CheckCopyrightAInternal(char *szPFB,
  912. DWORD wSize,
  913. char *szVendor)
  914. {
  915. struct T1Arg t1Arg;
  916. struct TTArg ttArg;
  917. /* Set up arguments to ConvertTypefaceA() */
  918. t1Arg.metrics = NULL;
  919. t1Arg.upem = (short)2048;
  920. t1Arg.filter = GLYPHFILTER;
  921. t1Arg.name = szPFB;
  922. ttArg.precision = (short)200;
  923. ttArg.tag = NULL;
  924. ttArg.name = "NIL:";
  925. lastCP = FAILURE;
  926. strcpy(lastVendor, "");
  927. (void)ConvertT1toTT(&ttArg, &t1Arg, NTCheckCopyright, NULL);
  928. strncpy(szVendor, lastVendor, wSize);
  929. szVendor[MIN(wSize, strlen(lastVendor))] = '\0';
  930. return lastCP;
  931. }
  932. short STDCALL CheckCopyrightA(char *szPFB,
  933. DWORD wSize,
  934. char *szVendor)
  935. {
  936. short iRet;
  937. try
  938. {
  939. iRet = CheckCopyrightAInternal(szPFB,wSize,szVendor);
  940. }
  941. except (EXCEPTION_EXECUTE_HANDLER)
  942. {
  943. iRet = BADINPUTFILE;
  944. }
  945. return iRet;
  946. }
  947. /******************************Public*Routine******************************\
  948. *
  949. * short STDCALL CheckInfA (
  950. *
  951. * If pfm and inf files are in the same directory only pfm is recognized
  952. * and inf file is ignored.
  953. *
  954. * History:
  955. * 27-Apr-1994 -by- Bodin Dresevic [BodinD]
  956. * Wrote it.
  957. *
  958. * Returns: 16-bit encoded value indicating error and type of file where
  959. * error occurred. (see fvscodes.h) for definitions.
  960. * The following table lists the "status" portion of the codes
  961. * returned.
  962. *
  963. * FVS_SUCCESS
  964. * FVS_INVALID_FONTFILE
  965. * FVS_FILE_OPEN_ERR
  966. * FVS_FILE_BUILD_ERR
  967. * FVS_FILE_EXISTS
  968. * FVS_INSUFFICIENT_BUF
  969. *
  970. \**************************************************************************/
  971. short CreatePFM(char *pszINF, char *pszAFM, char *pszPFM);
  972. BOOL bGetDescFromInf(char * pszINF, DWORD cjDesc, char *pszDesc);
  973. BOOL bFileExists(char *pszFile)
  974. {
  975. HFILE hf;
  976. if ((hf = _lopen(pszFile, OF_READ)) != -1)
  977. {
  978. _lclose(hf);
  979. return TRUE;
  980. }
  981. return FALSE;
  982. }
  983. short STDCALL CheckInfA (
  984. char *pszINF,
  985. DWORD cjDesc,
  986. char *pszDesc,
  987. DWORD cjPFM,
  988. char *pszPFM,
  989. DWORD cjPFB,
  990. char *pszPFB,
  991. BOOL *pbCreatedPFM,
  992. char *pszFontPath
  993. )
  994. {
  995. char achPFM[MAX_PATH];
  996. char achPFB[MAX_PATH];
  997. char achAFM[MAX_PATH];
  998. DWORD cjKey;
  999. char *pszParent = NULL; // points to the where parent dir of the inf file is
  1000. char *pszBare = NULL; // "bare" .inf name, initialization essential
  1001. short result = FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  1002. BOOL bAfmExists = FALSE;
  1003. BOOL bPfbExists = FALSE;
  1004. //
  1005. // This is a real hack use of pbCreatedPFM.
  1006. // It's the best solution with the time we have.
  1007. //
  1008. BOOL bCheckForExistingPFM = *pbCreatedPFM;
  1009. *pbCreatedPFM = FALSE;
  1010. // example:
  1011. // if pszINF -> "c:\psfonts\fontinfo\foo_____.inf"
  1012. // then pszParent -> "fontinfo\foo_____.inf"
  1013. cjKey = strlen(pszINF) + 1;
  1014. if (cjKey < 5) // 5 = strlen(".pfm") + 1;
  1015. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF);
  1016. // check if a pfm file exists in the SAME directory.
  1017. // Use the buffer on the stack to produce the path for the pfm file:
  1018. strcpy(achPFM, pszINF);
  1019. strcpy(&achPFM[cjKey - 5],".PFM");
  1020. // try to open pfm file to check if it exists:
  1021. if (bCheckForExistingPFM && bFileExists(achPFM))
  1022. {
  1023. // we found the pfm file, therefore we do not report this .inf file.
  1024. return FVS_MAKE_CODE(FVS_FILE_EXISTS, FVS_FILE_PFM);
  1025. }
  1026. // pfm file is NOT found, go on to check if .afm and .pfb files exists:
  1027. // We will first check if .afm and .pfb files exists in the same dir as .inf
  1028. strcpy(achAFM, pszINF);
  1029. strcpy(&achAFM[cjKey - 5],".AFM");
  1030. strcpy(achPFB, pszINF);
  1031. strcpy(&achPFB[cjKey - 5],".PFB");
  1032. bAfmExists = bFileExists(achAFM);
  1033. bPfbExists = bFileExists(achPFB);
  1034. if (!bAfmExists || !bPfbExists)
  1035. {
  1036. // we did not find the .afm and .pfb files in the same dir as .inf
  1037. // we will check two more directories for the .afm and .pfb files
  1038. // 1) the parent directory of the .inf file for .pfb file
  1039. // 2) the afm subdirectory of the .inf parent directory for .afm file
  1040. //
  1041. // This is meant to handle the standard configuration of files produced
  1042. // on user's hard drive by unlocking fonts from Adobe's CD or from a
  1043. // previous installation of atm manager on this machine.
  1044. // This configuration is as follows:
  1045. // c:\psfonts\ *.pfb files are here
  1046. // c:\psfonts\afm *.afm files are here
  1047. // c:\psfonts\fontinfo *.inf files are here
  1048. // c:\psfonts\pfm *.pfm files that are created on the fly
  1049. // are PUT here by atm.
  1050. // We will instead put the files in windows\system dir where all other
  1051. // fonts are, it may not be possible to write pmf files on the media
  1052. // from where we are installing fonts
  1053. pszBare = &pszINF[cjKey - 5];
  1054. for ( ; pszBare > pszINF; pszBare--)
  1055. {
  1056. if ((*pszBare == '\\') || (*pszBare == ':'))
  1057. {
  1058. pszBare++; // found it
  1059. break;
  1060. }
  1061. }
  1062. // check if full path to .inf file was passed in or a bare
  1063. // name itself was passed in to look for .inf file in the current dir
  1064. if ((pszBare > pszINF) && (pszBare[-1] == '\\'))
  1065. {
  1066. // skip '\\' and search backwards for another '\\':
  1067. for (pszParent = &pszBare[-2]; pszParent > pszINF; pszParent--)
  1068. {
  1069. if ((*pszParent == '\\') || (*pszParent == ':'))
  1070. {
  1071. pszParent++; // found it
  1072. break;
  1073. }
  1074. }
  1075. // create .pfb file name in the .inf parent directory:
  1076. strcpy(&achPFB[pszParent - pszINF], pszBare);
  1077. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1078. // create .afm file name in the afm subdirectory of the .inf
  1079. // parent directory:
  1080. strcpy(&achAFM[pszParent - pszINF], "afm\\");
  1081. strcpy(&achAFM[pszParent - pszINF + 4], pszBare);
  1082. strcpy(&achAFM[strlen(achAFM) - 4], ".AFM");
  1083. }
  1084. else if (pszBare == pszINF)
  1085. {
  1086. // bare name was passed in, to check for the inf file in the "." dir:
  1087. strcpy(achPFB, "..\\");
  1088. strcpy(&achPFB[3], pszBare); // 3 == strlen("..\\")
  1089. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1090. strcpy(achAFM, "..\\afm\\");
  1091. strcpy(&achAFM[7], pszBare); // 7 == strlen("..\\afm\\")
  1092. strcpy(&achAFM[strlen(achAFM) - 4], ".AFM");
  1093. }
  1094. else
  1095. {
  1096. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK);
  1097. }
  1098. // check again if we can find the files, if not fail.
  1099. if (!bAfmExists && !bFileExists(achAFM))
  1100. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_AFM);
  1101. if (!bPfbExists && !bFileExists(achPFB))
  1102. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFB);
  1103. }
  1104. // now we have paths to .inf .afm and .pfb files. Now let us see
  1105. // what the caller wants from us:
  1106. if (pszDesc)
  1107. {
  1108. // we need to return description string in the buffer supplied
  1109. if (!bGetDescFromInf(pszINF, (DWORD)cjDesc, pszDesc))
  1110. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF);
  1111. }
  1112. // copy pfb file path out if requested
  1113. if (pszPFB)
  1114. {
  1115. if ((strlen(achPFB) + 1) < cjPFB)
  1116. strcpy(pszPFB,achPFB);
  1117. else
  1118. return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK);
  1119. }
  1120. // the caller wants a pfm file created from inf,afm files
  1121. // For now and probably for ever we will put this file in
  1122. // the %windir%\system, or %windir%\fonts for the secure system.
  1123. if (pszPFM)
  1124. {
  1125. UINT cjSystemDir;
  1126. char *pszAppendHere; // append "bare" name here
  1127. // copy the first directory of the font path into the buffer provided
  1128. // It is expected that this routine will get something like
  1129. // "c:\foo" pointing to font path
  1130. strcpy(achPFM,pszFontPath);
  1131. pszAppendHere = &achPFM[strlen(pszFontPath) - 1];
  1132. if (*pszAppendHere != '\\')
  1133. {
  1134. pszAppendHere++;
  1135. *pszAppendHere = '\\';
  1136. }
  1137. pszAppendHere++;
  1138. // find bare name of the .inf file if we do not have already:
  1139. if (!pszBare)
  1140. {
  1141. pszBare = &pszINF[cjKey - 5];
  1142. for ( ; pszBare > pszINF; pszBare--)
  1143. {
  1144. if ((*pszBare == '\\') || (*pszBare == ':'))
  1145. {
  1146. pszBare++; // found it
  1147. break;
  1148. }
  1149. }
  1150. }
  1151. // append Bare name to the %windir%system\ path
  1152. strcpy(pszAppendHere, pszBare);
  1153. // finally change .inf extension to .pfm extension
  1154. strcpy(&pszAppendHere[strlen(pszAppendHere) - 4], ".PFM");
  1155. // copy out:
  1156. strcpy(pszPFM, achPFM);
  1157. result = CreatePFM(pszINF, achAFM, pszPFM);
  1158. *pbCreatedPFM = (FVS_STATUS(result) == FVS_SUCCESS);
  1159. if (!(*pbCreatedPFM))
  1160. return result;
  1161. }
  1162. return FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  1163. }
  1164. /******************************Public*Routine******************************\
  1165. *
  1166. * short STDCALL CheckType1AInternal
  1167. *
  1168. * Effects: See if we are going to report this as a valid type 1 font
  1169. *
  1170. * Warnings:
  1171. *
  1172. * History:
  1173. * 29-Apr-1994 -by- Bodin Dresevic [BodinD]
  1174. * Wrote it.
  1175. *
  1176. * Returns: 16-bit encoded value indicating error and type of file where
  1177. * error occurred. (see fvscodes.h) for definitions.
  1178. * The following table lists the "status" portion of the codes
  1179. * returned.
  1180. *
  1181. * FVS_SUCCESS
  1182. * FVS_INVALID_FONTFILE
  1183. * FVS_FILE_OPEN_ERR
  1184. * FVS_FILE_BUILD_ERR
  1185. * FVS_INVALID_ARG
  1186. * FVS_FILE_IO_ERR
  1187. * FVS_BAD_VERSION
  1188. * FVS_FILE_EXISTS
  1189. * FVS_INSUFFICIENT_BUF
  1190. *
  1191. \**************************************************************************/
  1192. short STDCALL CheckType1AInternal (
  1193. char *pszKeyFile,
  1194. DWORD cjDesc,
  1195. char *pszDesc,
  1196. DWORD cjPFM,
  1197. char *pszPFM,
  1198. DWORD cjPFB,
  1199. char *pszPFB,
  1200. BOOL *pbCreatedPFM,
  1201. char *pszFontPath
  1202. )
  1203. {
  1204. DWORD cjKey;
  1205. *pbCreatedPFM = FALSE; // initialization is essential.
  1206. cjKey = strlen(pszKeyFile) + 1;
  1207. if (cjKey < 5) // 5 = strlen(".pfm") + 1;
  1208. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK);
  1209. if (!_strcmpi(&pszKeyFile[cjKey - 5], ".PFM"))
  1210. {
  1211. // copy out pfm string when asked to do so:
  1212. if (pszPFM && (cjKey < cjPFM))
  1213. {
  1214. if (cjKey < cjPFM)
  1215. strcpy(pszPFM, pszKeyFile);
  1216. else
  1217. return FVS_MAKE_CODE(FVS_INSUFFICIENT_BUF, FVS_FILE_UNK);
  1218. }
  1219. return CheckPfmA(
  1220. pszKeyFile,
  1221. cjDesc,
  1222. pszDesc,
  1223. cjPFB,
  1224. pszPFB
  1225. );
  1226. }
  1227. else if (!_strcmpi(&pszKeyFile[cjKey - 5], ".INF"))
  1228. {
  1229. return CheckInfA (
  1230. pszKeyFile,
  1231. cjDesc,
  1232. pszDesc,
  1233. cjPFM,
  1234. pszPFM,
  1235. cjPFB,
  1236. pszPFB,
  1237. pbCreatedPFM,
  1238. pszFontPath
  1239. );
  1240. }
  1241. else
  1242. {
  1243. // this font is not our friend
  1244. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_UNK);
  1245. }
  1246. }
  1247. /******************************Public*Routine******************************\
  1248. *
  1249. * CheckType1WithStatusA, try / except wrapper
  1250. *
  1251. * Effects:
  1252. *
  1253. * Warnings:
  1254. *
  1255. * History:
  1256. * 14-Jun-1994 -by- Bodin Dresevic [BodinD]
  1257. * Wrote it.
  1258. *
  1259. * Returns: 16-bit encoded value indicating error and type of file where
  1260. * error occurred. (see fvscodes.h) for definitions.
  1261. * The following table lists the "status" portion of the codes
  1262. * returned.
  1263. *
  1264. * FVS_SUCCESS
  1265. * FVS_INVALID_FONTFILE
  1266. * FVS_FILE_OPEN_ERR
  1267. * FVS_FILE_BUILD_ERR
  1268. * FVS_INVALID_ARG
  1269. * FVS_FILE_IO_ERR
  1270. * FVS_BAD_VERSION
  1271. * FVS_FILE_EXISTS
  1272. * FVS_INSUFFICIENT_BUF
  1273. * FVS_EXCEPTION
  1274. *
  1275. \**************************************************************************/
  1276. short STDCALL CheckType1WithStatusA (
  1277. char *pszKeyFile,
  1278. DWORD cjDesc,
  1279. char *pszDesc,
  1280. DWORD cjPFM,
  1281. char *pszPFM,
  1282. DWORD cjPFB,
  1283. char *pszPFB,
  1284. BOOL *pbCreatedPFM,
  1285. char *pszFontPath
  1286. )
  1287. {
  1288. short status;
  1289. try
  1290. {
  1291. status = CheckType1AInternal (
  1292. pszKeyFile,
  1293. cjDesc,
  1294. pszDesc,
  1295. cjPFM,
  1296. pszPFM,
  1297. cjPFB,
  1298. pszPFB,
  1299. pbCreatedPFM,
  1300. pszFontPath);
  1301. }
  1302. except (EXCEPTION_EXECUTE_HANDLER)
  1303. {
  1304. status = FVS_MAKE_CODE(FVS_EXCEPTION, FVS_FILE_UNK);
  1305. }
  1306. return status;
  1307. }
  1308. /******************************Public*Routine******************************\
  1309. *
  1310. * CheckType1A, try / except wrapper
  1311. *
  1312. * Effects:
  1313. *
  1314. * Warnings:
  1315. *
  1316. * History:
  1317. * 14-Jun-1994 -by- Bodin Dresevic [BodinD]
  1318. * Wrote it.
  1319. \**************************************************************************/
  1320. BOOL STDCALL CheckType1A (
  1321. char *pszKeyFile,
  1322. DWORD cjDesc,
  1323. char *pszDesc,
  1324. DWORD cjPFM,
  1325. char *pszPFM,
  1326. DWORD cjPFB,
  1327. char *pszPFB,
  1328. BOOL *pbCreatedPFM,
  1329. char *pszFontPath
  1330. )
  1331. {
  1332. short status = CheckType1WithStatusA(pszKeyFile,
  1333. cjDesc,
  1334. pszDesc,
  1335. cjPFM,
  1336. pszPFM,
  1337. cjPFB,
  1338. pszPFB,
  1339. pbCreatedPFM,
  1340. pszFontPath);
  1341. return (FVS_STATUS(status) == FVS_SUCCESS);
  1342. }
  1343. /******************************Public*Routine******************************\
  1344. *
  1345. * FindPfb, given pfm file, see if pfb file exists in the same dir or in the
  1346. * parent directory of the pfm file
  1347. *
  1348. * History:
  1349. * 14-Jun-1994 -by- Bodin Dresevic [BodinD]
  1350. * Wrote it.
  1351. *
  1352. * Returns: 16-bit encoded value indicating error and type of file where
  1353. * error occurred. (see fvscodes.h) for definitions.
  1354. * The following table lists the "status" portion of the codes
  1355. * returned.
  1356. *
  1357. * FVS_SUCCESS
  1358. * FVS_INVALID_FONTFILE
  1359. * FVS_FILE_OPEN_ERR
  1360. *
  1361. \**************************************************************************/
  1362. short STDCALL FindPfb (
  1363. char *pszPFM,
  1364. char *achPFB
  1365. )
  1366. {
  1367. DWORD cjKey;
  1368. char *pszParent = NULL; // points to the where parent dir of the inf file is
  1369. char *pszBare = NULL; // "bare" .inf name, initialization essential
  1370. // example:
  1371. // if pszPFM -> "c:\psfonts\pfm\foo_____.pfm"
  1372. // then pszParent -> "pfm\foo_____.pfm"
  1373. cjKey = strlen(pszPFM) + 1;
  1374. if (cjKey < 5) // 5 = strlen(".pfm") + 1;
  1375. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM);
  1376. // go on to check if .pfb file exists:
  1377. // We will first check .pfb file exists in the same dir as .pfm
  1378. strcpy(achPFB, pszPFM);
  1379. strcpy(&achPFB[cjKey - 5],".PFB");
  1380. if (!bFileExists(achPFB))
  1381. {
  1382. // we did not find the .pfb file in the same dir as .pfm
  1383. // Now check the parent directory of the .pfm file
  1384. pszBare = &pszPFM[cjKey - 5];
  1385. for ( ; pszBare > pszPFM; pszBare--)
  1386. {
  1387. if ((*pszBare == '\\') || (*pszBare == ':'))
  1388. {
  1389. pszBare++; // found it
  1390. break;
  1391. }
  1392. }
  1393. // check if full path to .pfm was passed in or a bare
  1394. // name itself was passed in to look for .pfm file in the current dir
  1395. if ((pszBare > pszPFM) && (pszBare[-1] == '\\'))
  1396. {
  1397. // skip '\\' and search backwards for another '\\':
  1398. for (pszParent = &pszBare[-2]; pszParent > pszPFM; pszParent--)
  1399. {
  1400. if ((*pszParent == '\\') || (*pszParent == ':'))
  1401. {
  1402. pszParent++; // found it
  1403. break;
  1404. }
  1405. }
  1406. // create .pfb file name in the .pfm parent directory:
  1407. strcpy(&achPFB[pszParent - pszPFM], pszBare);
  1408. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1409. }
  1410. else if (pszBare == pszPFM)
  1411. {
  1412. // bare name was passed in, to check for the inf file in the "." dir:
  1413. strcpy(achPFB, "..\\");
  1414. strcpy(&achPFB[3], pszBare); // 3 == strlen("..\\")
  1415. strcpy(&achPFB[strlen(achPFB) - 4], ".PFB");
  1416. }
  1417. else
  1418. {
  1419. return FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_PFM); // We should never get here.
  1420. }
  1421. // check again if we can find the file, if not fail.
  1422. if (!bFileExists(achPFB))
  1423. {
  1424. return FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_PFB);
  1425. }
  1426. }
  1427. // now we have paths to .pfb file in the buffer provided by the caller.
  1428. return FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK);
  1429. }