home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / clib / progs / timslib / OtherBits / c / XferSend < prev   
Encoding:
Text File  |  1993-01-22  |  7.3 KB  |  243 lines

  1. /* XferSend.c */
  2. /*                           
  3.  
  4.   #####                 #         #
  5.     #    #              #      #  #
  6.     #                   #         #
  7.     #   ##  ####   #### #     ##  ####
  8.     #    #  # # # #     #      #  #   #
  9.     #    #  # # #  ###  #      #  #   #
  10.     #    #  # # #     # #      #  #   #
  11.     #   ### # # # ####  ##### ### ####
  12.  
  13. -----------------------------------------------------------------------------
  14.  
  15. This is source for use with the 'DeskLib' Wimp C programming library for
  16. Risc OS. I currently use v1.04 of DeskLib.  This source is FreeWare, which
  17. means you can use it to write commercial applications, but you may not charge
  18. *in any way* for the distribution of this source.  I (Tim Browse) retain
  19. all copyright on this source.
  20.  
  21. This source is provided 'as is' and I offer no guarantees that is useful,
  22. bug-free, commented, that it will compile, or even that it exists.
  23.  
  24. If it breaks in half, you own both pieces.
  25.  
  26. All source © Tim Browse 1993
  27.  
  28. -----------------------------------------------------------------------------
  29.  
  30. */
  31.  
  32. /* A replacement for Acorn's xfersend, using DeskLib */
  33.  
  34. /* ANSI includes */
  35. #include <string.h>
  36.  
  37. /* Risc OS Lib includes */
  38. #include "werr.h"
  39. #include "bbc.h"
  40.  
  41. /* DeskLib includes */
  42. #include "DeskLib.Core.h"
  43. #include "DeskLib.Wimp.h"
  44. #include "DeskLib.WimpSWIs.h"
  45. #include "DeskLib.Screen.h"
  46. #include "DeskLib.Event.h"
  47. #include "DeskLib.EventMsg.h"
  48. #include "DeskLib.Error.h"
  49. #include "DeskLib.Coord.h"
  50. #include "DeskLib.SWI.h"
  51.  
  52. #include "Timslib.swis.h"
  53.  
  54. #include "XferSend.h"
  55.  
  56. typedef struct
  57. {
  58.   int               filetype;
  59.   char             *name;
  60.   int               estsize;
  61.   xfersend_saveproc savetofile;
  62.   void             *handle;
  63.   unsigned int      myref;
  64. } xfersend_block;
  65.  
  66. BOOL export_finished,
  67.      export_successful;
  68.  
  69. /* Forward declarations of handlers fpr claiming/releasing events */
  70.  
  71. static BOOL DataSaveAckHandler(event_pollblock *event, void *handle);
  72. static BOOL DataLoadAckHandler(event_pollblock *event, void *handle);
  73. static BOOL XferFailHandler(event_pollblock *event, void *handle);
  74.  
  75. static BOOL DataSaveAckHandler(event_pollblock *event, void *handle)
  76. {
  77.   xfersend_block *info = (xfersend_block *) handle;
  78.   message_block   *message;
  79.   message_destinee destinee;
  80.  
  81.   /* If this isn't a reply to the message we sent, ignore it */
  82.   if (event->data.message.header.yourref != info->myref)
  83.     return FALSE;
  84.  
  85.   /* We've got a filename to use, so save the data to it */
  86.   export_successful = 
  87.     info->savetofile(event->data.message.data.datasaveack.filename, info->handle);
  88.  
  89.   /* Send a DataLoad message back */
  90.   destinee.value = event->data.message.header.sender;
  91.  
  92.   message = &event->data.message;
  93.   message->header.action  = message_DATALOAD;
  94.   message->header.yourref = message->header.myref;
  95.  
  96.   message->header.size    = sizeof(message_header) + sizeof(message_dataload);
  97.  
  98.   Wimp_SendMessage(event_USERMESSAGERECORDED, message, destinee, 0);
  99.  
  100.   /* Make a note of the myref field */
  101.   info->myref = message->header.myref;
  102.   return TRUE;
  103. }
  104.  
  105. static BOOL DataLoadAckHandler(event_pollblock *event, void *handle)
  106. {
  107.   xfersend_block *info = (xfersend_block *) handle;
  108.   
  109.   /* If this isn't a reply to the message we sent, ignore it */
  110.   if (event->data.message.header.yourref != info->myref)
  111.     return FALSE;
  112.  
  113.   /* Transfer is finished */
  114.   export_finished = TRUE;
  115.  
  116.   /* Release the message events we've claimed */
  117.   EventMsg_Release(message_DATASAVEACK, event_ANY, DataSaveAckHandler);
  118.   EventMsg_Release(message_DATALOADACK, event_ANY, DataLoadAckHandler);
  119.   Event_Release(event_USERMESSAGEACK, event_ANY, event_ANY, XferFailHandler, handle);
  120.  
  121.   return TRUE;
  122. }
  123.  
  124. static BOOL XferFailHandler(event_pollblock *event, void *handle)
  125. {
  126.   /* One of our messages wasn't replied to, so abort the transfer. */
  127.   export_finished = TRUE;
  128.   export_successful = FALSE;
  129.  
  130.   /* Release the message events we've claimed */
  131.   EventMsg_Release(message_DATASAVEACK, event_ANY, DataSaveAckHandler);
  132.   EventMsg_Release(message_DATALOADACK, event_ANY, DataLoadAckHandler);
  133.   Event_Release(event_USERMESSAGEACK, event_ANY, event_ANY, XferFailHandler, handle);
  134.  
  135.   /* If we sent a DataLoad and no reply was forthcoming, complain about lack of
  136.      response - see Risc OS 2 PRMs p1266
  137.   */
  138.   if (event->data.message.header.action == message_DATALOAD)
  139.     werr(FALSE, "Data transfer failed: Receiver died.");
  140.  
  141.   return TRUE;
  142. }  
  143.  
  144. static BOOL DragHandler(event_pollblock *event, void *handle)
  145. {
  146.   xfersend_block *info = (xfersend_block *) handle;
  147.   mouse_block ptr;
  148.   message_block message;
  149.   message_destinee destinee;
  150.  
  151.   /* Get end point of drag */ 
  152.   Wimp_GetPointerInfo(&ptr);
  153.  
  154.   /* Ask for DataSaveAck and DataLoadAck messages, and UserMessageAck events
  155.      to be sent to our handlers.
  156.   */
  157.   EventMsg_Claim(message_DATASAVEACK, event_ANY, DataSaveAckHandler, handle);
  158.   EventMsg_Claim(message_DATALOADACK, event_ANY, DataLoadAckHandler, handle);
  159.   Event_Claim(event_USERMESSAGEACK, event_ANY, event_ANY, XferFailHandler, handle);
  160.  
  161.   /* Set up a DataSave message to send to this end point */
  162.  
  163.   destinee.window = ptr.window;
  164.  
  165.   message.header.size    = sizeof(message_header) + sizeof(message_datasave);
  166.  
  167.   message.header.yourref = 0; /* original message */
  168.   message.header.action  = message_DATASAVE;
  169.  
  170.   message.data.datasave.window   = ptr.window;
  171.   message.data.datasave.icon     = ptr.icon;
  172.   message.data.datasave.pos      = ptr.pos;
  173.   message.data.datasave.estsize  = info->estsize;
  174.   message.data.datasave.filetype = info->filetype;
  175.   strcpy(message.data.datasave.leafname, info->name);
  176.  
  177.   /* Send the DataSave message */
  178.   Wimp_SendMessage(event_USERMESSAGERECORDED, &message, destinee, 0);
  179.  
  180.   /* Make a note of the 'myref' field */
  181.   info->myref = message.header.myref;
  182.  
  183.   return TRUE;
  184.  
  185.  
  186. BOOL XferSend(int filetype, char *name, int estsize, 
  187.               xfersend_saveproc savetofile, event_pollblock *event, void *handle)
  188. {
  189.   xfersend_block xfersend;
  190.  
  191.   icon_block   icon;
  192.   window_state state;
  193.   drag_block   drag;
  194.  
  195.   /* Save info for handler to get at */
  196.   xfersend.filetype   = filetype;
  197.   xfersend.name       = name;
  198.   xfersend.estsize    = estsize;
  199.   xfersend.savetofile = savetofile;
  200.   xfersend.handle     = handle;
  201.  
  202.  
  203.   /* Drag a fixed box around the screen */
  204.   drag.type   = drag_FIXEDBOX;
  205.  
  206.   /* Get the bounding box of the icon user is dragging */
  207.   Error_Check(Wimp_GetIconState(event->data.mouse.window, event->data.mouse.icon,
  208.                                 &icon));
  209.  
  210.   /* Convert to screen co-ordinates */
  211.   Error_Check(Wimp_GetWindowState(event->data.mouse.window, &state));
  212.   Coord_RectToScreen(&icon.workarearect, (convert_block *) &state.openblock.screenrect);
  213.  
  214.   /* Make this the size of the box */
  215.   drag.screenrect = icon.workarearect;
  216.  
  217.   /* Constrain to whole screen (ie unconstrained) */
  218.   drag.parent.min.x = 0;
  219.   drag.parent.min.y = 0;
  220.   drag.parent.max = screen_size;
  221.  
  222.   /* Claim drag events */
  223.   Event_Claim(event_USERDRAG, event_ANY, event_ANY, DragHandler, (void *) &xfersend);
  224.  
  225.   /* Initiate drag */
  226.   Error_Check(Wimp_DragBox(&drag));
  227.  
  228.   /* Keep polling until drag received by our handler and dealt with */
  229.   export_finished = FALSE;
  230.   export_successful = FALSE;
  231.  
  232.   /* Keep polling for events until the file is saved */
  233.   while (!export_finished)
  234.     Event_Poll();
  235.  
  236.   /* Release drag events */
  237.   Event_Release(event_USERDRAG, event_ANY, event_ANY, DragHandler, (void *) &xfersend);
  238.  
  239.   /* Return value according to whether it worked or not... */
  240.   return export_successful;
  241. }
  242.