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