home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************
- * *
- * Module: xferstream.c (part of gstream package) *
- * *
- * Version: 0.01 *
- * *
- * Author: Simon Proven *
- * *
- * Owner: Simon Proven 1993 *
- * *
- * Purpose: To provide gstream access to the wimp data *
- * transfer protcols. *
- * *
- * Uses: gstream, stdlib, string, osstream, ramstream, *
- * werr, wimp, wimpt, win, event *
- * *
- * Conditions: *
- * You can produce and sell executable code from *
- * this module freely. The source code may be *
- * distributed freely, but not for profit. *
- * *
- * If you like these modules alot, and use them *
- * in your own programs, feel free to thank me *
- * with cash - 10 or more will get you a disc *
- * with the latest versions and new stream types. *
- * *
- * Disclaimer: *
- * This software is supplied in good faith, but I *
- * cannot accept liability for any loss incurred *
- * through the use or inability to use any part *
- * of this software. *
- * *
- * How to contact me: *
- * *
- * email: snail mail: *
- * sproven@cs.strath.ac.uk Simon Proven, *
- * Castle Cottage, *
- * Portencross, *
- * West Kilbride, *
- * KA23 9QA *
- * SCOTLAND *
- * *
- * Tel. (+44) 294 829 721 *
- * *
- *************************************************************/
-
- /* This module allows saves to be initiated or loads to be recieved,
- * providing the user with a similar interface whether the RAM transfer
- * or scrap file methods are used. This module will default to using
- * the RAM transfer method, and will only use the scrap transfer method
- * if the other application involved in the transfer is not interested
- * in the RAM tranfer method.
- *
- * To operate correctly, this module requires the ramstream and osstream
- * modules also.
- *
- * Saves back to ourself won't work.
- */
-
- /* This function should be used to handle an incoming dataload, dataopen
- * or datasave message which the application wishes to pick up.
- *
- * The function will set up the stream and will return TRUE if the stream
- * could be opened or FALSE if it could not be opened.
- *
- * The user's code is expected to read all information regarding the file
- * type, name, modified flag etc, before the stream is opened.
- *
- * This stream will deal with sending all required messages to the other
- * task, and with all message reception.
- *
- * Note: if your applicatio recieves a message DataLoad with your_ref!=0
- * it should ignore the message but still call this function. This is
- * to ensure that the message gets to the right place. Otherwise, it
- * cannot be guaranteed to pick up the message as the message will NOT be
- * passed through the unknown message handler installed by this function.
- *
- * This stream type operates by attempting to open a ramfetch stream - if
- * that doesn't work, then the stream will try to use the scrap file method.
- *
- * This stream's write function simply calls gswrite for the daughter stream.
- * This stream has no buffer - all buffering is performed in the daughter
- * stream.
- */
-
- #include "gstream.h"
- #include "osstream.h"
- #include "ramstream.h"
- #include "werr.h"
- #include "wimp.h"
- #include "wimpt.h"
- #include "win.h"
- #include "event.h"
- #include <stdlib.h>
- #include <string.h>
-
- void setfiletype(char *name, int type)
- {
- os_filestr s;
-
- s.action=18; /* RISC OS 2 PRM page 849 - set file type */
- s.name=name;
- s.loadaddr=type;
- wimpt_complain(os_file(&s));
- }
-
- typedef enum
- {
- RAM,
- SCRAP,
- LOAD
- } xferrecv_type;
-
- static struct
- {
- xferrecv_type type; /* TRUE if using RAM data transfer, FALSE if using scrap file */
- int their_ref;
- int our_ref;
- wimp_t task;
- } xferrecv_status;
-
- static gstream xferrecv_stream;
- static int xferrecv_wentOK;
- static int xferrecv_busy;
-
- static int xferrecv_unknowns(wimp_eventstr *e, void *handle)
- {
- switch (e->e)
- {
- case wimp_ESEND:
- case wimp_ESENDWANTACK:
- if (e->data.msg.hdr.your_ref == xferrecv_status.our_ref)
- {
- switch(e->data.msg.hdr.action)
- {
- case wimp_MDATALOAD:
- xferrecv_busy=FALSE;
- xferrecv_wentOK=TRUE;
- xferrecv_status.their_ref=e->data.msg.hdr.my_ref;
- return TRUE;
- }
- }
- return(FALSE);
- case wimp_EACK:
- if (e->data.msg.hdr.my_ref == xferrecv_status.our_ref)
- {
- xferrecv_busy=FALSE;
- xferrecv_wentOK=FALSE;
- return TRUE;
- }
- default:
- return FALSE;
- }
- }
-
- static size_t xferrecv_read(void *ptr, size_t size, void *s)
- {
- gstream *stream=(gstream *) s;
- size=gsread(ptr, 1, size, &xferrecv_stream);
- stream->error=xferrecv_stream.error;
- return size;
- }
-
- static int xferrecv_close(void *s)
- {
- wimp_msgstr msg;
- int ok;
-
-
- switch (xferrecv_status.type)
- {
- case LOAD:
- msg.hdr.your_ref=xferrecv_status.their_ref;
- msg.hdr.action=wimp_MDATALOADOK;
- wimp_sendmessage(wimp_ESEND,&msg,xferrecv_status.task);
- ok=gsclose(&xferrecv_stream);
- if (!ok)
- return TRUE;
- else
- return FALSE;
- case RAM:
- ok=gsclose(&xferrecv_stream);
- if (!ok)
- return TRUE;
- else
- return FALSE;
- case SCRAP:
- msg.hdr.your_ref=xferrecv_status.their_ref;
- msg.hdr.action=wimp_MDATASAVEOK;
- wimp_sendmessage(wimp_ESEND,&msg,xferrecv_status.task);
- ok=gsclose(&xferrecv_stream);
- remove("<Wimp$Scrap>");
- if (!ok)
- return TRUE;
- else
- return FALSE;
- default:
- return FALSE;
- }
- }
-
- int gsopenxferrecv(wimp_eventstr *e, gstream *stream)
- {
- wimp_msgstr msg;
-
- if (e->data.msg.hdr.task==wimpt_task())
- {
- werr(FALSE,"Sorry - I can't drag files back to my own icon or windows");
- return FALSE;
- }
-
- if (e->data.msg.hdr.your_ref!=0)
- {
- xferrecv_unknowns(e,NULL);
- return FALSE;
- }
-
- stream->type=READ;
- stream->bufsize=0;
- stream->ungetsize=4;
- stream->ungetpos=0;
- stream->error=FALSE;
- if (!flex_alloc(&(stream->ungetbuf),4))
- {
- werr(FALSE,"Not enough space");
- return FALSE;
- }
- stream->io.read=xferrecv_read;
- stream->close=xferrecv_close;
-
- switch (e->data.msg.hdr.action)
- {
- case wimp_MDATALOAD:
- if (gsopenosr(e->data.msg.data.dataload.name,&xferrecv_stream))
- {
- /* succesfully opened stream */
- xferrecv_status.type=LOAD;
- xferrecv_status.their_ref=e->data.msg.hdr.my_ref;
- xferrecv_status.task=e->data.msg.hdr.task;
- return TRUE;
- }
- else
- {
- flex_free(&(stream->ungetbuf));
- return FALSE;
- }
- case wimp_MDATASAVE:
- {
- int ram;
-
- ram=gsopenramfetch(&(e->data.msg),&xferrecv_stream);
-
- switch (ram)
- {
- case 0:
-
- flex_free(&(stream->ungetbuf));
- return FALSE;
- case 1:
- xferrecv_status.type=RAM;
- return TRUE;
- case 2:
- xferrecv_status.type=SCRAP;
- msg.hdr.your_ref=e->data.msg.hdr.my_ref;
- msg.hdr.action=wimp_MDATASAVEOK;
- strcpy(msg.data.datasaveok.name,"<Wimp$Scrap>");
- msg.hdr.size=sizeof(wimp_msghdr)+sizeof(wimp_msgdatasaveok);
- msg.data.datasaveok.estsize=-1;
- wimp_sendmessage(wimp_ESENDWANTACK,&msg,e->data.msg.hdr.task);
- xferrecv_status.our_ref=msg.hdr.my_ref;
- win_add_unknown_event_processor(xferrecv_unknowns,NULL);
- xferrecv_busy=TRUE;
- do {event_process(); } while (xferrecv_busy);
- win_remove_unknown_event_processor(xferrecv_unknowns,NULL);
- if (xferrecv_wentOK)
- {
- if (gsopenosr("<Wimp$Scrap>",&xferrecv_stream))
- {
- return TRUE;
- }
- else
- {
- flex_free(&(stream->ungetbuf));
- return FALSE;
- }
- }
- else
- {
- flex_free(&(stream->ungetbuf));
- return FALSE;
- }
- default:
- return FALSE;
- }
- }
- default:
- return FALSE;
- }
- }
-
- static gstream xfersend_stream;
-
- typedef enum
- {
- xfersend_FILE,
- xfersend_RAM
- } xfersend_type;
-
- static struct
- {
- char *filename;
- char outfile[256];
- xfersend_type type;
- int filetype;
- int estsize;
- int our_ref;
- int their_ref;
- wimp_t task;
- int *safeptr;
- } xfersend_status;
-
- int xfersend_busy;
- int xfersend_wentOK;
-
- static int xfersend_unknowns(wimp_eventstr *e, void *handle)
- {
- switch(e->e)
- {
- case wimp_ESEND:
- case wimp_ESENDWANTACK:
- if (xfersend_status.our_ref==e->data.msg.hdr.your_ref)
- {
- switch(e->data.msg.hdr.action)
- {
- case wimp_MDATASAVEOK:
- *(xfersend_status.safeptr)=(e->data.msg.data.datasaveok.estsize!=-1);
- xfersend_status.task=e->data.msg.hdr.task;
- if (*(xfersend_status.safeptr))
- strcpy(xfersend_status.filename,(e->data.msg.data.datasaveok.name));
- strcpy(xfersend_status.outfile,e->data.msg.data.datasaveok.name);
- xfersend_busy=FALSE;
- xfersend_status.type=xfersend_FILE;
- xfersend_status.their_ref=e->data.msg.hdr.my_ref;
- if (gsopenosw(xfersend_status.outfile,&xfersend_stream))
- xfersend_wentOK=TRUE;
- else
- xfersend_wentOK=FALSE;
- return TRUE;
- case wimp_MRAMFETCH:
- xfersend_busy=FALSE;
- xfersend_status.type=xfersend_RAM;
- *(xfersend_status.safeptr)=FALSE;
- if (gsopenramsend(&(e->data.msg),&xfersend_stream))
- xfersend_wentOK=TRUE;
- else
- xfersend_wentOK=FALSE;
- return(TRUE);
- case wimp_MDATALOADOK:
- xfersend_busy=FALSE;
- xfersend_wentOK=TRUE;
- return(TRUE);
- }
- }
- break;
- case wimp_EACK:
- if (e->data.msg.hdr.my_ref==xfersend_status.our_ref)
- {
- switch (e->data.msg.hdr.action)
- {
- case wimp_MDATALOAD:
- werr(FALSE,"Data transfer failed: reciever died");
- xfersend_busy=FALSE;
- if (!*(xfersend_status.safeptr))
- remove(xfersend_status.outfile);
- xfersend_wentOK=FALSE;
- return(TRUE);
-
- default:
- xfersend_busy=FALSE;
- xfersend_wentOK=FALSE;
- return(TRUE);
- }
- }
- break;
- }
- return FALSE;
- }
-
- static size_t xfersend_write(void *ptr, size_t size, void *s)
- {
- gstream *stream=(gstream *) s;
- size=gswrite(ptr, 1, size, &xfersend_stream);
- stream->error=xfersend_stream.error;
- return size;
- }
-
- static int xfersend_close(void *s)
- {
- wimp_msgstr msg;
- int ok;
- gstream *stream=(gstream *) s;
-
- switch (xfersend_status.type)
- {
- case xfersend_FILE:
- ok=gsclose(&xfersend_stream);
- if (!ok)
- {
- os_error *e;
- setfiletype(xfersend_status.outfile,xfersend_status.filetype);
- msg.hdr.your_ref=xfersend_status.their_ref;
- msg.hdr.action=wimp_MDATALOAD;
- msg.hdr.size=sizeof(wimp_msghdr)+sizeof(wimp_msgdataload);
- strcpy(msg.data.dataload.name,xfersend_status.outfile);
- msg.data.dataload.type=xfersend_status.filetype;
- msg.data.dataload.type=xfersend_status.estsize;
- e=wimp_sendmessage(wimp_ESENDWANTACK,&msg,xfersend_status.task);
- xfersend_status.our_ref=msg.hdr.my_ref;
- if (!e)
- {
- xfersend_wentOK=TRUE;
- xfersend_busy=TRUE;
- win_add_unknown_event_processor(xfersend_unknowns,NULL);
- do { event_process(); } while (xfersend_busy);
- win_remove_unknown_event_processor(xfersend_unknowns,NULL);
- if (xfersend_wentOK)
- return TRUE;
- }
- else
- wimpt_complain(e);
- }
- stream->error=TRUE;
- return FALSE;
- case xfersend_RAM:
- ok=gsclose(&xfersend_stream);
- if (!ok)
- return TRUE;
- else
- {
- stream->error=TRUE;
- return FALSE;
- }
- default:
- return FALSE;
- }
- }
-
-
- /* this function should be called after a drag of a file from a saveas dbox.
- * leafname should be long enough to hold the full pathname of the saved
- * file.
- */
-
- int gsopenxfersend( char *name,
- int filetype,
- int estsize,
- int *safeptr,
- gstream *stream)
- {
- wimp_mousestr mouse; /* holds mouse position */
- wimp_msgstr msg;
- os_error *e;
-
- if ((e=wimp_get_point_info(&mouse))!=NULL)
- {
- wimpt_complain(e);
- return FALSE;
- }
-
- if (mouse.w==-1)
- return(FALSE); /* drag ended on background */
-
- stream->type=WRITE;
- stream->bufsize=0;
-
- stream->io.write=xfersend_write;
- stream->close=xfersend_close;
- stream->error=FALSE;
-
- msg.hdr.action=wimp_MDATASAVE;
- msg.hdr.size=sizeof(wimp_msghdr)+sizeof(wimp_msgdatasave);
- msg.hdr.your_ref=0;
- msg.data.datasave.w=mouse.w;
- msg.data.datasave.i=mouse.i;
- msg.data.datasave.x=mouse.x;
- msg.data.datasave.y=mouse.y;
- msg.data.datasave.type=filetype;
- msg.data.datasave.estsize=estsize;
- xfersend_status.filetype=filetype;
- xfersend_status.estsize=estsize;
- strcpy(msg.data.datasave.leaf,name);
- msg.data.datasave.leaf[11]='\0';
- xfersend_status.filename=name;
- xfersend_status.safeptr=safeptr;
-
- if ((e=wimp_sendwmessage(wimp_ESENDWANTACK,&msg,mouse.w,mouse.i))!=NULL)
- {
- wimpt_complain(e);
- return FALSE;
- }
- xfersend_status.our_ref=msg.hdr.my_ref;
- xfersend_busy=TRUE;
- xfersend_wentOK=FALSE;
- win_add_unknown_event_processor(xfersend_unknowns,NULL);
- do {event_process(); } while (xfersend_busy);
- win_remove_unknown_event_processor(xfersend_unknowns,NULL);
-
- return xfersend_wentOK;
- }
-
-