home *** CD-ROM | disk | FTP | other *** search
- enum
- {
- DRVR_MIN = 12,
- DRVR_MAX = 31,
- FONT_MIN = 0,
- FONT_MAX = 255,
- NFNT_MIN = 0,
- NFNT_MAX = 32767,
- FOND_MIN = 0,
- FOND_MAX = 32767,
- };
-
- #define CHARS_NEEDED(n) (((n)+31)/32*4)
-
- typedef struct
- {
- ResType type;
- LONGINT max;
- LONGINT free;
- uchar bitmap[CHARS_NEEDED(DRVR_MAX)];
- } drvr_map_t;
-
- typedef struct
- {
- ResType type;
- LONGINT max;
- LONGINT free;
- uchar bitmap[CHARS_NEEDED(FONT_MAX)];
- } font_map_t;
-
- typedef struct
- {
- ResType type;
- LONGINT max;
- LONGINT free;
- uchar bitmap[CHARS_NEEDED(NFNT_MAX)];
- } nfnt_map_t;
-
- typedef struct
- {
- ResType type;
- LONGINT max;
- LONGINT free;
- uchar bitmap[CHARS_NEEDED(FOND_MAX)];
- } fond_map_t;
-
- typedef struct
- {
- ResType type;
- LONGINT max;
- LONGINT free;
- uchar bitmap[0];
- } generic_map_t;
-
- typedef struct
- {
- drvr_map_t drvr_map;
- font_map_t font_map;
- nfnt_map_t nfnt_map;
- fond_map_t fond_map;
- ResType sentinel;
- } in_use_t, *in_use_ptr, **in_use_hand;
-
- /* Locks the handle h and returns a pointer to the first generic_map_t
- contained in h. */
-
- generic_map_t *
- first_map (in_use_hand h)
- {
- generic_map_t *retval;
-
- HLock (h);
- retval = (generic_map_t *) *h;
- return retval->type ? retval : 0;
- }
-
- /* Returns the next generic_map_t that follows mapp. If there there is none,
- 0 is returned and h is unlocked. */
-
- generic_map_t *
- next_map (in_use_hand h, generic_map_t *mapp)
- {
- generic_map_t *retval;
-
- retval = (generic_map_t *)
- ((char *) mapp + sizeof(generic_map_t) + CHARS_NEEDED(mapp->max));
-
- if (!retval->type)
- {
- HUnlock(h);
- retval = 0;
- }
- return retval;
- }
-
- /* Exactly the same as CountTypes, except only the resource file with the
- refnum of rn is consulted. */
-
- INTEGER
- CountTypesRN (INTEGER rn)
- {
- INTEGER savern, retval;
-
- savern = CurResFile ();
- UseResFile (rn);
- retval = Count1Types ();
- UseResFile (savern);
- return retval;
- }
-
- /* Exactly the same as CountResources, except only the resource file with the
- refnum rn is consulted. */
-
- INTEGER
- CountResourcesRN (INTEGER rn, ResType type)
- {
- INTEGER savern, retval;
-
- savern = CurResFile ();
- UseResFile (rn);
- retval = Count1Resources (type);
- UseResFile (savern);
- return retval;
- }
-
- /* Calls PBGetFCBInfo to fill what fcbrp points to with the appropriate values
- for rn. The return value is whatever PBGetFCBInfo returns. */
-
- OSErr
- getfcbinfo (INTEGER rn, FCBPBRec *fcbrp)
- {
- fcbrp->ioCompletion = 0;
- fcbrp->ioVRefNum = 0;
- fcbrp->ioRefNum = rn;
- fcbrp->ioFCBIndx = 0;
-
- retval = PBGetFCBInfo (fcbrp, false);
- return retval;
- }
-
- enum { writableFlag = 1 };
-
- /* Returns noErr if rn is a writable file,
- otherwise returns appropriate error. */
-
- OSErr
- is_writable (INTEGER rn)
- {
- OSErr retval;
- FCBPBRec fcbr;
-
- retval = getfcbinfo (rn, &fcbr);
- if (retval == noErr)
- retval = fcbr.ioFCBFlags & writableFlag ? noErr : fLckdErr;
- return retval;
- }
-
- /* Returns the number of 512 byte blocks free on the volume that contains
- the file with refnum rn. An error results in 0 free blocks reported. */
-
- ULONGINT
- room_on_volume_with_file (INTEGER rn)
- {
- OSErr err;
- FCBPBRec fcbr;
- ULONGINT retval;
-
- err = getfcbinfo (rn, &fcbr);
- if (err != noErr)
- retval = 0;
- else
- {
- VCB *vcbp;
-
- vcbp = fcbr.fcbVPtr;
- retval = vcbp->vcbFreeBks * vcbp->vcbAlBlkSiz / 512;
- }
- return retval;
- }
-
- /* Returns the number of 512 byte blocks taken up by the file with refnum
- rn. An error results in (LONGINT) -1L being returned. */
-
- ULONGINT
- file_length (INTEGER rn)
- {
- OSErr err;
- FCBPBRec fcbr;
- ULONGINT retval;
-
- err = getfcbinfo (rn, &fcbr);
- if (err != noErr)
- retval = (ULONGINT) -1L;
- else
- retval = fcbr.fcbPLen / 512;
- return retval;
- }
-
- /* Exactly like GetResource, except limited to the file specified by rn. */
-
- Handle
- GetResourceRN (INTEGER rn, ResType type, INTEGER id)
- {
- INTEGER savern;
- Handle retval;
-
- savern = CurResFile ();
- UseResFile (rn);
- retval = Get1Resource (type, id);
- UseResFile (savern);
- return retval;
- }
-
- /* Exactly the same as AddResource, except its action is limited to the file
- with the refnum rn. */
-
- void
- AddResourceRN (INTEGER rn, Handle h, ResType type, INTEGER id, Str255 name)
- {
- INTEGER savern;
-
- savern = CurResFile ();
- UseResFile (rn);
- AddResource (h, type, id, name);
- UseResFile (savern);
- }
-
- /* Exactly the same as GetIndType, except its action is limited to the file
- with the refnum rn. */
-
- void
- GetIndTypeRN (INTEGER rn, ResType *typep, INTEGER type_num)
- {
- INTEGER savern;
-
- savern = CurResFile ();
- UseResFile (rn);
- Get1IndType (typep, type_num);
- UseResFile (savern);
- }
-
- /* Exactly the same as GetIndResource except limited to resources from the
- file with refnum rn. */
-
- Handle
- GetIndResourceRN (INTEGER rn, ResType type, INTEGER id)
- {
- INTEGER savern;
- Handle retval;
-
- savern = CurResFile ();
- UseResFile (rn);
- retval = Get1IndResource (type, id);
- UseResFile (savern);
- return retval;
- }
-
- /* Returns true when the bit bitnum is set in bitmap, false otherwise. */
-
- boolean_t
- bit_test (unsigned char bitmap[], ULONGINT bitnum)
- {
- boolean_t retval;
-
- retval = BitTst ((Ptr) bitmap, bitnum) ? true : false;
- return retval;
- }
-
- /* Scans through bitmap looking for the first bit with value tofind. We
- don't care about running off the end of the map, because we already know
- that we'll find the value somewhere in the map. We should probably make
- our bitmaps more sane, but we don't right now. */
-
- ULONGINT
- find_first_bit (unsigned char bitmap[], int tofind)
- {
- unsigned char not_set;
- unsigned char *ucp;
- unsigned char u;
- ULONGINT retval;
-
- if (tofind)
- not_set = 0;
- else
- not_set = 0xff;
- for (retval = 0, ucp = bitmap; *ucp == not_set; ++ucp, retval += 8)
- ;
- u = *ucp;
- for (mask = (1 << 7), tofind = (tofind & 1) << 7;
- (u & mask) != tofind; mask >>= 1, tofind >>= 1, ++retval)
- ;
- return retval;
- }
-
- /* Sets to value toset the bit bitnum in bitmap. */
-
- void
- bit_set_to_value (unsigned char bitmap[], ULONGINT bitnum, int toset)
- {
- if (toset)
- BitSet ((Ptr) bitmap, bitnum);
- else
- BitClr ((Ptr) bitmap, bitnum);
- }
-
- /* Fill in initial values for the generic_map_t pointed to by gmp.
- The type and max fields are set directly from type and max. The
- bitmap is set to all zeros, except with ones in all the locations
- less than min. We also scan the system file for types that are
- already in use and mark them. */
-
- void
- init_in_use_info (generic_map_t *gmp, ResType type, INTEGER min, INTEGER max)
- {
- int i, n_res;
- BOOLEAN save_resload;
-
- gmp->type = type;
- gmp->max = max;
- gmp->free = max - min + 1;
- memset (gmp->bitmap, 0, CHARS_NEEDED(max));
- for (i = 0; i < min; ++i)
- bit_set_to_value (gmp->bitmap, i, 1);
-
- save_resload = ResLoad;
- SetResLoad (false);
-
- n_res = CountResouresRN (SysMap, type);
- for (i = 1; i <= n_res; ++i)
- {
- Handle h;
- INTEGER id;
- ResType t;
- Str255 name;
-
- h = GetIndResourceRN (SysMap, type, i);
- GetResInfo (h, &id, &t, name);
- if (!bit_test (gmp->bitmap, id))
- {
- bit_set_to_value (gmp->bitmap, id, 1);
- --gmp->free;
- }
- }
-
- SetResLoad (save_resload);
- }
-
- #define IN_USE_TYPE 'nUSE'
- enum { IN_USE_ID = 0 };
-
- /* Picks up the in use info for the file rn. Usually this is just the
- resource 'nUSE' with id 0, but if that resource doesn't exist, the
- information has to be created based on what's in the System file.
- The return value is noErr, unless an error occurs. */
-
- OSErr
- get_in_use_info (INTEGER rn, in_use_hand *usehandp)
- {
- Handle h;
- OSErr retval;
-
- h = GetResourceRN (rn, IN_USE_TYPE, IN_USE_ID);
- if (h)
- {
- LoadResource (h);
- *usehandp = h;
- retval = noErr;
- }
- else
- {
- h = NewHandle (sizeof(***usehandp));
- if (!h)
- retval = MemErr ();
- else
- {
- in_use_ptr iup;
-
- HLock (h);
- iup = *h;
- init_in_use_info ((generic_map_t *) &iup->drvr_map, 'DRVR',
- DRVR_MIN, DRVR_MAX);
-
- init_in_use_info ((generic_map_t *) &iup->font_map, 'FONT',
- FONT_MIN, FONT_MAX);
-
- init_in_use_info ((generic_map_t *) &iup->nfnt_map, 'NFNT',
- NFNT_MIN, NFNT_MAX);
-
- init_in_use_info ((generic_map_t *) &iup->fond_map, 'FOND',
- FOND_MIN, FOND_MAX);
-
- iup->sentinel = 0;
- HUnlock (h);
- AddResourceRN (rn, h, IN_USE_TYPE, IN_USE_ID, (StringPtr) 0);
- retval = ResErr ();
- }
- }
- return retval;
- }
-
- typedef struct mapping_link_str
- {
- INTEGER old_id;
- INTEGER new_id;
- struct mapping_link_str *next;
- } mapping_link_t;
-
- typedef struct
- {
- ResType type;
- mapping_link_t *head;
- } mapping_list_t;
-
- typedef struct
- {
- mapping_list_t list[4];
- } mapping_t;
-
- /* Allocate room for a new link, then fill in its fields with old_id,
- new_id and next. Store the pointer to the new link to where newpp
- points and return noErr if successful. Don't modify *newpp on
- failure. */
-
- OSErr
- new_map_link (map_link_t **newpp, INTEGER old_id, INTEGER new_id,
- mapping_link_t *next);
- {
- OSErr retval;
- mapping_link_t *linkp;
-
- linkp = NewPtr(sizeof(*linkp));
- if (!linkp)
- retval = MemErr();
- else
- {
- retval = noErr;
- linkp->old_id = old_id;
- linkp->new_id = new_id;
- linkp->next = next;
- *newpp = linkp;
- }
- return retval;
- }
-
- /* Adds a mapping to the mapping_t pointed to by mappingp. The mapping
- consists of a type, and old_id and a new_id. Returns noErr when
- successful, a Mac error value otherwise. */
-
- OSErr
- add_mapping (ResType type, mapping_t *mappingp, INTEGER old_id, INTEGER new_id)
- {
- int i;
- OSErr retval;
-
- for (i = 0; (i < NELEM(mappingp->list) &&
- mappingp->list[i].type && mappingp->list[i].type != type); ++i)
- ;
- if (i == NELEM(mappingp->list))
- {
- DebugStr("\ptried to map too many types");
- retval = fsDSIntErr;
- }
- else
- {
- mappingp->list[i].type = type;
- retval = new_map_link (&list[i].head, old_id, new_id, list[i].head);
- }
- return retval;
- }
-
- /* Sets the mapping_t pointed to by mappingp to zeros so that we can add
- information to it. */
-
- void init_map (mapping_t *mappingp)
- {
- memset (mappingp, 0, sizeof(*mappingp));
- }
-
- /*
- * Makes sure all resources that need to be copied can have a proper
- * mapping. If it succeeds, enough information is stored in *mappingp
- * so that the mapping doesn't need to be done again. Parameter
- * from_rn is the refnum of the file that is being merged with the
- * master file. Parameter master_rn is the refnum of the master file
- * itself. Returns noErr on success, or an error value if something
- * goes wrong.
- */
-
- OSErr
- setup_map (INTEGER from_rn, INTEGER master_rn, mapping_t *mappingp)
- {
- OSErr retval;
-
- init_map (mappingp);
- retval = is_writable (master_rn);
- if (retval == noErr)
- {
- if (room_on_volume_with_file (master_rn) < file_length (from_rn))
- retval = dskFullErr;
- else
- {
- in_use_hand in_useh;
-
- retval = get_in_use_info (master_rn, &in_useh);
- if (retval == noErr)
- {
- generic_map_t *gp;
- BOOLEAN save_resload;
-
- save_resload = ResLoad;
- SetResLoad (false);
- for (gp = first_map (in_useh); gp; gp = next_map (in_useh, gp))
- {
- INTEGER n_res, n;
-
- n_res = CountResouresRN (from_rn, gp->type);
- if (n_res > gp->free)
- retval = tooManyResources;
- else
- {
- for (n = 1; retval == noErr && n <= n_res; ++n)
- {
- h = GetIndResourceRN (from_rn, gp->type, n);
- GetResInfo (h, &id, &t, name);
- if (!bit_test (gp->bitmap, id))
- new_id = id;
- else
- new_id = find_first_bit (gp->bitmap, 0);
- bit_set_to_value (gp->bitmap, new_id, 1);
- retval = add_mapping (gp->type, mappingp, id, new_id);
- }
- }
- gp->free -= n_res;
- }
- ChangedResource (in_useh);
- SetResLoad (save_resload);
- }
- }
- }
- return retval;
- }
-
- enum { OWNED_MASK = 0xF800, DRVR_ID = 0xF800 };
-
- /* Returns true if a given ID represents a
- resource that is owned by a DRVR. */
-
- boolean_t
- owned_drvr_id_p (INTEGER id)
- {
- return (id & OWNED_MASK) == DRVR_ID;
- }
-
- enum { OWNER_SHIFT = 5, OWNER_MASK = 0x3F << OWNER_SHIFT };
-
- /* Returns the id of the owner of an owned id. */
-
- INTEGER
- owned_id (INTEGER id)
- {
- return (id & OWNER_MASK) >> OWNER_SHIFT;
- }
-
- /* Use the mapping_t pointed to by mappingp to map type, old_id into a new
- id which is returned. If there is no map, -1L is returned, which is an
- impossible id. */
-
- LONGINT
- find_map (ResType type, INTEGER old_id, mapping_t *mappingp)
- {
- LONGINT retval;
- int i;
-
- retval = -1L;
-
- for (i = 0; i < NELEM(mappingp->list) && mappingp->list[i].type != type; ++i)
- ;
-
- if (mappingp->list[i].type == type)
- {
- mapping_link_t *mp;
-
- for (mp = mappingp->list[i].head; mp && mp->old_id != old_id;
- mp = mp->next)
- ;
- if (mp->old_id == old_id)
- retval = (LONGINT) (unsigned int) mp->new_id;
- }
-
- return retval;
- }
-
- enum { VAR_MASK = 0x1F };
-
- /* Given an owned_id and an id, construct a new id that is tagged as an
- owned by DRVR id. */
-
- INTEGER
- make_owned_drvr_id (INTEGER owned_id, INTEGER id)
- {
- return DRVR_ID | ((owned_id & VAR_MASK) << OWNER_SHIFT) | (id & VAR_MASK);
- }
-
- /* Returns whether a given resource should be copied into the master file.
- If it should, then *idp is updated to contain the new id of this resource.
- The id number pointed to by idp will only change when there's a conflict
- with a preexisting id number. The parametr from_rn is the refnum
- of the file being added to the master file, master_rn is the refnum of
- the master file itself. The parameter mappingp points to the mapping
- information that was already determined and saved for later. */
-
- BOOLEAN
- map_id (ResType type, INTEGER *idp, INTEGER from_rn, INTEGER master_rn,
- const mapping_t *mappingp)
- {
- BOOLEAN retval;
-
- if (owned_drvr_id_p (*idp))
- {
- INTEGER old_owned;
- LONGINT new_id;
-
- old_owned = owned_id (*idp);
- new_id = find_map ('DRVR', old_owned, mappingp);
- if (new_id >= 0)
- {
- *idp = make_owned_drvr_id (newid, *idp);
- retval = TRUE;
- }
- else
- retval = FALSE;
- }
- else
- {
- LONGINT new_id;
-
- switch (type)
- {
- case 'DRVR':
- case 'FONT':
- case 'NFNT':
- case 'FOND':
- new_id = find_map (type, *idp, mappingp);
- if (new_id >= 0)
- {
- *idp = new_id;
- retval = TRUE;
- }
- else
- retval = FALSE;
- break;
- default:
- retval = FALSE;
- }
- }
- return retval;
- }
-
- typedef struct
- {
- INTEGER size;
- INTEGER style;
- INTEGER id;
- } font_assoc_t;
-
- /* Maps the data of certain resource types (currently only FONDs) that
- incorporate ids that may have been mapped. The Handle h is a handle
- to the resource, mappingp points to previously determined mapping info. */
-
- void
- map_data (ResType type, Handle h, const mapping_t *mappingp)
- {
- switch (type)
- {
- case 'FOND':
- {
- INTEGER *ip;
- INTEGER n_items;
- font_assoc_t *fap;
-
- HLock(h);
- ip = (INTEGER *) ((char *) *h + 20 * sizeof(INTEGER) +
- 3 * sizeof(LONGINT));
- n_items = *ip + 1;
- fap = (font_assoc_t *) (ip + 1);
- DebugStr("\pCheck to make sure I have correct offsets. Look for better way using .h files");
- while (--n_items >= 0)
- {
- INTEGER old_id;
- LONGINT new_id;
-
- old_id = fap->id;
- if (old_id <= FONT_MAX)
- new_id = find_map ('FONT', old_id, mappingp);
- else
- new_id = -1;
- if (new_id < 0)
- new_id = find_map ('NFNT', old_id, mappingp);
- if (new_id >= 0)
- fap->id = new_id;
- }
- HUnlock(h);
- }
- break;
- }
- }
-
- /* Frees up any memory that may have been allocated and stuck in the mapping_t
- pointed to by mappingp. */
-
- void teardown_map (mapping_t *mappingp)
- {
- int i;
-
- for (i = 0; i < NELEM(mappingp->list); ++i)
- {
- mapping_link_t *mp, *next;
-
- for (mp = mappingp->list[i].head; mp; mp = next)
- {
- next = mp->next;
- DisposPtr(mp);
- }
- }
- /* memset(mappingp, 0, sizeof(*mappingp)); */
- }
-
- /* Merges all the Font and DA resources from the file with refnum from_file_rn
- into the file with refnum master_file_rn. On success noErr is returned.
- On failure an error value is returned. */
-
- OSErr
- AddToMasterFile (INTEGER from_file_rn, INTEGER master_file_rn)
- {
- OSErr err;
- mapping_t mapping;
-
- err = setup_map (from_file_rn, master_file_rn, &mapping);
- if (err == noEErr)
- {
- INTEGER type_num, type_num_max;
- BOOLEAN save_resload;
-
- type_num_max = CountTypesRN (from_file_rn);
- save_resload = ResLoad;
- SetResLoad (false);
- for (type_num = 1; type_num <= type_num_max; ++type_num)
- {
- ResType type;
-
- GetIndTypeRN (from_file_rn, &type, type_num);
- res_num_max = CountResourcesRN (from_file_rn, type);
- for (res_num = 1; res_num <= res_num_max; ++res_num)
- {
- Handle h;
- Str255 name;
-
- h = GetIndResourceRN (from_file_rn, type, res_num);
- GetResInfo (h, &id, &t, name);
- if (map_id (type, &id, from_file_rn, master_file_rn, &mapping))
- {
- LoadResource (h);
- DetachResource (h);
- map_data (type, h, &mapping);
- AddResourceRN (master_file_rn, h, type, id, name);
- }
- }
- }
- SetResLoad (save_resload);
- }
- teardown_map (&mapping);
- }
-
- #if defined( REMOVE_FROM_MASTER_FILE_SUPPORT )
-
- /* Sets up the info needed to recognize which resources from the
- master file with refnum master_rn need to be removed as part of the
- process of getting rid of all font and DA resources that were
- originally copied into the master file from the file with the
- refnum from_rn. The parameter unmappingp points to where this
- "unmapping" information should be stored. For simplicity we use
- the mapping_t routines and just know that if there is any mapping
- at all, this means that resource will be deleted. */
-
- OSErr
- setup_unmap (INTEGER from_rn, INTEGER master_rn, mapping_t *unmappingp)
- {
- OSErr retval;
-
- init_map (unmappingp);
- retval = is_writable (master_rn);
- if (retval == noErr)
- {
- /* TODO: There are a few different ways that we can do the
- unmapping. One way would be to log the mappings as part of
- the mapping process. We could put the log in the master
- file, then all that would be needed here would be to identify
- which file from_rn represents and use that to look up a list
- of resources to nuke. Another way would be to checksum all
- of the resources in the file with refnum from_rn and then use
- that to identify which resources to nuke. A third way would
- be to punt all the code for removing a file from the master
- file and just rebuild the master file from scratch, using all
- the files that are already there, except the one we're
- removing. This method requires less code in this file and
- also has the benefit of forcing a periodic rebuild, which
- might be useful by itself. */
- }
- return retval;
- }
-
- /* A predicate that returns true if a given resource should be deleted as
- part of the process of removing the contents of one file from the master
- file. */
-
- boolean_t
- delete_p (ResType type, INTEGER id, const mapping_t *unmappingp)
- {
- boolean_t retval;
-
- retval = false;
- if (owned_drvr_id_p (id))
- {
- INTEGER owner_id;
-
- owner_id = owned_id (id);
- if (find_map ('DRVR', owner_id, unmappingp) >= 0)
- retval = true;
- }
- if (!retval && find_map (type, id, unmappingp))
- retval = true;
- return retval;
- }
-
- typedef struct link_str
- {
- link_str *next;
- Handle resource;
- } link_t;
-
- /* Undoes the action of AddToMasterFile and returns noErr on success, or an
- error code if there is trouble. All the font and da resources present
- in the file with refnum from_file_rn are removed from the master file,
- which has a refnum of master_file_rn. */
-
- OSErr
- RemoveFromMasterFile (INTEGER from_file_rn, INTEGER master_file_rn)
- {
- mapping_t unmapping;
- OSErr err;
-
- err = setup_unmap (from_file_rn, master_file_rn, &unmapping);
- if (err == noErr)
- {
- link_t *headp;
-
- type_num_max = CountTypesRN (master_file_rn);
- save_resload = ResLoad;
- SetResLoad (false);
- headp = 0;
- for (type_num = 1; type_num <= type_num_max; ++type_num)
- {
- GetIndTypeRN (master_file_rn, &type, type_num);
- res_num_max = CountResourcesRN (master_file_rn, type);
- for (res_num = 1; res_num <= res_num_max; ++res_num)
- {
- h = GetIndResourceRN (master_file_rn, type, res_num);
- GetResInfo (h, &id, &t, name);
- if (delete_p (type, id, &unmapping))
- {
- link_t *newlinkp;
- newlinkp = (link_t *) NewPtr (sizeof(link_t));
- assert (newlinkp);
- newlinkp->next = headp;
- newlinkp->resource = h;
- headp = newlinkp;
- }
- }
- }
- while (headp)
- {
- oldp = headp;
- headp = headp->next;
- RmveResource (oldp->resource);
- DisposPtr (oldp);
- }
- }
- return err;
- }
-
- #endif /* defined( REMOVE_FROM_MASTER_FILE_SUPPORT ) */
-