home *** CD-ROM | disk | FTP | other *** search
/ Executor 2.0 / executorv2.0.iso / pc / dos / extra / source / browser / browser.hqx / Browser / fontda.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-22  |  21.8 KB  |  944 lines

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