/*

   This program reads a MAC format Adobe Font file and unpacks it so
   that it can be loaded as a program into a PostScript printer.  Note
   that it does not decrypt the file.

   I don't beleive that unpacking (as opposed to decrypting) should be a
   violation of the license agreement, but then again, I am not a
   lawyer.  In short, as far as the legalities go, you are on your own.

   This program was compiled and tested on an IBM PC/AT with Turbo C
   Version 2.01.  It should build with little trouble using any ANSI C
   compiler.

   Modifications for the Amiga: Removed the inclusion of "io.h" and added
   a MOTOROLA define to select the type of byte ordering. The program
   requires a MacBinary file of the font to do its magic.

*/


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

#define MOTOROLA

#define COMMENT_BLOCK       0
#define ASCII_BLOCK         1
#define HEX_BLOCK           2
#define EOF_BLOCK           3
#define PREAMBLE_LENGTH     0x180L
#define MAX_LINELEN         78
#define MAX_EVEN_LINELEN    MAX_LINELEN & (~1)
/*
   Define error codes
*/
#define E_IPO 1
#define E_COI 2                       /* Can't open input */
#define E_COO 3                       /* Can't open output */
#define E_BIF 4                       /* Bad input file format */


const char *errmsg[] = {
   "\nSuccess %s\n",
   "\nCan't Open Input file %s\n",
   "\nCan't open Output file %s\n",
   "\nBad Input Format %s\n",
	""
};


void EXIT(int code,char *text)
{
   printf(errmsg[code], text ? text : "");
   exit(code);
}

char tohex[] = {"0123456789ABCDEF"};       /* Array to convert to hex */



/*
    read_block_header()

    The font block header consists of a Motorola-format long integer
    consisting of the block length (not including the length of the
    length field), and a byte (padded to an int) consisting of the block
    type.
*/

int read_block_header(FILE *infile, unsigned long *blksiz, int *blktyp)
{
  int i;

	/*
	 read and convert the Motorola long
	 */
#if MOTOROLA
	for (i=0; i<4; i++)
		*((unsigned char *)blksiz+i) = (unsigned char) fgetc(infile);
#else
	for (i=3; i>=0; i--)
		*((unsigned char *)blksiz+i) = (unsigned char) fgetc(infile);
#endif
	/*
	 get the block type
	 */
	*blktyp =  fgetc(infile);
	/*
	 discard the padding
	 */
	fgetc(infile);
	/*
	 adjust the block size to reflect the bytes remaining to read
	 */
	*blksiz -=2L;
	/*
   flag any problem with the block type
	*/
  return (*blktyp < EOF_BLOCK);
}


void main (int argc, char *argv[])
{

int           linlen;              /* length of current line */
FILE          *infile;             /* Input file */
FILE          *outfile;            /* Output file */
unsigned char ch;                  /* a character */
unsigned long blksiz;              /* size of data block */
int           blktyp;              /* block type */


/* Open the input file and output file */

   /*
    check for proper number of command-line parameters
    */
   if (argc != 3)
     EXIT(E_IPO, NULL);
   /*
    identify and open input file
    */
	 if ((infile = fopen(argv[1],"rb")) == NULL)
		 EXIT(E_COI,argv[1]);
   /*
    identify and open output file
    */
	 if ((outfile = fopen(argv[2],"wb")) == NULL)
		 EXIT(E_COO,argv[2]);
   /*
    Macintosh font files have a preamble to discard, so seek past the
    preamble.
    */
    fseek(infile, PREAMBLE_LENGTH, SEEK_SET);
    /*
     Do an initial check on the file to see if it looks like a
     PostScript font file.  Here we check to see if the first block type
     in ASCII.
    */
    read_block_header(infile, &blksiz, &blktyp);
    if (blktyp != 1)
    {
      printf("PostScript font program not in correct format\n");
      EXIT(E_BIF, argv[1]);
    }

   /*
      output the PostScript "magic number" and the text to invoke the
      server dictionary password
   */
   fputs("%!\n",outfile);
   fputs("serverdict begin 0 exitserver\n",outfile);

   /*
    reseek the start source file
    */
	 fseek(infile, PREAMBLE_LENGTH, SEEK_SET);

   /*
    while there are blocks in the source file, process them
    */
   while (read_block_header(infile, &blksiz, &blktyp))
	 {
		 switch (blktyp)
		 {
       case ASCII_BLOCK:
         /*
          read and output the ASCII characters in the ASCII block
          */
				 for ( ; blksiz > 0; blksiz--)
				 {
           ch = fgetc(infile);
           if (ch != '\015')
             fputc(ch,outfile);    /* if not a carriage return character */
           else
             fputs("\n",outfile);  /* otherwise end the string */
				 }
				 break;

       case HEX_BLOCK:
         for (linlen=MAX_EVEN_LINELEN;
              blksiz > 0;
              blksiz--, linlen-=2 )
				 {
					 if (linlen <= 0)
					 {
             /* force a new line */
             fputs("\n",outfile);
             linlen=MAX_EVEN_LINELEN;
					 }
           ch = fgetc(infile);
           fputc(tohex[ch/16], outfile);
           fputc(tohex[ch%16], outfile);
				 }
         fputs("\n",outfile);
				 break;

			 default:
				 /* skip comments */
         fseek(infile, (long)blksiz, SEEK_CUR);
				 break;
		 }
	 }
   /*
     Close the files and return success
    */
   fclose(infile);
   fclose(outfile);
   EXIT(0,NULL);
}
