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