home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / comm / revrdist.sit / RevRdist / RevRdist src / pref.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-30  |  25.0 KB  |  1,146 lines  |  [TEXT/KAHL]

  1. /*
  2.  * pref.c - routines to handle preferences dialog
  3.  */
  4.  
  5. #include "RevRdist.h"
  6. #include <TransSkelProto.h>
  7.  
  8. static Boolean            cancelled;
  9. static Boolean            prefAltered = 0;
  10.  
  11. static Integer            curItem = 0;    /* current editText field */
  12.  
  13. /*
  14.  * Special keycodes
  15.  */
  16. #define    ENTER        0x03
  17. #define    BACKSPACE    0x08
  18. #define    TAB            0x09
  19. #define    RETURN        0x0d
  20. #define    CLEAR        0x1b
  21.  
  22. /*
  23.  * prefinfo - mapping among preference resource id's, Prefs[].p[] indexes,
  24.  *    and preferences dialog item numbers.
  25.  * Note that not all values apply to all entries.
  26.  */
  27. static struct prefinfo
  28. {
  29.     Integer        p_id;            /* Resource ID of preference */
  30.     Integer        p_in;            /* Item number in dialog */
  31.     StringPtr    p_nm;            /* Name of resource */
  32. } pi[] = {
  33.      { STR_ZONE,        PRF_ZONE,        0 } /* PS_ZONE */
  34.     ,{ STR_SRVR,        PRF_SRVR,        0 }    /* PS_SRVR */
  35.     ,{ STR_USER,        PRF_USER,        0 }    /* PS_USER */
  36.     ,{ STR_PASS,        PRF_PASS,        0 }    /* PS_PASS */
  37.     ,{ STR_DISTF,        PRF_DISTF,        0 }    /* PS_DISTF */
  38.     ,{ STR_MASTF,        PRF_MASTF,        0 }    /* PS_MASTF */
  39.     ,{ STR_JUNKF,        PRF_JUNKF,        0 }    /* PS_JUNKF */
  40.     ,{ JUNK_PARM,        0,                0 }    /* PS_MAX & Junking info */
  41.     ,{ TIME_INTERVAL,    PRF_INTERVAL,    0 }    /* PS_TIME */
  42.     ,{ 0,                PRF_JMIN,        0 }    /* split-out parts of junk info */
  43.     ,{ 0,                PRF_JMAX,        0 }
  44.     ,{ 0,                PRF_DMIN,        0 }        
  45. };
  46.  
  47. #define    PICOUNT    (sizeof pi / sizeof (struct prefinfo))
  48.  
  49. /*
  50.  * Options to setPref()
  51.  */
  52. enum sp_action
  53. {
  54.      SP_WORKTODIALOG                /* copy P_WORK to dialog */
  55.     ,SP_DIALOGTOWORK                /* copy dialog values to P_WORK */
  56.     ,SP_CHECKONLY                    /* check if dialog and P_WORK differ */
  57. };
  58.  
  59. static void prefEvent (Integer, EventRecord *);
  60. static void prefClose (void);
  61. static void prefClobber (void);
  62. static void prefDoActivate (Integer);
  63. static OSErr prefOpen (void);
  64. static void prefSetLong (Integer, Longint);
  65. static void prefSetText (Integer, StringHandle);
  66. static pascal Boolean prefSFGfilter (ParmBlkPtr);
  67. static OSErr prefWrite (void);
  68. static void edittext (Integer, Integer, Integer);
  69. static void setPref (enum sp_action);
  70.  
  71.  
  72.  
  73. /*
  74.  *=========================================================================
  75.  * doPref () - start up preferences dialog
  76.  * exit:    PrefDialog set
  77.  *=========================================================================
  78.  */
  79. void
  80. doPref ()
  81. {
  82.  
  83.     cancelled = false;
  84.     if (Flags & DB_LOCKED)
  85.         return;
  86.     if (PrefDialog)
  87.     {
  88.         SelectWindow ((WindowPtr) PrefDialog);
  89.     }
  90.     else
  91.     {
  92.         PrefDialog =
  93.             GetNewDialog (RSRC_BASE+WIND_PREF, nil, (WindowPtr) -1L);
  94.         if (PrefDialog == nil)
  95.             return;
  96.         SkelDialog (PrefDialog, prefEvent, prefClose, prefClobber);
  97.         setPref (SP_WORKTODIALOG);
  98.     }
  99.     ShowWindow ((WindowPtr) PrefDialog);
  100. }
  101.  
  102.  
  103.  
  104. /*
  105.  *=========================================================================
  106.  * prefClobber () - get rid of the preferences dialog resources
  107.  *=========================================================================
  108.  */
  109. void
  110. prefClobber ()
  111. {
  112.     if (PrefDialog)
  113.         DisposDialog (PrefDialog);
  114.     PrefDialog = nil;
  115. }
  116.  
  117.  
  118. /*
  119.  *=========================================================================
  120.  * prefClose () - exit the preferences dialog
  121.  * entry:    cancelled true if dialog closed via cancel button
  122.  * exit:    preferences (possibly) set based on final values in dialog
  123.  *=========================================================================
  124.  */
  125. void
  126. prefClose ()
  127. {
  128.  
  129.     if (! cancelled)
  130.     {
  131.         setPref (SP_DIALOGTOWORK);
  132.         prefDoFMenu (FILE_CLOSE);
  133.         if (cancelled)
  134.             return;
  135.     }
  136.     prefDoActivate (0);
  137.     cancelled = false;
  138.     SkelRmveDlog (PrefDialog);
  139. }
  140.  
  141.  
  142. /*
  143.  *=========================================================================
  144.  * prefDoActivate (flag) - handle activate/deactivate events
  145.  * entry:    flag <> 0 if activate, 0 for deactivate
  146.  *=========================================================================
  147.  */
  148. static
  149. void
  150. prefDoActivate (flag)
  151.     Integer        flag;
  152. {
  153.     MenuHandle        m;                /* handle for File menu */
  154.  
  155.     if (Flags & DB_LOCKED)
  156.         flag = 0;
  157.     m = GetMHandle (2);            /* enable/disable file-related items */
  158.     if (m)
  159.     {
  160.         if (flag)
  161.         {
  162.             EnableItem (m, FILE_OPEN);
  163.             EnableItem (m, FILE_SAVE);
  164.             EnableItem (m, FILE_SAVEAS);
  165.         }
  166.         else
  167.         {
  168.             DisableItem (m, FILE_OPEN);
  169.             DisableItem (m, FILE_SAVE);
  170.             DisableItem (m, FILE_SAVEAS);
  171.         }
  172.     }
  173.     m = GetMHandle (3);
  174.     if (m)
  175.     {
  176.         if (flag)                    /* enable/disable Edit menu */
  177.             EnableItem (m, 0);
  178.         else
  179.             DisableItem (m, 0);
  180.         DrawMenuBar ();
  181.     }
  182. }
  183.  
  184.  
  185. /*
  186.  *=========================================================================
  187.  * prefDoFMenu (itemNo) - handle File menu for preferences
  188.  * entry:    item = selected item number
  189.  *=========================================================================
  190.  */
  191.  
  192. void
  193. prefDoFMenu (itemNo)
  194.     Integer            itemNo;
  195. {
  196.     cnode_t *            cn;            /* ptr to fi->f_info */
  197.     OSErr                error;
  198.     file_info_t *        fi;            /* ptr to prefs file info */
  199.     Integer                i;            /* temp */
  200.     prefs_t *            pw;            /* ptr to working prefs */
  201.     prefs_t *            pf;            /* ptr to file prefs */
  202.     Integer                ref;        /* refNum for prefs file */
  203.     Boolean                savemod;    /* initial value of p_modified */
  204.     StringHandle        sh;            /* handle to prompt, etc */
  205.     Boolean                wasset;        /* previous value of f_set */
  206.     Point                where;        /* for SF package */
  207.     CInfoPBRec            cb;
  208.     SFReply                reply;
  209.     Str255                s;            /* string temp */
  210.     SFTypeList            sftypes;
  211.  
  212.     if (!PrefDialog)
  213.         return;
  214.     fi = &File_list[FL_PREF];
  215.     cn = &fi->f_info;
  216.     pw = &Prefs[P_WORK];
  217.     pf = &Prefs[P_FILE];
  218.     wasset = fi->f_set;
  219.     cancelled = false;
  220.     Clue0 = (SP)"\pdoPrefMenu";
  221.     where.h = 100; where.v = 100;
  222.     
  223.     switch (itemNo)
  224.     {
  225.     case FILE_SAVEAS:
  226.         fi = &File_list[FL_TEMP];
  227.         cn = &fi->f_info;
  228.         freeInfo (fi);
  229.         GetWTitle (PrefDialog, s);
  230.         if (s[0] < sizeof (cn->name))
  231.             COPYPS (s, cn->name);
  232.         pw->p_modified = true;
  233.  
  234.         /* fall into */
  235.     case FILE_SAVE:
  236.         if (! wasset)
  237.             pw->p_modified = true;    /* force writing */
  238.         setPref (SP_DIALOGTOWORK);    /* copy values from dialog to work */
  239.         prefMerge (P_FILE, false);    /* copy from work to file */
  240.         if (pw->p_modified)
  241.         {
  242.             /*
  243.              * Even if we think we know about a file, check that it
  244.              * is still there, since the user might delete it while
  245.              * we aren't looking
  246.              */
  247.             if (fi->f_set)
  248.             {
  249.                 error = getInfo (cn->name, fi->f_vol, cn->parID, cn);
  250.                 if (error ||
  251.                     (cn->in.f.finfo.fdCreator != CREATOR &&
  252.                      cn->in.f.finfo.fdType != TYPE_CONT))
  253.                 {
  254.                     fi->f_set = 0;
  255.                     fi->f_vol = 0;
  256.                 }
  257.             }
  258.             if (!fi->f_set && cn->name[0] == 0)
  259.             {
  260.                 sh = (StringHandle) GetResource ('STR ', STR_PREFS);
  261.                 if (**sh < sizeof (cn->name))
  262.                     COPYPS (*sh, cn->name);
  263.                 ReleaseResource ((Handle) sh);
  264.             }
  265.             while (!fi->f_set)
  266.             {
  267.             /*
  268.              * Keep trying to save until succeed or user cancels
  269.              */
  270.                 sh = (StringHandle) GetResource ('STR ', STR_PSAVE);
  271.                 HLock ((Handle) sh);
  272.                 SFPutFile (where, *sh, cn->name, (ProcPtr) 0,
  273.                     &reply);
  274.                 HUnlock ((Handle) sh);
  275.                 ReleaseResource ((Handle) sh);
  276.                 if (reply.good == false)
  277.                 {
  278.                     cancelled = true;
  279.                     break;
  280.                 }
  281.                 SetVol (nil, reply.vRefNum);
  282.                 CreateResFile (reply.fName);
  283.                 error = ResError ();
  284.                 if (error)
  285.                 {
  286.                     if (error != dupFNErr)
  287.                     {
  288. syserr:
  289.                         ClueID = error;
  290.                         panic (false, E_FILE, reply.fName, nil);
  291.                         if (Quit)
  292.                         {
  293.                             Quit = false;
  294.                             break;
  295.                         }
  296.                         continue;
  297.                     }
  298.                     fi->f_vol = reply.vRefNum;
  299.                     error = getInfoByPath (reply.fName, fi);
  300.                     if (error)
  301.                         goto syserr;
  302.                     if (cn->in.f.finfo.fdCreator != CREATOR &&
  303.                         cn->in.f.finfo.fdType != TYPE_CONT)
  304.                     {
  305.                         panic (true, E_TYPE, reply.fName, nil);
  306.                         Quit = false;
  307.                         continue;
  308.                     }
  309.                 }
  310.                 else
  311.                 {
  312.                     /*
  313.                      * If we created it, we need to set its finder info
  314.                      */
  315.                     ZERO (cb);
  316.                     cb.hFileInfo.ioNamePtr = reply.fName;
  317.                     cb.hFileInfo.ioVRefNum = reply.vRefNum;
  318.                     if (error = PBGetCatInfo (&cb, false))
  319.                         goto syserr;
  320.                     cb.hFileInfo.ioDirID = 0;
  321.                     cb.hFileInfo.ioFlFndrInfo.fdType = TYPE_PREF;
  322.                     cb.hFileInfo.ioFlFndrInfo.fdCreator = CREATOR;
  323.                     if (error = PBSetCatInfo (&cb, false))
  324.                         goto syserr;
  325.                     fi->f_vol = reply.vRefNum;
  326.                     if (error = getInfoByPath (reply.fName, fi))
  327.                         goto syserr;
  328.                 }
  329.             } /* end while */
  330.             if (!fi->f_set)
  331.                 break;
  332.             /*
  333.              * Finally, open the file
  334.              */
  335.             sh = fi->f_path;
  336.             HLock ((Handle) sh);
  337.             ref = OpenRFPerm(*sh, fi->f_vol, fsRdWrPerm);
  338.             HUnlock ((Handle) sh);
  339.             if (ref == -1)
  340.             {
  341.                 ClueID = ResError ();
  342.                 panic (true, E_FILE, cn->name, nil);
  343.                 pw->p_modified = true;
  344.                 Quit = false;
  345.                 cancelled = true;
  346.                 break;
  347.             }
  348.             fi->f_ref = ref;
  349.             error = prefWrite ();
  350.             CloseResFile (ref);
  351.             fi->f_ref = 0;
  352.             if (error)
  353.             {
  354.                 ClueID = error;
  355.                 panic (true, E_SYS, (SP)"\pprefWrite", nil);
  356.                 Quit = false;
  357.                 pw->p_modified = true;
  358.                 pf->p_modified = true;
  359.                 cancelled = true;
  360.                 break;
  361.             }
  362.             pw->p_modified = false;
  363.             if (fi == &File_list[FL_TEMP])
  364.             {
  365.                 /*
  366.                  * If we used FL_TEMP, copy to FL_PREF and zap FL_TEMP
  367.                  */
  368.                 freeInfo (&File_list[FL_PREF]);
  369.                 File_list[FL_PREF] = *fi;
  370.                 ZEROAT (fi);
  371.                 fi = &File_list[FL_PREF];
  372.                 cn = &fi->f_info;
  373.             }
  374.             SetWTitle (PrefDialog, cn->name);
  375.         } /* end if modified */
  376.         break;
  377.  
  378.     case FILE_OPEN:
  379.     case FILE_CLOSE:
  380.         /*
  381.          * Check if we should save changes before closing
  382.          */
  383.         savemod = pw->p_modified;
  384.         if (pw->p_modified || (setPref (SP_CHECKONLY), pw->p_modified))
  385.         {
  386.             pw->p_modified = savemod;
  387.             GetWTitle (PrefDialog, s);
  388.             ParamText (s, nil, nil, nil);
  389.             i = CautionAlert (RSRC_BASE+ALERT_SAVE, nil);
  390.             if (i == SAVE_CANCEL)
  391.             {
  392.                 cancelled = true;
  393.                 break;
  394.             }
  395.             if (i == SAVE_YES)
  396.             {
  397.                 prefDoFMenu (FILE_SAVE);
  398.                 if (cancelled)
  399.                     break;
  400.             }
  401.         }
  402.         pw->p_modified = false;
  403.         pf->p_modified = false;
  404.         if (fi->f_set && fi->f_ref)
  405.             CloseResFile (fi->f_ref);
  406.         fi->f_ref = 0;
  407.         fi->f_set = false;
  408.         if (itemNo != FILE_OPEN)
  409.             break;
  410.         
  411.         /*
  412.          * Continue with opening file
  413.          */
  414.         sftypes[0] = TYPE_PREF;
  415.         sftypes[1] = TYPE_CONT;
  416.         sftypes[2] = 'APPL';
  417.         SFGetFile (where, (SP)"", (FilterProc)prefSFGfilter, 3, &sftypes,
  418.                     (ProcPtr)nil, &reply);
  419.         if (reply.good == false)
  420.             break;
  421.         fi->f_vol = reply.vRefNum;
  422.         error = getInfoByPath (reply.fName, fi);
  423.         if (!error)
  424.             error = prefFFetch (fi);
  425.         if (!error)
  426.         {
  427.             prefMerge (P_WORK, false);
  428.             setPref (SP_WORKTODIALOG);
  429.         }
  430.         if (error)
  431.         {
  432.             ClueID = error;
  433.             panic (false, E_FILE, reply.fName, nil);
  434.             Quit = false;
  435.             fi->f_set = false;
  436.         }
  437.         break;
  438.     } /* end itemNo switch */
  439.     if (cancelled)
  440.         Quit = false;
  441. }
  442.  
  443.  
  444. /*
  445.  *=========================================================================
  446.  * prefEvent (itemNo, theEvent) - handle events in preferences dialog
  447.  * entry:    itemNo = the item number in dialog
  448.  *            theEvent = ptr to event record significant to dialog
  449.  *=========================================================================
  450.  */
  451. void
  452. prefEvent (itemNo, theEvent)
  453.     Integer            itemNo;
  454.     EventRecord *    theEvent;
  455. {
  456.     Integer            key;            /* key character or code */
  457.  
  458.     switch (theEvent->what)
  459.     {
  460.     case mouseDown:
  461.     /*
  462.      * If we have an active editText item, close it out first
  463.      */
  464.         if (curItem)
  465.             edittext (curItem, 0, 0);
  466.         curItem = 0;
  467.         switch (itemNo)
  468.         {
  469.         case PRF_CANCEL:
  470.             cancelled = true;
  471.             prefClose ();
  472.             break;
  473.         case PRF_GO:
  474.             Pending = PA_GO;
  475.             setPref (SP_DIALOGTOWORK);
  476.             HideWindow (PrefDialog);
  477.             break;
  478.         }
  479.         break;
  480.  
  481.     case keyDown:
  482.         key = theEvent->message & 0xff;
  483.         if (key == '\t')
  484.         {
  485.             /*
  486.              * On tab, the supplied item is the *next* item, rather than
  487.              * the one just left
  488.              */
  489.             itemNo -= 2;
  490.             if (itemNo <= 2)
  491.                 itemNo = PRF_LAST;
  492.         }
  493.         edittext (itemNo, key, theEvent->modifiers);
  494.         break;
  495.         
  496.     case activateEvt:
  497.         prefDoActivate (theEvent->modifiers & activeFlag);
  498.         break;
  499.     }
  500. }
  501.  
  502.  
  503.  
  504. /*
  505.  *=========================================================================
  506.  * prefFetch (ref) - fetch preferences from resource file
  507.  * entry:    ref = fRefNum of opened resource file
  508.  * returns:    0 if no problems
  509.  *            <> 0 = system error
  510.  *            Note: a missing resource does not count as a problem
  511.  *=========================================================================
  512.  */
  513.  
  514. OSErr
  515. prefFetch (res)
  516.     Integer res;
  517. {
  518.             OSErr            error = 0;
  519.             Handle            h;
  520.             int                i;            /* Prefs[].p[] index */
  521.             Integer            id;            /* for GetResInfo */
  522.             Ptr                p;            /* temp pointer */
  523.             Integer            saveres;    /* current resource file */
  524. register    StringHandle    sh;
  525.             ResType            type;        /* for GetResInfo */
  526.             Str255            s;            /* resource name from GetResInfo */
  527.  
  528.     saveres = CurResFile ();
  529.     if (saveres != res)
  530.     {
  531.         UseResFile (res);
  532.         error = ResError ();
  533.         if (error)
  534.         {
  535.             saveres = res;
  536.             goto errout;
  537.         }
  538.     }
  539.     /*
  540.      * Free any FILE handles which differ from the WORK ones
  541.      */
  542.     for (i = 0; i < PS_MAX; i++)
  543.     {
  544.         if ((sh = Prefs[P_FILE].p[i]) != 0 && sh != Prefs[P_WORK].p[i])
  545.             DisposHandle ((Handle) sh);
  546.     }
  547.     setmem ((char *)&Prefs[P_FILE], sizeof (prefs_t), 0);
  548.  
  549.     /*
  550.      * Fetch new values from resource file.  It is not an error for the
  551.      * resource to not exist.
  552.      * Also, save the name of a resource the first time we encounter one.
  553.      */
  554.     for (i = 0; i <= PS_MAX + 1; i++)
  555.     {
  556.         sh = (StringHandle) Get1Resource ((i < PS_MAX) ? 'STR ' : TYPE_LONG,
  557.                                 pi[i].p_id);
  558.         if (sh)
  559.         {
  560.             if (pi[i].p_nm == 0)
  561.             {
  562.                 GetResInfo ((Handle)sh, &id, &type, (SP)s);
  563.                 if (type == 'STR ' && s[0])
  564.                 {
  565.                     p = NewPtr ((Size) s[0] + 1);
  566.                     if (p)
  567.                         COPYPS (s, p);
  568.                     pi[i].p_nm = (StringPtr) p;
  569.                 }
  570.             }
  571.         }
  572.         else
  573.             if ((error = ResError ()) != resNotFound && error != 0)
  574.                 goto errout;
  575.         if (i < PS_MAX)
  576.         {
  577.             Prefs[P_FILE].p[i] = sh;
  578.             if (sh)
  579.                 DetachResource ((Handle) sh);
  580.         }
  581.         else
  582.         {
  583.             if (sh)
  584.             {
  585.                 switch (i)
  586.                 {
  587.                 case PS_MAX:
  588.                     BlockMove (*sh, (Ptr)&Prefs[P_FILE].p_jparam,
  589.                         sizeof (junkp_t));
  590.                     break;
  591.                 case PS_TIME:
  592.                     BlockMove (*sh, (Ptr)&Prefs[P_FILE].p_interval,
  593.                         sizeof (Prefs[P_FILE].p_interval));
  594.                     break;
  595.                 }
  596.                 ReleaseResource ((Handle) sh);
  597.             }
  598.         }
  599.     }
  600.  
  601.     error = 0;
  602.     Prefs[P_FILE].p_modified = false;
  603.     if (res != saveres)
  604.     {
  605.         UseResFile (saveres);
  606.         error = ResError ();
  607.     }
  608.     return error;
  609.  
  610. errout:
  611.     if (error == 0)
  612.         error = ResError ();
  613.     if (error == 0)
  614.         error = memFullErr;
  615.     if (res != saveres)
  616.         UseResFile (saveres);
  617.     return error;
  618. }
  619.  
  620.  
  621. /*
  622.  *=========================================================================
  623.  * prefFFetch (fi) - open preferences file and then fetch values
  624.  * entry:    fi = ptr to file_info structure describing file to open
  625.  * exit:    0 if no error, preferences fetched, file closed
  626.  *            OSErr on error
  627.  *=========================================================================
  628.  */
  629. OSErr
  630. prefFFetch (fi)
  631. register file_info_t *    fi;
  632. {
  633.     OSErr                error;
  634.     Integer                firef;            /* value from fi->f_ref */
  635.     Integer                ref;            /* file reference */
  636.     
  637.     ref = firef = fi->f_ref;
  638.     if (ref == 0)
  639.     {
  640.         HLock ((Handle) fi->f_path);
  641.         ref = OpenRFPerm (*fi->f_path, fi->f_vol, fsRdPerm);
  642.         HUnlock ((Handle) fi->f_path);
  643.         if (ref == -1)
  644.         {
  645.             error = ResError ();
  646.             if (error == 0)
  647.                 error = fnfErr;
  648.             return error;
  649.         }
  650.         fi->f_ref = ref;
  651.     }
  652.     error = prefFetch (ref);
  653.     if (firef == 0)                    /* if we opened file, close it */
  654.     {
  655.         (void) CloseResFile (ref);
  656.         fi->f_ref = 0;
  657.     }
  658.     return (error);
  659. }
  660.  
  661.  
  662.  
  663.  
  664. /*
  665.  *=========================================================================
  666.  * prefMerge (dest, merge) - copy preferences between Prefs[] elements
  667.  * entry:    dest = which element is the destination [P_WORK, P_FILE]
  668.  *            merge = false to copy in toto, true to copy only if not null
  669.  *=========================================================================
  670.  */
  671. void
  672. prefMerge (dest, merge)
  673.     pindex_t        dest;
  674.     Boolean            merge;
  675. {
  676.     int                i;
  677.     StringHandle    sh;
  678.     pindex_t        src;
  679.     
  680.     src = (dest == P_WORK) ? P_FILE : P_WORK;
  681.     Prefs[dest].p_modified = true;
  682.     if (!merge)
  683.     {
  684.         /*
  685.          * Here to copy/replace
  686.          */
  687.         for (i = 0; i < PS_MAX; i++)
  688.         {
  689.             if ((sh = Prefs[dest].p[i]) != 0 && sh != Prefs[src].p[i])
  690.                      DisposHandle ((Handle) sh);
  691.         }
  692.         Prefs[dest] = Prefs[src];
  693.         return;
  694.     }
  695.     /*
  696.      * Here to merge
  697.      */
  698.     for (i = 0; i < PS_MAX; i++)
  699.     {
  700.         if (Prefs[src].p[i] != 0)
  701.         {
  702.             if ((sh = Prefs[dest].p[i]) != 0 && sh != Prefs[src].p[i])
  703.                 DisposHandle ((Handle) sh);
  704.             Prefs[dest].p[i] = Prefs[src].p[i];
  705.         }
  706.     }
  707.     if (Prefs[src].p_interval != 0)
  708.         Prefs[dest].p_interval = Prefs[src].p_interval;
  709.     if (Prefs[src].p_jparam.min != 0)
  710.         Prefs[dest].p_jparam.min = Prefs[src].p_jparam.min;
  711.     if (Prefs[src].p_jparam.max != 0)
  712.         Prefs[dest].p_jparam.max = Prefs[src].p_jparam.max;
  713.     if (Prefs[src].p_jparam.space != 0)
  714.         Prefs[dest].p_jparam.space = Prefs[src].p_jparam.space;
  715. }
  716.  
  717.  
  718.  
  719. /*
  720.  *=========================================================================
  721.  * prefSetLong(itemNo, value) - set pref dialog item value from long integer
  722.  * entry:    itemNo = dialog item number
  723.  *            value = new value
  724.  *=========================================================================
  725.  */
  726. void
  727. prefSetLong (itemNo, value)
  728.     Integer        itemNo;
  729.     Longint        value;
  730. {
  731.     Handle        item;
  732.     Integer        itemType;
  733.     Rect        r;
  734.     Str255        st;
  735.  
  736.     itemType = -1;
  737.     GetDItem (PrefDialog, itemNo, &itemType, &item, &r);
  738.     if (itemType == editText)
  739.     {
  740.         NumToString (value, (SP) st);
  741.         SetIText (item, (SP) st);
  742.     }
  743. }
  744.  
  745.  
  746.  
  747. /*
  748.  *=========================================================================
  749.  * prefSetText (itemNo, sh) - set pref dialog value from handle
  750.  * entry:    itemNo = item number to change
  751.  *            sh = handle to string containing new value
  752.  *=========================================================================
  753.  */
  754. void
  755. prefSetText (itemNo, sh)
  756.     Integer            itemNo;
  757.     StringHandle    sh;
  758. {
  759.     Handle        item;
  760.     Integer        itemType;
  761.     Rect        r;
  762.     SignedByte    handleState;
  763.     
  764.     itemType = -1;
  765.     GetDItem (PrefDialog, itemNo, &itemType, &item, &r);
  766.     
  767.     if (sh && *sh && itemType == editText)
  768.     {
  769.         handleState = HGetState ((Handle) sh);
  770.         HLock ((Handle) sh);
  771.         SetIText (item, *sh);
  772.         HSetState ((Handle) sh, handleState);
  773.     }
  774. }
  775.  
  776.  
  777. /*
  778.  *=========================================================================
  779.  * prefSFGfilter (pb) - filter for SFGetFile call to open existing prefs file
  780.  * entry:    pb = pointer to paramBlock with info about potential file
  781.  *=========================================================================
  782.  */
  783. pascal
  784. Boolean
  785. prefSFGfilter (pb)
  786.     ParmBlkPtr        pb;
  787. {
  788.     /*
  789.      * File must have resource fork
  790.      */
  791.     if (pb->fileParam.ioFlRLgLen == 0)
  792.         return true;
  793.     /*
  794.      * If it is application, it must be copy of RevRdist
  795.      */
  796.     if (pb->fileParam.ioFlFndrInfo.fdType == 'APPL'
  797.     &&  pb->fileParam.ioFlFndrInfo.fdCreator != CREATOR)
  798.         return true;
  799.     return false;
  800. }
  801.  
  802.  
  803.  
  804.  
  805. /*
  806.  *=========================================================================
  807.  * prefWrite () - Write FILE preferences to file
  808.  * entry:    CurResFile() is the file to write the resources to
  809.  * returns:    0 if no error, else OSErr
  810.  *=========================================================================
  811.  */
  812. OSErr
  813. prefWrite ()
  814. {
  815.     OSErr            error;
  816.     int                i;
  817.     Integer            id;                    /* resource id */
  818.     Handle            h1, h2;
  819.     Size            len;                /* needed resource size */
  820.     prefs_t *        p;                    /* ptr to Prefs[P_FILE] */
  821.     Ptr                vp;                    /* temp pointer */
  822.  
  823.     error = 0;
  824.     p = &Prefs[P_FILE];
  825.     /*
  826.      * First, write the string resources
  827.      */
  828.     for (i = 0; i < PS_MAX; i++)
  829.     {
  830.         h1 = (Handle) p->p[i];
  831.         if (h1 == 0)
  832.             continue;
  833.         id = pi[i].p_id;
  834.         h2 = Get1Resource ('STR ', id);
  835.         if (h2 == 0)
  836.         {
  837.             h2 = h1;
  838.             error = HandToHand (&h2);
  839.             if (error) goto syserr;
  840.             AddResource (h2, 'STR ', id, pi[i].p_nm);
  841.             if (error = ResError ()) goto syserr;
  842.         }
  843.         else
  844.         {
  845.             len = **h1 + 1;
  846.             SetHandleSize (h2, len);
  847.             if (error = MemError ())
  848.                 goto syserr;
  849.             COPYPS ((SP)(*h1), (SP)(*h2));
  850.             ChangedResource (h2);
  851.         }
  852.     }
  853.     /*
  854.      * Ditto for the junking parameters
  855.      */
  856.     error = 0;
  857.     for (i = PS_MAX; i <= PS_TIME; i++)
  858.     {
  859.         id = pi[i].p_id;
  860.         switch (id)
  861.         {
  862.         case JUNK_PARM:
  863.             len = sizeof (junkp_t);
  864.             vp = (Ptr)&p->p_jparam;
  865.             break;
  866.         case TIME_INTERVAL:
  867.             len = sizeof (p->p_interval);
  868.             vp = (Ptr)&p->p_interval;
  869.             break;
  870.         default:
  871.             continue;
  872.         }
  873.         h2 = Get1Resource (TYPE_LONG, id);
  874.         if (h2 == 0)
  875.         {
  876.             h2 = NewHandle (len);
  877.             if (h2 == 0)
  878.                 goto syserr;
  879.             AddResource (h2, TYPE_LONG, id, pi[i].p_nm);
  880.             if (error = ResError ()) goto syserr;
  881.         }
  882.         else
  883.         {
  884.             SetHandleSize (h2, len);
  885.         }
  886.         BlockMove (vp, *h2, len);
  887.         ChangedResource (h2);
  888.         error = ResError ();
  889.         if (error)
  890.             goto syserr;
  891.     }
  892.     Prefs[P_FILE].p_modified = false;
  893.     return error;
  894.  
  895. syserr:
  896.     if (error == 0)
  897.         error = memFullErr;
  898.     return error;
  899. }
  900.  
  901.  
  902. /*
  903.  *=========================================================================
  904.  * edittext (itemNo, key, modifiers) - handle keyDown in dialog item
  905.  * entry:    itemNo = affected item number
  906.  *            key = character code
  907.  *            modifiers = modifiers from eventRecord
  908.  *=========================================================================
  909.  */
  910. static
  911. void
  912. edittext (itemNo, key, modifiers)
  913.     Integer            itemNo;
  914.     Integer            key;
  915.     Integer            modifiers;
  916. {
  917.     Boolean            changed;        /* item string altered ? */
  918.     int                i;                /* temp */
  919.     Integer            itemType;        /* dialog item type */
  920.     Handle            item;            /* dialog item structure */
  921.     Longint            l;                /* long temp */
  922.     Rect            r;                /* needed for GetDItem */
  923.     Integer            t;                /* temp */
  924.     Str255            st;                /* string temp */
  925.  
  926.     /*
  927.      * See if it's an item we care about
  928.      */
  929.     for (i = 0; i < PICOUNT; i++)
  930.         if (pi[i].p_in == itemNo)
  931.             break;
  932.     if (i >= PICOUNT)
  933.     {
  934.         curItem = 0;
  935.         return;                        /* don't care */
  936.     }
  937.     if (key == BACKSPACE && modifiers & shiftKey)
  938.         key = CLEAR;
  939.     GetDItem (PrefDialog, itemNo, &itemType, &item, &r);
  940.     GetIText (item, (SP) st);
  941.     changed = false;
  942.     /*
  943.      * On CLEAR key, restore original value
  944.      */
  945.     if (key == CLEAR)
  946.     {
  947.         prefs_t *        p;
  948.         
  949.         p = &Prefs[P_WORK];
  950.         if (i < PS_MAX)
  951.             COPYPS (*p->p[i], st);
  952.         else
  953.         {
  954.             switch (itemNo)
  955.             {
  956.             case PRF_INTERVAL:    l = p->p_interval; break;
  957.             case PRF_JMIN:        l = p->p_jparam.min; break;
  958.             case PRF_JMAX:        l = p->p_jparam.max; break;
  959.             case PRF_DMIN:        l = p->p_jparam.space; break;
  960.             default:
  961.                 goto skip;
  962.             }
  963.             NumToString (l, st);
  964.         }
  965. skip:
  966.         changed = true;
  967.     }
  968.     /*
  969.      * Handle finishing with an item
  970.      */
  971.     if (key == ENTER || key == TAB || key == RETURN || key == 0)
  972.     {
  973.         if (key && st[st[0]] == key)
  974.         {
  975.             st[0]--;
  976.             changed = true;
  977.         }
  978.         if (i >= PS_MAX)
  979.         {
  980.             StringToNum ((SP) st, &l);
  981.             NumToString (l, (SP) st);
  982.             changed = true;
  983.         }
  984.     }
  985.     if (changed)
  986.         SetIText (item, st);
  987.     if (key == ENTER || key == RETURN)
  988.     {
  989.         itemNo += 2;
  990.         if (itemNo > PRF_LAST)
  991.             itemNo = PRF_SRVR;
  992.         SelIText (PrefDialog, itemNo, 0, 32767);
  993.     }
  994.     if (key == CLEAR)
  995.     {
  996.         t = st[0];
  997.         SelIText (PrefDialog, itemNo, t, t);
  998.     }
  999.     curItem = itemNo;
  1000. }
  1001.  
  1002.  
  1003.  
  1004. /*
  1005.  *=========================================================================
  1006.  * setPref (flag) - set preference variables to/from dialog contents
  1007.  * entry:    flag =     SP_WORKTODIALOG -> copy values from P_WORK to dialog
  1008.  *                    SP_DIALOGTOWORK -> copy the other way
  1009.  *                    SP_CHECKONLY -> same as SP_DIALOGTOWORK, except that
  1010.  *                        no values are changed, but p_modified is set if
  1011.  *                        any would have been changed.
  1012.  *             PrefDialog set
  1013.  * exit:    Prefs[P_WORK].p_modified possibly set
  1014.  *=========================================================================
  1015.  */
  1016. void
  1017. setPref (action)
  1018.     enum sp_action        action;
  1019. {
  1020.     file_info_t *        fi;
  1021.     int                    i, j;            /* temp index */
  1022.     Handle                item;            /* for GetDItem */
  1023.     Integer                itemType;        /* for GetDItem */
  1024.     Boolean                modified;        /* set true if dialog value changed */
  1025.     prefs_t *            p;
  1026.     Rect                r;                /* for GetDItem */
  1027.     StringHandle        sh;
  1028.     Longint                value;            /* temp value for junking params */
  1029.     unsigned long *        vp;                /* pointer to a value */
  1030.     junkp_t                jparam;            /* copy of junking params */
  1031.     Str255                s;                /* string temp */
  1032.  
  1033.     fi = &File_list[FL_PREF];
  1034.     p = &Prefs[P_WORK];
  1035.     jparam = p->p_jparam;
  1036.     modified = false;
  1037.     if (action == SP_WORKTODIALOG)
  1038.     {
  1039.         for (i = 0; i < PICOUNT; i++)
  1040.         {
  1041.             if (i < PS_MAX)
  1042.             {
  1043.                 sh = p->p[i];
  1044.                 if (sh)
  1045.                     prefSetText (pi[i].p_in, sh);
  1046.             }
  1047.             else
  1048.             {
  1049.                 switch (pi[i].p_in)
  1050.                 {
  1051.                 case PRF_INTERVAL:value = p->p_interval;    break;
  1052.                 case PRF_JMIN:    value = jparam.min;        break;
  1053.                 case PRF_JMAX:    value = jparam.max;        break;
  1054.                 case PRF_DMIN:    value = jparam.space;    break;
  1055.                 default:
  1056.                     continue;
  1057.                 }
  1058.                 prefSetLong (pi[i].p_in, value);
  1059.             }
  1060.         }
  1061.         /*
  1062.          * Set prefs window title to file name
  1063.          */
  1064.         if (fi->f_set)
  1065.             COPYPS (fi->f_info.name, s);
  1066.         else
  1067.             COPYPS (*Untitled, s);
  1068.         SetWTitle (PrefDialog, s);
  1069.         return;
  1070.     }
  1071.     /*
  1072.      * Here for DIALOGTOWORK and CHECKONLY
  1073.      */
  1074.     for (i = 0; i < PICOUNT; i++)
  1075.     {
  1076.         j = pi[i].p_in;
  1077.         if (j)
  1078.         {
  1079.             itemType = -1;
  1080.             GetDItem (PrefDialog, pi[i].p_in, &itemType, &item, &r);
  1081.             if (itemType != editText)
  1082.                 continue;            /* should not happen */
  1083.             GetIText (item, s);
  1084.         }
  1085.         if (i < PS_MAX)
  1086.         {
  1087.             /*
  1088.              * Handle simple strings
  1089.              */
  1090.             sh = p->p[i];
  1091.             if (s[0] == 0)
  1092.             {
  1093.                 if (sh == 0 || **sh == 0)
  1094.                     continue;
  1095.             }
  1096.             if (sh)
  1097.             {
  1098.                 HLock ((Handle) sh);
  1099.                 j = RelString (*sh, s, false, true);
  1100.                 HUnlock ((Handle) sh);
  1101.             }
  1102.             else
  1103.             {
  1104.                 sh = (StringHandle) NewHandle ((Size) s[0] + 1);
  1105.                 if (sh == 0)
  1106.                     continue;
  1107.                 p->p[i] = sh;
  1108.                 j = 1;
  1109.             }
  1110.             if (j)
  1111.             {
  1112.                 if (action == SP_DIALOGTOWORK)
  1113.                 {
  1114.                     SetHandleSize ((Handle) sh, (Size) s[0] + 1);
  1115.                     if (MemError ())
  1116.                         continue;
  1117.                     COPYPS (s, *sh);
  1118.                 }
  1119.                 modified = true;
  1120.             }
  1121.         }
  1122.         else
  1123.         {
  1124.             StringToNum (s, &value);
  1125.             switch (j)
  1126.             {
  1127.             case PRF_INTERVAL:vp = &p->p_interval;        break;
  1128.             case PRF_JMIN:    vp = &jparam.min;        break;
  1129.             case PRF_JMAX:    vp = &jparam.max;        break;
  1130.             case PRF_DMIN:    vp = &jparam.space;        break;
  1131.             default:
  1132.                 continue;
  1133.             }
  1134.             if ((unsigned long) value != *vp)
  1135.             {
  1136.                 if (action == SP_DIALOGTOWORK)
  1137.                     *vp = value;
  1138.                 modified = true;
  1139.             }
  1140.         }
  1141.     }
  1142.     if (action == SP_DIALOGTOWORK)
  1143.         p->p_jparam = jparam;
  1144.     if (modified)
  1145.         p->p_modified = true;
  1146. }