diff options
Diffstat (limited to 'src/cmd/postscript/misc/macfont.c')
-rw-r--r-- | src/cmd/postscript/misc/macfont.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/src/cmd/postscript/misc/macfont.c b/src/cmd/postscript/misc/macfont.c new file mode 100644 index 00000000..59244a19 --- /dev/null +++ b/src/cmd/postscript/misc/macfont.c @@ -0,0 +1,299 @@ +/* + * + * Program that converts Macintosh font files to a format that works on Unix + * systems. Essentially all the information needed came from the Adobe paper + * "Supporting Downloadable PostScript Fonts". To use the program type, + * + * macfont font.mac >font.unix + * + * where font.mac is the font file, exactly as it came over from a Macintosh, + * and font.unix is equivalent host resident font file usable on Unix systems. + * + */ + +#include <stdio.h> +#include <signal.h> + +#define OFF 0 +#define ON 1 + +#define NON_FATAL 0 +#define FATAL 1 + +#define FALSE 0 +#define TRUE 1 + +char **argv; +int argc; + +char *prog_name; + +int x_stat; +int debug = OFF; +int ignore = OFF; + +FILE *fp_in; +FILE *fp_out; + +/*****************************************************************************/ + +main(agc, agv) + + int agc; + char *agv[]; + +{ + +/* + * + * Macintosh to Unix font converter. + * + */ + + argc = agc; + argv = agv; + prog_name = argv[0]; + + fp_in = stdin; + fp_out = stdout; + + options(); + arguments(); + exit(x_stat); + +} /* End of main */ + +/*****************************************************************************/ + +options() + +{ + + int ch; + char *names = "DI"; + + extern char *optarg; + extern int optind; + +/* + * + * Command line options. + * + */ + + while ( (ch = getopt(argc, argv, names)) != EOF ) { + switch ( ch ) { + case 'D': /* debug flag */ + debug = ON; + break; + + case 'I': /* ignore FATAL errors */ + ignore = ON; + break; + + case '?': /* don't understand the option */ + error(FATAL, ""); + break; + + default: /* don't know what to do for ch */ + error(FATAL, "missing case for option %c\n", ch); + break; + } /* End switch */ + } /* End while */ + + argc -= optind; + argv += optind; + +} /* End of options */ + +/*****************************************************************************/ + +arguments() + +{ + + +/* + * + * Everything else is an input file. No arguments or '-' means stdin. + * + */ + + if ( argc < 1 ) + conv(); + else + while ( argc > 0 ) { + if ( strcmp(*argv, "-") == 0 ) + fp_in = stdin; + else if ( (fp_in = fopen(*argv, "r")) == NULL ) + error(FATAL, "can't open %s", *argv); + conv(); + if ( fp_in != stdin ) + fclose(fp_in); + argc--; + argv++; + } /* End while */ + +} /* End of arguments */ + +/*****************************************************************************/ + +conv() + +{ + + int blocksize; + int blocktype; + +/* + * + * The first four bytes (in a block) are the block size, the fifth is the block + * type, and the sixth always appears to be NULL. Type 0 blocks are comments and + * are always skipped. Type 1 blocks are ASCII text, type 2 is binary data that + * should be converted to hex, while type 5 blocks represent the end of the font + * file. Commment block lengths appear to be from the first byte, while other + * lengths seem to be measured from block type byte (ie. the fifth byte). Type + * four blocks aren't used, while type 3 blocks mean an end of file indication + * should be sent to the printer. Haven't done anything with type 3 blocks. + * + */ + + while ( 1 ) { + blocksize = getint(fp_in); + blocktype = getc(fp_in); + getc(fp_in); + if ( debug == ON ) + fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize); + switch ( blocktype ) { + case 0: /* comment - skip blockcount bytes */ + fseek(fp_in, (long) blocksize - 6, 1); + break; + + case 1: + asciitext(blocksize - 2); + break; + + case 2: + hexdata(blocksize - 2); + break; + + case 3: + case 4: + error(FATAL, "resource type %d not implemented", blocktype); + break; + + case 5: + return; + + default: + error(FATAL, "unknown resource type %d", blocktype); + } /* End switch */ + } /* End while */ + +} /* End of conv */ + +/*****************************************************************************/ + +asciitext(count) + + int count; /* bytes left in the block */ + +{ + + int ch; + int i = 0; + +/* + * + * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines + * is all I've done. + * + */ + + for ( i = 0; i < count; i++ ) { + if ( (ch = getc(fp_in)) == '\r' ) + ch = '\n'; + putc(ch, fp_out); + } /* End for */ + +} /* End of asciitext */ + +/*****************************************************************************/ + +hexdata(count) + + int count; /* bytes left in the block */ + +{ + + int i; + int n; + +/* + * + * Reads the next count bytes and converts each byte to hex. Also starts a new + * line every 80 hex characters. + * + */ + + for ( i = 0, n = 0; i < count; i++ ) { + fprintf(fp_out, "%.2X", getc(fp_in)); + if ( (++n % 40) == 0 ) + putc('\n', fp_out); + } /* End for */ + +} /* End of hexdata */ + +/*****************************************************************************/ + +getint() + +{ + + int val; + int i; + +/* + * + * Reads the next four bytes into an integer and returns the value to the caller. + * First two bytes are probably always 0. + * + */ + + for ( i = 0, val = (getc(fp_in) & 0377); i < 3; i++ ) + val = (val << 8) | (getc(fp_in) & 0377); + + return(val); + +} /* End of getint */ + +/*****************************************************************************/ + +error(kind, mesg, a1, a2, a3) + + + int kind; + char *mesg; + unsigned a1, a2, a3; + +{ + +/* + * + * Print *mesg then quit if kind is FATAL. + * + */ + + if ( mesg != NULL && *mesg != '\0' ) { + fprintf(stderr, "%s: ", prog_name); + fprintf(stderr, mesg, a1, a2, a3); + putc('\n', stderr); + } /* End if */ + + if ( kind == FATAL && ignore == OFF ) + exit(x_stat | 01); + +} /* End of error */ + +/*****************************************************************************/ + |