macfont.c (5672B)
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 14 #include <stdio.h> 15 #include <signal.h> 16 17 #define OFF 0 18 #define ON 1 19 20 #define NON_FATAL 0 21 #define FATAL 1 22 23 #define FALSE 0 24 #define TRUE 1 25 26 char **argv; 27 int argc; 28 29 char *prog_name; 30 31 int x_stat; 32 int debug = OFF; 33 int ignore = OFF; 34 35 FILE *fp_in; 36 FILE *fp_out; 37 38 /*****************************************************************************/ 39 40 main(agc, agv) 41 42 int agc; 43 char *agv[]; 44 45 { 46 47 /* 48 * 49 * Macintosh to Unix font converter. 50 * 51 */ 52 53 argc = agc; 54 argv = agv; 55 prog_name = argv[0]; 56 57 fp_in = stdin; 58 fp_out = stdout; 59 60 options(); 61 arguments(); 62 exit(x_stat); 63 64 } /* End of main */ 65 66 /*****************************************************************************/ 67 68 options() 69 70 { 71 72 int ch; 73 char *names = "DI"; 74 75 extern char *optarg; 76 extern int optind; 77 78 /* 79 * 80 * Command line options. 81 * 82 */ 83 84 while ( (ch = getopt(argc, argv, names)) != EOF ) { 85 switch ( ch ) { 86 case 'D': /* debug flag */ 87 debug = ON; 88 break; 89 90 case 'I': /* ignore FATAL errors */ 91 ignore = ON; 92 break; 93 94 case '?': /* don't understand the option */ 95 error(FATAL, ""); 96 break; 97 98 default: /* don't know what to do for ch */ 99 error(FATAL, "missing case for option %c\n", ch); 100 break; 101 } /* End switch */ 102 } /* End while */ 103 104 argc -= optind; 105 argv += optind; 106 107 } /* End of options */ 108 109 /*****************************************************************************/ 110 111 arguments() 112 113 { 114 115 116 /* 117 * 118 * Everything else is an input file. No arguments or '-' means stdin. 119 * 120 */ 121 122 if ( argc < 1 ) 123 conv(); 124 else 125 while ( argc > 0 ) { 126 if ( strcmp(*argv, "-") == 0 ) 127 fp_in = stdin; 128 else if ( (fp_in = fopen(*argv, "r")) == NULL ) 129 error(FATAL, "can't open %s", *argv); 130 conv(); 131 if ( fp_in != stdin ) 132 fclose(fp_in); 133 argc--; 134 argv++; 135 } /* End while */ 136 137 } /* End of arguments */ 138 139 /*****************************************************************************/ 140 141 conv() 142 143 { 144 145 int blocksize; 146 int blocktype; 147 148 /* 149 * 150 * The first four bytes (in a block) are the block size, the fifth is the block 151 * type, and the sixth always appears to be NULL. Type 0 blocks are comments and 152 * are always skipped. Type 1 blocks are ASCII text, type 2 is binary data that 153 * should be converted to hex, while type 5 blocks represent the end of the font 154 * file. Commment block lengths appear to be from the first byte, while other 155 * lengths seem to be measured from block type byte (ie. the fifth byte). Type 156 * four blocks aren't used, while type 3 blocks mean an end of file indication 157 * should be sent to the printer. Haven't done anything with type 3 blocks. 158 * 159 */ 160 161 while ( 1 ) { 162 blocksize = getint(fp_in); 163 blocktype = getc(fp_in); 164 getc(fp_in); 165 if ( debug == ON ) 166 fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize); 167 switch ( blocktype ) { 168 case 0: /* comment - skip blockcount bytes */ 169 fseek(fp_in, (long) blocksize - 6, 1); 170 break; 171 172 case 1: 173 asciitext(blocksize - 2); 174 break; 175 176 case 2: 177 hexdata(blocksize - 2); 178 break; 179 180 case 3: 181 case 4: 182 error(FATAL, "resource type %d not implemented", blocktype); 183 break; 184 185 case 5: 186 return; 187 188 default: 189 error(FATAL, "unknown resource type %d", blocktype); 190 } /* End switch */ 191 } /* End while */ 192 193 } /* End of conv */ 194 195 /*****************************************************************************/ 196 197 asciitext(count) 198 199 int count; /* bytes left in the block */ 200 201 { 202 203 int ch; 204 int i = 0; 205 206 /* 207 * 208 * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines 209 * is all I've done. 210 * 211 */ 212 213 for ( i = 0; i < count; i++ ) { 214 if ( (ch = getc(fp_in)) == '\r' ) 215 ch = '\n'; 216 putc(ch, fp_out); 217 } /* End for */ 218 219 } /* End of asciitext */ 220 221 /*****************************************************************************/ 222 223 hexdata(count) 224 225 int count; /* bytes left in the block */ 226 227 { 228 229 int i; 230 int n; 231 232 /* 233 * 234 * Reads the next count bytes and converts each byte to hex. Also starts a new 235 * line every 80 hex characters. 236 * 237 */ 238 239 for ( i = 0, n = 0; i < count; i++ ) { 240 fprintf(fp_out, "%.2X", getc(fp_in)); 241 if ( (++n % 40) == 0 ) 242 putc('\n', fp_out); 243 } /* End for */ 244 245 } /* End of hexdata */ 246 247 /*****************************************************************************/ 248 249 getint() 250 251 { 252 253 int val; 254 int i; 255 256 /* 257 * 258 * Reads the next four bytes into an integer and returns the value to the caller. 259 * First two bytes are probably always 0. 260 * 261 */ 262 263 for ( i = 0, val = (getc(fp_in) & 0377); i < 3; i++ ) 264 val = (val << 8) | (getc(fp_in) & 0377); 265 266 return(val); 267 268 } /* End of getint */ 269 270 /*****************************************************************************/ 271 272 error(kind, mesg, a1, a2, a3) 273 274 275 int kind; 276 char *mesg; 277 unsigned a1, a2, a3; 278 279 { 280 281 /* 282 * 283 * Print *mesg then quit if kind is FATAL. 284 * 285 */ 286 287 if ( mesg != NULL && *mesg != '\0' ) { 288 fprintf(stderr, "%s: ", prog_name); 289 fprintf(stderr, mesg, a1, a2, a3); 290 putc('\n', stderr); 291 } /* End if */ 292 293 if ( kind == FATAL && ignore == OFF ) 294 exit(x_stat | 01); 295 296 } /* End of error */ 297 298 /*****************************************************************************/