home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine 1997 / ARCHIVE_97.iso / discs / mag_discs / volume_08 / issue_06 / risc_os / DataTrans < prev    next >
Text File  |  1988-12-12  |  19KB  |  473 lines

  1. Communication with the Filer: the Data Transfer Protocol
  2. ========================================================
  3.  
  4. These protocols are understood by the Filer, and by applications that load
  5. and save files. In fact, the Filer is not a particularly special case. The
  6. following cases are considered:
  7.  
  8. (1) The user drags an icon from an application to a Filer window.
  9. The application saves the file.
  10.  
  11. (2) The user drags an icon from an application to a window of another
  12. application. The transfer is achieved via a temporary file.
  13.  
  14. (3) The user drags an icon from an application to a window of another
  15. application. The transfer is achieved (if both sides agree) using direct
  16. transfer of memory between the two address spaces.
  17.  
  18. (4) The user drags an icon from the Filer to the window of an application.
  19. The application inserts or loads the file.
  20.  
  21. (5) The user double-clicks on an icon in the Filer. An existing application
  22. opens the file.
  23.  
  24. There are other cases which generalise some of these, with an application
  25. "pretending" to be the Filer. For instance, when a message arrives for
  26. MailMan, it simulates case (5) to cause the editor to display the incoming
  27. message.
  28.  
  29. This section assumes knowledge of the Wimp program interface. It is separate
  30. because the facilities are actually provided by the Filer rather than the
  31. Wimp. Careful study of the sections on message passing is recommended.
  32.  
  33. The protocols do not specify whether event codes 17 or 18 are used within
  34. the protocol, as either is acceptable at any stage of the protocols. Type 18
  35. messages are needed when confirmation of non-reply is required, which is
  36. provided by the Wimp. Type 18 messages are recommended when a reply is
  37. expected.
  38.  
  39. Also, messages may include excess junk at the end of the form. The
  40. precise size of the message is not part of the protocol.
  41.  
  42. Some of the message formats have unused or copied portions. This is to make
  43. it easier to reply to certain messages by overwriting some fields in the
  44. incoming message and then just sending it back. Note, however, that these
  45. are essential parts of the protocol and must be copied precisely in order to
  46. adhere to the protocol. In some cases acknowledgements and replies are not
  47. used, this makes it especially important to stick to the letter of this document
  48. (rather than just "hacking until it works with the Filer") to prevent surprises
  49. when programs from different sources are brought together.
  50.  
  51. The following message is sent by an application wishing to save a document (or a
  52. selected part of a document):
  53.  
  54. 1  DataSave
  55.  
  56.    R0     17 (usually)
  57.    R1!0   size
  58.      !12  0
  59.      !16  1 ; DataSave
  60.      !20  destination window handle             ;
  61.      !24  destination window icon               ; copied from
  62.      !28  destination x coord (screen coords)   ; Wimp_GetPointerInfo
  63.      !32  destination y coord (screen coords)   ;
  64.      !36  estimated size of data, in bytes
  65.      !40  file type of data
  66.      !44  proposed leaf-name of file, 0-terminated
  67.  
  68. The destination window handle, icon and coordinates are those generated by
  69. Wimp_GetPointerInfo at the end of a drag.
  70.  
  71. The file type word is a value in the range 0..&fff for typed files, or one of the
  72. following:
  73.     &1000 for a directory
  74.     &2000 for an application directory
  75.     &3000 for a load/exec file
  76.  
  77. If the target window is a directory viewer (or any other window which wishes
  78. the information to be written only to a file) then it replies as follows:
  79.  
  80. 2  DataSaveAck (save data to file)
  81.  
  82.    R0     17 (usually)
  83.    R1!0   size
  84.      !12  my-ref field of DataSave message
  85.      !16  2  ; save data to here
  86.      !20..40 ; left unchanged from relevant DataSave
  87.      !44  full path-name of file, 0-terminated
  88.  
  89. Note that the type and size information are typically ignored when
  90. generating this response. The Filer implements this form of reply for
  91. directory viewer windows.
  92.  
  93. An editor, on receiving this reply, should save the data specified by the
  94. user in the named file. If this save fails, report using Wimp_ReportError
  95. and the transaction stops.
  96.  
  97. The editor should also mark the document as not modified, if the whole
  98. document is being saved (rather than some selected portion). An exception to
  99. this is that if the "estimated size" field of the DataSaveAck is negative
  100. then do not mark the document as unmodified: this is a signal from the
  101. recipient that this file is a temporary one, rather than a good repository
  102. for future versions of the file. When marking the document as unmodified,
  103. also remember the full path-name so that future saves can be performed
  104. without the user having to drag icons.
  105.  
  106. The editor then issues this acknowledgement:
  107.  
  108. 3  DataLoad (drag file from Filer / I have saved data to a file)
  109.  
  110.    R0     18 (usually)
  111.    R1!0   size
  112.      !12  my-ref field of DataSaveAck message (or 0 if from Filer)
  113.      !16  3 ; load data from here
  114.      !20  destination window handle             ;
  115.      !24  destination icon handle               ; copied from
  116.      !28  destination x coord (screen coords)   ; Wimp_GetPointerInfo
  117.      !32  destination y coord (screen coords)   ;
  118.      !36  must be <= 0 ; size field in other messages
  119.      !40  file type
  120.      !44  full path-name of file, 0-terminated
  121.  
  122. (This acknowledgement is not used by the Filer, but is used in cases
  123. where the file is a temporary file used to communicate between
  124. two applications).
  125.  
  126. This message is also used in an entirely independent context. The Filer
  127. sends this message when a file has been dragged into a window belonging to
  128. another application. The application is then free to copy or insert the
  129. file, if it so desires. If it does so successfully it should reply as
  130. follows:
  131.  
  132. 4  DataLoadAck
  133.  
  134.    R0     17 (usually)
  135.    R1!0   size
  136.      !12  my-ref field of DataLoad message
  137.      !16  4 ; DataLoadAck
  138.  
  139. This message is only sent if the load was successful.
  140.  
  141. Thus, the case of a file being saved to the Filer in fact involves 4 messages
  142. being sent:
  143. (1)  DataSave        (application to Filer)
  144. (2)  DataSaveAck     (Filer back to application)
  145.                      (application saves the file)
  146. (3)  DataLoad        (application to Filer, as acknowlegement)
  147.                      (the Filer just turns this around, doing nothing)
  148. (4)  DataLoadAck     (Filer to application)
  149.                      (if this is not received, the application generates an
  150.                      error "Bad Data Transfer, Receiver Dead" and
  151.                      deletes the file that it had saved)
  152. Messages (3) and (4) do not actually lead to significant action in the
  153. save-to-Filer case, but in fact the same code also provides the save
  154. operation to another application, using a temporary file. A fuller discussion
  155. of this appears below, when the possibility of in-memory data transfer has
  156. also been introduced.
  157.  
  158. 5  DataOpen (broadcast for double-clicked file)
  159.  
  160. This protocol is used to broadcast to all running applications just before
  161. "opening" a file whose icon has been double-clicked. It allows
  162. already-running applications to open the file instead. Typically this will be
  163. used by an editor which is capable of editing several documents of the same
  164. type, so that only one instance of the application runs (using much less
  165. space than if a separate copy of the application were run for each document).
  166.  
  167.    R0     18 (usually)
  168.    R1!0   size
  169.      !12  0
  170.      !16  5                 ; destination info request
  171.      !20  window handle of dirviewer
  172.      !24  0 ; icon handle not used
  173.      !28  x-offset of icon being opened within viewer
  174.      !32  y                 ; allows for 'zoom' box if implemented
  175.      !36  must be <= 0 ; size field in other messages
  176.      !40  file type
  177.      !44  full path-name of file, 0-terminated.
  178.  
  179. DataLoadAck is returned by the application which loads the file.
  180. If this is not received, then the Filer will *Run the file.
  181.  
  182. An application directory that was double-clicked with the shift key held down, is
  183. broadcast as a directory.
  184.  
  185. If data is to be transferred between two applications without going out to a
  186. file, then the following reply initiates the in-core transfer protocol:
  187.  
  188. 6  RAMFetch (transfer data to buffer in my workspace)
  189.  
  190.    R0     18 (error message if not acknowledged)
  191.    R1!0   size
  192.      !12  my-ref field of DataSave message
  193.      !16  6 ; RAM fetch.
  194.      !20  buffer address
  195.      !24  buffer size (bytes)
  196.  
  197. The original sender replies as follows:
  198.  
  199. 7  RAMTransmit (I have transferred some data to a buffer in your workspace)
  200.  
  201.    R0     18 (error message if not acknowledged)
  202.    R1!0   size
  203.      !12  my-ref field of RAMFetch message
  204.      !16  7 ; RAM transmit.
  205.      !20  buffer address             ; copy of value sent in RAM fetch
  206.      !24  number of bytes written to buffer
  207.           (if buffer not full, send another RAMFetch)
  208.  
  209. To write the data into the receiver's buffer, use the following call:
  210.  
  211. Wimp_TransferBlock
  212. Entry:  R0 = task handle of source
  213.         R1 --> source buffer
  214.         R2 = task handle of destination
  215.         R3 --> destination buffer
  216.         R4 = buffer length
  217.         buffer addresses and length are byte-aligned (not nec. word-aligned)
  218.         if the buffer addresses are within application space,
  219.            they are validated to ensure they are within the correct task
  220. Errors: "Invalid task handle"
  221.         "Wimp transfer out of range"
  222.  
  223. The receiver's buffer is not entirely filled then the receiver will
  224. assume that this is the end of the operation. No further confirmation
  225. is required.
  226.  
  227. If the receiver's buffer is filled then it will send a further RAMFetch
  228. message. This need not specify the same buffer or buffer size. Thus the
  229. operation continues until all data is transferred.
  230.  
  231. If the other end of the protocol does not answer then cancel the operation
  232. quietly, without generating an error message. The other end (e.g. if it ran
  233. out of space) will have already have complained.
  234.  
  235. Application code for direct file transfer
  236. -----------------------------------------
  237.  
  238. To save a file:
  239.  
  240. 1. Transmit DataSave message.
  241.  
  242. 2. If DataSaveAck returned, save the file. If there are errors in this
  243. process, report them to the user and cease the transaction. If the save
  244. succeeds, send a DataLoad.
  245.  
  246. 3. If DataLoadAck is not returned, (because the receiver is dead or badly
  247. written) then the sender should delete the file and report an error message
  248. saying "data transfer failed".  Thus the Filer must acknowledge DataLoad, or
  249. else all files saved to it will be subsequently deleted.
  250.  
  251. 3. If RAMFetch returned, send RAMTransmit and loop until done
  252.  
  253. NOTE:  all messages in this protocol apart from the DataSave should quote the
  254.        other side's my_ref field in their your_ref fields, to ensure that the
  255.        messages are acknowledged correctly.
  256.  
  257. NOTE:  In all cases where an unknown message action is received by an
  258.        application, it MUST ignore the message completely.
  259.  
  260. To receieve a file from another application:
  261.  
  262. 1. Receive DataSave message.
  263.  
  264. 2. If data can be loaded from RAM, send back a RAMFetch
  265. (look at approx data size in DataSave message, but do not
  266. rely on its absolute accuracy, ie. be prepared for MORE
  267. data than that to be sent).
  268.  
  269. If RAMFetch not acknowledged, load from a file (step 3)
  270.  
  271. If RAMTransmit received,
  272.   finished if buffer NOT filled,
  273.   else send another RAMFetch and loop.
  274.   If any RAMFetch other than the 1st is not acknowledged,
  275.     report error "data transfer failed".
  276.   (There's no need to check your_ref field if RAMFetch (18) used,
  277.     since the RAMFetch will not be acknowledged.)
  278.  
  279. 3. If data must be in a file, return DataSaveAck "<Wimp$Scrap>". If DataLoad
  280. is received, load the file, delete it and return DataLoadAck. Note that the
  281. your_ref field of the DataLoad tells the receiver whether the file is the
  282. scrap file.
  283.  
  284. Minimal functionality is for the sender to only cope with DataSaveAck, and
  285. for the receiver to only cope with file-based I/O.  If the receiver wishes to
  286. engage in RAMFetch operations, it should be prepared for the sender to be
  287. ignorant of that protocol - ie. it should be prepared to revert to the scrap
  288. file mechanism.
  289.  
  290. An Explanation of the Data Transfer Protocols
  291. ========================================
  292.  
  293. Ignoring direct RAM transfer for the moment, all data transfer operations in
  294. the RISC OS desktop world can be accomplished using 4 message types.  These
  295. are:
  296.  
  297.         DataSave
  298.         DataSaveAck
  299.         DataLoad
  300.         DataLoadAck
  301.  
  302. The various operations that an application must deal with are as follows:
  303.  
  304.         1a) Saving data to a file
  305.         1b) Saving data to another application
  306.         2a) Loading data from a file
  307.         2b) Loading data from another application
  308.  
  309. The protocols involved in each of these cases is described below - note that
  310. it is assumed that all replies carry the myref of the message they are
  311. replying to in their yourref field:
  312.  
  313.  
  314. 1a) Saving data to a file
  315. -------------------------
  316.  
  317. Application receives User_Drag_Box event (the file box has been dropped)
  318. Application calls Wimp_GetPointerInfo to find out where the pointer is
  319. Application sends Message_DataSave to the destination, with the leafname
  320. Filer replies with Message_DataSaveAck with "directoryname.leafname"
  321. Application saves data to the file
  322. Application sends Message_DataLoad to the Filer
  323. Filer replies with Message_DataLoadAck
  324. Everyone is happy.
  325.  
  326.  
  327. 1b) Saving data to another application
  328. --------------------------------------
  329.  
  330. Application receives User_Drag_Box event (the file box has been dropped)
  331. Application calls Wimp_GetPointerInfo to find out where the pointer is
  332. Application sends Message_DataSave to the destination, with the leaf-name
  333. ExternalTask replies with Message_DataSaveAck with "<Wimp$Scrap>"
  334. Application saves data to the file
  335. Application sends Message_DataLoad to the ExternalTask
  336. ExternalTask loads and deletes the scrap file
  337. ExternalTask replies with Message_DataLoadAck
  338. Everyone is happy.
  339.  
  340.  
  341. 2a) Loading data from a file
  342. ----------------------------
  343.  
  344. Filer sends Message_DataLoad to the application
  345. Application loads the file
  346. Application replies with Message_DataLoadAck
  347. Everyone is happy.
  348.  
  349.  
  350. 2b) Loading data from another application
  351. -----------------------------------------
  352.  
  353. ExternalTask sends Message_DataSave to the application
  354. Application replies with Message_DataSaveAck to "<Wimp$Scrap>"
  355. ExternalTask saves data to the file
  356. ExternalTask sends Message_DataLoad to the application
  357. Application loads and deletes the scrap file
  358. Application replies with Message_DataLoadAck
  359. Everyone is happy.
  360.  
  361.  
  362. Summary
  363. -------
  364.  
  365. As one would expect, (1b) and (2b) are symmetrical, so that any task can send
  366. data to any other, rather than some tasks being senders and some receivers. 
  367. An additional advantage of this method is the overlap between file transfer
  368. between applications and file transfer to and from the Filer.
  369.  
  370. Note that in protocols (1b) and (2b) it is the loader of the data who is
  371. responsible for deleting the scrap file afterwards, which is logical since it
  372. is the loader who invented the scrap file in the first place!
  373.  
  374. The following summarises the application code necessary for loading and
  375. saving files:
  376.  
  377.  
  378. Loading files
  379. -------------
  380.  
  381. Received Message_DataSave: respond with Message_DataSaveAck to "<Wimp$Scrap>"
  382.                            make a note of the myref field of your reply
  383.  
  384. Received Message_DataLoad: load the indicated file
  385.                            if your_ref = scrap my_ref, delete the file
  386.                            reply with Message_DataLoadAck
  387.  
  388. Saving files
  389. ------------
  390.  
  391. Determine destination using drag operation followed by Wimp_GetPointerInfo
  392. Send Message_DataSave including your proposed leafname
  393.  
  394. Received Message_DataSaveAck: save data to the indicated file
  395.                               reply with Message_DataLoad for same filename
  396.  
  397. Received Message_DataLoadAck: usually ignored, but can be useful
  398.  
  399.  
  400. Direct RAM transfer
  401. -------------------
  402.  
  403. For the experts, it is possible to indulge in more efficient data transfer
  404. where two applications are involved (ie. protocols (1b) and (2b)).
  405.  
  406. Basically, instead of replying with Message_DataSaveAck to "<Wimp$Scrap>", an
  407. application should reply first with Message_RAMFetch, and if that is not
  408. acknowledged, revert to returning the conventional <Wimp$Scrap> message.
  409.  
  410.     Message_RAMFetch
  411.         R0 = 18 (so that message must be acknowledged)
  412.         R1!0   size
  413.           !12  my-ref field of DataSave message
  414.           !16  6 ; RAM fetch.
  415.           !20  buffer address
  416.           !24  buffer size (bytes)
  417.  
  418. From the sender's end, it is permissible to totally ignore Message_RAMFetch,
  419. in which case the more usual scrap file method is used.  If the RAM transfer
  420. protocol is understood, however, Wimp_TransferBlock can used to transfer data
  421. into the other task's workspace.
  422.  
  423. After transferring the data, a RAMTransmit message should be sent.
  424. If the buffer was filled by the sender, the receiver should process the data
  425. and then send another RAMFetch.  If the buffer is not full, this implies that
  426. the file transfer is complete, and there is no need for any further
  427. communication.  Note that this means that if the file length fits into a
  428. whole number of buffers, then the last block must contain 0 bytes of data.
  429.  
  430. Note that it is possible for an application to support RAM transfer on
  431. loading or saving or neither or both as required - indeed, it may be that an
  432. application can cope with direct RAM transfer for certain filetypes but not
  433. for others, and its capability may be different when loading and saving data.
  434. The protocols described allow for 'cop-out' by either the sender or the
  435. receiver of the data.
  436.  
  437. New Summary
  438. -----------
  439.  
  440. Including the RAM transfer protocols, the application code looks like this:
  441.  
  442.  
  443. Loading files
  444. -------------
  445.  
  446. Received Message_DataSave: respond with RAMFetch to appropriate buffer
  447.                            if not acknowledged,
  448.                              respond with Message_DataSaveAck to "<Wimp$Scrap>"
  449.                              make a note of the myref field of your reply
  450.  
  451. Received Message_RAMTransmit: process data in buffer
  452.                               if buffer was filled, send another RAMFetch
  453.                               otherwise all data has been sent
  454.  
  455. Received Message_DataLoad: load the indicated file
  456.                            if your_ref = scrap my_ref, delete the file
  457.                            reply with Message_DataLoadAck
  458.  
  459. Saving files
  460. ------------
  461.  
  462. Determine destination using drag operation followed by Wimp_GetPointerInfo
  463. Send Message_DataSave including your proposed leafname.
  464.  
  465. Received Message_RAMFetch: call Wimp_TransferBlock to transfer data
  466.                            send Message_RAMTransmit for appropriate amount
  467.                            if buffer filled, expect a RAMFetch in reply
  468.  
  469. Received Message_DataSaveAck: save data to the indicated file
  470.                               reply with Message_DataLoad for same filename
  471.  
  472. Received Message_DataLoadAck: usually ignored, but can be useful
  473.