home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc095.zip / ckmsfp.c < prev    next >
C/C++ Source or Header  |  1989-08-22  |  17KB  |  518 lines

  1. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
  2. /* Ported to Megamax native Macintosh C compiler. */
  3. /* Edit by Bill on Wed May 15, 15:48 */
  4. /* change name of rtol to sfprtol, make it the common file rtol rtn */
  5. /* either use RSRC & BINA if .RSRC extension, or use current defaults */
  6. /* Edit by Bill on Wed May 15, 15:48 */
  7. /* in initfilerecv make sure kermit flag binary is set */
  8.  
  9. /*
  10.  * file ckmsfp.c
  11.  *
  12.  * Module of MacKermit containing standard file package calls:
  13.  *
  14.  *    dosenddialog() - Send file...
  15.  *    dorecvdialog() - Receive file...
  16.  *    dogetfdialog() - Get file from server...
  17.  *
  18.  * Bill Schilit, May, 1984
  19.  *
  20.  * Copyright (C) 1985, Trustees of Columbia University in the City of
  21.  * New York.  Permission is granted to any individual or institution to
  22.  * use, copy, or redistribute this software so long as it is not sold
  23.  * for profit, provided this copyright notice is retained.
  24.  *
  25.  */
  26.  
  27. #include "ckcdeb.h"
  28. #include "ckcker.h"        /* Kermit definitions */
  29.  
  30. #define    __SEG__ ckmsfp
  31. #include <ctype.h>
  32.  
  33. #include <files.h>
  34. #include <errors.h>
  35. #include <controls.h>
  36. #include <dialogs.h>
  37. #include <packages.h>
  38. #include <events.h>
  39.  
  40. #include "ckmdef.h"        /* Common Mac module definitions */
  41. #include "ckmres.h"        /* resource defs */
  42.  
  43. FILINF filargs;            /* is global */
  44.  
  45. int radflgs[] = {FIL_DATA, FIL_RSRC, FIL_TEXT, FIL_BINA};
  46. int radnotflgs[] = {FIL_RSRC, FIL_DATA, FIL_BINA, FIL_TEXT};
  47.  
  48. /* Globals used by SEND dialog */
  49.  
  50. SFReply sfr;            /* holds file info */
  51. Boolean sendselflg;        /* TRUE means file was selected */
  52. Boolean sendasflg;        /* TRUE means AS field is active */
  53.  
  54. int sendusercvdef = FALSE;    /* use rec. file mode defaults as send defaults */
  55.  
  56. /****************************************************************************/
  57. /* gethdl - return a control handle given a resource ID */
  58. /****************************************************************************/
  59. Handle
  60. gethdl (item, dp)
  61. DialogPtr dp;
  62. {
  63.     short itype;
  64.     Rect ibox;
  65.     Handle ihdl;
  66.  
  67.     GetDItem (dp, item, &itype, &ihdl, &ibox);
  68.     return (ihdl);
  69. }                /* gethdl */
  70.  
  71.  
  72.  
  73. /****************************************************************************/
  74. /* setfilflgs - Manage the filflg word and radio controls.
  75.  *
  76.  * Flags will be changed when the resource ID of item hit (passed to
  77.  * this routine) is one of the radio items, or alternately routines can
  78.  * modify the filflg word itself and the radio items will be updated
  79.  * accordingly.
  80.  *
  81.  * N.B. Each dialog using these flags has them defined with the same
  82.  * DITL item numbers.
  83.  *
  84.  */
  85. /****************************************************************************/
  86. setfilflgs (item, dlg)
  87. DialogPtr dlg;
  88. {
  89.     ControlHandle ctlhdl;
  90.     int i;
  91.  
  92.     switch(item) {
  93.     case RADITM_MACB:    /* MacBinary mode */
  94.     filargs.filflg &= ~FIL_TEXT;
  95.     filargs.filflg |= FIL_BINA | FIL_RSRC | FIL_DATA;
  96.     break;
  97.     
  98.     case RADITM_TEXT:    /* Text mode */
  99.     if ((filargs.filflg & (FIL_RSRC | FIL_DATA)) == (FIL_RSRC | FIL_DATA))
  100.         filargs.filflg &= ~FIL_RSRC;
  101.     filargs.filflg &= ~FIL_BINA;
  102.     filargs.filflg |= FIL_TEXT;
  103.     break;
  104.     
  105.     case RADITM_BINA:    /* Binary mode */
  106.     if ((filargs.filflg & (FIL_RSRC | FIL_DATA)) == (FIL_RSRC | FIL_DATA))
  107.         filargs.filflg &= ~FIL_RSRC;
  108.     filargs.filflg &= ~FIL_TEXT;
  109.     filargs.filflg |= FIL_BINA;
  110.     break;
  111.     
  112.     case RADITM_DATA:    /* Data fork */
  113.     filargs.filflg &= ~FIL_RSRC;
  114.     filargs.filflg |= FIL_DATA;
  115.     break;
  116.     
  117.     case RADITM_RSRC:    /* Resource fork */
  118.     filargs.filflg &= ~FIL_DATA;
  119.     filargs.filflg |= FIL_RSRC;
  120.     break;
  121.  
  122.     }
  123.     /* if MacBinary mode */
  124.     if ((filargs.filflg & (FIL_RSRC | FIL_DATA)) == (FIL_RSRC | FIL_DATA)) {
  125.     SetCtlValue (getctlhdl(RADITM_MACB, dlg), btnOn);
  126.     SetCtlValue (getctlhdl(RADITM_TEXT, dlg), btnOff);
  127.     SetCtlValue (getctlhdl(RADITM_BINA, dlg), btnOff);
  128.  
  129.     SetCtlValue (getctlhdl(RADITM_DATA, dlg), btnOn);
  130.     SetCtlValue (getctlhdl(RADITM_RSRC, dlg), btnOn);
  131.     HiliteControl(getctlhdl(RADITM_DATA, dlg), 255);  /* disable it */
  132.     HiliteControl(getctlhdl(RADITM_RSRC, dlg), 255);  /* disable it */
  133.     } else {    /* not MacBinary mode */
  134.     SetCtlValue (getctlhdl(RADITM_MACB, dlg), btnOff);
  135.     HiliteControl(getctlhdl(RADITM_DATA, dlg), 0);  /* enable it */
  136.     HiliteControl(getctlhdl(RADITM_RSRC, dlg), 0);  /* enable it */
  137.     for (i = RADITM_FIRST; i <= RADITM_LAST; i++) {    /* update all */
  138.         ctlhdl = getctlhdl (i, dlg);    /* get a handle on his radio item */
  139.         SetCtlValue (ctlhdl,
  140.            (filargs.filflg & radflgs[i - RADITM_FIRST]) ? btnOn : btnOff);
  141.     }
  142.     }
  143. }                /* setfilflgs */
  144.  
  145.  
  146.  
  147. /****************************************************************************/
  148. /****************************************************************************/
  149. setfilnams (remfid, dlg)
  150. DialogPtr dlg;
  151. {
  152.     filargs.filrem[0] = 0;    /* no remote file */
  153.  
  154.     strcpy (filargs.fillcl, &sfr.fName);    /* copy sfr into local name
  155.                          * stg */
  156.  
  157.     if (remfid != 0)        /* fetch remote name if present */
  158.     GetIText (gethdl (remfid, dlg), filargs.filrem);    /* in an edittext field */
  159.  
  160.     binary = (filargs.filflg & FIL_BINA);    /* selected binary mode? */
  161. }                /* setfilnams */
  162.  
  163.  
  164.  
  165. Boolean isfolder;
  166.  
  167. /****************************************************************************/
  168. /* sendmydlg - SFPGetFIle item hit filter for "send file" dialog.
  169.  *
  170.  * This filter is called by SFPGetFile to let the programmer handle hits
  171.  * on his custom items.  Our items are 2 sets of buttons for selecting
  172.  * the fork (data or resource) and the transfer mode (binary or text).
  173.  * Also we have an EditText item for filling in the AS name.
  174.  *
  175.  * The buttons are set when the user clicks, but they also are given
  176.  * values depending on the selection of a file.  If the file's type is
  177.  * "APPL" then controls "Resource" and "Binary" are automaticlly set,
  178.  * otherwise the controls "Data" and "Text" are set.  SF-File keeps the
  179.  * SFReply upto date when a file name is selected, but...  unfortunately
  180.  * we are called before the SFReply is updated and so when we notice
  181.  * "getNmList" is hit we defer our update for one cycle.
  182.  *
  183.  * Our other item, the TextEdit item to set the "AS" file name, can be
  184.  * enabled or disabled to allow the selection of a file name by typing a
  185.  * character (standard SFGetFile stuff).  By using the global flag
  186.  * sendasflg and an event filter we switch between sending the chars to
  187.  * SF-File for filename selection and to ModalDialog for TextEdit of our
  188.  * AS name.  Since it would be nice to get rid of that blinking cursor
  189.  * in the TextEdit item our DITL has an invisible EditText item which
  190.  * becomes active for this purpose.
  191.  *
  192.  * At startup the AS field is disabled (the invisible EditText is
  193.  * current and sndasflg is FALSE).  The user can make AS active by
  194.  * clicking in it.  The user can toggle by clicking on the StatText
  195.  * "AS" -- though I won't tell anybody if you don't.
  196.  *
  197.  */
  198. /****************************************************************************/
  199. pascal short
  200. sendmydlg (ITEM, DLG)
  201. short ITEM;
  202. DialogPtr DLG;
  203. {
  204.     Boolean isappl;        /* file is an application */
  205.     short RSLT;
  206.  
  207.     p2cstr (&sfr.fName);    /* convert filename to C form */
  208.     if (sendselflg) {        /* file name selection occured? */
  209.     sendselflg = FALSE;    /* yes, don't do this again */
  210.  
  211.     zltor (&sfr.fName, filargs.filrem);    /* convert to remote form */
  212.     SetIText (gethdl (SEND_ASFN, DLG),    /* display converted name */
  213.           filargs.filrem);    /* in "As" field */
  214.     setfilnams (SEND_ASFN, DLG);    /* set file names since double */
  215.     /* clicking fouls us */
  216.  
  217.     filargs.filflg &= ~FIL_RBDT;    /* turn off all of our flags */
  218.     isappl = (sfr.fType == 'APPL');    /* application? */
  219.     if ((sfr.fName.length == 0) && !isfolder) {    /* check for folder */
  220.         /* change the button if necessary */
  221.         SetCTitle (getctlhdl (getOpen, DLG), "Open");
  222.         isfolder = TRUE;
  223.     } else if ((sfr.fName.length != 0) && isfolder) {
  224.         SetCTitle (getctlhdl (getOpen, DLG), "Send");
  225.         isfolder = FALSE;
  226.     }
  227.  
  228.     if (sendusercvdef) {    /* use recieve file type defaults */
  229.         filargs.filflg = filargs.fildflg;
  230.     } else {        /* figure out defaults on our own */
  231.         filargs.filflg |= (isappl) ?    /* update flags */
  232.         (FIL_RSRC | FIL_BINA) :    /* application */
  233.         (FIL_DATA | FIL_TEXT);    /* not application */
  234.     }
  235.     }
  236.     switch (ITEM) {        /* according to the item */
  237.       case getNmList:        /* user hit file name */
  238.     if (sendasflg) {    /* "As" active? */
  239.         sendasflg = FALSE;    /* yes -> deactivate "As" name */
  240.         SelIText (DLG, SEND_INVT, 0, 256);    /* activate invisible
  241.                          * editText  */
  242.     }
  243.     sendselflg = TRUE;    /* next time around set buttons */
  244.     break;            /* nothing more to do in this pass */
  245.  
  246.       case SEND_ASFN:        /* hit EditText for "AS" */
  247.     sendasflg = TRUE;    /* let modal filter pass to us */
  248.     break;
  249.  
  250.       case getOpen:        /* done? */
  251.     setfilnams (SEND_ASFN, DLG);    /* set file names */
  252.     break;            /* done... */
  253.  
  254.       case SEND_ALL:        /* hit send all check box */
  255.     filargs.filflg ^= FIL_ALLFL;    /* toggle send all flag */
  256.  
  257.  
  258.     SetCtlValue (getctlhdl (SEND_ALL, DLG),    /* set the ctl value
  259.                          * according to the flag */
  260.              (filargs.filflg & FIL_ALLFL) ? btnOn : btnOff);
  261.     break;
  262.     }
  263.  
  264.     setfilflgs (ITEM, DLG);    /* check for and handle radio items */
  265.     c2pstr (&sfr.fName);    /* convert back to pascal form */
  266.     RSLT = ITEM;        /* pass item back */
  267.     return RSLT;
  268. }                /* sendmydlg */
  269.  
  270.  
  271.  
  272. /****************************************************************************/
  273. /* sendfilter - SFPGetFile event filter for "send file" dialog.
  274.  *
  275.  * This filter is the same form as a ModalDialog filter, it is used
  276.  * internally by SFPGetFile's ModalDialog call.  Our filter allows the
  277.  * user to select a file by typing the first character, which is a
  278.  * normal function of SFGetFile but is broken when we use EditText in
  279.  * our customized SFGetFile box.  Return 0x1000+char in itemhit to
  280.  * SFGetFile instead of letting ModalDialog handle it with a call to
  281.  * TextEdit.  Using a global flag "sendasflg" we decide to send the
  282.  * character to TextEdit via ModalDialog, or to SFGetFile.
  283.  *
  284.  */
  285. /****************************************************************************/
  286. pascal Boolean
  287. sendfilter (THEDIALOG, THEEVENT, ITEMHIT)
  288. DialogPtr THEDIALOG;
  289. EventRecord *THEEVENT;
  290. short *ITEMHIT;
  291. {
  292.     Boolean RETVAL;        /* returned value */
  293.  
  294.     RETVAL = FALSE;        /* default is to left Modal handle */
  295.  
  296.     if (THEEVENT->what == keyDown)    /* key down? */
  297.     if (!sendasflg) {    /* and the text isn't selected? */
  298.         /* then use as file name selector */
  299.         /* return char+0x1000 to SFPGetfile... */
  300.         *ITEMHIT = 0x1000 + (THEEVENT->message & 0x7f);
  301.         RETVAL = TRUE;    /* let SFP handle it, not modal */
  302.     }
  303.     return RETVAL;
  304. }                /* sendfilter */
  305.  
  306.  
  307.  
  308. /****************************************************************************/
  309. /* recvmydlg - SFPPutFile item filter for "receive file" dialog. */
  310. /****************************************************************************/
  311. pascal short
  312. recvmydlg (ITEM, DLG)
  313. short ITEM;
  314. DialogPtr DLG;
  315. {
  316.     short RSLT;
  317.  
  318.     RSLT = ITEM;
  319.  
  320.     switch (ITEM) {
  321.       case RECV_PROC:
  322.     filargs.filflg &= ~FIL_DODLG;    /* no more dialogs for me! */
  323.     RSLT = RECV_RBTN;    /* did "OK" */
  324.  
  325.       case RECV_RBTN:
  326.     p2cstr (&sfr.fName);    /* convert filename to C form */
  327.     setfilnams (0, DLG);    /* set names */
  328.     c2pstr (&sfr.fName);    /* convert back to pascal form */
  329.     break;
  330.     }
  331.     setfilflgs (ITEM, DLG);    /* check for and handle radios */
  332.     return RSLT;
  333. }                /* recvmydlg */
  334.  
  335.  
  336.  
  337. short recvpt[] = {75, 100};    /* Used as Point */
  338. short sendpt[] = {75, 80};    /* Used as Point */
  339.  
  340. /****************************************************************************/
  341. /* dosenddialog - Use SFPGetFile to fetch a file to send. */
  342. /* lclf: local file name;  remf: remote file name */
  343. /****************************************************************************/
  344. dosenddialog (lclf, remf)
  345. char *lclf[], *remf[];
  346. {
  347.     filargs.filflg = 0;
  348.     sendasflg = FALSE;        /* "AS" starts off inactive */
  349.     sendselflg = TRUE;        /* need to update file buttons */
  350.  
  351.     isfolder = FALSE;
  352.     SFPGetFile ((Point *) sendpt, "", NILPROC, -1,    /* all file types, 2
  353.                              * filters */
  354.         NILPTR, sendmydlg, &sfr, DLG_SEND, sendfilter);
  355.     *lclf = filargs.fillcl;
  356.     *remf = filargs.filrem;
  357.     filargs.filvol = sfr.vRefNum;    /* remember volume number */
  358.     return (sfr.good);        /* pass back return */
  359. }                /* dosenddialog */
  360.  
  361.  
  362.  
  363. /****************************************************************************/
  364. /****************************************************************************/
  365. dorecvdialog (fn, lclf)
  366. char *lclf[], *fn;
  367. {
  368.     int err;
  369.  
  370.     if (!(filargs.filflg & FIL_DODLG)) { /* don't want to do dialogs? */
  371.     *lclf = "";        /* then use a null string */
  372.     return;            /* and return now */
  373.     }
  374.     for (;;) {            /* keep trying */
  375.     filargs.filflg &= ~(FIL_RBDT);    /* clear file modes */
  376.     filargs.filflg |= sfprtol (fn);    /* convert fn and set modes */
  377.     SFPPutFile ((Point *) recvpt, "Receive as:", fn,
  378.             recvmydlg, &sfr, DLG_RECV, NILPROC);
  379.     *lclf = filargs.fillcl;
  380.     filargs.filvol = sfr.vRefNum;    /* remember volume number */
  381.  
  382.     if (!sfr.good) {    /* CANCEL */
  383.         cxseen = TRUE;    /* indicate cancel */
  384.         return;
  385.     } else {
  386.         /* delete if there */
  387.         err = FSDelete (filargs.fillcl, filargs.filvol);
  388.         if (err == fnfErr)    /* everything ok? */
  389.         return;        /* yes, return now */
  390.     }
  391.  
  392.     if (ioutil (err))
  393.         return;        /* until no error */
  394.     }
  395. }                /* dorecvdialog */
  396.  
  397.  
  398.  
  399. /****************************************************************************/
  400. /****************************************************************************/
  401. initfilrecv ()
  402. {
  403.     filargs.filflg = filargs.fildflg;    /* default flags are active */
  404.     warn = !(filargs.filflg & FIL_OKILL);    /* set kermit flag */
  405.     binary = (filargs.filflg & FIL_BINA);    /* selected binary mode? */
  406.     filargs.filsiz = 0;        /* no known size */
  407. }                /* initfilrecv */
  408.  
  409.  
  410.  
  411. /****************************************************************************/
  412. /* initialize the file settings, called only at init time            */
  413. /****************************************************************************/
  414. initfilset ()
  415. {
  416.     filargs.filvol = 0;        /* default volume is always default */
  417.     filargs.fildflg = FIL_DATA | FIL_TEXT;    /* default file setting */
  418.     /* if no settings file */
  419. }                /* initfilset */
  420.  
  421.  
  422.  
  423. /****************************************************************************/
  424. /****************************************************************************/
  425. int
  426. dogetfdialog (remf)
  427. char *remf[];
  428. {
  429.     DialogPtr getfdlg;
  430.     ControlHandle getbhdl;
  431.     Handle remfhdl;
  432.     short item;
  433.  
  434.     getfdlg = GetNewDialog (DLG_GETF, NILPTR, (WindowPtr) - 1);
  435.     circleOK(getfdlg);
  436.     
  437.     remfhdl = gethdl (GETF_REMF, getfdlg);
  438.     getbhdl = getctlhdl (GETF_GETB, getfdlg);
  439.     HiliteControl (getbhdl, 255);    /* start with deactive Get button */
  440.  
  441.     for (;;) {
  442.     ModalDialog (NILPROC, &item);
  443.     switch (item) {
  444.       case ok:
  445.         if (filargs.filrem[0] == '\0')    /* no file name? */
  446.         break;        /* then they hit CR, don't allow */
  447.         *remf = filargs.filrem;    /* fill in for return */
  448.         initfilrecv ();    /* init recv flags */
  449.       case cancel:
  450.         DisposDialog (getfdlg);
  451.         return (item == ok);
  452.       case GETF_REMF:
  453.         GetIText (remfhdl, filargs.filrem);
  454.         HiliteControl (getbhdl, (filargs.filrem[0] == 0) ? 255 : 0);
  455.         break;
  456.     }
  457.     }
  458. }                /* dogetfdialog */
  459.  
  460.  
  461.  
  462. #define RSXLEN 5        /* ".rsrc" length */
  463.  
  464. /****************************************************************************/
  465. /* sfprtol - translate remote file name to a local file name and */
  466. /*          and figure out the flags as well. */
  467. /****************************************************************************/
  468. int
  469. sfprtol (fn)
  470. char *fn;
  471. {
  472.     int l;
  473.     register char *cp;
  474.     
  475.     for (cp = fn; *cp; cp++) {        /* convert to lower case */
  476.     if (isupper(*cp))
  477.         *cp = tolower(*cp);
  478.     if (*cp == ':')            /* nuke colons (for Mac) */
  479.         *cp = '_';
  480.     }
  481.     
  482.     if ((l = strlen (fn)) > RSXLEN &&    /* big enough? */
  483.     (strcmp (&fn[l - RSXLEN], ".rsrc") == 0 ||    /* and matches
  484.                              * extension? */
  485.      strcmp (&fn[l - RSXLEN], ".RSRC") == 0)) {    /* either way? */
  486.     fn[l - RSXLEN] = '\0';    /* so remove the extension */
  487.     return (FIL_BINA | FIL_RSRC);    /* want rsrc and binary */
  488.     }
  489.     return (filargs.fildflg & FIL_RBDT);    /* else return default */
  490. }                /* sfprtol */
  491.  
  492. /****************************************************************************/
  493. /*
  494.  *    set_cwd - set the working directory
  495.  *       Originally wdset() from NCSA Telnet for the Macintosh, v2.2
  496.  */
  497. /****************************************************************************/
  498.  
  499. short cwdpt[] = {100, 100};    /* Used as Point */
  500.  
  501. int
  502. set_cwd()
  503. {
  504.     SFReply reply;
  505.     int err;
  506.  
  507.     err=SetVol (0L, filargs.filvol);
  508.     SFPPutFile ((Point *) sendpt, "Set Transfer Directory",
  509.         "Doesn't Matter", 0L, &reply, CWDBOXID, 0L);
  510.  
  511.     if(!reply.good) return(-1);
  512.     filargs.filvol = reply.vRefNum;
  513.     err = SetVol (0L, filargs.filvol);
  514.     if (err != noErr)
  515.         printerr("Trouble setting transfer directory:", err);
  516.     return (err);
  517. }
  518.