/* Title: -> c.xferrecv * Purpose: general purpose import of data by dragging icon * Requires: * BOOL */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Steel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "trace.h" #include "os.h" #include "bbc.h" #include "wimp.h" #include "wimpt.h" #include "win.h" #include "dbox.h" #include "typdat.h" #include "xfersend.h" #include "fileicon.h" #include "werr.h" #include "menu.h" #include "event.h" #include "xferrecv.h" #include "msgs.h" #define XOS_ReadVarVal 0x20023 typedef enum { xferrecv_state_Ask, xferrecv_state_Talk, xferrecv_state_Done, xferrecv_state_Broken } xferrecv_stateval ; static wimp_t xferrecv_sendertask ; static wimp_msgstr xferrecv_ack ; static xferrecv_buffer_processor xferrecv_processbuff ; static char *xferrecv_buffer ; static int xferrecv_buffersize ; static int xferrecv_state ; static int xferrecv_msgid ; static flex_ptr xferrecv__flex; static int xferrecv__returnBlockSize; static char xferrecv__nameToImport[256]; static int scrap_ref; static int xferrecv__fileissafe ; int xferrecv_checkinsert(char **filename) { wimp_eventstr *e = wimpt_last_event(); if ((e->e==wimp_ESENDWANTACK || e->e == wimp_ESEND) && (e->data.msg.hdr.action == wimp_MDATALOAD || e->data.msg.hdr.action == wimp_MDATAOPEN)) { tracef4("xferrecv_checkinsert returning filetype %x: %d %d %d\n", e->data.msg.data.dataload.type, scrap_ref,e->data.msg.hdr.your_ref,e->data.msg.hdr.my_ref) ; xferrecv__fileissafe = e->data.msg.hdr.your_ref != scrap_ref || scrap_ref==0 ; xferrecv_ack.hdr.action = wimp_MDATALOADOK ; xferrecv_ack.hdr.size = sizeof(wimp_msghdr) ; xferrecv_sendertask = e->data.msg.hdr.task ; xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ; *filename = e->data.msg.data.dataload.name ; if (xferrecv__fileissafe) strcpy(xferrecv__nameToImport,*filename); return e->data.msg.data.dataload.type ; } else return -1 ; } void xferrecv_insertfileok(void) { /* An insert has been completed successfully. This sends an acknowledge back to the original application. */ tracef0("xferrecv_insertfileok\n") ; if (!xferrecv__fileissafe) { tracef0("Must delete scrap file\n") ; os_cli("%remove ") ; } scrap_ref = 0 ; (void) wimp_sendmessage(wimp_ESEND, &xferrecv_ack, xferrecv_sendertask); } int xferrecv_checkprint(char **filename) { wimp_eventstr *e = wimpt_last_event(); if ((e->e==wimp_ESENDWANTACK || e->e == wimp_ESEND) && (e->data.msg.hdr.action == wimp_MPrintTypeOdd)) { tracef4("xferrecv_checkprint returning filetype %x: %d %d %d\n", e->data.msg.data.print.type, scrap_ref,e->data.msg.hdr.your_ref,e->data.msg.hdr.my_ref) ; xferrecv__fileissafe = 0 ; xferrecv_ack.hdr.action = wimp_MPrintTypeKnown ; xferrecv_ack.hdr.size = sizeof(wimp_msghdr)+sizeof(wimp_msgprint) ; xferrecv_sendertask = e->data.msg.hdr.task ; xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ; *filename = e->data.msg.data.print.name ; return e->data.msg.data.print.type ; } else return -1 ; } void xferrecv_printfileok(int type) { xferrecv_ack.data.print.type = type ; (void) wimp_sendmessage(wimp_ESEND, &xferrecv_ack, xferrecv_sendertask); } int xferrecv_checkimport(int *estsize) { wimp_eventstr *e = wimpt_last_event(); if ((e->e==wimp_ESENDWANTACK || e->e == wimp_ESEND) && e->data.msg.hdr.action == wimp_MDATASAVE) { xferrecv_ack.hdr.size = sizeof(wimp_msghdr) + sizeof(wimp_msgdatasaveok) ; xferrecv_sendertask = e->data.msg.hdr.task ; xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ; xferrecv_ack.hdr.action = wimp_MDATASAVEOK ; xferrecv_ack.data.datasaveok.w = e->data.msg.data.datasave.w ; xferrecv_ack.data.datasaveok.i = e->data.msg.data.datasave.i ; xferrecv_ack.data.datasaveok.x = e->data.msg.data.datasave.x ; xferrecv_ack.data.datasaveok.y = e->data.msg.data.datasave.y ; xferrecv_ack.data.datasaveok.type = e->data.msg.data.datasave.type ; *estsize = xferrecv_ack.data.datasaveok.estsize = e->data.msg.data.datasave.estsize ; strcpy(xferrecv__nameToImport,e->data.msg.data.datasave.leaf); tracef2("xferrecv_checkimport returning filetype %x from %d\n", e->data.msg.data.datasave.type,xferrecv_sendertask) ; return xferrecv_ack.data.datasaveok.type = e->data.msg.data.datasave.type ; } else return -1 ; } /* * char *xferrecv_nameToImport(void) * * Use * Returns the name of the file to import (full pathname if available). * * Returns * A pointer to a read-only string. */ char *xferrecv_nameToImport(void) { return (xferrecv__nameToImport); } static void xferrecv_sendRAMFETCH(void) { char *addr = xferrecv_ack.data.ramfetch.addr ; int size = xferrecv_ack.data.ramfetch.nbytes ; int action = xferrecv_ack.hdr.action ; tracef2("xferrecv_sendRAMFETCH with buffer %x, size %d :", (int) xferrecv_buffer,xferrecv_buffersize) ; xferrecv_ack.hdr.action = wimp_MRAMFETCH ; xferrecv_ack.data.ramfetch.addr = xferrecv_buffer ; xferrecv_ack.data.ramfetch.nbytes = xferrecv_buffersize ; (void) wimp_sendmessage(wimp_ESENDWANTACK, &xferrecv_ack, xferrecv_sendertask); xferrecv_msgid = xferrecv_ack.hdr.my_ref ; tracef1(" ramfetch msg id %d\n",xferrecv_msgid) ; xferrecv_ack.data.ramfetch.addr=addr ; xferrecv_ack.data.ramfetch.nbytes=size ; xferrecv_ack.hdr.action = action ; } static BOOL xferrecv_unknown_events(wimp_eventstr *e, void *handle) { handle = handle ; #if TRACE tracef("xferrecv_unknown_events %d %d %d %d %d\n",e->e, e->data.msg.hdr.action,e->data.msg.hdr.my_ref, e->data.msg.hdr.your_ref,xferrecv_msgid) ; #endif if ((e->e == wimp_ESEND || e->e == wimp_ESENDWANTACK) && e->data.msg.hdr.your_ref == xferrecv_msgid && e->data.msg.hdr.action == wimp_MRAMTRANSMIT) { tracef2("xferrecv got ramtransmit of %d into %d\n", e->data.msg.data.ramtransmit.nbyteswritten,xferrecv_buffersize) ; if (e->data.msg.data.ramtransmit.nbyteswritten == xferrecv_buffersize) { /* other end has filled our buffer; better try and allocate some more space */ if (xferrecv_processbuff(&xferrecv_buffer, &xferrecv_buffersize)) { /* can go on */ tracef2("users buffer processor set buffer %x, size %d\n", (int) xferrecv_buffer, xferrecv_buffersize) ; xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ; xferrecv_sendRAMFETCH() ; xferrecv_state = xferrecv_state_Talk ; } else { tracef0("users buffer processor failed: break down\n") ; xferrecv_state = xferrecv_state_Broken ; } } else { tracef0("xferrecv had final ramtransmit; set done state\n") ; xferrecv_state = xferrecv_state_Done ; xferrecv_buffersize=e->data.msg.data.ramtransmit.nbyteswritten; if (xferrecv_buffersize!=0) { if (!xferrecv_processbuff(&xferrecv_buffer, &xferrecv_buffersize)) xferrecv_state = xferrecv_state_Broken ; } xferrecv_buffersize = e->data.msg.data.ramtransmit.nbyteswritten ; } } else if (e->e == wimp_EACK && e->data.msg.hdr.my_ref == xferrecv_msgid) { tracef0("xferrecv ramfetch bounced: ") ; /* got our message back */ if (xferrecv_state == xferrecv_state_Ask) xferrecv_importByScrap(); else { tracef0("tell the user the protocol fell down\n") ; werr(0, msgs_lookup("xferrecv2:Data transfer failed.")) ; } xferrecv_state = xferrecv_state_Broken ; } else return FALSE ; return TRUE ; } /* * void xferrecv_importByScrap(void) * * Use * Tells xferrecv not to bother with RAM transfer, but to use the * file instead. It checks that the system variables and * everything are set up right beforehand. */ void xferrecv_importByScrap(void) { os_regset r ; tracef0("ask for Wimp$Scrap transfer\n") ; /* first check that variable exists */ r.r[0] = (int) "Wimp$Scrap" ; r.r[1] = NULL ; r.r[2] = -1 ; r.r[3] = 0 ; r.r[4] = 3 ; os_swix(XOS_ReadVarVal, &r) ; if (r.r[2]==0) werr(0,msgs_lookup("xferrecv1:Can't transfer file (use *Set Wimp$Scrap )")) ; else { strcpy(xferrecv_ack.data.datasaveok.name, "") ; xferrecv_ack.data.datasaveok.estsize = -1 ; /* file is not safe with us */ (void) wimp_sendmessage(wimp_ESEND, &xferrecv_ack, xferrecv_sendertask); scrap_ref = xferrecv_ack.hdr.my_ref ; } } int xferrecv_doimport(char *buf, int size, xferrecv_buffer_processor p) { /* Receives data into the buffer; calls the buffer processor if the buffer given becomes full. Returns TRUE if the transaction completed sucessfully. */ win_add_unknown_event_processor(xferrecv_unknown_events, 0) ; tracef0("xferrecv_doimport entered\n") ; xferrecv_processbuff = p ; xferrecv_buffer = buf ; xferrecv_buffersize = size ; xferrecv_sendRAMFETCH() ; xferrecv_state = xferrecv_state_Ask ; xferrecv__fileissafe = FALSE ; do { event_process() ; } while (xferrecv_state < xferrecv_state_Done) ; win_remove_unknown_event_processor(xferrecv_unknown_events, 0) ; return (xferrecv_state == xferrecv_state_Done ? xferrecv_buffersize : -1 ) ; } /* * BOOL xferrecv__returnBlockBuffProcessor(char **buff,int *size) * * Use * Buffer processor for xferrecv_returnImportedBlock. */ static BOOL xferrecv__returnBlockBuffProcessor(char **buff,int *size) { if (!flex_extend(xferrecv__flex,xferrecv__returnBlockSize+8192)) return (FALSE); xferrecv__returnBlockSize+=8192; *buff+=*size; *size=8192; return (TRUE); } /* * int xferrecv_returnImportedBlock(flex_ptr p) * * Use * Performs the data import if possible, and returns with the block filled * with *ALL* the imported data i.e. it obviates the need of any work on * your part for the data transfer. This is the life, huh? If anything * went wrong, it returns -1 as for xferrecv_doimport * * Parameters * flex_ptr p == flex pointer to nothing in particular (certainly not a * flex block - one is allocated for you). Remember to free it after * you've read all the data! Also ensure that flex has been initialised. * If there is no data to import (i.e. the import failed) then p is freed * of any data that may have been stored there. * * Returns * -1 for failure, or the total size of the imported data for success */ int xferrecv_returnImportedBlock(flex_ptr p) { xferrecv__flex=p; if (!flex_alloc(p,xferrecv_ack.data.datasaveok.estsize)) return (-1); xferrecv__returnBlockSize=xferrecv_ack.data.datasaveok.estsize; if (xferrecv_doimport(*p,xferrecv_ack.data.datasaveok.estsize, xferrecv__returnBlockBuffProcessor)==-1) { flex_free(p); return (-1); } return (xferrecv__returnBlockSize); } BOOL xferrecv_file_is_safe() { return xferrecv__fileissafe ; } /* end */