home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / gstream / c / xferstream < prev   
Encoding:
Text File  |  1993-05-08  |  13.8 KB  |  511 lines

  1. /*************************************************************
  2. *                                                            *
  3. *    Module: xferstream.c (part of gstream package)          *
  4. *                                                            *
  5. *   Version: 0.01                                            *
  6. *                                                            *
  7. *    Author: Simon Proven                                    *
  8. *                                                            *
  9. *     Owner:  Simon Proven 1993                             *
  10. *                                                            *
  11. *   Purpose: To provide gstream access to the wimp data      *
  12. *            transfer protcols.                              *
  13. *                                                            *
  14. *      Uses: gstream, stdlib, string, osstream, ramstream,   *
  15. *            werr, wimp, wimpt, win, event                   *
  16. *                                                            *
  17. * Conditions:                                                *
  18. *             You can produce and sell executable code from  *
  19. *             this module freely.  The source code may be    *
  20. *             distributed freely, but not for profit.        *
  21. *                                                            *
  22. *             If you like these modules alot, and use them   *
  23. *             in your own programs, feel free to thank me    *
  24. *             with cash - 10 or more will get you a disc    *
  25. *             with the latest versions and new stream types. *
  26. *                                                            *
  27. * Disclaimer:                                                *
  28. *             This software is supplied in good faith, but I *
  29. *             cannot accept liability for any loss incurred  *
  30. *             through the use or inability to use any part   *
  31. *             of this software.                              *
  32. *                                                            *
  33. * How to contact me:                                         *
  34. *                                                            *
  35. * email:                      snail mail:                    *
  36. * sproven@cs.strath.ac.uk     Simon Proven,                  *
  37. *                             Castle Cottage,                *
  38. *                             Portencross,                   *
  39. *                             West Kilbride,                 *
  40. *                             KA23 9QA                       *
  41. *                             SCOTLAND                       *
  42. *                                                            *
  43. * Tel. (+44) 294 829 721                                     *
  44. *                                                            *
  45. *************************************************************/
  46.  
  47. /* This module allows saves to be initiated or loads to be recieved,
  48.  * providing the user with a similar interface whether the RAM transfer
  49.  * or scrap file methods are used.  This module will default to using
  50.  * the RAM transfer method, and will only use the scrap transfer method
  51.  * if the other application involved in the transfer is not interested
  52.  * in the RAM tranfer method.
  53.  *
  54.  * To operate correctly, this module requires the ramstream and osstream
  55.  * modules also.
  56.  *
  57.  * Saves back to ourself won't work.
  58.  */
  59.  
  60. /* This function should be used to handle an incoming dataload, dataopen
  61.  * or datasave message which the application wishes to pick up.
  62.  *
  63.  * The function will set up the stream and will return TRUE if the stream
  64.  * could be opened or FALSE if it could not be opened.
  65.  *
  66.  * The user's code is expected to read all information regarding the file
  67.  * type, name, modified flag etc, before the stream is opened.
  68.  *
  69.  * This stream will deal with sending all required messages to the other
  70.  * task, and with all message reception.
  71.  *
  72.  * Note: if your applicatio recieves a message DataLoad with your_ref!=0
  73.  * it should ignore the message but still call this function.  This is
  74.  * to ensure that the message gets to the right place.  Otherwise, it 
  75.  * cannot be guaranteed to pick up the message as the message will NOT be
  76.  * passed through the unknown message handler installed by this function.
  77.  *
  78.  * This stream type operates by attempting to open a ramfetch stream - if
  79.  * that doesn't work, then the stream will try to use the scrap file method.
  80.  *
  81.  * This stream's write function simply calls gswrite for the daughter stream.
  82.  * This stream has no buffer - all buffering is performed in the daughter
  83.  * stream.
  84.  */
  85.  
  86. #include "gstream.h"
  87. #include "osstream.h"
  88. #include "ramstream.h"
  89. #include "werr.h"
  90. #include "wimp.h"
  91. #include "wimpt.h"
  92. #include "win.h"
  93. #include "event.h"
  94. #include <stdlib.h>
  95. #include <string.h>
  96.  
  97. void setfiletype(char *name, int type)
  98. {
  99.     os_filestr s;
  100.  
  101.     s.action=18; /* RISC OS 2 PRM page 849 - set file type */
  102.     s.name=name;
  103.     s.loadaddr=type;
  104.     wimpt_complain(os_file(&s));
  105. }
  106.  
  107. typedef enum
  108. {
  109.     RAM,
  110.     SCRAP,
  111.     LOAD
  112. } xferrecv_type;
  113.  
  114. static struct
  115. {
  116.     xferrecv_type    type;    /* TRUE if using RAM data transfer, FALSE if using scrap file */
  117.     int        their_ref;
  118.     int        our_ref;
  119.     wimp_t        task;
  120. } xferrecv_status;
  121.  
  122. static gstream xferrecv_stream;
  123. static int xferrecv_wentOK;
  124. static int xferrecv_busy;
  125.  
  126. static int xferrecv_unknowns(wimp_eventstr *e, void *handle)
  127. {
  128.     switch (e->e)
  129.     {
  130.         case wimp_ESEND:
  131.         case wimp_ESENDWANTACK:
  132.             if (e->data.msg.hdr.your_ref == xferrecv_status.our_ref)
  133.             {
  134.                 switch(e->data.msg.hdr.action)
  135.                 {
  136.                     case wimp_MDATALOAD:
  137.                         xferrecv_busy=FALSE;
  138.                         xferrecv_wentOK=TRUE;
  139.                         xferrecv_status.their_ref=e->data.msg.hdr.my_ref;
  140.                         return TRUE;
  141.                 }
  142.             }
  143.             return(FALSE);
  144.         case wimp_EACK:
  145.             if (e->data.msg.hdr.my_ref == xferrecv_status.our_ref)
  146.             {
  147.                 xferrecv_busy=FALSE;
  148.                 xferrecv_wentOK=FALSE;
  149.                 return TRUE;
  150.             }
  151.         default:
  152.             return FALSE;
  153.     }
  154. }
  155.  
  156. static size_t xferrecv_read(void *ptr, size_t size, void *s)
  157. {
  158.     gstream *stream=(gstream *) s;
  159.     size=gsread(ptr, 1, size, &xferrecv_stream);
  160.     stream->error=xferrecv_stream.error;
  161.     return size;
  162. }
  163.  
  164. static int xferrecv_close(void *s)
  165. {
  166.     wimp_msgstr msg;
  167.     int ok;
  168.  
  169.  
  170.     switch (xferrecv_status.type)
  171.     {
  172.         case LOAD:
  173.             msg.hdr.your_ref=xferrecv_status.their_ref;
  174.             msg.hdr.action=wimp_MDATALOADOK;
  175.             wimp_sendmessage(wimp_ESEND,&msg,xferrecv_status.task);
  176.             ok=gsclose(&xferrecv_stream);
  177.             if (!ok)
  178.                 return TRUE;
  179.             else
  180.                 return FALSE;
  181.         case RAM:
  182.             ok=gsclose(&xferrecv_stream);
  183.             if (!ok)
  184.                 return TRUE;
  185.             else
  186.                 return FALSE;
  187.         case SCRAP:
  188.             msg.hdr.your_ref=xferrecv_status.their_ref;
  189.             msg.hdr.action=wimp_MDATASAVEOK;
  190.             wimp_sendmessage(wimp_ESEND,&msg,xferrecv_status.task);
  191.             ok=gsclose(&xferrecv_stream);
  192.             remove("<Wimp$Scrap>");
  193.             if (!ok)
  194.                 return TRUE;
  195.             else
  196.                 return FALSE;            
  197.         default:
  198.             return FALSE;
  199.     }
  200. }
  201.  
  202. int gsopenxferrecv(wimp_eventstr *e, gstream *stream)
  203. {
  204.     wimp_msgstr msg;
  205.  
  206.     if (e->data.msg.hdr.task==wimpt_task())
  207.     {
  208.         werr(FALSE,"Sorry - I can't drag files back to my own icon or windows");
  209.         return FALSE;
  210.     }
  211.  
  212.     if (e->data.msg.hdr.your_ref!=0)
  213.     {
  214.         xferrecv_unknowns(e,NULL);
  215.         return FALSE;
  216.     }
  217.  
  218.     stream->type=READ;
  219.     stream->bufsize=0;
  220.     stream->ungetsize=4;
  221.     stream->ungetpos=0;
  222.     stream->error=FALSE;
  223.     if (!flex_alloc(&(stream->ungetbuf),4))
  224.     {
  225.         werr(FALSE,"Not enough space");
  226.         return FALSE;
  227.     }
  228.     stream->io.read=xferrecv_read;
  229.     stream->close=xferrecv_close;
  230.  
  231.     switch (e->data.msg.hdr.action)
  232.     {
  233.         case wimp_MDATALOAD:
  234.             if (gsopenosr(e->data.msg.data.dataload.name,&xferrecv_stream))
  235.             {
  236.                 /* succesfully opened stream */
  237.                 xferrecv_status.type=LOAD;
  238.                 xferrecv_status.their_ref=e->data.msg.hdr.my_ref;
  239.                 xferrecv_status.task=e->data.msg.hdr.task;
  240.                 return TRUE;
  241.             }
  242.             else
  243.             {
  244.                 flex_free(&(stream->ungetbuf));
  245.                 return FALSE;
  246.             }
  247.         case wimp_MDATASAVE:
  248.         {
  249.             int ram;
  250.  
  251.             ram=gsopenramfetch(&(e->data.msg),&xferrecv_stream);
  252.  
  253.             switch (ram)
  254.             {
  255.                 case 0:
  256.  
  257.                     flex_free(&(stream->ungetbuf));
  258.                     return FALSE;
  259.                 case 1:
  260.                     xferrecv_status.type=RAM;
  261.                     return TRUE;
  262.                 case 2:
  263.                     xferrecv_status.type=SCRAP;
  264.                     msg.hdr.your_ref=e->data.msg.hdr.my_ref;
  265.                     msg.hdr.action=wimp_MDATASAVEOK;
  266.                     strcpy(msg.data.datasaveok.name,"<Wimp$Scrap>");
  267.                     msg.hdr.size=sizeof(wimp_msghdr)+sizeof(wimp_msgdatasaveok);
  268.                     msg.data.datasaveok.estsize=-1;
  269.                     wimp_sendmessage(wimp_ESENDWANTACK,&msg,e->data.msg.hdr.task);
  270.                     xferrecv_status.our_ref=msg.hdr.my_ref;
  271.                     win_add_unknown_event_processor(xferrecv_unknowns,NULL);
  272.                     xferrecv_busy=TRUE;
  273.                     do {event_process(); } while (xferrecv_busy);
  274.                     win_remove_unknown_event_processor(xferrecv_unknowns,NULL);
  275.                     if (xferrecv_wentOK)
  276.                     {
  277.                         if (gsopenosr("<Wimp$Scrap>",&xferrecv_stream))
  278.                         {
  279.                             return TRUE;
  280.                         }
  281.                         else
  282.                         {
  283.                             flex_free(&(stream->ungetbuf));
  284.                             return FALSE;
  285.                         }
  286.                     }
  287.                     else
  288.                     {
  289.                         flex_free(&(stream->ungetbuf));
  290.                         return FALSE;
  291.                     }
  292.                 default:
  293.                     return FALSE;
  294.             }
  295.         }
  296.         default:
  297.             return FALSE;
  298.     }
  299. }
  300.  
  301. static gstream xfersend_stream;
  302.  
  303. typedef enum
  304. {
  305.     xfersend_FILE,
  306.     xfersend_RAM
  307. } xfersend_type;
  308.  
  309. static struct
  310. {
  311.     char        *filename;
  312.     char        outfile[256];
  313.     xfersend_type    type;
  314.     int        filetype;
  315.     int        estsize;
  316.     int        our_ref;
  317.     int        their_ref;
  318.     wimp_t        task;
  319.     int        *safeptr;
  320. } xfersend_status;
  321.  
  322. int xfersend_busy;
  323. int xfersend_wentOK;
  324.  
  325. static int xfersend_unknowns(wimp_eventstr *e, void *handle)
  326. {
  327.     switch(e->e)
  328.     {
  329.         case wimp_ESEND:
  330.         case wimp_ESENDWANTACK:
  331.             if (xfersend_status.our_ref==e->data.msg.hdr.your_ref)
  332.             {
  333.                 switch(e->data.msg.hdr.action)
  334.                 {
  335.                     case wimp_MDATASAVEOK:
  336.                         *(xfersend_status.safeptr)=(e->data.msg.data.datasaveok.estsize!=-1);
  337.                         xfersend_status.task=e->data.msg.hdr.task;
  338.                         if (*(xfersend_status.safeptr))
  339.                             strcpy(xfersend_status.filename,(e->data.msg.data.datasaveok.name));
  340.                         strcpy(xfersend_status.outfile,e->data.msg.data.datasaveok.name);
  341.                         xfersend_busy=FALSE;
  342.                         xfersend_status.type=xfersend_FILE;
  343.                         xfersend_status.their_ref=e->data.msg.hdr.my_ref;
  344.                         if (gsopenosw(xfersend_status.outfile,&xfersend_stream))
  345.                             xfersend_wentOK=TRUE;
  346.                         else
  347.                             xfersend_wentOK=FALSE;
  348.                         return TRUE;
  349.                     case wimp_MRAMFETCH:
  350.                         xfersend_busy=FALSE;
  351.                         xfersend_status.type=xfersend_RAM;
  352.                         *(xfersend_status.safeptr)=FALSE;
  353.                         if (gsopenramsend(&(e->data.msg),&xfersend_stream))
  354.                             xfersend_wentOK=TRUE;
  355.                         else
  356.                             xfersend_wentOK=FALSE;
  357.                         return(TRUE);
  358.                     case wimp_MDATALOADOK:
  359.                         xfersend_busy=FALSE;
  360.                         xfersend_wentOK=TRUE;
  361.                         return(TRUE);
  362.                 }
  363.             }
  364.             break;
  365.         case wimp_EACK:
  366.             if (e->data.msg.hdr.my_ref==xfersend_status.our_ref)
  367.             {
  368.                 switch (e->data.msg.hdr.action)
  369.                 {
  370.                         case wimp_MDATALOAD:
  371.                         werr(FALSE,"Data transfer failed: reciever died");
  372.                         xfersend_busy=FALSE;
  373.                         if (!*(xfersend_status.safeptr))
  374.                             remove(xfersend_status.outfile);
  375.                         xfersend_wentOK=FALSE;
  376.                         return(TRUE);
  377.                         
  378.                     default:
  379.                         xfersend_busy=FALSE;
  380.                         xfersend_wentOK=FALSE;
  381.                         return(TRUE);
  382.                 }
  383.             }
  384.             break;
  385.     }
  386.     return FALSE;
  387. }
  388.  
  389. static size_t xfersend_write(void *ptr, size_t size, void *s)
  390. {
  391.     gstream *stream=(gstream *) s;
  392.     size=gswrite(ptr, 1, size, &xfersend_stream);
  393.     stream->error=xfersend_stream.error;
  394.     return size;    
  395. }
  396.  
  397. static int xfersend_close(void *s)
  398. {
  399.     wimp_msgstr msg;
  400.     int ok;
  401.     gstream *stream=(gstream *) s;
  402.  
  403.     switch (xfersend_status.type)
  404.     {
  405.         case xfersend_FILE:
  406.             ok=gsclose(&xfersend_stream);
  407.             if (!ok)
  408.             {
  409.                 os_error *e;
  410.                 setfiletype(xfersend_status.outfile,xfersend_status.filetype);
  411.                 msg.hdr.your_ref=xfersend_status.their_ref;
  412.                 msg.hdr.action=wimp_MDATALOAD;
  413.                 msg.hdr.size=sizeof(wimp_msghdr)+sizeof(wimp_msgdataload);
  414.                 strcpy(msg.data.dataload.name,xfersend_status.outfile);
  415.                 msg.data.dataload.type=xfersend_status.filetype;
  416.                 msg.data.dataload.type=xfersend_status.estsize;
  417.                 e=wimp_sendmessage(wimp_ESENDWANTACK,&msg,xfersend_status.task);
  418.                 xfersend_status.our_ref=msg.hdr.my_ref;
  419.                 if (!e)
  420.                 {
  421.                     xfersend_wentOK=TRUE;
  422.                     xfersend_busy=TRUE;
  423.                     win_add_unknown_event_processor(xfersend_unknowns,NULL);
  424.                     do { event_process(); } while (xfersend_busy);
  425.                     win_remove_unknown_event_processor(xfersend_unknowns,NULL);
  426.                     if (xfersend_wentOK)
  427.                         return TRUE;
  428.                 }
  429.                 else
  430.                     wimpt_complain(e);
  431.             }
  432.             stream->error=TRUE;
  433.             return FALSE;
  434.         case xfersend_RAM:
  435.             ok=gsclose(&xfersend_stream);
  436.             if (!ok)
  437.                 return TRUE;
  438.             else
  439.             {
  440.                 stream->error=TRUE;
  441.                 return FALSE;
  442.             }
  443.         default:
  444.             return FALSE;
  445.     }
  446. }
  447.  
  448.  
  449. /* this function should be called after a drag of a file from a saveas dbox.
  450.  * leafname should be long enough to hold the full pathname of the saved
  451.  * file.
  452.  */
  453.  
  454. int gsopenxfersend(    char            *name,
  455.             int            filetype,
  456.             int            estsize,
  457.             int            *safeptr,
  458.             gstream            *stream)
  459. {
  460.     wimp_mousestr    mouse;    /* holds mouse position */
  461.     wimp_msgstr    msg;
  462.     os_error    *e;
  463.  
  464.     if ((e=wimp_get_point_info(&mouse))!=NULL)
  465.     {
  466.         wimpt_complain(e);
  467.         return FALSE;
  468.     }
  469.  
  470.     if (mouse.w==-1)
  471.         return(FALSE);    /* drag ended on background */
  472.  
  473.     stream->type=WRITE;
  474.     stream->bufsize=0;
  475.  
  476.     stream->io.write=xfersend_write;
  477.     stream->close=xfersend_close;
  478.     stream->error=FALSE;
  479.  
  480.     msg.hdr.action=wimp_MDATASAVE;
  481.     msg.hdr.size=sizeof(wimp_msghdr)+sizeof(wimp_msgdatasave);
  482.     msg.hdr.your_ref=0;
  483.     msg.data.datasave.w=mouse.w;
  484.     msg.data.datasave.i=mouse.i;
  485.     msg.data.datasave.x=mouse.x;
  486.     msg.data.datasave.y=mouse.y;
  487.     msg.data.datasave.type=filetype;
  488.     msg.data.datasave.estsize=estsize;
  489.     xfersend_status.filetype=filetype;
  490.     xfersend_status.estsize=estsize;
  491.     strcpy(msg.data.datasave.leaf,name);
  492.     msg.data.datasave.leaf[11]='\0';
  493.     xfersend_status.filename=name;
  494.     xfersend_status.safeptr=safeptr;
  495.  
  496.     if ((e=wimp_sendwmessage(wimp_ESENDWANTACK,&msg,mouse.w,mouse.i))!=NULL)
  497.     {
  498.         wimpt_complain(e);
  499.         return FALSE;
  500.     }
  501.     xfersend_status.our_ref=msg.hdr.my_ref;
  502.     xfersend_busy=TRUE;
  503.     xfersend_wentOK=FALSE;
  504.     win_add_unknown_event_processor(xfersend_unknowns,NULL);
  505.     do {event_process(); } while (xfersend_busy);
  506.     win_remove_unknown_event_processor(xfersend_unknowns,NULL);
  507.  
  508.     return xfersend_wentOK;
  509. }
  510.  
  511.