macfont.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. *
  3. * Program that converts Macintosh font files to a format that works on Unix
  4. * systems. Essentially all the information needed came from the Adobe paper
  5. * "Supporting Downloadable PostScript Fonts". To use the program type,
  6. *
  7. * macfont font.mac >font.unix
  8. *
  9. * where font.mac is the font file, exactly as it came over from a Macintosh,
  10. * and font.unix is equivalent host resident font file usable on Unix systems.
  11. *
  12. */
  13. #include <stdio.h>
  14. #include <signal.h>
  15. #define OFF 0
  16. #define ON 1
  17. #define NON_FATAL 0
  18. #define FATAL 1
  19. #define FALSE 0
  20. #define TRUE 1
  21. char **argv;
  22. int argc;
  23. char *prog_name;
  24. int x_stat;
  25. int debug = OFF;
  26. int ignore = OFF;
  27. FILE *fp_in = stdin;
  28. FILE *fp_out = stdout;
  29. /*****************************************************************************/
  30. main(agc, agv)
  31. int agc;
  32. char *agv[];
  33. {
  34. /*
  35. *
  36. * Macintosh to Unix font converter.
  37. *
  38. */
  39. argc = agc;
  40. argv = agv;
  41. prog_name = argv[0];
  42. options();
  43. arguments();
  44. exit(x_stat);
  45. } /* End of main */
  46. /*****************************************************************************/
  47. options()
  48. {
  49. int ch;
  50. char *names = "DI";
  51. extern char *optarg;
  52. extern int optind;
  53. /*
  54. *
  55. * Command line options.
  56. *
  57. */
  58. while ( (ch = getopt(argc, argv, names)) != EOF ) {
  59. switch ( ch ) {
  60. case 'D': /* debug flag */
  61. debug = ON;
  62. break;
  63. case 'I': /* ignore FATAL errors */
  64. ignore = ON;
  65. break;
  66. case '?': /* don't understand the option */
  67. error(FATAL, "");
  68. break;
  69. default: /* don't know what to do for ch */
  70. error(FATAL, "missing case for option %c\n", ch);
  71. break;
  72. } /* End switch */
  73. } /* End while */
  74. argc -= optind;
  75. argv += optind;
  76. } /* End of options */
  77. /*****************************************************************************/
  78. arguments()
  79. {
  80. /*
  81. *
  82. * Everything else is an input file. No arguments or '-' means stdin.
  83. *
  84. */
  85. if ( argc < 1 )
  86. conv();
  87. else
  88. while ( argc > 0 ) {
  89. if ( strcmp(*argv, "-") == 0 )
  90. fp_in = stdin;
  91. else if ( (fp_in = fopen(*argv, "r")) == NULL )
  92. error(FATAL, "can't open %s", *argv);
  93. conv();
  94. if ( fp_in != stdin )
  95. fclose(fp_in);
  96. argc--;
  97. argv++;
  98. } /* End while */
  99. } /* End of arguments */
  100. /*****************************************************************************/
  101. conv()
  102. {
  103. int blocksize;
  104. int blocktype;
  105. /*
  106. *
  107. * The first four bytes (in a block) are the block size, the fifth is the block
  108. * type, and the sixth always appears to be NULL. Type 0 blocks are comments and
  109. * are always skipped. Type 1 blocks are ASCII text, type 2 is binary data that
  110. * should be converted to hex, while type 5 blocks represent the end of the font
  111. * file. Commment block lengths appear to be from the first byte, while other
  112. * lengths seem to be measured from block type byte (ie. the fifth byte). Type
  113. * four blocks aren't used, while type 3 blocks mean an end of file indication
  114. * should be sent to the printer. Haven't done anything with type 3 blocks.
  115. *
  116. */
  117. while ( 1 ) {
  118. blocksize = getint(fp_in);
  119. blocktype = getc(fp_in);
  120. getc(fp_in);
  121. if ( debug == ON )
  122. fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);
  123. switch ( blocktype ) {
  124. case 0: /* comment - skip blockcount bytes */
  125. fseek(fp_in, (long) blocksize - 6, 1);
  126. break;
  127. case 1:
  128. asciitext(blocksize - 2);
  129. break;
  130. case 2:
  131. hexdata(blocksize - 2);
  132. break;
  133. case 3:
  134. case 4:
  135. error(FATAL, "resource type %d not implemented", blocktype);
  136. break;
  137. case 5:
  138. return;
  139. default:
  140. error(FATAL, "unknown resource type %d", blocktype);
  141. } /* End switch */
  142. } /* End while */
  143. } /* End of conv */
  144. /*****************************************************************************/
  145. asciitext(count)
  146. int count; /* bytes left in the block */
  147. {
  148. int ch;
  149. int i = 0;
  150. /*
  151. *
  152. * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines
  153. * is all I've done.
  154. *
  155. */
  156. for ( i = 0; i < count; i++ ) {
  157. if ( (ch = getc(fp_in)) == '\r' )
  158. ch = '\n';
  159. putc(ch, fp_out);
  160. } /* End for */
  161. } /* End of asciitext */
  162. /*****************************************************************************/
  163. hexdata(count)
  164. int count; /* bytes left in the block */
  165. {
  166. int i;
  167. int n;
  168. /*
  169. *
  170. * Reads the next count bytes and converts each byte to hex. Also starts a new
  171. * line every 80 hex characters.
  172. *
  173. */
  174. for ( i = 0, n = 0; i < count; i++ ) {
  175. fprintf(fp_out, "%.2X", getc(fp_in));
  176. if ( (++n % 40) == 0 )
  177. putc('\n', fp_out);
  178. } /* End for */
  179. } /* End of hexdata */
  180. /*****************************************************************************/
  181. getint()
  182. {
  183. int val;
  184. int i;
  185. /*
  186. *
  187. * Reads the next four bytes into an integer and returns the value to the caller.
  188. * First two bytes are probably always 0.
  189. *
  190. */
  191. for ( i = 0, val = (getc(fp_in) & 0377); i < 3; i++ )
  192. val = (val << 8) | (getc(fp_in) & 0377);
  193. return(val);
  194. } /* End of getint */
  195. /*****************************************************************************/
  196. error(kind, mesg, a1, a2, a3)
  197. int kind;
  198. char *mesg;
  199. unsigned a1, a2, a3;
  200. {
  201. /*
  202. *
  203. * Print *mesg then quit if kind is FATAL.
  204. *
  205. */
  206. if ( mesg != NULL && *mesg != '\0' ) {
  207. fprintf(stderr, "%s: ", prog_name);
  208. fprintf(stderr, mesg, a1, a2, a3);
  209. putc('\n', stderr);
  210. } /* End if */
  211. if ( kind == FATAL && ignore == OFF )
  212. exit(x_stat | 01);
  213. } /* End of error */
  214. /*****************************************************************************/