home *** CD-ROM | disk | FTP | other *** search
/ Executor 2.0 / executorv2.0.iso / pc / dos / extra / source / browser / browser.hqx / Browser / newfontda.c < prev    next >
Encoding:
Text File  |  1995-06-06  |  20.3 KB  |  892 lines

  1. enum
  2. {
  3.   DRVR_MIN = 12,
  4.   DRVR_MAX = 31,
  5.   FONT_MIN = 0,
  6.   FONT_MAX = 255,
  7.   NFNT_MIN = 0,
  8.   NFNT_MAX = 32767,
  9.   FOND_MIN = 0,
  10.   FOND_MAX = 32767,
  11. };
  12.  
  13. #define CHARS_NEEDED(n) (((n)+31)/32*4)
  14.  
  15. typedef struct
  16. {
  17.   ResType type;
  18.   LONGINT max;
  19.   LONGINT free;
  20.   uchar bitmap[CHARS_NEEDED(DRVR_MAX)];
  21. } drvr_map_t;
  22.  
  23. typedef struct
  24. {
  25.   ResType type;
  26.   LONGINT max;
  27.   LONGINT free;
  28.   uchar bitmap[CHARS_NEEDED(FONT_MAX)];
  29. } font_map_t;
  30.  
  31. typedef struct
  32. {
  33.   ResType type;
  34.   LONGINT max;
  35.   LONGINT free;
  36.   uchar bitmap[CHARS_NEEDED(NFNT_MAX)];
  37. } nfnt_map_t;
  38.  
  39. typedef struct
  40. {
  41.   ResType type;
  42.   LONGINT max;
  43.   LONGINT free;
  44.   uchar bitmap[CHARS_NEEDED(FOND_MAX)];
  45. } fond_map_t;
  46.  
  47. typedef struct
  48. {
  49.   ResType type;
  50.   LONGINT max;
  51.   LONGINT free;
  52.   uchar bitmap[0];
  53. } generic_map_t;
  54.  
  55. typedef struct
  56. {
  57.   drvr_map_t drvr_map;
  58.   font_map_t font_map;
  59.   nfnt_map_t nfnt_map;
  60.   fond_map_t fond_map;
  61.   ResType sentinel;
  62. } in_use_t, *in_use_ptr, **in_use_hand;
  63.  
  64. /* Locks the handle h and returns a pointer to the first generic_map_t
  65.    contained in h.  */
  66.  
  67. generic_map_t *
  68. first_map (in_use_hand h)
  69. {
  70.   generic_map_t *retval;
  71.  
  72.   HLock (h);
  73.   retval = (generic_map_t *) *h;
  74.   return retval->type ? retval : 0;
  75. }
  76.  
  77. /* Returns the next generic_map_t that follows mapp.  If there there is none,
  78.    0 is returned and h is unlocked.  */
  79.  
  80. generic_map_t *
  81. next_map (in_use_hand h, generic_map_t *mapp)
  82. {
  83.   generic_map_t *retval;
  84.  
  85.   retval = (generic_map_t *)
  86.     ((char *) mapp + sizeof(generic_map_t) + CHARS_NEEDED(mapp->max));
  87.  
  88.   if (!retval->type)
  89.     {
  90.       HUnlock(h);
  91.       retval = 0;
  92.     }
  93.   return retval;
  94. }
  95.  
  96. /* Exactly the same as CountTypes, except only the resource file with the
  97.    refnum of rn is consulted.  */
  98.  
  99. INTEGER
  100. CountTypesRN (INTEGER rn)
  101. {
  102.   INTEGER savern, retval;
  103.  
  104.   savern = CurResFile ();
  105.   UseResFile (rn);
  106.   retval = Count1Types ();
  107.   UseResFile (savern);
  108.   return retval;
  109. }
  110.  
  111. /* Exactly the same as CountResources, except only the resource file with the
  112.    refnum rn is consulted.  */
  113.  
  114. INTEGER
  115. CountResourcesRN (INTEGER rn, ResType type)
  116. {
  117.   INTEGER savern, retval;
  118.  
  119.   savern = CurResFile ();
  120.   UseResFile (rn);
  121.   retval = Count1Resources (type);
  122.   UseResFile (savern);
  123.   return retval;
  124. }
  125.  
  126. /* Calls PBGetFCBInfo to fill what fcbrp points to with the appropriate values
  127.    for rn.  The return value is whatever PBGetFCBInfo returns.  */
  128.  
  129. OSErr
  130. getfcbinfo (INTEGER rn, FCBPBRec *fcbrp)
  131. {
  132.   fcbrp->ioCompletion = 0;
  133.   fcbrp->ioVRefNum = 0;
  134.   fcbrp->ioRefNum = rn;
  135.   fcbrp->ioFCBIndx = 0;
  136.   
  137.   retval = PBGetFCBInfo (fcbrp, false);
  138.   return retval;
  139. }
  140.  
  141. enum { writableFlag = 1 };
  142.  
  143. /* Returns noErr if rn is a writable file,
  144.    otherwise returns appropriate error.  */
  145.  
  146. OSErr
  147. is_writable (INTEGER rn)
  148. {
  149.   OSErr retval;
  150.   FCBPBRec fcbr;
  151.  
  152.   retval = getfcbinfo (rn, &fcbr);
  153.   if (retval == noErr)
  154.     retval = fcbr.ioFCBFlags & writableFlag ? noErr : fLckdErr;
  155.   return retval;
  156. }
  157.  
  158. /* Returns the number of 512 byte blocks free on the volume that contains
  159.    the file with refnum rn.  An error results in 0 free blocks reported.   */
  160.  
  161. ULONGINT
  162. room_on_volume_with_file (INTEGER rn)
  163. {
  164.   OSErr err;
  165.   FCBPBRec fcbr;
  166.   ULONGINT retval;
  167.  
  168.   err = getfcbinfo (rn, &fcbr);
  169.   if (err != noErr)
  170.     retval = 0;
  171.   else
  172.     {
  173.       VCB *vcbp;
  174.  
  175.       vcbp = fcbr.fcbVPtr;
  176.       retval = vcbp->vcbFreeBks * vcbp->vcbAlBlkSiz / 512;
  177.     }
  178.   return retval;
  179. }
  180.  
  181. /* Returns the number of 512 byte blocks taken up by the file with refnum
  182.    rn.  An error results in (LONGINT) -1L being returned.  */
  183.  
  184. ULONGINT
  185. file_length (INTEGER rn)
  186. {
  187.   OSErr err;
  188.   FCBPBRec fcbr;
  189.   ULONGINT retval;
  190.  
  191.   err = getfcbinfo (rn, &fcbr);
  192.   if (err != noErr)
  193.     retval = (ULONGINT) -1L;
  194.   else
  195.     retval = fcbr.fcbPLen / 512;
  196.   return retval;
  197. }
  198.  
  199. /* Exactly like GetResource, except limited to the file specified by rn.  */
  200.  
  201. Handle
  202. GetResourceRN (INTEGER rn, ResType type, INTEGER id)
  203. {
  204.   INTEGER savern;
  205.   Handle retval;
  206.  
  207.   savern = CurResFile ();
  208.   UseResFile (rn);
  209.   retval = Get1Resource (type, id);
  210.   UseResFile (savern);
  211.   return retval;
  212. }
  213.  
  214. /* Exactly the same as AddResource, except its action is limited to the file
  215.    with the refnum rn.  */
  216.  
  217. void
  218. AddResourceRN (INTEGER rn, Handle h, ResType type, INTEGER id, Str255 name)
  219. {
  220.   INTEGER savern;
  221.  
  222.   savern = CurResFile ();
  223.   UseResFile (rn);
  224.   AddResource (h, type, id, name);
  225.   UseResFile (savern);
  226. }
  227.  
  228. /* Exactly the same as GetIndType, except its action is limited to the file
  229.    with the refnum rn.  */
  230.  
  231. void
  232. GetIndTypeRN (INTEGER rn, ResType *typep, INTEGER type_num)
  233. {
  234.   INTEGER savern;
  235.  
  236.   savern = CurResFile ();
  237.   UseResFile (rn);
  238.   Get1IndType (typep, type_num);
  239.   UseResFile (savern);
  240. }
  241.  
  242. /* Exactly the same as GetIndResource except limited to resources from the
  243.    file with refnum rn. */
  244.  
  245. Handle
  246. GetIndResourceRN (INTEGER rn, ResType type, INTEGER id)
  247. {
  248.   INTEGER savern;
  249.   Handle retval;
  250.  
  251.   savern = CurResFile ();
  252.   UseResFile (rn);
  253.   retval = Get1IndResource (type, id);
  254.   UseResFile (savern);
  255.   return retval;
  256. }
  257.  
  258. /* Returns true when the bit bitnum is set in bitmap, false otherwise.  */
  259.  
  260. boolean_t
  261. bit_test (unsigned char bitmap[], ULONGINT bitnum)
  262. {
  263.   boolean_t retval;
  264.  
  265.   retval = BitTst ((Ptr) bitmap, bitnum) ? true : false;
  266.   return retval;
  267. }
  268.  
  269. /* Scans through bitmap looking for the first bit with value tofind.  We
  270.  don't care about running off the end of the map, because we already know
  271.  that we'll find the value somewhere in the map.  We should probably make
  272.  our bitmaps more sane, but we don't right now.  */
  273.  
  274. ULONGINT
  275. find_first_bit (unsigned char bitmap[], int tofind)
  276. {
  277.   unsigned char not_set;
  278.   unsigned char *ucp;
  279.   unsigned char u;
  280.   ULONGINT retval;
  281.  
  282.   if (tofind)
  283.     not_set = 0;
  284.   else
  285.     not_set = 0xff;
  286.   for (retval = 0, ucp = bitmap; *ucp == not_set; ++ucp, retval += 8)
  287.     ;
  288.   u = *ucp;
  289.   for (mask = (1 << 7), tofind = (tofind & 1) << 7;
  290.        (u & mask) != tofind; mask >>= 1, tofind >>= 1, ++retval)
  291.     ;
  292.   return retval;
  293. }
  294.  
  295. /* Sets to value toset the bit bitnum in bitmap.  */
  296.  
  297. void
  298. bit_set_to_value (unsigned char bitmap[], ULONGINT bitnum, int toset)
  299. {
  300.   if (toset)
  301.     BitSet ((Ptr) bitmap, bitnum);
  302.   else
  303.     BitClr ((Ptr) bitmap, bitnum);
  304. }
  305.  
  306. /* Fill in initial values for the generic_map_t pointed to by gmp.
  307.    The type and max fields are set directly from type and max.  The
  308.    bitmap is set to all zeros, except with ones in all the locations
  309.    less than min.  We also scan the system file for types that are
  310.    already in use and mark them.  */
  311.  
  312. void
  313. init_in_use_info (generic_map_t *gmp, ResType type, INTEGER min, INTEGER max)
  314. {
  315.   int i, n_res;
  316.   BOOLEAN save_resload;
  317.  
  318.   gmp->type = type;
  319.   gmp->max = max;
  320.   gmp->free = max - min + 1;
  321.   memset (gmp->bitmap, 0, CHARS_NEEDED(max));
  322.   for (i = 0; i < min; ++i)
  323.     bit_set_to_value (gmp->bitmap, i, 1);
  324.           
  325.   save_resload = ResLoad;
  326.   SetResLoad (false);
  327.  
  328.   n_res = CountResouresRN (SysMap, type);
  329.   for (i = 1; i <= n_res; ++i)
  330.     {
  331.       Handle h;
  332.       INTEGER id;
  333.       ResType t;
  334.       Str255 name;
  335.  
  336.       h = GetIndResourceRN (SysMap, type, i);
  337.       GetResInfo (h, &id, &t, name);
  338.       if (!bit_test (gmp->bitmap, id))
  339.     {
  340.       bit_set_to_value (gmp->bitmap, id, 1);
  341.       --gmp->free;
  342.     }
  343.     }
  344.  
  345.   SetResLoad (save_resload);
  346. }
  347.  
  348. #define IN_USE_TYPE 'nUSE'
  349. enum { IN_USE_ID = 0 };
  350.  
  351. /* Picks up the in use info for the file rn.  Usually this is just the
  352.    resource 'nUSE' with id 0, but if that resource doesn't exist, the
  353.    information has to be created based on what's in the System file.
  354.    The return value is noErr, unless an error occurs.  */
  355.  
  356. OSErr
  357. get_in_use_info (INTEGER rn, in_use_hand *usehandp)
  358. {
  359.   Handle h;
  360.   OSErr retval;
  361.  
  362.   h = GetResourceRN (rn, IN_USE_TYPE, IN_USE_ID);
  363.   if (h)
  364.     {
  365.       LoadResource (h);
  366.       *usehandp = h;
  367.       retval = noErr;
  368.     }
  369.   else
  370.     {
  371.       h = NewHandle (sizeof(***usehandp));
  372.       if (!h)
  373.     retval = MemErr ();
  374.       else
  375.     {
  376.       in_use_ptr iup;
  377.  
  378.       HLock (h);
  379.       iup = *h;
  380.       init_in_use_info ((generic_map_t *) &iup->drvr_map, 'DRVR',
  381.                 DRVR_MIN, DRVR_MAX);
  382.  
  383.       init_in_use_info ((generic_map_t *) &iup->font_map, 'FONT',
  384.                 FONT_MIN, FONT_MAX);
  385.  
  386.       init_in_use_info ((generic_map_t *) &iup->nfnt_map, 'NFNT',
  387.                 NFNT_MIN, NFNT_MAX);
  388.  
  389.       init_in_use_info ((generic_map_t *) &iup->fond_map, 'FOND',
  390.                 FOND_MIN, FOND_MAX);
  391.  
  392.       iup->sentinel = 0;
  393.       HUnlock (h);
  394.       AddResourceRN (rn, h, IN_USE_TYPE, IN_USE_ID, (StringPtr) 0);
  395.       retval = ResErr ();
  396.     }
  397.     }
  398.   return retval;
  399. }
  400.  
  401. typedef struct mapping_link_str
  402. {
  403.   INTEGER old_id;
  404.   INTEGER new_id;
  405.   struct mapping_link_str *next;
  406. } mapping_link_t;
  407.  
  408. typedef struct
  409. {
  410.   ResType type;
  411.   mapping_link_t *head;
  412. } mapping_list_t;
  413.  
  414. typedef struct
  415. {
  416.   mapping_list_t list[4];
  417. } mapping_t;
  418.  
  419. /* Allocate room for a new link, then fill in its fields with old_id,
  420.    new_id and next.  Store the pointer to the new link to where newpp
  421.    points and return noErr if successful.  Don't modify *newpp on
  422.    failure.  */
  423.  
  424. OSErr
  425. new_map_link (map_link_t **newpp, INTEGER old_id, INTEGER new_id,
  426.           mapping_link_t *next);
  427. {
  428.   OSErr retval;
  429.   mapping_link_t *linkp;
  430.   
  431.   linkp = NewPtr(sizeof(*linkp));
  432.   if (!linkp)
  433.     retval = MemErr();
  434.   else
  435.     {
  436.       retval = noErr;
  437.       linkp->old_id = old_id;
  438.       linkp->new_id = new_id;
  439.       linkp->next = next;
  440.       *newpp = linkp;
  441.     }
  442.   return retval;
  443. }
  444.  
  445. /* Adds a mapping to the mapping_t pointed to by mappingp.  The mapping
  446.    consists of a type, and old_id and a new_id.  Returns noErr when
  447.    successful, a Mac error value otherwise.  */
  448.  
  449. OSErr
  450. add_mapping (ResType type, mapping_t *mappingp, INTEGER old_id, INTEGER new_id)
  451. {
  452.   int i;
  453.   OSErr retval;
  454.  
  455.   for (i = 0; (i < NELEM(mappingp->list) &&
  456.            mappingp->list[i].type && mappingp->list[i].type != type); ++i)
  457.     ;
  458.   if (i == NELEM(mappingp->list))
  459.     {
  460.       DebugStr("\ptried to map too many types");
  461.       retval = fsDSIntErr;
  462.     }
  463.   else
  464.     {
  465.       mappingp->list[i].type = type;
  466.       retval = new_map_link (&list[i].head, old_id, new_id, list[i].head);
  467.     }
  468.   return retval;
  469. }
  470.  
  471. /* Sets the mapping_t pointed to by mappingp to zeros so that we can add
  472.    information to it.  */
  473.  
  474. void init_map (mapping_t *mappingp)
  475. {
  476.   memset (mappingp, 0, sizeof(*mappingp));
  477. }
  478.  
  479. /*
  480.  * Makes sure all resources that need to be copied can have a proper
  481.  * mapping.  If it succeeds, enough information is stored in *mappingp
  482.  * so that the mapping doesn't need to be done again.  Parameter
  483.  * from_rn is the refnum of the file that is being merged with the
  484.  * master file.  Parameter master_rn is the refnum of the master file
  485.  * itself.  Returns noErr on success, or an error value if something
  486.  * goes wrong.  
  487.  */
  488.  
  489. OSErr
  490. setup_map (INTEGER from_rn, INTEGER master_rn, mapping_t *mappingp)
  491. {
  492.   OSErr retval;
  493.  
  494.   init_map (mappingp);
  495.   retval = is_writable (master_rn);
  496.   if (retval == noErr)
  497.     {
  498.       if (room_on_volume_with_file (master_rn) < file_length (from_rn))
  499.     retval = dskFullErr;
  500.       else
  501.     {
  502.       in_use_hand in_useh;
  503.       
  504.       retval = get_in_use_info (master_rn, &in_useh);
  505.       if (retval == noErr)
  506.         {
  507.           generic_map_t *gp;
  508.           BOOLEAN save_resload;
  509.           
  510.           save_resload = ResLoad;
  511.           SetResLoad (false);
  512.           for (gp = first_map (in_useh); gp; gp = next_map (in_useh, gp))
  513.         {
  514.           INTEGER n_res, n;
  515.           
  516.           n_res = CountResouresRN (from_rn, gp->type);
  517.           if (n_res > gp->free)
  518.             retval = tooManyResources;
  519.           else
  520.             {
  521.               for (n = 1; retval == noErr && n <= n_res; ++n)
  522.             {
  523.               h = GetIndResourceRN (from_rn, gp->type, n);
  524.               GetResInfo (h, &id, &t, name);
  525.               if (!bit_test (gp->bitmap, id))
  526.                 new_id = id;
  527.               else
  528.                 new_id = find_first_bit (gp->bitmap, 0);
  529.               bit_set_to_value (gp->bitmap, new_id, 1);
  530.               retval = add_mapping (gp->type, mappingp, id, new_id);
  531.             }
  532.             }
  533.           gp->free -= n_res;
  534.         }
  535.           ChangedResource (in_useh);
  536.           SetResLoad (save_resload);
  537.         }
  538.     }
  539.     }
  540.   return retval;
  541. }
  542.  
  543. enum { OWNED_MASK = 0xF800, DRVR_ID = 0xF800 };
  544.  
  545. /* Returns true if a given ID represents a
  546.    resource that is owned by a DRVR.  */
  547.  
  548. boolean_t
  549. owned_drvr_id_p (INTEGER id)
  550. {
  551.   return (id & OWNED_MASK) == DRVR_ID;
  552. }
  553.  
  554. enum { OWNER_SHIFT = 5, OWNER_MASK = 0x3F << OWNER_SHIFT };
  555.  
  556. /* Returns the id of the owner of an owned id.  */
  557.  
  558. INTEGER
  559. owned_id (INTEGER id)
  560. {
  561.   return (id & OWNER_MASK) >> OWNER_SHIFT;
  562. }
  563.  
  564. /* Use the mapping_t pointed to by mappingp to map type, old_id into a new
  565.    id which is returned.  If there is no map, -1L is returned, which is an
  566.    impossible id.  */
  567.  
  568. LONGINT
  569. find_map (ResType type, INTEGER old_id, mapping_t *mappingp)
  570. {
  571.   LONGINT retval;
  572.   int i;
  573.  
  574.   retval = -1L;
  575.   
  576.   for (i = 0; i < NELEM(mappingp->list) && mappingp->list[i].type != type; ++i)
  577.     ;
  578.  
  579.   if (mappingp->list[i].type == type)
  580.     {
  581.       mapping_link_t *mp;
  582.  
  583.       for (mp = mappingp->list[i].head; mp && mp->old_id != old_id;
  584.        mp = mp->next)
  585.     ;
  586.       if (mp->old_id == old_id)
  587.     retval = (LONGINT) (unsigned int) mp->new_id;
  588.     }
  589.  
  590.   return retval;
  591. }
  592.  
  593. enum { VAR_MASK = 0x1F };
  594.  
  595. /* Given an owned_id and an id, construct a new id that is tagged as an
  596.    owned by DRVR id.  */
  597.  
  598. INTEGER
  599. make_owned_drvr_id (INTEGER owned_id, INTEGER id)
  600. {
  601.   return DRVR_ID | ((owned_id & VAR_MASK) << OWNER_SHIFT) | (id & VAR_MASK);
  602. }
  603.  
  604. /* Returns whether a given resource should be copied into the master file.
  605.    If it should, then *idp is updated to contain the new id of this resource.
  606.    The id number pointed to by idp will only change when there's a conflict
  607.    with a preexisting id number.  The parametr from_rn is the refnum
  608.    of the file being added to the master file, master_rn is the refnum of
  609.    the master file itself.   The parameter mappingp points to the mapping
  610.    information that was already determined and saved for later.  */
  611.  
  612. BOOLEAN
  613. map_id (ResType type, INTEGER *idp, INTEGER from_rn, INTEGER master_rn,
  614.     const mapping_t *mappingp)
  615. {
  616.   BOOLEAN retval;
  617.  
  618.   if (owned_drvr_id_p (*idp))
  619.     {
  620.       INTEGER old_owned;
  621.       LONGINT new_id;
  622.  
  623.       old_owned = owned_id (*idp);
  624.       new_id = find_map ('DRVR', old_owned, mappingp);
  625.       if (new_id >= 0)
  626.     {
  627.       *idp = make_owned_drvr_id (newid, *idp);
  628.       retval = TRUE;
  629.     }
  630.       else
  631.     retval = FALSE;
  632.     }
  633.   else
  634.     {
  635.       LONGINT new_id;
  636.       
  637.       switch (type)
  638.     {
  639.     case 'DRVR':
  640.     case 'FONT':
  641.     case 'NFNT':
  642.     case 'FOND':
  643.       new_id = find_map (type, *idp, mappingp);
  644.       if (new_id >= 0)
  645.         {
  646.           *idp = new_id;
  647.           retval = TRUE;
  648.         }
  649.       else
  650.         retval = FALSE;
  651.       break;
  652.     default:
  653.       retval = FALSE;
  654.     }
  655.     }
  656.   return retval;
  657. }
  658.  
  659. typedef struct
  660. {
  661.   INTEGER size;
  662.   INTEGER style;
  663.   INTEGER id;
  664. } font_assoc_t;
  665.  
  666. /* Maps the data of certain resource types (currently only FONDs) that
  667.    incorporate ids that may have been mapped.  The Handle h is a handle
  668.    to the resource, mappingp points to previously determined mapping info.  */
  669.  
  670. void
  671. map_data (ResType type, Handle h, const mapping_t *mappingp)
  672. {
  673.   switch (type)
  674.     {
  675.     case 'FOND':
  676.       {
  677.     INTEGER *ip;
  678.     INTEGER n_items;
  679.     font_assoc_t *fap;
  680.  
  681.     HLock(h);
  682.     ip = (INTEGER *) ((char *) *h + 20 * sizeof(INTEGER) +
  683.               3 * sizeof(LONGINT));
  684.     n_items = *ip + 1;
  685.     fap = (font_assoc_t *) (ip + 1);
  686. DebugStr("\pCheck to make sure I have correct offsets.  Look for better way using .h files");
  687.     while (--n_items >= 0)
  688.       {
  689.         INTEGER old_id;
  690.         LONGINT new_id;
  691.  
  692.         old_id = fap->id;
  693.         if (old_id <= FONT_MAX)
  694.           new_id = find_map ('FONT', old_id, mappingp);
  695.         else
  696.           new_id = -1;
  697.         if (new_id < 0)
  698.           new_id = find_map ('NFNT', old_id, mappingp);
  699.         if (new_id >= 0)
  700.           fap->id = new_id;
  701.       }
  702.     HUnlock(h);
  703.       }
  704.       break;
  705.     }
  706. }
  707.  
  708. /* Frees up any memory that may have been allocated and stuck in the mapping_t
  709.    pointed to by mappingp.  */
  710.  
  711. void teardown_map (mapping_t *mappingp)
  712. {
  713.   int i;
  714.  
  715.   for (i = 0; i < NELEM(mappingp->list); ++i)
  716.     {
  717.       mapping_link_t *mp, *next;
  718.  
  719.       for (mp = mappingp->list[i].head; mp; mp = next)
  720.     {
  721.       next = mp->next;
  722.       DisposPtr(mp);
  723.     }
  724.     }
  725.   /* memset(mappingp, 0, sizeof(*mappingp)); */
  726. }
  727.  
  728. /* Merges all the Font and DA resources from the file with refnum from_file_rn
  729.    into the file with refnum master_file_rn.  On success noErr is returned.
  730.    On failure an error value is returned.  */
  731.  
  732. OSErr
  733. AddToMasterFile (INTEGER from_file_rn, INTEGER master_file_rn)
  734. {
  735.   OSErr err;
  736.   mapping_t mapping;
  737.  
  738.   err = setup_map (from_file_rn, master_file_rn, &mapping);
  739.   if (err == noEErr)
  740.     {
  741.       INTEGER type_num, type_num_max;
  742.       BOOLEAN save_resload;
  743.  
  744.       type_num_max = CountTypesRN (from_file_rn);
  745.       save_resload = ResLoad;
  746.       SetResLoad (false);
  747.       for (type_num = 1; type_num <= type_num_max; ++type_num)
  748.     {
  749.       ResType type;
  750.  
  751.       GetIndTypeRN (from_file_rn, &type, type_num);
  752.       res_num_max = CountResourcesRN (from_file_rn, type);
  753.       for (res_num = 1; res_num <= res_num_max; ++res_num)
  754.         {
  755.           Handle h;
  756.           Str255 name;
  757.  
  758.           h = GetIndResourceRN (from_file_rn, type, res_num);
  759.           GetResInfo (h, &id, &t, name);
  760.           if (map_id (type, &id, from_file_rn, master_file_rn, &mapping))
  761.         {
  762.           LoadResource (h);
  763.           DetachResource (h);
  764.           map_data (type, h, &mapping);
  765.           AddResourceRN (master_file_rn, h, type, id, name);
  766.         }
  767.         }
  768.     }
  769.       SetResLoad (save_resload);
  770.     }
  771.   teardown_map (&mapping);
  772. }
  773.  
  774. #if defined( REMOVE_FROM_MASTER_FILE_SUPPORT )
  775.  
  776. /* Sets up the info needed to recognize which resources from the
  777.    master file with refnum master_rn need to be removed as part of the
  778.    process of getting rid of all font and DA resources that were
  779.    originally copied into the master file from the file with the
  780.    refnum from_rn.  The parameter unmappingp points to where this
  781.    "unmapping" information should be stored.  For simplicity we use
  782.    the mapping_t routines and just know that if there is any mapping
  783.    at all, this means that resource will be deleted.  */
  784.  
  785. OSErr
  786. setup_unmap (INTEGER from_rn, INTEGER master_rn, mapping_t *unmappingp)
  787. {
  788.   OSErr retval;
  789.  
  790.   init_map (unmappingp);
  791.   retval = is_writable (master_rn);
  792.   if (retval == noErr)
  793.     {
  794.       /* TODO: There are a few different ways that we can do the
  795.      unmapping.  One way would be to log the mappings as part of
  796.      the mapping process.  We could put the log in the master
  797.      file, then all that would be needed here would be to identify
  798.      which file from_rn represents and use that to look up a list
  799.      of resources to nuke.  Another way would be to checksum all
  800.      of the resources in the file with refnum from_rn and then use
  801.      that to identify which resources to nuke.  A third way would
  802.      be to punt all the code for removing a file from the master
  803.      file and just rebuild the master file from scratch, using all
  804.      the files that are already there, except the one we're
  805.      removing.  This method requires less code in this file and
  806.      also has the benefit of forcing a periodic rebuild, which
  807.      might be useful by itself.  */
  808.     }
  809.   return retval;
  810. }
  811.  
  812. /* A predicate that returns true if a given resource should be deleted as
  813.    part of the process of removing the contents of one file from the master
  814.    file.  */
  815.  
  816. boolean_t
  817. delete_p (ResType type, INTEGER id, const mapping_t *unmappingp)
  818. {
  819.   boolean_t retval;
  820.  
  821.   retval = false;
  822.   if (owned_drvr_id_p (id))
  823.     {
  824.       INTEGER owner_id;
  825.  
  826.       owner_id = owned_id (id);
  827.       if (find_map ('DRVR', owner_id, unmappingp) >= 0)
  828.     retval = true;
  829.     }
  830.   if (!retval && find_map (type, id, unmappingp))
  831.     retval = true;
  832.   return retval;
  833. }
  834.  
  835. typedef struct link_str
  836. {
  837.   link_str *next;
  838.   Handle resource;
  839. } link_t;
  840.  
  841. /*  Undoes the action of AddToMasterFile and returns noErr on success, or an
  842.     error code if there is trouble.  All the font and da resources present
  843.     in the file with refnum from_file_rn are removed from the master file,
  844.     which has a refnum of master_file_rn.  */
  845.  
  846. OSErr
  847. RemoveFromMasterFile (INTEGER from_file_rn, INTEGER master_file_rn)
  848. {
  849.   mapping_t unmapping;
  850.   OSErr err;
  851.  
  852.   err = setup_unmap (from_file_rn, master_file_rn, &unmapping);
  853.   if (err == noErr)
  854.     {
  855.       link_t *headp;
  856.  
  857.       type_num_max = CountTypesRN (master_file_rn);
  858.       save_resload = ResLoad;
  859.       SetResLoad (false);
  860.       headp = 0;
  861.       for (type_num = 1; type_num <= type_num_max; ++type_num)
  862.     {
  863.       GetIndTypeRN (master_file_rn, &type, type_num);
  864.       res_num_max = CountResourcesRN (master_file_rn, type);
  865.       for (res_num = 1; res_num <= res_num_max; ++res_num)
  866.         {
  867.           h = GetIndResourceRN (master_file_rn, type, res_num);
  868.           GetResInfo (h, &id, &t, name);
  869.           if (delete_p (type, id, &unmapping))
  870.         {
  871.           link_t *newlinkp;
  872.           newlinkp = (link_t *) NewPtr (sizeof(link_t));
  873.           assert (newlinkp);
  874.           newlinkp->next = headp;
  875.           newlinkp->resource = h;
  876.           headp = newlinkp;
  877.         }
  878.         }
  879.     }
  880.       while (headp)
  881.     {
  882.       oldp = headp;
  883.       headp = headp->next;
  884.       RmveResource (oldp->resource);
  885.       DisposPtr (oldp);
  886.     }
  887.     }
  888.   return err;
  889. }
  890.  
  891. #endif /* defined( REMOVE_FROM_MASTER_FILE_SUPPORT ) */
  892.