home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / code / desklib / !DeskLib / h / Save < prev    next >
Encoding:
Text File  |  1994-04-24  |  11.3 KB  |  275 lines

  1. /*
  2.     ####             #    #     # #
  3.     #   #            #    #       #          The FreeWare C library for 
  4.     #   #  ##   ###  #  # #     # ###             RISC OS machines
  5.     #   # #  # #     # #  #     # #  #   ___________________________________
  6.     #   # ####  ###  ##   #     # #  #                                      
  7.     #   # #        # # #  #     # #  #    Please refer to the accompanying
  8.     ####   ### ####  #  # ##### # ###    documentation for conditions of use
  9.     ________________________________________________________________________
  10.  
  11.     File:    save.h
  12.     Author:  Copyright © 1994 Julian Smith 
  13.     Version: 1.00 (24 Apr 1994)
  14.     Purpose: Automate handling of save-as windows
  15. */
  16.  
  17. #ifndef __dl_save_h
  18. #define __dl_save_h
  19.  
  20. #ifndef __dl_event_h
  21. #include "DeskLib:Event.h"
  22. #endif
  23.  
  24. #include <stdio.h>
  25.  
  26.  
  27.  
  28. typedef BOOL (*save_filesaver)( FILE *f, void *ref);
  29.   /*  This type of function should save data to file stream 'f', using info in
  30.    *  'ref'. It should return TRUE if an error occurred.
  31.    *  'ref' is the (void *) originally passed to Save_InitSaveWindowHandler
  32.    */
  33.  
  34. typedef int (*save_ramsaver)(
  35.   task_handle  sourcetask,                  /* our task handle */
  36.   void         *ref,
  37.   task_handle  desttask,
  38.   void         *destbuffer,
  39.   unsigned int buffersize,
  40.   int          progress       /* how many bytes have been transfered so far  */
  41.   );
  42.   
  43.   /* This type of function should Wimp_TransferBlock data. Note that you can do
  44.    * this using multiple Wimp_TransferBlock's if this is more convinient.
  45.    * Should return the total number of bytes transfered into 'destbuffer' - if
  46.    * less than buffersize, then transfer has finished. If <0, error has
  47.    * occurred.
  48.    * 'ref' is the (void *) originally passed to Save_InitSaveWindowHandler
  49.    */
  50.  
  51.  
  52.  
  53.  
  54. typedef enum
  55. {
  56.   save_SAVEOK    = 0,
  57.   save_RECEIVERFAILED,
  58.   save_FILESAVERFAILED,
  59.   save_RAMSAVERFAILED
  60. } save_result;
  61.  
  62.  
  63. typedef void (*save_resulthandler)( save_result result, void *ref);
  64.   /* Called after any attempt to save. */
  65.  
  66. typedef struct
  67. {
  68.   window_handle    window;        /*  Window that the save icons are in */
  69.  
  70.   union
  71.   {
  72.     unsigned int  value;
  73.     struct
  74.     {
  75.       unsigned int  is_menu         : 1;  /* Savewindow is part of menu  */
  76.       unsigned int  is_save_window  : 1;  /* Close window after save?    */
  77.       unsigned int  we_are_dragging : 1;  /* Are we dragging file icon?  */
  78.       unsigned int  quit_after_save : 1;  /* Click/drag was with Select  */
  79.       unsigned int  release_after   : 1;  /* Release all handlers when   */
  80.                                           /* the window/menu is closed?  */
  81.       unsigned int  padding         : 27;
  82.     } data;
  83.   } flags;
  84.   
  85.   icon_handle         dragsprite;
  86.   icon_handle         okbutton;
  87.   icon_handle         cancelbutton;
  88.   icon_handle         filenameicon;
  89.   save_filesaver      filesaver;
  90.   save_ramsaver       ramsaver;
  91.   save_resulthandler  resulthandler;
  92.   size_t              estimatedsize;
  93.   void                *ref;
  94.   int                 ram_progress;          /* Num of bytes ram-transfered. */
  95.   unsigned int        last_message_ref;      /* So we know which incoming    */
  96.                                              /* messages are replies to us   */
  97. } save_saveblock;
  98.   
  99.   
  100.   /* 
  101.   ********************************************************************
  102.   
  103.   This struct contains all the info needed to deal with saving using 
  104.   the RISC OS data transfer protocol.
  105.   
  106.   It is used internally by the Save_* functions - you shouldn't need 
  107.   to use it normally. It is included here because 
  108.   Save_InitSaveWindowHandler returns a pointer to it, so that you can 
  109.   call Save_ReleaseSaveWindowHandler if you are using RO2 and have to 
  110.   detect menu closing manually, and also you might want to change the 
  111.   field 'ref' if the user presses a 'Selection' button in the save
  112.   window (you might also want to change 'filesaver' and 'ramsaver' in
  113.   this case). 
  114.   
  115.   Also, you could change 'is_menu' if a menu-leaf savewindow changes 
  116.   into to a free-standing savewindow (this will only work if you have 
  117.   .flags.data.release_after = FALSE - the saveblock wil be free-ed and 
  118.   all Event_ handlers released when the menu is closed otherwise.
  119.   
  120.   fn 'filesaver' is called when the data needs to be saved to a file.
  121.   
  122.   fn 'ramsaver' is called when the data needs to be RAM transfered.
  123.   
  124.   'ref' is passed to file/ramsaver - it should enable these functions 
  125.   to save the right piece of data.
  126.  
  127.   You can change the following things after you have called 
  128.   Save_InitSaveWindowHandler:
  129.   
  130.     is_menu, 
  131.     is_save_window, 
  132.     filesaver, 
  133.     ramsaver, 
  134.     resulthandler, 
  135.     estimatedsize, 
  136.     ref.
  137.  
  138.   Don't change any of the icon or window handles, as these will have 
  139.   been used with Event_Claim, so if you change them, when Save_* calls 
  140.   Event_Release, DeskLib will complain.
  141.   
  142.   Also, don't change any other fields (there is no reason to anyway)
  143.   as these are used internally and are assumed to be const.
  144.   *********************************************************************
  145.   */
  146.  
  147.  
  148.  
  149. save_saveblock *Save_InitSaveWindowHandler(
  150.   window_handle      window,           /* handle of the window to deal with  */
  151.   BOOL               is_menu,          /* is this window part of a menu?     */
  152.                                        /* if TRUE Save_* will close it after */
  153.                                        /* 'Select'-saves                     */
  154.   BOOL               is_save_window,   /* is this window just a save window? */
  155.                                        /* if TRUE Save_* will close it after */
  156.                                        /* 'Select'-saves                     */
  157.   BOOL               release_after,    /* release all Save_ handlers when    */
  158.                                        /* window/menu is closed?             */
  159.   icon_handle        dragsprite,       /* handle of the dragable file-icon   */
  160.   icon_handle        okbutton,         /* handle of 'OK' or 'Save' button    */
  161.   icon_handle        cancelbutton,     /* handle of the 'Cancel' button      */
  162.   icon_handle        filenameicon,     /* handle of the writable fname icon  */
  163.   save_filesaver     filesaver,        /* fn which saves data to a file      */
  164.   save_ramsaver      ramsaver,         /* fn which does Wimp_TransferBlocks  */
  165.   save_resulthandler resulthandler,    /* fn to report success of save to    */
  166.   size_t      estimatedsize,           /* size of data  (estimate)           */
  167.   void      *ref                       /* ref passed to all saver functions  */
  168.   );
  169.  
  170.   /* 
  171.   ****************************************************************************
  172.   
  173.   To implement RISC OS saving, call this function - it does all the message
  174.   handling needed, and calls 'filesaver' or 'ramsaver' when needed, passing
  175.   'ref' to them so that they know what needs saving.
  176.   
  177.   'ismenu' should be TRUE if 'window' is part of a menu tree, and FALSE if 
  178.   'window' is normal window. This is used to know when to stop handling the
  179.   save.
  180.   e.g. when menu is closed, or when save-window is closed.
  181.   
  182.   
  183.   Things you need to do:
  184.   
  185.   1  Create a conventional save-window with icons for Save, Cancel, and 
  186.      dragging, and an *indirected* text icon for the filename.
  187.      (e.g. put this in a 'Templates' file).
  188.      The filename icon *must* be indirected.
  189.   2  Put a default file/leafname in to the filename icon.
  190.   3  Make the dragable icon be whatever file-icon is appropriate
  191.   4  Write a function which can save the data to a file.  *Required*
  192.   5  Write a function which can Wimp_TransferBlock the data.  *Optional*
  193.   6  Write a function to be called with result of any save  *Optional*
  194.   7  Create a reference, 'ref', to the data so that the saver functions 
  195.      know what data to save.
  196.   8  Call Save_InitSaveWindowHandler
  197.      You can do this anytime - e.g. just before/after you create a menu that
  198.      includes the save window, when you open the save box in response to
  199.      (for e.g.) a F3 keypress, or when you receive a message_MENUWARNING which
  200.      heralds the opening of your save-window.
  201.   
  202.   YOU are responsible for opening the savewindow and dealing with menu
  203.   handling. All Save_* does is handle the sprite-drgging, button pressing and
  204.   data transfer protocol which originate in the save window.
  205.    
  206.   Then, when the user tries to save the data, the only thing which you get to
  207.   know about is that either your 'filesaver' or 'ramsaver' is called, with the
  208.   'ref' you originally passed to Save_InitSaveWindowHandler.
  209.   If a save is attempted, 'resulthandler' will be called, with the
  210.   success/failure of the save.
  211.   
  212.   Thats it.
  213.   
  214.   Notes:
  215.   The 'filenameicon' may be altered by Save_InitSaveWindowHandler - it
  216.   replaces the first control chr by ASCII 0, as this works with standard C
  217.   functions, and some template text icons seem to be terminated by ASCII 13.
  218.   
  219.   if you use 'release_after = FALSE', the Event_ handlers will still be in
  220.   place after the window/menu has closed. This is so you can keep a single
  221.   window for all saves, and register it with Save_ just once when your
  222.   application starts up.
  223.   If your application deals with different pieces of data, you'll have to
  224.   update the 'ref' field in the Save_saveblock returned by
  225.   Save_InitSaveWindowHandler each time the window is opened.
  226.   
  227.   Save_* registers a handler for when the save window is closed, which 
  228.   Event_Release's all of the Save_* handlers for drag/click/message handling
  229.   etc. This means you can have a save window with a close icon as well
  230.   as/instead of the 'cancel' icon, and makes the whole thing a bit more robust.
  231.   
  232.   You can miss out any of the icons in the window by using a negative icon
  233.   handle. This will prevent any Event_Claim's for the icon.
  234.   
  235.   If 'ramsaver' == NULL, then 'filesaver' will always be used.
  236.   If 'resulthandler' == NULL, a default handler will be used, which will do an 
  237.   'Error_Report' if a save fails.
  238.   
  239.   if 'resulthandler' != NULL, it will be called after any attempt to save the
  240.   data, with 'ref' and one of the following flags:
  241.    
  242.   save_SAVEOK = 0    receiver signals the save went OK
  243.   save_SAVERECEIVERFAILED  receiver didn't signal it has received the data
  244.   save_SAVESAVERFAILED  your 'filesaver' function signalled an error
  245.   save_SAVERAMFAILED  your 'ramsaver'  function signalled an error
  246.   
  247.   This is so that your app doesn't go away thinking data has been saved when 
  248.   it hasn't. Note that your saver functions will not be aware of any problem
  249.   in the second case, where the receiver fails to load the scrap file.
  250.   
  251.   If you want to implement a 'Selection' button in the save window, you should 
  252.   register a separate handler for event_CLICK on the 'Selection' button in the
  253.   save window, and when it is pressed, modify the saveblock previously
  254.   returned by Save_InitSaveWindowHandler, so that save_saveblock.ref points to
  255.   the selction data. You could also change the writable icon contents and the
  256.   'file/ramsave' functions etc etc.
  257.   
  258.   ****************************************************************************
  259.   */
  260.  
  261.  
  262.  
  263. void Save_ReleaseSaveHandlers(save_saveblock *saveblock);
  264.   /* You shouldn't need this normally because menu/window closing is detected
  265.    * by SaveBoxHandler, 'cos it detects message_MENUSDELEATED and event_CLOSE.
  266.    * NB, in RO2, there is no message_MENUSDELEATED, so you will have to call
  267.    * this function when you next open a menu, or something...
  268.    *
  269.    * Also, if you want to close a free-standing (i.e. not in a menu)
  270.    * save-window when <Escape> is pressed, you will need this function.
  271.    */
  272.  
  273. #endif
  274.  
  275.