mirror of https://git.wuffs.org/MWCC
1672 lines
41 KiB
C
1672 lines
41 KiB
C
#include "mwcc_decomp.h"
|
|
|
|
#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0)
|
|
|
|
// Fork Attributes
|
|
enum {
|
|
mapReadOnly = 0x80,
|
|
mapCompact = 0x40,
|
|
mapChanged = 0x20
|
|
};
|
|
|
|
// Resources
|
|
enum {
|
|
resSysHeap = 0x40,
|
|
resPurgeable = 0x20,
|
|
resLocked = 0x10,
|
|
resProtected = 8,
|
|
resPreload = 4,
|
|
resChanged = 2
|
|
};
|
|
|
|
#ifdef __MWERKS__
|
|
#pragma options align=mac68k
|
|
#endif
|
|
typedef struct {
|
|
char sysdata[66];
|
|
char type[4];
|
|
char creator[4];
|
|
char sysdata2[38];
|
|
char appdata[128];
|
|
} MemRsrcSysData; // assumed name
|
|
|
|
typedef struct { // Resource Header
|
|
UInt32 data_offs;
|
|
UInt32 map_offs;
|
|
UInt32 data_len;
|
|
UInt32 map_len;
|
|
} Ty70;
|
|
typedef struct { // Resource Map
|
|
Ty70 mem_hdr;
|
|
Handle mem_next_map_handle; // fixme for 64-bit probably
|
|
SInt16 mem_refnum;
|
|
UInt16 fork_attr;
|
|
UInt16 typelist_offs;
|
|
UInt16 namelist_offs;
|
|
UInt16 types_idx;
|
|
} Ty73;
|
|
typedef struct { // Resource Type List Item
|
|
OSType type;
|
|
UInt16 rsrc_idx;
|
|
UInt16 ref_list_offs;
|
|
} Ty75;
|
|
typedef struct { // Reference List Item
|
|
UInt16 id;
|
|
UInt16 name_offs;
|
|
unsigned char attr;
|
|
unsigned char data_offs[3];
|
|
Handle mem_rsrc_handle;
|
|
} Ty77;
|
|
typedef struct { // Name List Item
|
|
unsigned char len;
|
|
} Ty80;
|
|
typedef struct { // Resource
|
|
UInt32 len;
|
|
} Ty82;
|
|
#ifdef __MWERKS__
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
typedef struct MemRefList {
|
|
UInt16 id;
|
|
OSType type;
|
|
StringPtr name;
|
|
unsigned char attr;
|
|
Handle hand;
|
|
struct MemRefList *next;
|
|
} MemRefList;
|
|
|
|
typedef struct MemRsrcTypeList {
|
|
OSType type;
|
|
MemRefList *ref_list;
|
|
struct MemRsrcTypeList *next;
|
|
} MemRsrcTypeList;
|
|
|
|
typedef struct MemRsrcMap {
|
|
SInt16 refnum;
|
|
UInt16 fork_attr;
|
|
MemRsrcTypeList *type_list;
|
|
MemRsrcSysData sys_data;
|
|
struct MemRsrcMap *prev;
|
|
} MemRsrcMap;
|
|
|
|
typedef struct ResRef {
|
|
OSSpec spec;
|
|
int ref;
|
|
struct ResRef *next;
|
|
} ResRef;
|
|
|
|
static OSErr resError;
|
|
static SInt16 cur_res_file;
|
|
Boolean ResLoad;
|
|
static MemRsrcMap *maplist;
|
|
static ResRef *resForkList;
|
|
static ResRef *resForkLast;
|
|
static Boolean UseResourceForkInfo;
|
|
|
|
// Forward declarations
|
|
static void ReadResourceFork(SInt16 ref, SInt8 permission, void *file_data, SInt32 file_size);
|
|
|
|
Boolean OS_UsingMacResourceForkInfo() {
|
|
return UseResourceForkInfo;
|
|
}
|
|
|
|
void OS_UseMacResourceForkInfo(Boolean which) {
|
|
UseResourceForkInfo = which;
|
|
}
|
|
|
|
OSErr SystemInitResources(OSSpec *spec) {
|
|
FSSpec prog;
|
|
void *file_data;
|
|
SInt32 file_len;
|
|
|
|
maplist = 0;
|
|
cur_res_file = 0;
|
|
|
|
if (!OS_LoadMacResourceFork(spec, &file_data, &file_len)) {
|
|
ReadResourceFork(-1, 1, file_data, file_len);
|
|
cur_res_file = -1;
|
|
resError = noErr;
|
|
return noErr;
|
|
} else {
|
|
if (!OS_OSSpec_To_FSSpec(spec, &prog) && !FSpOpenResFile(&prog, 1)) {
|
|
resError = noErr;
|
|
return noErr;
|
|
} else {
|
|
resError = fnfErr;
|
|
return fnfErr;
|
|
}
|
|
}
|
|
}
|
|
|
|
static MemRsrcMap *NewResourceMap(SInt16 ref, UInt16 attr, MemRsrcTypeList *list, void *unk) {
|
|
MemRsrcMap **scan;
|
|
MemRsrcMap *nw;
|
|
|
|
scan = &maplist;
|
|
nw = malloc(sizeof(MemRsrcMap));
|
|
|
|
if (!nw) {
|
|
resError = memFullErr;
|
|
return 0;
|
|
}
|
|
|
|
nw->refnum = ref;
|
|
nw->fork_attr = attr;
|
|
nw->type_list = list;
|
|
nw->prev = *scan;
|
|
*scan = nw;
|
|
return nw;
|
|
}
|
|
|
|
static MemRsrcTypeList *NewTypeListEntry(MemRsrcTypeList **scan, OSType type, MemRefList *list, MemRsrcTypeList *next) {
|
|
MemRsrcTypeList *nw;
|
|
|
|
while (*scan)
|
|
scan = &(*scan)->next;
|
|
|
|
nw = malloc(sizeof(MemRsrcTypeList));
|
|
if (!nw) {
|
|
resError = memFullErr;
|
|
return 0;
|
|
}
|
|
|
|
nw->type = type;
|
|
nw->ref_list = list;
|
|
nw->next = next;
|
|
*scan = nw;
|
|
return nw;
|
|
}
|
|
|
|
static MemRefList *NewRefListEntry(MemRefList **scan, UInt16 id, OSType type, StringPtr name, unsigned char attr, Handle hand) {
|
|
MemRefList *prev;
|
|
MemRefList *nw;
|
|
char mname[256];
|
|
|
|
prev = 0;
|
|
if (name)
|
|
p2cstrcpy(mname, name);
|
|
else
|
|
strcpy(mname, "(none)");
|
|
|
|
while (*scan && (*scan)->id != id) {
|
|
prev = *scan;
|
|
scan = &(*scan)->next;
|
|
}
|
|
|
|
nw = malloc(sizeof(MemRefList));
|
|
if (!nw) {
|
|
resError = memFullErr;
|
|
return 0;
|
|
}
|
|
|
|
nw->id = id;
|
|
nw->type = type;
|
|
nw->name = name;
|
|
nw->attr = attr;
|
|
nw->hand = hand;
|
|
if (prev) {
|
|
nw->next = prev->next;
|
|
prev->next = nw;
|
|
} else {
|
|
nw->next = 0;
|
|
}
|
|
*scan = nw;
|
|
return nw;
|
|
}
|
|
|
|
static MemRsrcMap *FindResourceMap(SInt16 ref) {
|
|
MemRsrcMap *list = maplist;
|
|
|
|
while (list) {
|
|
if (list->refnum == ref)
|
|
return list;
|
|
list = list->prev;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRsrcMap *FindResourceMap2(SInt16 ref, MemRsrcMap **next) {
|
|
MemRsrcMap *list = maplist;
|
|
|
|
*next = 0;
|
|
while (list) {
|
|
if (list->refnum == ref)
|
|
return list;
|
|
*next = list;
|
|
list = list->prev;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void DeleteResources(SInt16 refNum) {
|
|
MemRsrcMap *rm, *rmnext;
|
|
MemRsrcTypeList *mtyptmp, *mtyp;
|
|
MemRefList *mrletmp, *mrle;
|
|
|
|
rm = FindResourceMap2(refNum, &rmnext);
|
|
if (rm) {
|
|
mtyp = rm->type_list;
|
|
while (mtyp) {
|
|
mrle = mtyp->ref_list;
|
|
while (mrle) {
|
|
if (mrle->hand)
|
|
DisposeHandle(mrle->hand);
|
|
if (mrle->name)
|
|
free(mrle->name);
|
|
mrletmp = mrle;
|
|
mrle = mrle->next;
|
|
free(mrletmp);
|
|
}
|
|
mtyptmp = mtyp;
|
|
mtyp = mtyp->next;
|
|
free(mtyptmp);
|
|
}
|
|
|
|
if (rmnext)
|
|
rmnext->prev = rm->prev;
|
|
else
|
|
maplist = rm->prev;
|
|
free(rm);
|
|
}
|
|
}
|
|
|
|
#define RF_READ(buf, offset, count, failBranch) \
|
|
do { \
|
|
SInt32 __offs = (offset); \
|
|
if (!file_data) { \
|
|
if ((resError = SetFPos(ref, fsFromStart, __offs)) != noErr) goto failBranch; \
|
|
if ((resError = FSRead(ref, (SInt32 *) &(count), buf)) != noErr) goto failBranch; \
|
|
} else { \
|
|
if ((__offs + (count)) > file_size) goto failBranch; \
|
|
memcpy(buf, ((unsigned char *) file_data) + __offs, (count)); \
|
|
} \
|
|
} while(0)
|
|
|
|
static void ReadResourceFork(SInt16 ref, SInt8 permission, void *file_data, SInt32 file_size) {
|
|
MemRsrcMap *rm;
|
|
Ty70 thdr;
|
|
Ty70 *dhdr;
|
|
MemRsrcSysData tsys;
|
|
MemRsrcSysData *dsys;
|
|
Ty73 *dmap;
|
|
Ty75 *dtyp;
|
|
Ty77 *drle;
|
|
Ty80 *dnam;
|
|
void *buffer;
|
|
SInt32 msize;
|
|
SInt32 cnt;
|
|
SInt32 ref_offs;
|
|
int rcnt;
|
|
MemRsrcTypeList *mtyp;
|
|
Ty82 tent;
|
|
SInt32 esize;
|
|
SInt32 offs;
|
|
Handle hand;
|
|
unsigned char *name;
|
|
unsigned char *nameptr;
|
|
|
|
if (!file_data) {
|
|
if ((resError = GetEOF(ref, &file_size)) != noErr)
|
|
goto mapFail;
|
|
}
|
|
|
|
if (file_size < 90)
|
|
goto mapFail;
|
|
|
|
cnt = sizeof(Ty70);
|
|
RF_READ(&thdr, 0, cnt, mapFail);
|
|
|
|
ref_offs = cnt;
|
|
cnt = ((thdr.map_offs < thdr.data_offs) ? thdr.map_offs : thdr.data_offs) - sizeof(Ty70);
|
|
if (cnt > sizeof(MemRsrcSysData))
|
|
cnt = sizeof(MemRsrcSysData);
|
|
RF_READ(&tsys, ref_offs, cnt, mapFail);
|
|
|
|
msize = thdr.map_len;
|
|
buffer = malloc(msize);
|
|
if (!buffer)
|
|
goto memFail;
|
|
|
|
ref_offs = thdr.map_offs;
|
|
RF_READ(buffer, ref_offs, msize, mapFail);
|
|
|
|
if (
|
|
(thdr.map_offs > file_size)
|
|
|| ((thdr.map_offs + thdr.map_len) > file_size)
|
|
|| (thdr.data_offs > file_size)
|
|
|| ((thdr.data_offs + thdr.data_len) > file_size)
|
|
|| ((thdr.map_offs < thdr.data_offs) ? ((thdr.map_offs + thdr.map_len) != thdr.data_offs) : ((thdr.data_offs + thdr.data_len) != thdr.map_offs))
|
|
)
|
|
goto mapFail;
|
|
|
|
rm = NewResourceMap(ref, ((permission == 1) ? mapReadOnly : 0) | mapCompact, 0, 0);
|
|
if (!rm)
|
|
goto memFail;
|
|
|
|
rm->sys_data = tsys;
|
|
|
|
dmap = (Ty73 *) buffer;
|
|
if ((dmap->typelist_offs + thdr.map_offs) > file_size)
|
|
goto freeAndMapFail;
|
|
dtyp = (Ty75 *) (((unsigned char *) buffer) + dmap->typelist_offs + 2);
|
|
if ((dmap->namelist_offs + thdr.map_offs) > file_size)
|
|
goto freeAndMapFail;
|
|
dnam = (Ty80 *) (((unsigned char *) buffer) + dmap->namelist_offs);
|
|
if (dmap->types_idx != 0xFFFF) {
|
|
for (cnt = 0; cnt <= dmap->types_idx; cnt++) {
|
|
mtyp = NewTypeListEntry(&rm->type_list, dtyp[cnt].type, 0, 0);
|
|
if (!mtyp)
|
|
goto freeAndReturn;
|
|
|
|
if ((thdr.map_offs + dmap->typelist_offs + dtyp[cnt].ref_list_offs) > file_size)
|
|
goto freeAndMapFail;
|
|
|
|
drle = (Ty77 *) (((unsigned char *) dtyp) + dtyp[cnt].ref_list_offs - 2);
|
|
if (dtyp[cnt].rsrc_idx != 0xFFFF) {
|
|
for (rcnt = 0; rcnt <= dtyp[cnt].rsrc_idx; rcnt++) {
|
|
ref_offs = (drle[rcnt].data_offs[0] << 16) | (drle[rcnt].data_offs[1] << 8) | drle[rcnt].data_offs[2];
|
|
offs = thdr.data_offs + ref_offs;
|
|
if (offs > file_size)
|
|
goto freeAndMapFail;
|
|
esize = 4;
|
|
RF_READ(&tent, offs, esize, freeAndMapFail);
|
|
|
|
offs += esize;
|
|
if ((thdr.data_offs + ref_offs + tent.len) > file_size)
|
|
goto freeAndMapFail;
|
|
|
|
hand = NewHandle(tent.len);
|
|
if (!hand)
|
|
goto freeAndMapFail;
|
|
|
|
HLock(hand);
|
|
RF_READ(*hand, offs, tent.len, freeAndMapFail);
|
|
HUnlock(hand);
|
|
|
|
if (drle[rcnt].name_offs != 0xFFFF) {
|
|
nameptr = (StringPtr) (dnam + drle[rcnt].name_offs);
|
|
name = malloc(nameptr[0] + 1);
|
|
memcpy(name, nameptr, nameptr[0] + 1);
|
|
} else {
|
|
name = 0;
|
|
}
|
|
|
|
if (!NewRefListEntry(&mtyp->ref_list, drle[rcnt].id, dtyp[cnt].type, name, drle[rcnt].attr, hand))
|
|
goto freeAndReturn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(buffer);
|
|
resError = noErr;
|
|
return;
|
|
freeAndMapFail:
|
|
resError = mapReadErr;
|
|
freeAndReturn:
|
|
DeleteResources(ref);
|
|
if (buffer)
|
|
free(buffer);
|
|
return;
|
|
memFail:
|
|
resError = memFullErr;
|
|
return;
|
|
mapFail:
|
|
resError = mapReadErr;
|
|
}
|
|
|
|
static void GetResourceSizes(MemRsrcMap *rm, SInt32 *data_size, SInt32 *name_size, SInt32 *reflist_size, SInt32 *typelist_size) {
|
|
MemRsrcTypeList *mtyp;
|
|
MemRefList *mrle;
|
|
|
|
*data_size = *name_size = *reflist_size = *typelist_size = 0;
|
|
|
|
mtyp = rm->type_list;
|
|
while (mtyp) {
|
|
mrle = mtyp->ref_list;
|
|
while (mrle) {
|
|
*name_size += !mrle->name ? 0 : (mrle->name[0] + 1);
|
|
*data_size += (!mrle->hand ? 0 : GetHandleSize(mrle->hand)) + 4;
|
|
*reflist_size += 12;
|
|
mrle = mrle->next;
|
|
}
|
|
*typelist_size += 8;
|
|
mtyp = mtyp->next;
|
|
}
|
|
}
|
|
|
|
static SInt32 GetResourceTypesCount(MemRsrcMap *dm) {
|
|
SInt32 tmp;
|
|
MemRsrcTypeList *mtyp;
|
|
|
|
tmp = 0;
|
|
mtyp = dm->type_list;
|
|
while (mtyp) {
|
|
mtyp = mtyp->next;
|
|
++tmp;
|
|
}
|
|
|
|
return tmp;
|
|
}
|
|
|
|
static SInt32 GetResourceEntriesCount(MemRsrcTypeList *mtyp) {
|
|
SInt32 tmp;
|
|
MemRefList *mrle;
|
|
|
|
tmp = 0;
|
|
mrle = mtyp->ref_list;
|
|
while (mrle) {
|
|
mrle = mrle->next;
|
|
++tmp;
|
|
}
|
|
|
|
return tmp;
|
|
}
|
|
|
|
#define RF_HANDLE_INSERT(hand, what, offset, size) \
|
|
do { \
|
|
SInt32 __offs = (offset); \
|
|
SInt32 __len = (size); \
|
|
if ((SInt32) (__offs + __len) > GetHandleSize(hand)) { \
|
|
resError = mapReadErr; \
|
|
return; \
|
|
} else { \
|
|
memcpy(*hand + __offs, (what), __len); \
|
|
} \
|
|
} \
|
|
while (0)
|
|
|
|
static void WriteResourceFork(SInt16 ref) {
|
|
MemRsrcMap *rm;
|
|
Ty70 dhdr;
|
|
Ty70 thdr;
|
|
MemRsrcSysData tsys;
|
|
Ty73 dmap;
|
|
Ty73 tmap;
|
|
Handle hand_ref;
|
|
SInt32 reflist_size, typelist_size;
|
|
SInt32 name_size, data_size;
|
|
SInt32 reflist_offs, typelist_offs;
|
|
SInt32 name_offs, data_offs;
|
|
MemRsrcTypeList *mtyp;
|
|
Ty75 dtyp;
|
|
Ty75 ttyp;
|
|
MemRefList *mrle;
|
|
Ty77 drle;
|
|
Ty77 trle;
|
|
Ty82 dent;
|
|
Ty82 tent;
|
|
SInt32 sz;
|
|
|
|
rm = FindResourceMap(ref);
|
|
if (!rm) {
|
|
resError = resFNotFound;
|
|
return;
|
|
}
|
|
|
|
if (rm->refnum == -1) {
|
|
resError = resFNotFound;
|
|
return;
|
|
}
|
|
|
|
if (rm->fork_attr & mapReadOnly) {
|
|
resError = resAttrErr;
|
|
return;
|
|
}
|
|
|
|
if (!(rm->fork_attr & mapChanged)) {
|
|
return;
|
|
}
|
|
|
|
GetResourceSizes(rm, &data_size, &name_size, &reflist_size, &typelist_size);
|
|
dhdr.data_offs = sizeof(dhdr) + sizeof(tsys);
|
|
dhdr.data_len = data_size;
|
|
dhdr.map_offs = sizeof(dhdr) + sizeof(tsys) + data_size;
|
|
dhdr.map_len = name_size + reflist_size + typelist_size + sizeof(dmap);
|
|
|
|
hand_ref = NewHandle(dhdr.map_offs + dhdr.map_len);
|
|
if (!hand_ref) {
|
|
resError = MemError();
|
|
return;
|
|
}
|
|
|
|
HLock(hand_ref);
|
|
memset(*hand_ref, 0, dhdr.map_offs + dhdr.map_len);
|
|
thdr = dhdr;
|
|
// This is where it would be endian-swapped i guess
|
|
RF_HANDLE_INSERT(hand_ref, &thdr, 0, sizeof(thdr));
|
|
|
|
tsys = rm->sys_data;
|
|
RF_HANDLE_INSERT(hand_ref, &tsys, sizeof(thdr), sizeof(tsys));
|
|
|
|
dmap.mem_hdr = thdr;
|
|
dmap.mem_next_map_handle = 0;
|
|
dmap.mem_refnum = 0;
|
|
dmap.fork_attr = rm->fork_attr & ~resChanged; // bug! should be mapChanged
|
|
dmap.typelist_offs = sizeof(dmap) - 2;
|
|
dmap.namelist_offs = typelist_size + reflist_size + sizeof(dmap);
|
|
dmap.types_idx = GetResourceTypesCount(rm) - 1;
|
|
tmap = dmap;
|
|
RF_HANDLE_INSERT(hand_ref, &tmap, dhdr.map_offs, sizeof(tmap));
|
|
|
|
// Now write the actual shit
|
|
name_offs = 0;
|
|
data_offs = 0;
|
|
reflist_offs = 0;
|
|
typelist_offs = 0;
|
|
mtyp = rm->type_list;
|
|
while (mtyp) {
|
|
dtyp.type = mtyp->type;
|
|
dtyp.rsrc_idx = GetResourceEntriesCount(mtyp) - 1;
|
|
dtyp.ref_list_offs = typelist_size + reflist_offs + 2;
|
|
ttyp = dtyp;
|
|
RF_HANDLE_INSERT(hand_ref, &ttyp, (dhdr.map_offs + dmap.typelist_offs + 2) + typelist_offs, sizeof(ttyp));
|
|
|
|
mrle = mtyp->ref_list;
|
|
while (mrle) {
|
|
#line 943
|
|
OPTION_ASSERT(reflist_offs < dmap.namelist_offs);
|
|
|
|
drle.id = mrle->id;
|
|
drle.name_offs = (mrle->name) ? name_offs : -1;
|
|
drle.attr = mrle->attr & ~resChanged;
|
|
drle.data_offs[0] = (data_offs & 0xFF0000) >> 16;
|
|
drle.data_offs[1] = (data_offs & 0x00FF00) >> 8;
|
|
drle.data_offs[2] = (data_offs & 0x0000FF);
|
|
drle.mem_rsrc_handle = 0;
|
|
trle = drle;
|
|
RF_HANDLE_INSERT(hand_ref, &trle, (dhdr.map_offs + dmap.typelist_offs + 2) + typelist_size + reflist_offs, sizeof(trle));
|
|
|
|
reflist_offs += sizeof(trle);
|
|
if (mrle->name) {
|
|
#line 962
|
|
if (dhdr.map_offs < dhdr.data_offs)
|
|
OPTION_ASSERT(name_offs + dmap.namelist_offs + dhdr.map_offs < dhdr.data_offs);
|
|
RF_HANDLE_INSERT(hand_ref, mrle->name, dhdr.map_offs + dmap.namelist_offs + drle.name_offs, mrle->name[0] + 1);
|
|
name_offs += mrle->name[0] + 1;
|
|
}
|
|
|
|
#line 970
|
|
OPTION_ASSERT(data_offs < dhdr.data_len);
|
|
OPTION_ASSERT(mrle->hand!=NULL);
|
|
if (dhdr.map_offs > dhdr.data_offs)
|
|
OPTION_ASSERT(data_offs + dhdr.data_offs < dhdr.map_offs);
|
|
|
|
HLock(mrle->hand);
|
|
dent.len = GetHandleSize(mrle->hand);
|
|
tent = dent;
|
|
RF_HANDLE_INSERT(hand_ref, &tent, dhdr.data_offs + data_offs, sizeof(tent));
|
|
data_offs += sizeof(tent);
|
|
RF_HANDLE_INSERT(hand_ref, *mrle->hand, dhdr.data_offs + data_offs, dent.len);
|
|
data_offs += dent.len;
|
|
HUnlock(mrle->hand);
|
|
|
|
mrle = mrle->next;
|
|
}
|
|
|
|
mtyp = mtyp->next;
|
|
typelist_offs += sizeof(ttyp);
|
|
}
|
|
|
|
sz = GetHandleSize(hand_ref);
|
|
if ((resError = SetFPos(ref, fsFromStart, 0)) != noErr)
|
|
return;
|
|
if ((resError = SetEOF(ref, sz)) != noErr)
|
|
return;
|
|
if ((resError = FSWrite(ref, &sz, *hand_ref)) != noErr)
|
|
return;
|
|
HUnlock(hand_ref);
|
|
DisposeHandle(hand_ref);
|
|
}
|
|
|
|
static void WriteEmptyResourceFork(SInt16 ref) {
|
|
Ty70 dhdr;
|
|
MemRsrcSysData dsys;
|
|
Ty73 dmap;
|
|
Handle hand_ref;
|
|
SInt32 sz;
|
|
|
|
dhdr.map_offs = sizeof(dhdr) + sizeof(dsys);
|
|
dhdr.map_len = sizeof(dmap);
|
|
dhdr.data_offs = sizeof(dhdr) + sizeof(dsys) + sizeof(dmap);
|
|
dhdr.data_len = 0;
|
|
|
|
memset(&dsys, 0, sizeof(dsys));
|
|
memset(&dsys.creator, 0, sizeof(dsys.creator));
|
|
memset(&dsys.type, 0, sizeof(dsys.type));
|
|
|
|
dmap.mem_hdr = dhdr;
|
|
dmap.mem_next_map_handle = 0;
|
|
dmap.mem_refnum = 0;
|
|
dmap.fork_attr = 0;
|
|
dmap.typelist_offs = sizeof(dmap) - 2;
|
|
dmap.namelist_offs = sizeof(dmap) - 2;
|
|
dmap.types_idx = 0xFFFF;
|
|
|
|
hand_ref = NewHandle(sizeof(dhdr) + sizeof(dsys) + sizeof(dmap));
|
|
if (!hand_ref) {
|
|
resError = MemError();
|
|
return;
|
|
}
|
|
|
|
HLock(hand_ref);
|
|
memset(*hand_ref, 0, sizeof(dhdr) + sizeof(dsys) + sizeof(dmap));
|
|
RF_HANDLE_INSERT(hand_ref, &dhdr, 0, sizeof(dhdr));
|
|
RF_HANDLE_INSERT(hand_ref, &dsys, sizeof(dhdr), sizeof(dsys));
|
|
RF_HANDLE_INSERT(hand_ref, &dmap, sizeof(dhdr) + sizeof(dsys), sizeof(dmap));
|
|
|
|
sz = GetHandleSize(hand_ref);
|
|
if ((resError = SetFPos(ref, fsFromStart, 0)) != noErr)
|
|
return;
|
|
if ((resError = SetEOF(ref, sz)) != noErr)
|
|
return;
|
|
if ((resError = FSWrite(ref, &sz, *hand_ref)) != noErr)
|
|
return;
|
|
HUnlock(hand_ref);
|
|
DisposeHandle(hand_ref);
|
|
}
|
|
|
|
static MemRsrcTypeList *FindResourceType1(MemRsrcMap *rm, OSType theType) {
|
|
MemRsrcTypeList *mtyp;
|
|
|
|
mtyp = rm->type_list;
|
|
while (mtyp) {
|
|
if (mtyp->type == theType)
|
|
return mtyp;
|
|
mtyp = mtyp->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static SInt32 CountResourceType1(MemRsrcMap *rm, OSType theType) {
|
|
MemRsrcTypeList *mtyp;
|
|
|
|
mtyp = rm->type_list;
|
|
while (mtyp) {
|
|
if (mtyp->type == theType)
|
|
return GetResourceEntriesCount(mtyp);
|
|
mtyp = mtyp->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static SInt32 CountResourceType(OSType theType) {
|
|
MemRsrcMap *rm;
|
|
SInt32 total;
|
|
|
|
total = 0;
|
|
rm = FindResourceMap(cur_res_file);
|
|
|
|
while (rm) {
|
|
total += CountResourceType1(rm, theType);
|
|
rm = rm->prev;
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
static MemRefList *FindIndResource1(MemRsrcMap *rm, OSType theType, SInt16 index) {
|
|
MemRsrcTypeList *mtyp;
|
|
MemRefList *mrle;
|
|
|
|
mtyp = rm->type_list;
|
|
while (mtyp) {
|
|
if (mtyp->type == theType) {
|
|
mrle = mtyp->ref_list;
|
|
while (mrle && --index > 0) {
|
|
mrle = mrle->next;
|
|
}
|
|
return mrle;
|
|
}
|
|
mtyp = mtyp->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRefList *FindIndResource(OSType theType, SInt16 index) {
|
|
MemRsrcMap *rm = FindResourceMap(cur_res_file);
|
|
MemRefList *mrle;
|
|
|
|
while (rm) {
|
|
mrle = FindIndResource1(rm, theType, index);
|
|
if (mrle)
|
|
return mrle;
|
|
rm = rm->prev;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRefList *FindResourceTypeAndID1(MemRsrcMap *rm, OSType theType, SInt16 theID) {
|
|
MemRsrcTypeList *mtyp = FindResourceType1(rm, theType);
|
|
MemRefList *mref;
|
|
|
|
if (mtyp) {
|
|
mref = mtyp->ref_list;
|
|
while (mref) {
|
|
if (mref->id == theID)
|
|
return mref;
|
|
mref = mref->next;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRefList *FindResourceTypeAndID(OSType theType, SInt16 theID) {
|
|
MemRsrcMap *rm = FindResourceMap(cur_res_file);
|
|
MemRefList *mref;
|
|
|
|
while (rm) {
|
|
mref = FindResourceTypeAndID1(rm, theType, theID);
|
|
if (mref)
|
|
return mref;
|
|
rm = rm->prev;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRefList *FindResourceTypeAndName1(MemRsrcMap *rm, OSType theType, ConstStringPtr theName) {
|
|
MemRsrcTypeList *mtyp;
|
|
MemRefList *mref;
|
|
|
|
mtyp = FindResourceType1(rm, theType);
|
|
if (mtyp) {
|
|
mref = mtyp->ref_list;
|
|
while (mref) {
|
|
if (mref->name && EqualString(mref->name, theName, 0, 0))
|
|
return mref;
|
|
mref = mref->next;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRefList *FindResourceTypeAndName(OSType theType, ConstStringPtr theName) {
|
|
MemRsrcMap *rm = FindResourceMap(cur_res_file);
|
|
MemRefList *mref;
|
|
|
|
while (rm) {
|
|
mref = FindResourceTypeAndName1(rm, theType, theName);
|
|
if (mref)
|
|
return mref;
|
|
rm = rm->prev;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRefList *FindResourceHandle1(MemRsrcMap *rm, Handle theResource) {
|
|
MemRsrcTypeList *mtyp;
|
|
MemRefList *mrle;
|
|
|
|
for (mtyp = rm->type_list; mtyp; mtyp = mtyp->next) {
|
|
for (mrle = mtyp->ref_list; mrle; mrle = mrle->next) {
|
|
if (mrle->hand == theResource)
|
|
return mrle;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static MemRefList *FindResourceHandle(Handle theResource) {
|
|
MemRsrcMap *rm;
|
|
MemRefList *mrle;
|
|
|
|
for (rm = FindResourceMap(cur_res_file); rm; rm = rm->prev) {
|
|
mrle = FindResourceHandle1(rm, theResource);
|
|
if (mrle)
|
|
return mrle;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int RemoveResourceHandle1(MemRsrcMap *rm, Handle theResource) {
|
|
MemRsrcTypeList *mtyp, *pmtyp;
|
|
MemRefList *mrle, *pmrle;
|
|
|
|
mtyp = rm->type_list;
|
|
pmtyp = 0;
|
|
while (mtyp) {
|
|
mrle = mtyp->ref_list;
|
|
pmrle = 0;
|
|
while (mrle) {
|
|
if (mrle->hand == theResource) {
|
|
if (pmrle)
|
|
pmrle->next = mrle->next;
|
|
else
|
|
mtyp->ref_list = mrle->next;
|
|
free(mrle);
|
|
|
|
if (!mtyp->ref_list) {
|
|
if (pmtyp)
|
|
pmtyp->next = mtyp->next;
|
|
else
|
|
rm->type_list = mtyp->next;
|
|
free(mtyp);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
pmrle = mrle;
|
|
mrle = mrle->next;
|
|
}
|
|
pmtyp = mtyp;
|
|
mtyp = mtyp->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int RemoveResourceHandle(Handle theResource) {
|
|
MemRsrcMap *rm;
|
|
|
|
for (rm = FindResourceMap(cur_res_file); rm; rm = rm->prev) {
|
|
if (RemoveResourceHandle1(rm, theResource))
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static SInt16 FindResourceHandleFile1(MemRsrcMap *rm, Handle theResource) {
|
|
MemRsrcTypeList *mtyp;
|
|
MemRefList *mrle;
|
|
|
|
for (mtyp = rm->type_list; mtyp; mtyp = mtyp->next) {
|
|
for (mrle = mtyp->ref_list; mrle; mrle = mrle->next) {
|
|
if (mrle->hand == theResource)
|
|
return rm->refnum;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static SInt16 FindResourceHandleFile(Handle theResource) {
|
|
MemRsrcMap *rm;
|
|
MemRefList *mrle;
|
|
|
|
for (rm = FindResourceMap(cur_res_file); rm; rm = rm->prev) {
|
|
mrle = FindResourceHandle1(rm, theResource);
|
|
if (mrle)
|
|
return rm->refnum;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void OS_AddMacResourceForkRef(int ref, const OSSpec *spec) {
|
|
ResRef *nw;
|
|
|
|
nw = malloc(sizeof(ResRef));
|
|
if (nw) {
|
|
nw->spec = *spec;
|
|
nw->ref = ref;
|
|
nw->next = 0;
|
|
if (resForkLast)
|
|
resForkLast->next = nw;
|
|
else
|
|
resForkList = nw;
|
|
resForkLast = nw;
|
|
}
|
|
}
|
|
|
|
void OS_RemoveMacResourceForkRef(int ref) {
|
|
ResRef *lst;
|
|
ResRef *prev;
|
|
|
|
lst = resForkList;
|
|
prev = 0;
|
|
while (lst && lst->ref != ref) {
|
|
prev = lst;
|
|
lst = lst->next;
|
|
}
|
|
|
|
if (lst) {
|
|
if (prev) {
|
|
prev->next = lst->next;
|
|
if (!prev->next)
|
|
resForkLast = prev;
|
|
} else {
|
|
resForkList = lst->next;
|
|
if (!resForkList)
|
|
resForkLast = 0;
|
|
}
|
|
free(lst);
|
|
}
|
|
}
|
|
|
|
OSSpec *OS_GetMacResourceForkFromRef(int ref) {
|
|
ResRef *lst;
|
|
|
|
for (lst = resForkList; lst; lst = lst->next) {
|
|
if (lst->ref == ref)
|
|
return &lst->spec;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
Boolean OS_SearchMacResourceForkList(const OSSpec *rspec, int *ref) {
|
|
ResRef *lst;
|
|
|
|
for (lst = resForkList; lst; lst = lst->next) {
|
|
if (OS_EqualSpec(&lst->spec, rspec)) {
|
|
*ref = lst->ref;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int OS_SetMacResourceForkCreatorAndType(int ref, OSType creator, OSType type) {
|
|
int err;
|
|
UInt32 buf[2];
|
|
UInt32 sz;
|
|
MemRsrcMap *rm;
|
|
|
|
if (!OS_GetMacResourceForkFromRef(ref)) {
|
|
sz = 8;
|
|
buf[0] = type;
|
|
buf[1] = creator;
|
|
err = OS_Seek(ref, OSSeekAbs, 0x52);
|
|
if (!err) {
|
|
err = OS_Write(ref, buf, &sz);
|
|
if (!err && sz == 8) {
|
|
err = 0;
|
|
}
|
|
}
|
|
} else {
|
|
rm = FindResourceMap(OS_RefToMac(ref));
|
|
if (!rm) {
|
|
err = 2;
|
|
} else if (rm->fork_attr & mapReadOnly) {
|
|
err = 13;
|
|
} else {
|
|
rm->sys_data.creator[0] = (creator & 0xFF000000) >> 24;
|
|
rm->sys_data.creator[1] = (creator & 0x00FF0000) >> 16;
|
|
rm->sys_data.creator[2] = (creator & 0x0000FF00) >> 8;
|
|
rm->sys_data.creator[3] = (creator & 0x000000FF);
|
|
rm->sys_data.type[0] = (type & 0xFF000000) >> 24;
|
|
rm->sys_data.type[1] = (type & 0x00FF0000) >> 16;
|
|
rm->sys_data.type[2] = (type & 0x0000FF00) >> 8;
|
|
rm->sys_data.type[3] = (type & 0x000000FF);
|
|
rm->fork_attr |= mapChanged;
|
|
err = 0;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int OS_GetMacResourceForkCreatorAndType(int ref, OSType *creator, OSType *type) {
|
|
int err;
|
|
UInt32 buf[2];
|
|
UInt32 sz;
|
|
MemRsrcMap *rm;
|
|
|
|
if (!OS_GetMacResourceForkFromRef(ref)) {
|
|
sz = 8;
|
|
err = OS_Seek(ref, OSSeekAbs, 0x52);
|
|
if (!err) {
|
|
err = OS_Read(ref, buf, &sz);
|
|
if (!err && sz == 8) {
|
|
err = 0;
|
|
*type = buf[0];
|
|
*creator = buf[1];
|
|
}
|
|
}
|
|
} else {
|
|
rm = FindResourceMap(OS_RefToMac(ref));
|
|
if (!rm) {
|
|
err = 2;
|
|
} else {
|
|
*creator = (rm->sys_data.creator[0] << 24) | (rm->sys_data.creator[1] << 16) | (rm->sys_data.creator[2] << 8) | rm->sys_data.creator[3];
|
|
*type = (rm->sys_data.type[0] << 24) | (rm->sys_data.type[1] << 16) | (rm->sys_data.type[2] << 8) | rm->sys_data.type[3];
|
|
err = 0;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
void OS_CleanupMacResourceForkDir(const OSPathSpec *dir) {
|
|
OS_Rmdir(dir);
|
|
}
|
|
|
|
OSErr OS_MacDumpResourceFork(SInt16 ref, Boolean dumpContents) {
|
|
MemRsrcMap *rm;
|
|
MemRsrcTypeList *tl;
|
|
MemRefList *rl;
|
|
char name[256];
|
|
unsigned char *ptr;
|
|
SInt32 idx;
|
|
SInt32 size;
|
|
char safe[16];
|
|
int spaces;
|
|
|
|
rm = FindResourceMap(ref);
|
|
if (!rm) {
|
|
fprintf(stderr, "Could not find resource fork for ref = %d\n", ref);
|
|
return fnfErr;
|
|
}
|
|
|
|
printf("Fork attributes = %04X\n", rm->fork_attr);
|
|
printf("Creator = '%4.4s'; Type = '%4.4s'\n", rm->sys_data.creator, rm->sys_data.type);
|
|
printf("Types:\n");
|
|
|
|
for (tl = rm->type_list; tl; tl = tl->next) {
|
|
printf("'%c%c%c%c':\n",
|
|
(tl->type & 0xFF000000) >> 24,
|
|
(tl->type & 0x00FF0000) >> 16,
|
|
(tl->type & 0x0000FF00) >> 8,
|
|
(tl->type & 0x000000FF)
|
|
);
|
|
for (rl = tl->ref_list; rl; rl = rl->next) {
|
|
if (rl->type != tl->type)
|
|
printf("!!! RefList type '%c%c%c%c' does not match TypeList type !!!\n",
|
|
(rl->type & 0xFF000000) >> 24,
|
|
(rl->type & 0x00FF0000) >> 16,
|
|
(rl->type & 0x0000FF00) >> 8,
|
|
(rl->type & 0x000000FF)
|
|
);
|
|
|
|
if (rl->name)
|
|
p2cstrcpy(name, rl->name);
|
|
else
|
|
strcpy(name, "<none>");
|
|
|
|
printf("\tID = %d '%s'\n", rl->id, name);
|
|
printf("\tAttributes: ");
|
|
if (rl->attr & resSysHeap)
|
|
printf("SysHeap ");
|
|
if (rl->attr & resPurgeable)
|
|
printf("Purgeable ");
|
|
if (rl->attr & resLocked)
|
|
printf("Locked ");
|
|
if (rl->attr & resProtected)
|
|
printf("Protected ");
|
|
if (rl->attr & resPreload)
|
|
printf("Preload ");
|
|
if (rl->attr & resChanged)
|
|
printf("Changed ");
|
|
printf("\n");
|
|
|
|
if (dumpContents) {
|
|
size = GetHandleSize(rl->hand);
|
|
HLock(rl->hand);
|
|
ptr = (unsigned char *) *rl->hand;
|
|
idx = 0;
|
|
printf("Contents:");
|
|
|
|
while (idx < size) {
|
|
if ((idx % 16) == 0) {
|
|
printf("\n%08X: ", idx);
|
|
memset(safe, ' ', 16);
|
|
}
|
|
printf("%02X ", ptr[idx]);
|
|
if (isprint(ptr[idx]))
|
|
safe[idx & 15] = ptr[idx];
|
|
else
|
|
safe[idx & 15] = '.';
|
|
|
|
if (((idx % 16) == 15) || (idx + 1) == size) {
|
|
spaces = (((idx & 15) + 15) & ~15) - (idx & 15);
|
|
while (spaces--)
|
|
printf(" ");
|
|
printf(" %16.16s", safe);
|
|
}
|
|
|
|
++idx;
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("\n");
|
|
CloseResFile(ref);
|
|
return noErr;
|
|
}
|
|
|
|
OSErr FSpOpenRF(const FSSpec *fss, SInt8 permission, SInt16 *refNum) {
|
|
OSErr err;
|
|
int oserr;
|
|
FSSpec rfss;
|
|
OSSpec spec, rspec;
|
|
Boolean create;
|
|
|
|
create = (permission != fsRdPerm);
|
|
oserr = OS_FSSpec_To_OSSpec(fss, &spec);
|
|
if (oserr)
|
|
return OS_MacError(oserr);
|
|
|
|
oserr = OS_GetRsrcOSSpec(&spec, &rspec, create);
|
|
if (oserr)
|
|
return OS_MacError(oserr);
|
|
|
|
oserr = OS_OSSpec_To_FSSpec(&rspec, &rfss);
|
|
if (oserr)
|
|
return OS_MacError(oserr);
|
|
|
|
if (OS_Status(&rspec) && create)
|
|
HCreate(rfss.vRefNum, rfss.parID, rfss.name, 'CWIE', 'rsrc');
|
|
|
|
err = HOpen(rfss.vRefNum, rfss.parID, rfss.name, permission, refNum);
|
|
if (!err)
|
|
OS_AddMacResourceForkRef(OS_MacToRef(*refNum), &rspec);
|
|
|
|
return err;
|
|
}
|
|
|
|
OSErr HOpenRF(SInt16 vRefNum, SInt32 dirID, ConstStringPtr fileName, SInt8 permission, SInt16 *refNum) {
|
|
FSSpec fss;
|
|
OSErr __err;
|
|
|
|
__err = FSMakeFSSpec(vRefNum, dirID, fileName, &fss);
|
|
if (__err != noErr && __err != fnfErr) {
|
|
return __err;
|
|
} else {
|
|
return FSpOpenRF(&fss, permission, refNum);
|
|
}
|
|
}
|
|
|
|
OSErr InitResources() {
|
|
MemRsrcMap *map;
|
|
|
|
map = maplist;
|
|
cur_res_file = 0;
|
|
while (map) {
|
|
cur_res_file = map->refnum;
|
|
map = map->prev;
|
|
}
|
|
|
|
ResLoad = 1;
|
|
resError = noErr;
|
|
return 0;
|
|
}
|
|
|
|
OSErr ResError() {
|
|
return resError;
|
|
}
|
|
|
|
void FSpCreateResFile(const FSSpec *fss, OSType creator, OSType fileType, ScriptCode scriptTag) {
|
|
int oserr;
|
|
OSSpec spec, rspec;
|
|
SInt16 ref;
|
|
|
|
FSpCreate(fss, creator, fileType, scriptTag);
|
|
oserr = OS_FSSpec_To_OSSpec(fss, &spec);
|
|
if (oserr) {
|
|
resError = OS_MacError(oserr);
|
|
return;
|
|
}
|
|
|
|
oserr = OS_GetRsrcOSSpec(&spec, &rspec, 1);
|
|
if (oserr) {
|
|
resError = OS_MacError(oserr);
|
|
return;
|
|
}
|
|
|
|
if (OS_Status(&rspec)) {
|
|
oserr = OS_Create(&rspec, &OS_TEXTTYPE);
|
|
if (oserr) {
|
|
resError = OS_MacError(oserr);
|
|
return;
|
|
}
|
|
|
|
resError = FSpOpenRF(fss, 3, &ref);
|
|
if (!resError) {
|
|
WriteEmptyResourceFork(ref);
|
|
FSClose(ref);
|
|
}
|
|
} else {
|
|
resError = dupFNErr;
|
|
}
|
|
|
|
}
|
|
|
|
void HCreateResFile(SInt16 vRefNum, SInt32 dirID, ConstStringPtr fileName) {
|
|
FSSpec fss;
|
|
OSErr __err;
|
|
|
|
__err = FSMakeFSSpec(vRefNum, dirID, fileName, &fss);
|
|
if (__err != noErr && __err != fnfErr) {
|
|
resError = __err;
|
|
} else {
|
|
FSpCreateResFile(&fss, 'CWIE', kUnknownType, -1);
|
|
}
|
|
}
|
|
|
|
OSErr FSpOpenResFile(const FSSpec *fss, SInt8 permission) {
|
|
SInt16 ref;
|
|
SInt32 size;
|
|
|
|
if (permission != fsRdPerm)
|
|
FSpCreate(fss, 'CWIE', 'TEXT', -1);
|
|
|
|
resError = FSpOpenRF(fss, (permission == fsWrPerm) ? fsRdWrPerm : permission, &ref);
|
|
if (!resError) {
|
|
GetEOF(ref, &size);
|
|
if (size == 0 && permission != fsRdPerm)
|
|
WriteEmptyResourceFork(ref);
|
|
ReadResourceFork(ref, permission, 0, 0);
|
|
if (resError) {
|
|
FSClose(ref);
|
|
CloseResFile(ref);
|
|
ref = -1;
|
|
}
|
|
cur_res_file = ref;
|
|
} else {
|
|
ref = -1;
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
OSErr HOpenResFile(SInt16 vRefNum, SInt32 dirID, ConstStringPtr fileName, SInt8 permission) {
|
|
FSSpec fss;
|
|
OSErr __err;
|
|
|
|
__err = FSMakeFSSpec(vRefNum, dirID, fileName, &fss);
|
|
if (__err != noErr && __err != fnfErr)
|
|
return __err;
|
|
return FSpOpenResFile(&fss, permission);
|
|
}
|
|
|
|
SInt16 CurResFile() {
|
|
return cur_res_file;
|
|
}
|
|
|
|
void UseResFile(SInt16 refNum) {
|
|
MemRsrcMap *map;
|
|
|
|
for (map = maplist; map; map = map->prev) {
|
|
if (map->refnum == refNum) {
|
|
cur_res_file = refNum;
|
|
resError = noErr;
|
|
return;
|
|
}
|
|
}
|
|
|
|
resError = resFNotFound;
|
|
}
|
|
|
|
SInt16 HomeResFile(Handle theResource) {
|
|
SInt16 refnum = FindResourceHandleFile(theResource);
|
|
resError = (refnum == -1) ? resNotFound : 0;
|
|
return refnum;
|
|
}
|
|
|
|
Handle GetResource(OSType theType, SInt16 theID) {
|
|
MemRefList *mref;
|
|
|
|
mref = FindResourceTypeAndID(theType, theID);
|
|
if (mref) {
|
|
resError = noErr;
|
|
return mref->hand;
|
|
} else {
|
|
resError = ResLoad ? resNotFound : noErr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Handle Get1Resource(OSType theType, SInt16 theID) {
|
|
MemRsrcMap *rm;
|
|
MemRefList *mref;
|
|
|
|
rm = FindResourceMap(cur_res_file);
|
|
if (!rm) {
|
|
resError = resFNotFound;
|
|
return 0;
|
|
}
|
|
|
|
mref = FindResourceTypeAndID1(rm, theType, theID);
|
|
if (mref) {
|
|
resError = noErr;
|
|
return mref->hand;
|
|
} else {
|
|
resError = ResLoad ? resNotFound : noErr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Handle GetNamedResource(OSType theType, ConstStringPtr theName) {
|
|
MemRefList *mref;
|
|
|
|
mref = FindResourceTypeAndName(theType, theName);
|
|
if (mref) {
|
|
resError = noErr;
|
|
return mref->hand;
|
|
} else {
|
|
resError = ResLoad ? resNotFound : noErr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Handle Get1NamedResource(OSType theType, ConstStringPtr theName) {
|
|
MemRsrcMap *rm;
|
|
MemRefList *mref;
|
|
|
|
rm = FindResourceMap(cur_res_file);
|
|
if (!rm) {
|
|
resError = resFNotFound;
|
|
return 0;
|
|
}
|
|
|
|
mref = FindResourceTypeAndName1(rm, theType, theName);
|
|
if (mref) {
|
|
resError = noErr;
|
|
return mref->hand;
|
|
} else {
|
|
resError = (ResLoad != 0) ? resNotFound : noErr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void SetResLoad(Boolean load) {
|
|
ResLoad = load;
|
|
}
|
|
|
|
void MacEmul_LoadResource(Handle theResource) {
|
|
resError = (theResource == 0) ? nilHandleErr : 0;
|
|
}
|
|
|
|
void GetResInfo(Handle theResource, SInt16 *theID, OSType *theType, StringPtr name) {
|
|
MemRefList *mrle;
|
|
|
|
mrle = FindResourceHandle(theResource);
|
|
if (mrle) {
|
|
resError = noErr;
|
|
*theID = mrle->id;
|
|
*theType = mrle->type;
|
|
if (mrle->name)
|
|
_pstrcpy(name, mrle->name);
|
|
else
|
|
name[0] = 0;
|
|
} else {
|
|
resError = resNotFound;
|
|
}
|
|
}
|
|
|
|
void SetResInfo(Handle theResource, SInt16 theID, ConstStringPtr name) {
|
|
MemRefList *mrle;
|
|
|
|
mrle = FindResourceHandle(theResource);
|
|
if (mrle) {
|
|
resError = noErr;
|
|
if (mrle->name)
|
|
free(mrle->name);
|
|
mrle->name = malloc(name[0] + 1);
|
|
mrle->attr |= resChanged;
|
|
if (mrle->name)
|
|
_pstrcpy(mrle->name, name);
|
|
else
|
|
resError = memFullErr;
|
|
} else {
|
|
resError = resNotFound;
|
|
}
|
|
}
|
|
|
|
SInt16 GetResAttrs(Handle theResource) {
|
|
MemRefList *mrle;
|
|
|
|
mrle = FindResourceHandle(theResource);
|
|
if (mrle) {
|
|
resError = noErr;
|
|
return mrle->attr;
|
|
} else {
|
|
resError = resNotFound;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void SetResAttrs(Handle theResource, SInt16 attrs) {
|
|
MemRefList *mrle;
|
|
|
|
mrle = FindResourceHandle(theResource);
|
|
if (mrle) {
|
|
resError = noErr;
|
|
mrle->attr = attrs;
|
|
} else {
|
|
resError = resNotFound;
|
|
}
|
|
}
|
|
|
|
void ChangedResource(Handle theResource) {
|
|
MemRsrcMap *rm;
|
|
MemRefList *mrle;
|
|
|
|
rm = FindResourceMap(cur_res_file);
|
|
mrle = FindResourceHandle(theResource);
|
|
if (mrle) {
|
|
if (rm && (rm->fork_attr & mapReadOnly)) {
|
|
resError = resAttrErr;
|
|
} else {
|
|
resError = noErr;
|
|
mrle->attr |= resChanged;
|
|
rm->fork_attr |= mapChanged;
|
|
}
|
|
} else {
|
|
resError = resNotFound;
|
|
}
|
|
}
|
|
|
|
void AddResource(Handle theData, OSType theType, SInt16 theID, ConstStringPtr name) {
|
|
MemRsrcMap *rm;
|
|
MemRsrcTypeList *mtyp;
|
|
MemRefList *mrle;
|
|
StringPtr namecpy;
|
|
|
|
rm = FindResourceMap(cur_res_file);
|
|
if (rm) {
|
|
if (rm->fork_attr & mapReadOnly) {
|
|
resError = resAttrErr;
|
|
return;
|
|
}
|
|
|
|
resError = noErr;
|
|
mtyp = FindResourceType1(rm, theType);
|
|
if (!mtyp) {
|
|
mtyp = NewTypeListEntry(&rm->type_list, theType, 0, 0);
|
|
if (!mtyp) {
|
|
resError = memFullErr;
|
|
return;
|
|
}
|
|
rm->fork_attr |= mapChanged;
|
|
}
|
|
if (!theData || FindResourceHandle(theData)) {
|
|
resError = addResFailed;
|
|
return;
|
|
}
|
|
|
|
if (name && name[0]) {
|
|
namecpy = malloc(name[0] + 1);
|
|
_pstrcpy(namecpy, name);
|
|
} else {
|
|
namecpy = 0;
|
|
}
|
|
|
|
mrle = NewRefListEntry(&mtyp->ref_list, theID, theType, namecpy, 2, theData);
|
|
if (!mrle) {
|
|
resError = memFullErr;
|
|
return;
|
|
}
|
|
|
|
rm->fork_attr |= mapChanged;
|
|
} else {
|
|
resError = resFNotFound;
|
|
}
|
|
}
|
|
|
|
void UpdateResFile(SInt16 refnum) {
|
|
WriteResourceFork(refnum);
|
|
}
|
|
|
|
void WriteResource(Handle theResource) {
|
|
resError = noErr;
|
|
}
|
|
|
|
void SetResPurge(Boolean install) {
|
|
}
|
|
|
|
SInt16 CountResources(OSType theType) {
|
|
return CountResourceType(theType);
|
|
}
|
|
|
|
SInt16 Count1Resources(OSType theType) {
|
|
MemRsrcMap *rm;
|
|
|
|
rm = FindResourceMap(cur_res_file);
|
|
if (rm) {
|
|
resError = noErr;
|
|
return CountResourceType1(rm, theType);
|
|
} else {
|
|
resError = resFNotFound;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Handle GetIndResource(OSType theType, SInt16 index) {
|
|
MemRefList *mrle;
|
|
|
|
mrle = FindIndResource(theType, index);
|
|
resError = mrle ? 0 : resNotFound;
|
|
return mrle->hand;
|
|
}
|
|
|
|
Handle Get1IndResource(OSType theType, SInt16 index) {
|
|
MemRsrcMap *rm;
|
|
MemRefList *mrle;
|
|
|
|
rm = FindResourceMap(cur_res_file);
|
|
if (rm) {
|
|
mrle = FindIndResource1(rm, theType, index);
|
|
if (mrle) {
|
|
resError = noErr;
|
|
return mrle->hand;
|
|
} else {
|
|
resError = resNotFound;
|
|
return 0;
|
|
}
|
|
} else {
|
|
resError = resFNotFound;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
SInt16 Count1Types() {
|
|
MemRsrcMap *rm;
|
|
MemRsrcTypeList *rtl;
|
|
SInt16 count;
|
|
|
|
count = 0;
|
|
rm = FindResourceMap(cur_res_file);
|
|
if (rm) {
|
|
rtl = rm->type_list;
|
|
while (rtl) {
|
|
rtl = rtl->next;
|
|
++count;
|
|
}
|
|
} else {
|
|
resError = resFNotFound;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
void Get1IndType(OSType *theType, SInt16 index) {
|
|
MemRsrcMap *rm;
|
|
MemRsrcTypeList *rtl;
|
|
SInt16 count;
|
|
|
|
count = 1;
|
|
rm = FindResourceMap(cur_res_file);
|
|
if (rm) {
|
|
rtl = rm->type_list;
|
|
while (rtl && count < index) {
|
|
rtl = rtl->next;
|
|
++count;
|
|
}
|
|
if (rtl)
|
|
*theType = rtl->type;
|
|
else
|
|
resError = inputOutOfBounds;
|
|
} else {
|
|
resError = resFNotFound;
|
|
}
|
|
}
|
|
|
|
void ReleaseResource(Handle theResource) {
|
|
resError = noErr;
|
|
}
|
|
|
|
void DetachResource(Handle theResource) {
|
|
MemRefList *mrle;
|
|
SInt32 ns;
|
|
|
|
mrle = FindResourceHandle(theResource);
|
|
if (mrle) {
|
|
ns = GetHandleSize(theResource);
|
|
mrle->hand = NewHandle(ns);
|
|
if (!mrle->hand) {
|
|
resError = memFullErr;
|
|
} else {
|
|
HLock(mrle->hand);
|
|
HLock(theResource);
|
|
memcpy(*mrle->hand, *theResource, ns);
|
|
HUnlock(theResource);
|
|
HUnlock(mrle->hand);
|
|
resError = noErr;
|
|
}
|
|
} else {
|
|
resError = resNotFound;
|
|
}
|
|
}
|
|
|
|
void RemoveResource(Handle theResource) {
|
|
resError = RemoveResourceHandle(theResource) ? 0 : rmvResFailed;
|
|
}
|
|
|
|
void CloseResFile(SInt16 refNum) {
|
|
MemRsrcMap *rm = FindResourceMap(refNum);
|
|
|
|
if (rm && refNum != -1) {
|
|
WriteResourceFork(refNum);
|
|
DeleteResources(refNum);
|
|
FSClose(refNum);
|
|
}
|
|
|
|
cur_res_file = maplist ? maplist->refnum : 0;
|
|
}
|
|
|
|
SInt16 GetResFileAttrs(SInt16) {
|
|
MemRsrcMap *rm = FindResourceMap(cur_res_file);
|
|
|
|
if (rm) {
|
|
resError = 0;
|
|
return rm->fork_attr;
|
|
} else {
|
|
resError = resFNotFound;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Boolean LMGetResLoad() {
|
|
return 1;
|
|
}
|