Listing 2: Mac-to-Windows conversion routines

// MACRES.CPP by Jeff Heaton(jeffheaton@aol.com)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "macres.h"

#define GET_LONG(x,y) (MAC_LONG(x[y],x[y+1],x[y+2],x[y+3]))

MAC_RESOURCE::MAC_RESOURCE()
{
    buffer=NULL;
    length=0;
}

MAC_RESOURCE::~MAC_RESOURCE()
{
    length=0;
    if(buffer!=NULL)
        delete buffer;
}

// Setup - Used to read in 'len' bytes from 'fp'
// into this resource.
void MAC_RESOURCE::Setup(FILE *fp,long len)
{
    if(buffer!=NULL)
        delete buffer;
    length=len;
    buffer=new unsigned char[len+2];
    fread(buffer,1,len,fp);
}

MAC_RESOURCE_FILE::MAC_RESOURCE_FILE()
{
    fp=NULL;
    nextTypeLoc=nextResLoc=-1;
}

// Open - Will open 'fn' and read in all
// general info.
void MAC_RESOURCE_FILE::Open(char *fn)
{
    if( (fp=fopen(fn,"rb"))==NULL) {
        printf("%s can't open %s.\n");
        exit(1);
    }

// Read MACBINARY Header
    fread(buffer,1,128,fp);
    if( buffer[0] ||  buffer[74] || buffer[82] ) {
        printf("Error: Not a valid MACBINARY file.\n");
        exit(1);
    }

    resourceLocation=128+GET_LONG(buffer,83);
    if(resourceLocation%128)
        resourceLocation=((resourceLocation/128)+1)*128;

// Read Resource fork header
    fseek(fp,resourceLocation,SEEK_SET); // Move to resource fork
    fread(buffer,4,4,fp);
    offsetResourceData=GET_LONG(buffer,0);
    offsetResourceMap=GET_LONG(buffer,4);
    lengthResourceData=GET_LONG(buffer,8);
    lengthResourceMap=GET_LONG(buffer,12);

// Read in the first resource map entry
    fseek(fp,resourceLocation+offsetResourceMap,SEEK_SET);
    fread(buffer,1,30,fp);
    numTypes=MAC_WORD(buffer[28],buffer[29])+1;
    locationTypeList=resourceLocation+offsetResourceMap+28;
}

void MAC_RESOURCE_FILE::Close(void)
{
    if(fp!=NULL)
        fclose(fp);
    fp=NULL;
}

// GetFirstType - Used to get the name of the 
// first type of resource in this file.
void MAC_RESOURCE_FILE::GetFirstType(char *name)
{
    if(fp==NULL)
        return;
    nextTypeLoc=locationTypeList+2;
    GetNextType(name);
}

// GetNextType - Used in a loop after GetFirstType
// to each additional resource type in the file.
void MAC_RESOURCE_FILE::GetNextType(char *name)
{
    if(fp==NULL)
        return;
    fseek(fp,nextTypeLoc,0);
    fread(buffer,8,1,fp);
    memcpy(name,buffer,4);
    name[4]=0;
    nextTypeLoc=ftell(fp);
}

// GetFirstType - Used to get the resource id of the 
// first resource of the current type in the file.
void MAC_RESOURCE_FILE::GetFirstResource(short *res)
{
    if(fp==NULL)
        return;
    fseek(fp,nextTypeLoc-8,0);
    fread(buffer,8,1,fp);

    numThis=MAC_WORD(buffer[4],buffer[5]);
    numThis++;
    offsetReffList=MAC_WORD(buffer[6],buffer[7]);
    nextResLoc=(unsigned long)offsetReffList
        +(unsigned long)locationTypeList;
    GetNextResource(res);
}

// GetNextType - Used in a loop after GetFirstResource
// to get each additional resource id of this type
void MAC_RESOURCE_FILE::GetNextResource(short *res)
{
    if(fp==NULL)
        return;
    fseek(fp,nextResLoc,0);
    fread(buffer,12,1,fp);
    *res=MAC_WORD(buffer[0],buffer[1]);
    resourceData=MAC_TRI(buffer[5],buffer[6],buffer[7]);
    resourceData+=offsetResourceData+resourceLocation;
    nextResLoc=ftell(fp);
}

// LoadResource - Will load the Mac resource of 'type' and
// 'id' from the file.
MAC_RESOURCE *MAC_RESOURCE_FILE::LoadResource(char *type,short id)
{
    char n[80];
    MAC_RESOURCE *rtn;
    short x,y,s,hold3;
    long resourceSize,hold1,hold2;

    if(fp==NULL)
        return NULL;

    hold1=nextTypeLoc;
    hold2=nextResLoc;
    hold3=numThis;

// Loop through and then find that resource
// first lookup the type, and then find the id.

    GetFirstType(n);
    for(x=0;x<=GetNumTypes();x++) {
        if(!memcmp(type,n,4)) {
            GetFirstResource(&s);
            for(y=0;y<GetNumResources();y++) {
                if(id==s) {
                fseek(fp,resourceData,SEEK_SET);
                fread(buffer,4,1,fp);
                resourceSize=GET_LONG(buffer,0);
                rtn=new MAC_RESOURCE;
                rtn->Setup(fp,resourceSize);
                nextTypeLoc=hold1;
                nextResLoc=hold2;
                numThis=hold3;
                return rtn;
                }
                GetNextResource(&s);
            }    
        
        }
        GetNextType(n);
    }
    nextTypeLoc=hold1;
    nextResLoc=hold2;
    numThis=hold3;
    return NULL;
}

//End of File