/*
 * Macintosh font suitcase unpacker by John O'Neill
 *
 * Amiga modifications by Rico Mariani
 *
 * The -x flag is used to skip the 128 info section that is placed
 * at the head of the file when the suitcase is uploaded from
 * the Mac by some versions of xmodem.
 *
 * (C)1987 John O'Neill & Rico Mariani
 *
 */

#include <exec/types.h>
#include "extract.h"
#include <stdio.h>

void *malloc();
void *PtoC();
int debug = 1;

main(argc,argv)
int argc;
char **argv;
{
	unsigned char *res, rheader[16];
	int i, j, c;
	int Data_loc, Map_loc, Data_length, Map_length, Res_length;
	int Type_List_loc, Name_List_loc;
	int Num_Res_Types, Type_loc, Num_Fonts, Ref_List_loc;
	int Ref_loc, Res_ID, temp, Res_Name_loc, Res_Attributes;
	int Res_Data_loc;
	int Font_ID, Point_Size, Font_Num, Font_Size;
	unsigned char **Font_Name;
	unsigned char File_Name[32];
	FILE *f,*fontfile;
	int skip = 0;


	/* Start up */

	if (argc < 2 || argc > 4) {
		fprintf(stderr,"Usage: %s [-x] FontFile\n",argv[0]);
		exit(1);
	}

	if (!strcmp(argv[1],"-x"))
		skip = 1;

	f = fopen(argv[1+skip],"r");
	if (!f) {
		fprintf(stderr,"%s: Cannot open %s\n",argv[0],argv[1+skip]);
		exit(1);
	}


	/* Skip .info file sent by XMODEM */

	if (skip) for(i = 0; i < 128; i++) fgetc(f);

	/* Get resource file header */

	fread( rheader, sizeof(rheader), 1, f);

	Data_loc    = X_LONG(rheader + 0);
	Map_loc	    = X_LONG(rheader + 4);
	Data_length = X_LONG(rheader + 8);
	Map_length  = X_LONG(rheader + 12);
	Res_length  = Data_length + Map_length + 256;

	/* allocate memory for the rest of the resource */
	res = malloc(Res_length);

	/* read in everything but the header */
	fread( res+16, Res_length-16, 1, f );
	fclose(f);

	/* Look for FONT resources in the resource map */

	Type_List_loc = Map_loc + X_UWORD(res + Map_loc + 24);
	Name_List_loc = Map_loc + X_UWORD(res + Map_loc + 26);

	Num_Res_Types = 1 + X_UWORD(res + Type_List_loc);

	printf("There are %d Res Types in the file\n", Num_Res_Types);

	for(i = 0; i < Num_Res_Types; i++) {
		Type_loc = Type_List_loc + i*10 + 2;
		if (X_ULONG(res + Type_loc) == 'FONT') {
			Num_Fonts = 1 + X_UWORD(res+Type_loc+4);
			Ref_List_loc = Type_List_loc +
				X_UWORD(res + Type_loc + 6);
			printf("Found FONT rsrc with %d fonts\n", Num_Fonts);

		}
	}

	/* Get the FONT names first: this is the name of the Resources
	   which have ResId a multiple of 128 */

	Font_Num = 1;
	/* need one pointer for each possible font id */
	Font_Name = malloc(sizeof(char *) * 256);
	if (!Font_Name) {
		printf("Error, no memory for font name pointer array\n");
		exit(-1);
	}

	for(i = 0; i < Num_Fonts; i++) {
		Ref_loc    = Ref_List_loc + 12*i;
		Res_ID     = X_UWORD(res + Ref_loc);
		Font_ID    = Res_ID >> 7;
		Point_Size = Res_ID & 0x7f;

		if (Point_Size == 0) {
			temp = X_UWORD(res + Ref_loc + 2);

			if (temp == 0xffff) {
				Font_Name[Font_ID] = malloc(10);
				if (!Font_Name[Font_ID]) {
				    printf("Error, no memory for name\n");
				    exit(-1);
				}

				sprintf(Font_Name[Font_ID],"FONT%d",
					Font_Num );

				Font_Num++;
			}
			else {
				Res_Name_loc = Name_List_loc + temp;
				Font_Name[Font_ID] = PtoC(res+Res_Name_loc);
			}
		}
	}

	/* Get the info on each of the FONT resources found */

	for(i = 0; i < Num_Fonts; i++) {
		Ref_loc = Ref_List_loc + 12*i;
		Res_ID  = X_UWORD(res + Ref_loc );
		Font_ID = Res_ID >> 7;
		Point_Size = Res_ID & 0x7f;

		temp 	       = X_UWORD(res + Ref_loc + 2);
		Res_Name_loc   = (temp == 0xffff) ? -1 : Name_List_loc+temp;
		Res_Attributes = res[Ref_loc + 4];
		Res_Data_loc   = Data_loc + X_UTRIP(res + Ref_loc + 5);
		Font_Size      = X_ULONG( res + Res_Data_loc );

		if (Point_Size != 0) {
			for(j = 0;; j++) {
				c = Font_Name[Font_ID][j];
				if (c == ' ') c = '_';
				if (c != 0)
					File_Name[j] = c;
				else
					break;
			}

			File_Name[j] = '.';
			j++;
			sprintf(&File_Name[j],"%d",Point_Size);

			printf("Font:%s %d -> File:%s  (Size = %d)\n",
				Font_Name[Font_ID],Point_Size,File_Name,
				Font_Size);

			fontfile = fopen(File_Name,"w");
			if (!fontfile) {
				fprintf(stderr,"%s: Cannot open %s\n",
					argv[0],File_Name);
				exit(1);
			}

			fwrite( res+Res_Data_loc+4, Font_Size, 1, fontfile);
			fclose(fontfile);
		}
	}
}

void *PtoC(s1)
register unsigned char *s1;
{
	register unsigned char *s2;
	register int i;
	int len;
	unsigned char *s;

	len = *s1++;

	s = s2 = malloc(len + 1);
	if (!s2) {
		printf("Error, not enough memory to make C string\n");
		exit(-1);
	}

	for (i= len; --i>=0; ) *s2++ = *s1++;

	*s2 = 0;
	return(s);
}
