Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 *
 * 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 = stdin;
FILE    *fp_out = stdout;

/*****************************************************************************/

main(agc, agv)

    int         agc;
    char        *agv[];

{

/*
 *
 * Macintosh to Unix font converter.
 *
 */

    argc = agc;
    argv = agv;
    prog_name = argv[0];

    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 */

/*****************************************************************************/