home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckmsfp.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  18KB  |  522 lines

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