/* Edit by Bill on Wed May 15, 15:48 */ /* change name of rtol to sfprtol, make it the common file rtol rtn */ /* either use RSRC & BINA if .RSRC extension, or use current defaults */ /* Edit by Bill on Wed May 15, 15:48 */ /* in initfilerecv make sure kermit flag binary is set */ /* * file ckmsfp.c * * Module of MacKermit containing standard file package calls: * * dosenddialog() - Send file... * dorecvdialog() - Receive file... * dogetfdialog() - Get file from server... * * Bill Schilit, May, 1984 * * Copyright (C) 1985, Trustees of Columbia University in the City of * New York. Permission is granted to any individual or institution to * use, copy, or redistribute this software so long as it is not sold * for profit, provided this copyright notice is retained. * */ #include "ckcker.h" /* Kermit definitions */ #include "ckmdef.h" /* Common Mac module definitions */ #include "ckmres.h" /* resource defs */ #include "mac/quickdraw.h" #include "mac/osintf.h" #include "mac/toolintf.h" #include "mac/packintf.h" FILINF filargs; /* is global */ typedef struct { /* SFPGetFile event filter */ DialogPtr dlg; /* (in stack order) */ short item; } SFdlgFilterArgs; typedef struct { /* SFPGetFile item hit filter */ short *itemhit; /* (in stack order) */ EventRecord *theevent; DialogPtr thedialog; } ModalFilterArgs; #define DLG_GETF 3998 /* SFPutFile DLOG replacement */ #define DLG_RECV 3999 /* SFPutFile DLOG replacement */ #define DLG_SEND 4000 /* SFGetFile DLOG replacement */ #define DLG_FSET 1004 /* File settings */ /* Resource IDs for DLG_GETF DITL (3998) */ #define GETF_GETB OK /* "Get" button */ #define GETF_REMF 4 /* remote file name */ /* Resource IDs for DLG_RECV DITL (3999) */ #define RECV_RBTN putSave /* "Receive" button */ #define RECV_PROC 15 /* proceed without more dialogs */ #define RADITM_DATA 11 #define RADITM_RSRC 12 #define RADITM_TEXT 13 #define RADITM_BINA 14 #define RADITM_FIRST RADITM_DATA #define RADITM_LAST RADITM_BINA int radflgs[] = {FIL_DATA,FIL_RSRC,FIL_TEXT,FIL_BINA}; int radnotflgs[] = {FIL_RSRC,FIL_DATA,FIL_BINA,FIL_TEXT}; /* Resource IDs for DLG_SEND DITL (4000) */ #define SEND_ASFN 17 /* "As" file name */ #define SEND_INVT 16 /* invisible edit text */ /* Globals used by SEND dialog */ SFReply sfr; /* holds file info */ BOOL sendselflg, /* TRUE means file was selected */ sendasflg; /* TRUE means AS field is active */ /* gethdl - return a control handle given a resource ID */ Handle gethdl(item,dp) DialogPtr dp; { int itype; Rect ibox; Handle ihdl; GetDItem(dp,item,&itype,&ihdl,&ibox); return(ihdl); } #define getctlhdl(item,dp) (ControlHandle) gethdl(item,dp) /* setfilflgs - Manage the filflg word and radio controls. * * Flags will be changed when the resource ID of item hit (passed to * this routine) is one of the radio items, or alternately routines can * modify the filflg word itself and the radio items will be updated * accordingly. * * N.B. Each dialog using these flags has them defined with the same * DITL item numbers. * */ setfilflgs(item,dlg) DialogPtr dlg; { ControlHandle ctlhdl; int i; if (item >= RADITM_FIRST && /* check for item... is it */ item <= RADITM_LAST) /* a radio item for us? */ { filargs.filflg |= radflgs[item-RADITM_FIRST]; /* yes... set flag */ filargs.filflg &= ~radnotflgs[item-RADITM_FIRST]; /* clear opposite */ } for (i=RADITM_FIRST; i <= RADITM_LAST; i++) /* update all */ { ctlhdl = getctlhdl(i,dlg); /* get a handle on his radio item */ SetCtlValue(ctlhdl, (filargs.filflg & radflgs[i-RADITM_FIRST]) ? btnOn : btnOff); } } setfilnams(remfid,dlg) DialogPtr dlg; { filargs.filrem[0] = 0; /* no remote file */ p2cstr(sfr.fName); /* convert to c */ strcpy(filargs.fillcl,sfr.fName); /* copy sfr into local name stg */ c2pstr(sfr.fName); /* back into pascal string */ if (remfid != 0) /* fetch remote name if present */ GetIText(gethdl(remfid,dlg),filargs.filrem); /* in an edittext field */ binary = (filargs.filflg & FIL_BINA); /* selected binary mode? */ } /* sendmydlg - SFPGetFIle item hit filter for "send file" dialog. * * This filter is called by SFPGetFile to let the programmer handle hits * on his custom items. Our items are 2 sets of buttons for selecting * the fork (data or resource) and the transfer mode (binary or text). * Also we have an EditText item for filling in the AS name. * * The buttons are set when the user clicks, but they also are given * values depending on the selection of a file. If the file's type is * "APPL" then controls "Resource" and "Binary" are automaticlly set, * otherwise the controls "Data" and "Text" are set. SF-File keeps the * SFReply upto date when a file name is selected, but... unfortunately * we are called before the SFReply is updated and so when we notice * "getNmList" is hit we defer our update for one cycle. * * Our other item, the TextEdit item to set the "AS" file name, can be * enabled or disabled to allow the selection of a file name by typing a * character (standard SFGetFile stuff). By using the global flag * sendasflg and an event filter we switch between sending the chars to * SF-File for filename selection and to ModalDialog for TextEdit of our * AS name. Since it would be nice to get rid of that blinking cursor * in the TextEdit item our DITL has an invisible EditText item which * becomes active for this purpose. * * At startup the AS field is disabled (the invisible EditText is * current and sndasflg is FALSE). The user can make AS active by * clicking in it. The user can toggle by clicking on the StatText * "AS" -- though I won't tell anybody if you don't. * */ sendmydlg() { SFdlgFilterArgs args; short *rslt; BOOL isappl; /* file is an application */ rslt = (short *) getpargs(&args,sizeof(args)); if (sendselflg) /* file name selection occured? */ { sendselflg = FALSE; /* yes, don't do this again */ p2cstr(sfr.fName); zltor(sfr.fName,filargs.filrem); /* convert to remote form */ SetIText(gethdl(SEND_ASFN,args.dlg), /* display converted name */ filargs.filrem); /* in "As" field */ c2pstr(sfr.fName); /* back to pascal form */ setfilnams(SEND_ASFN,args.dlg); /* set file names since double */ /* clicking fouls us */ filargs.filflg &= ~FIL_RBDT; /* turn off all of our flags */ isappl = (strncmp(sfr.ftype.s,"APPL",4) == 0); /* application? */ filargs.filflg |= (isappl) ? /* update flags */ (FIL_RSRC | FIL_BINA) : /* application */ (FIL_DATA | FIL_TEXT); /* not application */ } switch (args.item) { /* according to the item */ case getNmList: /* user hit file name */ if (sendasflg) /* "As" active? */ { /* yes... */ sendasflg = FALSE; /* deactivate "As" name */ SelIText(args.dlg,SEND_INVT,0,256); /* activate invisible editText */ } sendselflg = TRUE; /* next time around set buttons */ break; /* nothing more to do in this pass */ case SEND_ASFN: /* hit EditText for "AS" */ sendasflg = TRUE; /* let modal filter pass to us */ break; case getOpen: /* done? */ setfilnams(SEND_ASFN,args.dlg); /* set file names */ break; /* done... */ } setfilflgs(args.item,args.dlg); /* check for and handle radio items */ *rslt = args.item; /* pass item back */ } /* sendfilter - SFPGetFile event filter for "send file" dialog. * * This filter is the same form as a ModalDialog filter, it is used * internally by SFPGetFile's ModalDialog call. Our filter allows the * user to select a file by typing the first character, which is a * normal function of SFGetFile but is broken when we use EditText in * our customized SFGetFile box. Return 0x1000+char in itemhit to * SFGetFile instead of letting ModalDialog handle it with a call to * TextEdit. Using a global flag "sendasflg" we decide to send the * character to TextEdit via ModalDialog, or to SFGetFile. * */ sendfilter() { ModalFilterArgs args; BOOL *retval; /* returned value */ retval = (BOOL *) getpargs(&args,sizeof(args)); *retval = FALSE; /* default is to left Modal handle */ if (args.theevent->what == keyDown) /* key down? */ if (!sendasflg) /* and the text isn't selected? */ { /* then use as file name selector */ *args.itemhit = 0x1000 + /* return char+0x1000 to */ (args.theevent->message & 0x7f); /* SFPGetfile... */ *retval = TRUE; /* let SFP handle it, not modal */ } } /* recvmydlg - SFPPutFile item filter for "receive file" dialog. * * */ recvmydlg() { SFdlgFilterArgs args; short *rslt; rslt = (short *) getpargs(&args,sizeof(args)); *rslt = args.item; switch (args.item) { case RECV_PROC: filargs.filflg &= ~FIL_DODLG; /* no more dialogs for me! */ *rslt = RECV_RBTN; /* did "OK" */ case RECV_RBTN: setfilnams(0,args.dlg); /* set names */ break; } setfilflgs(args.item,args.dlg); /* check for and handle radios */ } /* dosenddialog - Use SFPGetFile to fetch a file to send. */ short recvpt[] = {75,100}; short sendpt[] = {75,80}; dosenddialog(lclf,remf) char *lclf[],*remf[]; { filargs.filflg = 0; sendasflg = FALSE; /* "AS" starts off inactive */ sendselflg = TRUE; /* need to update file buttons */ sfr.fName[0] = 0; /* clear our old stuff */ SFPGetFile((Point *) sendpt,"",NILPROC,0, /* all file types, 2 filters */ NILPTR,sendmydlg,&sfr,DLG_SEND,sendfilter); *lclf = filargs.fillcl; *remf = filargs.filrem; filargs.filvol = sfr.vRefNum; /* remember volume number */ return(sfr.good); /* pass back return */ } dorecvdialog(fn,lclf) char *lclf[],*fn; { int err; if (!(filargs.filflg & FIL_DODLG)) /* don't want to do dialogs? */ { *lclf = ""; /* then use a null string */ return; /* and return now */ } for (;;) { /* keep trying */ filargs.filflg &= ~(FIL_RBDT); /* clear file modes */ filargs.filflg |= sfprtol(fn); /* convert fn and set modes */ SFPPutFile((Point *) recvpt,"Receive as:",fn, recvmydlg,&sfr,DLG_RECV,NILPROC); *lclf = filargs.fillcl; filargs.filvol = sfr.vRefNum; /* remember volume number */ if (!sfr.good) { /* CANCEL */ cxseen = TRUE; /* indicate cancel */ return; } else { err = FSDelete(filargs.fillcl,filargs.filvol); /* delete if there */ if (err == fnfErr) /* everything ok? */ return; /* yes, return now */ } if (ioutil(err)) return; /* until no error */ } } /* setfiledialog - enter file settings dialog. */ #define FSET_ATTEND 4 #define FSET_UNATTEND 5 #define FSET_SUPERSEDE 6 #define FSET_NEWNAMES 7 setradpair(rid1,rid2,bool,dlg) DialogPtr dlg; { SetCtlValue(getctlhdl(rid1,dlg),bool ? btnOn : btnOff); SetCtlValue(getctlhdl(rid2,dlg),bool ? btnOff : btnOn); } setfiledialog() { DialogPtr setfdlg; int item; setfdlg = GetNewDialog(DLG_FSET,NILPTR,(WindowPtr) -1); filargs.filflg = filargs.fildflg; /* use current defaults */ ShowWindow(setfdlg); /* show it */ for (;;) { setfilflgs(item,setfdlg); /* keep flags upto date */ setradpair(FSET_ATTEND,FSET_UNATTEND, (filargs.filflg & FIL_DODLG),setfdlg); setradpair(FSET_SUPERSEDE,FSET_NEWNAMES, (filargs.filflg & FIL_OKILL),setfdlg); ModalDialog(NILPROC,&item); switch (item) { case OK: filargs.fildflg = filargs.filflg; /* set default flags */ case Cancel: DisposDialog(setfdlg); /* all done with dialog */ return; /* can go home... */ case FSET_ATTEND: case FSET_UNATTEND: filargs.filflg ^= FIL_DODLG; /* toggle flag */ break; case FSET_SUPERSEDE: case FSET_NEWNAMES: filargs.filflg ^= FIL_OKILL; /* toggle flag */ break; } } } initfilrecv() { filargs.filflg = filargs.fildflg; /* default flags are active */ warn = !(filargs.filflg & FIL_OKILL); /* set kermit flag */ binary = (filargs.filflg & FIL_BINA); /* selected binary mode? */ filargs.filsiz = 0; /* no known size */ } initfilset() { filargs.filvol = 0; /* default volume is always default */ filargs.fildflg = FIL_DATA | FIL_TEXT; /* default file setting */ /* if no settings file */ } dogetfdialog(remf) char *remf[]; { DialogPtr getfdlg; ControlHandle getbhdl; Handle remfhdl; int item; getfdlg = GetNewDialog(DLG_GETF,NILPTR,(WindowPtr) -1); remfhdl = gethdl(GETF_REMF,getfdlg); getbhdl = getctlhdl(GETF_GETB,getfdlg); HiliteControl(getbhdl,255); /* start with deactive Get button */ ShowWindow(getfdlg); for (;;) { ModalDialog(NILPROC,&item); switch (item) { case OK: if (filargs.filrem[0] == '\0') /* no file name? */ break; /* then they hit CR, don't allow */ *remf = filargs.filrem; /* fill in for return */ initfilrecv(); /* init recv flags */ case Cancel: DisposDialog(getfdlg); return(item == OK); case GETF_REMF: GetIText(remfhdl,filargs.filrem); HiliteControl(getbhdl,(filargs.filrem[0] == 0) ? 255 : 0); break; } } } /* sfprtol - translate remote file name to a local file name and * and figure out the flags as well. */ #define RSXLEN 5 /* ".rsrc" length */ int sfprtol(fn) char *fn; { int l; if ((l = strlen(fn)) > RSXLEN && /* big enough? */ (strcmp(&fn[l-RSXLEN],".rsrc") == 0 || /* and matches extension? */ strcmp(&fn[l-RSXLEN],".RSRC") == 0)) /* either way? */ { fn[l-RSXLEN] = '\0'; /* so remove the extension */ return(FIL_BINA | FIL_RSRC); /* want rsrc and binary */ } return(filargs.fildflg & FIL_RBDT); /* else return default */ }