/* Copyright 1986, 1989, 1990 by Abacus Research and * Development, Inc. All rights reserved. */ #if !defined (OMIT_RCSID_STRINGS) char ROMlib_rcsid_resMod[] = "$Id: resMod.c 63 2004-12-24 18:19:43Z ctm $"; #endif /* Forward declarations in ResourceMgr.h (DO NOT DELETE THIS LINE) */ #include "rsys/common.h" #include "ResourceMgr.h" #include "FileMgr.h" #include "MemoryMgr.h" #include "ToolboxUtil.h" #include "rsys/resource.h" #include "rsys/glue.h" #include "rsys/mman.h" #include "rsys/file.h" P3(PUBLIC pascal trap, void, SetResInfo, Handle, res, INTEGER, id, StringPtr, name) { resmaphand map; typref *tr; resref *rr; char *sp; INTEGER sl; OSErr err; ROMlib_setreserr(ROMlib_findres(res, &map, &tr, &rr)); if (ResErr != noErr) return; if (rr->ratr & resProtected) { ROMlib_setreserr(resAttrErr); /* IV-18 */ return; } rr->rid = CW(id); if (name) { sl = U(name[0]); if (U(*(sp = (char *)STARH(map) + Hx(map, namoff) + Cx(rr->noff))) < sl || rr->noff == -1) { SetHandleSize((Handle) map, Hx(map, rh.maplen) + sl + 1); err = MemError(); if (ROMlib_setreserr(err)) return; rr->noff = CW(Hx(map, rh.maplen) - Hx(map, namoff)); HxX(map, rh.maplen) = CL(Hx(map, rh.maplen) + sl + 1); sp = (char *)STARH(map) + Hx(map, namoff) + Cx(rr->noff); warning_unimplemented ("we leak space here"); } str255assign(sp, name); } } P2(PUBLIC pascal trap, void, SetResAttrs, Handle, res, INTEGER, attrs) { resmaphand map; typref *tr; resref *rr; ROMlib_setreserr(ROMlib_findres(res, &map, &tr, &rr)); if (ResErr != noErr) return; rr->ratr = attrs; } P1(PUBLIC pascal trap, void, ChangedResource, Handle, res) { resmaphand map; typref *tr; resref *rr; Size oldsize, newsize; ROMlib_setreserr(ROMlib_findres(res, &map, &tr, &rr)); if (ResErr != noErr) return; if (rr->ratr & resProtected) { ROMlib_setreserr(resAttrErr); /* IV-18 */ return; } rr->ratr |= resChanged; HxX(map, resfatr) |= CWC(mapChanged); if (rr->doff[0] != 0xff || rr->doff[1] != 0xff || rr->doff[2] != 0xff) { oldsize = ROMlib_SizeResource(res, FALSE); newsize = GetHandleSize((Handle) MR(rr->rhand)); if (newsize > oldsize) { HxX(map, resfatr) |= CWC(mapCompact); rr->doff[0] = rr->doff[1] = rr->doff[2] = 0xff; } } } A2(PRIVATE, LONGINT, addtype, resmaphand, map, ResType, typ) { typref *tr, t; INTEGER i; LONGINT off; WALKTR(map, i, tr) if (tr->rtyp == CL(typ)) return((LONGINT)((char *)tr - (char *)STARH(map))); EWALKTR(tr) ROMlib_invalar(); t.rtyp = CL(typ); t.nres = CWC(-1); t.rloff = CW(NAMEOFF(map) - TYPEOFF(map)); off = (LONGINT)((char *)tr - (char *) STARH(map)); Munger((Handle) map, off, (Ptr) "", (LONGINT)0, (Ptr) &t, sizeof(t)); NUMTMINUS1X(map) = CW(NUMTMINUS1(map) + 1); MAPLENX(map) = CL(MAPLEN(map) + sizeof(t)); NAMEOFFX(map) = CW(NAMEOFF(map) + sizeof(t)); WALKTR(map, i, tr) tr->rloff = CW(CW(tr->rloff) + sizeof(t)); EWALKTR(tr) return(off); } A2(PRIVATE, LONGINT, addname, resmaphand, map, StringPtr, name) { LONGINT retval; if (!name || !name[0]) retval = -1; else { LONGINT namelen; namelen = U(name[0]) + 1; Munger((Handle) map, MAPLEN(map), (Ptr) "", (LONGINT)0, (Ptr) name, namelen); retval = MAPLEN(map) - NAMEOFF(map); MAPLENX(map) = CL(MAPLEN(map) + namelen); } return retval; } P4(PUBLIC pascal trap, void, AddResource, Handle, data, ResType, typ, INTEGER, id, StringPtr, name) { LONGINT toff, roff; typref *tr, *tr2; resref r, *rr; resmaphand map; INTEGER i, j; if (!data) { ROMlib_setreserr(addResFailed); return; } ROMlib_setreserr(noErr); map = ROMlib_rntohandl(Cx(CurMap), (Handle *)0); if (!map) { ROMlib_setreserr(resFNotFound); return; } if (ROMlib_findmapres(map, data, &tr, &rr) == noErr) { ROMlib_setreserr(addResFailed); /*-->*/ return; } ROMlib_setreserr(noErr); toff = addtype(map, typ); r.rid = CW(id); r.noff = CW(addname(map, name)); r.ratr = CB(resChanged); r.doff[0] = r.doff[1] = r.doff[2] = 0xff; HxX(map, resfatr) |= CWC(mapChanged); r.rhand = RM(data); HSetRBit (data); tr = (typref *)((char *)STARH(map) + toff); #if 1 WALKRR(map, tr, j, rr) if (Cx(rr->rid) > id) break; EWALKRR(rr) #else /* 0 */ rr = (resref *)((char *)STARH(map) + Hx(map, typoff) + Cx(tr->rloff)); #endif /* 0 */ roff = (LONGINT)((char *)rr - (char *) STARH(map)); /* roff is from the beginning of the map */ Munger((Handle) map, roff, (Ptr) "", (LONGINT) 0, (Ptr) &r, sizeof(resref)); roff -= TYPEOFF(map); /* roff is from the beginning of the typelist */ MAPLENX(map) = CL(MAPLEN(map) + sizeof(resref)); NAMEOFFX(map) = CW(NAMEOFF(map) + sizeof(resref)); tr2 = (typref *)((char *)STARH(map) + toff); tr2->nres = CW(CW(tr2->nres) + 1); WALKTR(map, i, tr) if (Cx(tr->rloff) >= roff && tr != tr2) /* if (Cx(tr->rloff) > roff) would probably work, but I'm chicken -- ctm */ tr->rloff = CW(CW(tr->rloff) + sizeof(resref)); EWALKTR(tr) } P1(PUBLIC pascal trap, void, RmveResource, Handle, res) { resmaphand map; typref *tr; resref *rr; LONGINT troff, rroff, nmoff, nlen; INTEGER i, j, tloss; #if !defined (LETGCCWAIL) nlen = 0; #endif /* LETGCCWAIL */ if (!res) { ROMlib_setreserr(rmvResFailed); /*-->*/ return; } map = ROMlib_rntohandl(Cx(CurMap), (Handle *)0); if (!map) { ROMlib_setreserr(resFNotFound); /*-->*/ return; } ROMlib_setreserr(ROMlib_findmapres(map, res, &tr, &rr)); if (ResErr != noErr) /*-->*/ return; if (rr->ratr & resProtected) { ROMlib_setreserr(rmvResFailed); /*-->*/ return; } HSetState(res, HGetState(res) & ~RSRCBIT); troff = (char *)tr - (char *) STARH(map); rroff = (char *)rr - (char *) STARH(map); if (rr->noff != -1) { nmoff = Cx(rr->noff) + NAMEOFF(map); nlen = U(*((char *)STARH(map) + nmoff)) + 1; Munger((Handle) map, nmoff, (Ptr)0, nlen, (Ptr) "", (LONGINT) 0); nmoff -= NAMEOFF(map); MAPLENX(map) = CL(MAPLEN(map) - nlen); } else nmoff = 0x7fff; HxX(map, resfatr) |= CWC(mapChanged|mapCompact); Munger((Handle) map, rroff, (Ptr)0, (LONGINT)sizeof(resref), (Ptr) "", (LONGINT) 0); rroff -= TYPEOFF(map); MAPLENX(map) = CL(MAPLEN(map) - sizeof(resref)); NAMEOFFX(map) = CW(NAMEOFF(map) - sizeof(resref)); tr = (typref *)((char *) STARH(map) + troff); tr->nres = CW(CW(tr->nres) - 1); if (tr->nres == -1) { ROMlib_invalar(); NUMTMINUS1X(map) = CW(NUMTMINUS1(map) - 1); Munger((Handle) map, troff, (Ptr)0, (LONGINT)sizeof(typref), (Ptr) "", (LONGINT) 0); tloss = sizeof(typref); MAPLENX(map) = CL(MAPLEN(map) - sizeof(typref)); NAMEOFFX(map) = CW(NAMEOFF(map) - sizeof(typref)); } else tloss = 0; WALKTR(map, i, tr) if (Cx(tr->rloff) > rroff) tr->rloff = CW(CW(tr->rloff) - sizeof(resref)); tr->rloff = CW(CW(tr->rloff) - tloss); WALKRR(map, tr, j, rr) if (Cx(rr->noff) > nmoff) rr->noff = CW(CW(rr->noff) - nlen); EWALKRR(rr) EWALKTR(tr) } /* writemap: given a map, writemap writes it out */ A1(PRIVATE, OSErr, writemap, resmaphand, map) { OSErr terr; LONGINT lc; terr = SetFPos(Hx(map, resfn), fsFromStart, 0L); if (terr != noErr) return(terr); lc = sizeof(reshead); terr = FSWriteAll(Hx(map, resfn), &lc, (Ptr) &(HxX(map, rh))); if (terr != noErr) return(terr); terr = SetFPos(Hx(map, resfn), fsFromStart, Hx(map, rh.rmapoff)); if (terr != noErr) return(terr); lc = Hx(map, rh.maplen); terr = FSWriteAll(Hx(map, resfn), &lc, (Ptr) STARH(map)); if (terr == noErr) HxX(map, resfatr) &= CWC(~(mapChanged)); return(terr); } /* ROMlib_wr: ROMlib_wr is the helper routine for WriteResource, the resource file associated with map is updated to include the resource pointed to by rr */ A2(PUBLIC, void, ROMlib_wr, resmaphand, map, resref *, rr) /* INTERNAL */ { LONGINT rsize, newloc, lc, swappedrsize; Handle res; res = (Handle) MR(rr->rhand); if ((rr->ratr & resChanged) && res) { rsize = GetHandleSize(res); if (rr->doff[0] == 0xFF && rr->doff[1] == 0xFF && rr->doff[2] == 0xFF) { newloc = Hx(map, rh.rmapoff) - Hx(map, rh.rdatoff); HxX(map, rh.rmapoff) = CL(Hx(map, rh.rmapoff) + rsize + sizeof(LONGINT)); HxX(map, rh.datlen) = CL(Hx(map, rh.datlen) + rsize + sizeof(LONGINT)); B3ASSIGN(rr->doff, newloc); } else newloc = B3TOLONG(rr->doff); ROMlib_setreserr(SetFPos(Hx(map, resfn), fsFromStart, Hx(map, rh.rdatoff) + newloc)); if (ResErr != noErr) return; lc = sizeof(LONGINT); swappedrsize = CL(rsize); ROMlib_setreserr(FSWriteAll(Hx(map, resfn), &lc, (Ptr) &swappedrsize)); if (ResErr != noErr) return; lc = rsize; ROMlib_setreserr(FSWriteAll(Hx(map, resfn), &lc, STARH(res))); if (ResErr != noErr) return; rr->ratr &= ~resChanged; } else ROMlib_setreserr(noErr); } typedef res_sorttype_t *sorttypeptr; typedef struct { sorttypeptr p PACKED_P; } HIDDEN_sorttypeptr; typedef HIDDEN_sorttypeptr *sorttypehand; A3(PRIVATE, void, fillst, sorttypehand, st, resref *, rp, resref *, rep) { res_sorttype_t *end = STARH(st), *sp; LONGINT newoff; end++->diskoff = -1; /* real disk offsets are always > 0 */ while (rp != rep) { newoff = B3TOLONG(rp->doff); #if 0 /* compiler botch if we leave the next line in */ gui_assert(newoff >= 0); #endif for (sp = end-1; newoff < sp->diskoff; sp--) ; sp++; BlockMove((Ptr) sp, (Ptr) (sp+1), (Size)(end - sp) * sizeof(res_sorttype_t)); sp->diskoff = newoff; sp->rrptr = rp; end++; rp++; } } A4(PRIVATE, void, getdat, INTEGER, fn, LONGINT, datoff, LONGINT, doff, Handle *, h) { LONGINT size, lc; gui_assert(datoff >= 0); gui_assert(doff >= 0); SetFPos(fn, fsFromStart, datoff + doff); lc = sizeof(LONGINT); FSReadAll(fn, &lc, (Ptr) &size); size = CL(size); gui_assert(size >= 0); *h = NewHandle(size); gui_assert(*h); HSetState(*h, RSRCBIT); lc = size; HLock(*h); FSReadAll(fn, &lc, STARH(*h)); gui_assert(lc == size); HUnlock(*h); } A4(PRIVATE, void, putdat, INTEGER, fn, LONGINT, datoff, LONGINT *, doffp, Handle, h) { LONGINT size = GetHandleSize(h), lc, swappedsize; gui_assert(size >= 0); gui_assert(datoff >= 0); gui_assert(*doffp >= 0); SetFPos(fn, fsFromStart, datoff + *doffp); lc = sizeof(LONGINT); swappedsize = CL(size); FSWriteAll(fn, &lc, (Ptr) &swappedsize); lc = size; HLock(h); FSWriteAll(fn, &lc, STARH(h)); HUnlock(h); *doffp += sizeof(LONGINT) + size; } A4(PRIVATE, LONGINT, walkst, res_sorttype_t *, sp, res_sorttype_t *, sep, INTEGER, fn, LONGINT, datoff) { LONGINT size; LONGINT doff; Handle h; LONGINT lc; doff = 0; while (sp != sep) { B3ASSIGN(sp->rrptr->doff, doff); #if 0 if (sp->rrptr->ratr & resChanged) { putdat(fn, datoff, &doff, (Handle) CL(sp->rrptr->rhand)); } else if (!sp->rrptr->rhand || !*(Handle)CL(sp->rrptr->rhand)) { getdat(fn, datoff, sp->diskoff, &h); putdat(fn, datoff, &doff, h); DisposHandle(h); } else if (doff != sp->diskoff) putdat(fn, datoff, &doff, (Handle) CL(sp->rrptr->rhand)); else doff += GetHandleSize((Handle) CL(sp->rrptr->rhand)) + sizeof(LONGINT); #else if (sp->rrptr->ratr & resChanged) { putdat(fn, datoff, &doff, (Handle) MR(sp->rrptr->rhand)); sp->rrptr->ratr &= ~resChanged; } else if (doff == sp->diskoff) { /* read and advance */ SetFPos(fn, fsFromStart, datoff + doff); lc = sizeof(LONGINT); FSReadAll(fn, &lc, (Ptr) &size); gui_assert(lc == sizeof(LONGINT)); size = CL(size); gui_assert(size >= 0); doff += size + sizeof(LONGINT); } else { getdat(fn, datoff, sp->diskoff, &h); putdat(fn, datoff, &doff, h); HSetState(h, HGetState(h) & ~RSRCBIT); DisposHandle(h); } #endif sp++; } return doff; } A1(PRIVATE, void, compactdata, resmaphand, map) { INTEGER nres; LONGINT resoff, datlen; sorttypehand st; resref *rr; INTEGER mapstate, ststate; resoff = TYPEOFF(map) + sizeof(INTEGER) + (NUMTMINUS1(map) + 1) * sizeof(typref); nres = (NAMEOFF(map) - resoff) / sizeof(resref); st = (sorttypehand) NewHandle((Size)sizeof(res_sorttype_t) * (nres + 1)); mapstate = HGetState((Handle) map); HLock((Handle) map); rr = (resref *)((char *) STARH(map) + resoff); fillst(st, rr, rr + nres); ststate = HGetState((Handle) st); HLock((Handle) st); datlen = walkst(STARH(st) + 1, STARH(st) + nres + 1, Hx(map, resfn), Hx(map, rh.rdatoff)); HSetState((Handle) st, ststate); HSetState((Handle) map, mapstate); HxX(map, resfatr) |= CWC(mapChanged); HxX(map, resfatr) &= CWC(~mapCompact); HxX(map, rh.rmapoff) = CL(sizeof(reshead) + sizeof(rsrvrec) + datlen); HxX(map, rh.datlen) = CL(datlen); DisposHandle((Handle) st); } P1(PUBLIC pascal trap, void, UpdateResFile, INTEGER, rn) { resmaphand map; INTEGER i, j; typref *tr; resref *rr; BOOLEAN needtowalk; fcbrec *fp; OSErr err; ioParam iopb; map = ROMlib_rntohandl(rn, (Handle *)0); if (!map) { ROMlib_setreserr(resFNotFound); return; } ROMlib_setreserr (noErr); /* * NOTE: This implementation looks more TRUE to what IMI-125 implies than * the one (above) it replaces. */ fp = PRNTOFPERR(Hx(map, resfn), &err); if (err == noErr && (fp->fcflags & fcwriteperm)) { needtowalk = TRUE; if (HxX(map, resfatr) & (CWC (mapCompact))) { compactdata(map); needtowalk = FALSE; } if (HxX(map, resfatr) & (CWC (mapChanged))) { if (needtowalk) { WALKTANDR(map, i, tr, j, rr) ROMlib_wr(map, rr); if (ResErr != noErr) return; EWALKTANDR(tr, rr) } ROMlib_setreserr(writemap(map)); if (ResErr != noErr) return; } iopb.ioRefNum = HxX(map, resfn); PBFlushFile((ParmBlkPtr) &iopb, FALSE); } } P1(PUBLIC pascal trap, void, WriteResource, Handle, res) { resmaphand map; typref *tr; resref *rr; ROMlib_setreserr(ROMlib_findres(res, &map, &tr, &rr)); if (ResErr != noErr) return; ROMlib_wr(map, rr); } P1(PUBLIC pascal trap, void, SetResPurge, BOOLEAN, install) { /* NOP */ ROMlib_setreserr (noErr); }