/*
 * 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);
}
