blob: 59244a1922d6039c81596b6e8f8cc00a4e3ffe56 [file] [log] [blame]
/*
*
* 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 */
/*****************************************************************************/