tmacfont.c - plan9port - [fork] Plan 9 from user space
HTML git clone git://src.adamsgaard.dk/plan9port
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tmacfont.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 /*****************************************************************************/