DeskLib 2.90a:Save.h


Contents


Introduction and Overview

This header defines functions to help automate the handling of save windows, by dealing with dragging icons to directories and the various datasave protocol messages. You register handlers to deal with the actual saving of data to file or ramtransfers to other applications.


Functions


Save_InitSaveWindowHandler

save_saveblock * Save_InitSaveWindowHandler(window_handle window, BOOL is_menu, BOOL is_save_window, BOOL release_after, icon_handle dragsprite, icon_handle okbutton, icon_handle cancelbutton, icon_handle filenameicon, save_filesaver filesaver, save_ramsaver ramsaver, save_resulthandler resulthandler, size_t estimatedsize, int filetype, void *ref);

You call this function to set up the given window to handle the RISC OS save protocol automatically for you.

You pass in handlers which are called when needed for saving to file, doing direct RAM transfers and to receive the result of the attempted save. All these handler functions will be passed the reference 'ref' that you specify here, so that they know what needs saving. The ramsaver and resulthandler are both optional, you can pass NULL rather than supply functions. If you don't specify a resulthandler, a default one will be used which will report any problems saving using Error_Report.

You also give a filetype and an estimated size for the data, to be used in the save protocol messages. These should be as accurate as possible.

You specify an OK button, a cancel button and a draggable icon to hold the "filetype" sprite. This should be an indirected icon (either text or sprite) with a buffer at least 9 characters long. You also pass the handle of a writable icon to hold the filename - this should be big enough to hold the the full pathname and start with a default leafname to be used for the file. You can leave out any of these except the filenameicon, in which case you whould pass a negative number instead of an icon handle for those parameters. When your save_filesaver function is called, it is passed the full pathname to save to.

You can also choose how the library deals with your window and the handlers attached to it. Setting 'release_after' to TRUE means that when the window is closed (by a click on OK or cancel or by the menu it is part of closing) all the handlers attached by this function will be released, ready for you to reattach again next time it is opened. Alternatively, you can set it to FALSE and handle the detaching yourself (with Save_ReleaseSaveHandlers) or else use the one window for all you saving and juse change the handlers, etc. as required. See the definition of a save_saveblock to see what can be changed directly by you.

Finally, you can set 'is_menu' to TRUE if the window is part of menu structure (eg. as a submenu), or FALSE if it is a free-standing window. This enables "Save" to close the menu or window appropriately when you click on "Cancel" or "OK" with the Select button. You set 'is_save_window' to TRUE if you want the window closed on Select clicks on OK, and FALSE if you want it left open (eg. if the window is not just a save window but also has other information deisplayed).

You are responsible for opening the window and dealing with any menus, radio buttons, etc. in the window - everything except the actual dragging, clicking on OK or Cancel and the data transfer protocol. You can change the handlers, reference and so on depending on these other clicks - see the definition of a save_saveblock to see what can be changed directly by you.


Save_ReleaseSaveHandlers

void Save_ReleaseSaveHandlers(save_saveblock *saveblock);

You only need to use this if you choose not to have the Save library remove handlers for you automatically when the window or menu closes (ie. if you pass FALSE for release_after when initialising the window).

The library also doesn't detect "Escape" being pressed in a free-standing save window, so if you want to use that to close the window, you'll presumably want to call this afterwards to release the handlers.


Save_SetFiletype

void Save_SetFiletype(save_saveblock *saveblock, int filetype);

Sets the sprite in the savewindow to be "file_..." and also alters the saveblock so that the filetype is used whenever date is saved to the filer or another application.

This can only be called after the saveblock has been initialised with a successful call to Save_InitSaveWindowHandler.


Types


save_filesaver

typedef BOOL (*save_filesaver)(char *filename, void *ref);

This type of function should save data to the given filename (which is automatically passed to it), and return TRUE if successful or FALSE otherwise. 'ref' is the reference originally passed to Save_InitSaveWindowHandler.


save_ramsaver

typedef int (*save_ramsaver)(task_handle sourcetask, void *ref, task_handle desttask, void *destbuffer, unsigned int buffersize, int progress);

This type of function should use Wimp_TransferBlock to place data in the given destination buffer belonging to the destination task.

The 'sourcetask' is our task handle, given here for convenience. 'ref' is the reference originally passed to Save_InitSaveWindowHandler and 'progress' is the number of bytes transferred so far.

You should return the number of bytes you have transferred into 'destbuffer', or a negative number if an error has occurred.

As the task requesting the data can ask for it in as many parts as are needed to transfer the data, the sequence of messages will continue until you return less than a full buffer or the destination task decides it is all transferred. ie. if you return a value less than 'buffersize' then that is the last transfer of the save.


save_result

typedef enum
{
save_SAVEOK = 0,
save_RECEIVERFAILED,
save_FILESAVERFAILED,
save_RAMSAVERFAILED
} save_result;

The various results that are possible from an attempt to save. Either it went successfully, or it failed in one of three ways - the receiver failed to load the scrap file, the file-saver failed or the ram-saver failed.


save_resulthandler

typedef void (*save_resulthandler)(save_result result, void *ref);

This type of function is called after any attempt to save, giving the result of the attempt.

This is so that your app doesn't go away thinking data has been saved when it hasn't. Note that your saver functions will not be aware of any problem in the second case, where the receiver fails to load the scrap file.


save_saveblock

typedef struct
{
window_handle window;
union
{
unsigned int value;
struct
{
unsigned int is_menu : 1;
unsigned int is_save_window : 1;
unsigned int we_are_dragging : 1;
unsigned int quit_after_save : 1;
unsigned int release_after : 1;
unsigned int padding : 27;

} data;

} flags;
icon_handle dragsprite;
icon_handle okbutton;
icon_handle cancelbutton;
icon_handle filenameicon;
save_filesaver filesaver;
save_ramsaver ramsaver;
save_resulthandler resulthandler;
size_t estimatedsize;
int filetype;
void *ref;
int ram_progress;
unsigned int last_message_ref;

} save_saveblock;

This struct holds all the information needed to handle saving using the RISC OS data transfer protocol. It is used internally by the Save functions, and so you shouldn't change most of the fields. Those that can be changed after a successful initial call to Save_InitSaveWindowHandler are given below.

'ref', 'filesaver', 'ramsaver', 'resulthandler' and 'estimatedsize' can all be changed, for instance in response to the user choosing to save a different format of file with a click on a radio button. If you do decide to change them in this way, you can use Save_SetFiletype to change the stored filetype and the file icon to match if necessary.

You can also set the flags 'is_menu' and 'is_save_window', for instance if you change a menu-leaf savewindow into a free-standing save window.