home *** CD-ROM | disk | FTP | other *** search
- /*
- #### # # # #
- # # # # # The FreeWare C library for
- # # ## ### # # # # ### RISC OS machines
- # # # # # # # # # # # ___________________________________
- # # #### ### ## # # # #
- # # # # # # # # # # Please refer to the accompanying
- #### ### #### # # ##### # ### documentation for conditions of use
- ________________________________________________________________________
-
- File: save.h
- Author: Copyright © 1994 Julian Smith
- Version: 1.00 (24 Apr 1994)
- Purpose: Automate handling of save-as windows
- */
-
- #ifndef __dl_save_h
- #define __dl_save_h
-
- #ifndef __dl_event_h
- #include "Event.h"
- #endif
-
- #include <stdio.h>
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- typedef BOOL (*save_filesaver)( FILE *f, void *ref);
- /* This type of function should save data to file stream 'f', using info in
- * 'ref'. It should return TRUE if an error occurred.
- * 'ref' is the (void *) originally passed to Save_InitSaveWindowHandler
- */
-
- typedef int (*save_ramsaver)(
- task_handle sourcetask, /* our task handle */
- void *ref,
- task_handle desttask,
- void *destbuffer,
- unsigned int buffersize,
- int progress /* how many bytes have been transfered so far */
- );
-
- /* This type of function should Wimp_TransferBlock data. Note that you can do
- * this using multiple Wimp_TransferBlock's if this is more convinient.
- * Should return the total number of bytes transfered into 'destbuffer' - if
- * less than buffersize, then transfer has finished. If <0, error has
- * occurred.
- * 'ref' is the (void *) originally passed to Save_InitSaveWindowHandler
- */
-
-
-
-
- typedef enum
- {
- save_SAVEOK = 0,
- save_RECEIVERFAILED,
- save_FILESAVERFAILED,
- save_RAMSAVERFAILED
- } save_result;
-
-
- typedef void (*save_resulthandler)( save_result result, void *ref);
- /* Called after any attempt to save. */
-
- typedef struct
- {
- window_handle window; /* Window that the save icons are in */
-
- union
- {
- unsigned int value;
- struct
- {
- unsigned int is_menu : 1; /* Savewindow is part of menu */
- unsigned int is_save_window : 1; /* Close window after save? */
- unsigned int we_are_dragging : 1; /* Are we dragging file icon? */
- unsigned int quit_after_save : 1; /* Click/drag was with Select */
- unsigned int release_after : 1; /* Release all handlers when */
- /* the window/menu is closed? */
- 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;
- void *ref;
- int ram_progress; /* Num of bytes ram-transfered. */
- unsigned int last_message_ref; /* So we know which incoming */
- /* messages are replies to us */
- } save_saveblock;
-
-
- /*
- ********************************************************************
-
- This struct contains all the info needed to deal with saving using
- the RISC OS data transfer protocol.
-
- It is used internally by the Save_* functions - you shouldn't need
- to use it normally. It is included here because
- Save_InitSaveWindowHandler returns a pointer to it, so that you can
- call Save_ReleaseSaveWindowHandler if you are using RO2 and have to
- detect menu closing manually, and also you might want to change the
- field 'ref' if the user presses a 'Selection' button in the save
- window (you might also want to change 'filesaver' and 'ramsaver' in
- this case).
-
- Also, you could change 'is_menu' if a menu-leaf savewindow changes
- into to a free-standing savewindow (this will only work if you have
- .flags.data.release_after = FALSE - the saveblock wil be free-ed and
- all Event_ handlers released when the menu is closed otherwise.
-
- fn 'filesaver' is called when the data needs to be saved to a file.
-
- fn 'ramsaver' is called when the data needs to be RAM transfered.
-
- 'ref' is passed to file/ramsaver - it should enable these functions
- to save the right piece of data.
-
- You can change the following things after you have called
- Save_InitSaveWindowHandler:
-
- is_menu,
- is_save_window,
- filesaver,
- ramsaver,
- resulthandler,
- estimatedsize,
- ref.
-
- Don't change any of the icon or window handles, as these will have
- been used with Event_Claim, so if you change them, when Save_* calls
- Event_Release, DeskLib will complain.
-
- Also, don't change any other fields (there is no reason to anyway)
- as these are used internally and are assumed to be const.
- *********************************************************************
- */
-
-
-
- save_saveblock *Save_InitSaveWindowHandler(
- window_handle window, /* handle of the window to deal with */
- BOOL is_menu, /* is this window part of a menu? */
- /* if TRUE Save_* will close it after */
- /* 'Select'-saves */
- BOOL is_save_window, /* is this window just a save window? */
- /* if TRUE Save_* will close it after */
- /* 'Select'-saves */
- BOOL release_after, /* release all Save_ handlers when */
- /* window/menu is closed? */
- icon_handle dragsprite, /* handle of the dragable file-icon */
- icon_handle okbutton, /* handle of 'OK' or 'Save' button */
- icon_handle cancelbutton, /* handle of the 'Cancel' button */
- icon_handle filenameicon, /* handle of the writable fname icon */
- save_filesaver filesaver, /* fn which saves data to a file */
- save_ramsaver ramsaver, /* fn which does Wimp_TransferBlocks */
- save_resulthandler resulthandler, /* fn to report success of save to */
- size_t estimatedsize, /* size of data (estimate) */
- void *ref /* ref passed to all saver functions */
- );
-
- /*
- ****************************************************************************
-
- To implement RISC OS saving, call this function - it does all the message
- handling needed, and calls 'filesaver' or 'ramsaver' when needed, passing
- 'ref' to them so that they know what needs saving.
-
- 'ismenu' should be TRUE if 'window' is part of a menu tree, and FALSE if
- 'window' is normal window. This is used to know when to stop handling the
- save.
- e.g. when menu is closed, or when save-window is closed.
-
-
- Things you need to do:
-
- 1 Create a conventional save-window with icons for Save, Cancel, and
- dragging, and an *indirected* text icon for the filename.
- (e.g. put this in a 'Templates' file).
- The filename icon *must* be indirected.
- 2 Put a default file/leafname in to the filename icon.
- 3 Make the dragable icon be whatever file-icon is appropriate
- 4 Write a function which can save the data to a file. *Required*
- 5 Write a function which can Wimp_TransferBlock the data. *Optional*
- 6 Write a function to be called with result of any save *Optional*
- 7 Create a reference, 'ref', to the data so that the saver functions
- know what data to save.
- 8 Call Save_InitSaveWindowHandler
- You can do this anytime - e.g. just before/after you create a menu that
- includes the save window, when you open the save box in response to
- (for e.g.) a F3 keypress, or when you receive a message_MENUWARNING which
- heralds the opening of your save-window.
-
- YOU are responsible for opening the savewindow and dealing with menu
- handling. All Save_* does is handle the sprite-drgging, button pressing and
- data transfer protocol which originate in the save window.
-
- Then, when the user tries to save the data, the only thing which you get to
- know about is that either your 'filesaver' or 'ramsaver' is called, with the
- 'ref' you originally passed to Save_InitSaveWindowHandler.
- If a save is attempted, 'resulthandler' will be called, with the
- success/failure of the save.
-
- Thats it.
-
- Notes:
- The 'filenameicon' may be altered by Save_InitSaveWindowHandler - it
- replaces the first control chr by ASCII 0, as this works with standard C
- functions, and some template text icons seem to be terminated by ASCII 13.
-
- if you use 'release_after = FALSE', the Event_ handlers will still be in
- place after the window/menu has closed. This is so you can keep a single
- window for all saves, and register it with Save_ just once when your
- application starts up.
- If your application deals with different pieces of data, you'll have to
- update the 'ref' field in the Save_saveblock returned by
- Save_InitSaveWindowHandler each time the window is opened.
-
- Save_* registers a handler for when the save window is closed, which
- Event_Release's all of the Save_* handlers for drag/click/message handling
- etc. This means you can have a save window with a close icon as well
- as/instead of the 'cancel' icon, and makes the whole thing a bit more robust.
-
- You can miss out any of the icons in the window by using a negative icon
- handle. This will prevent any Event_Claim's for the icon.
-
- If 'ramsaver' == NULL, then 'filesaver' will always be used.
- If 'resulthandler' == NULL, a default handler will be used, which will do an
- 'Error_Report' if a save fails.
-
- if 'resulthandler' != NULL, it will be called after any attempt to save the
- data, with 'ref' and one of the following flags:
-
- save_SAVEOK = 0 receiver signals the save went OK
- save_SAVERECEIVERFAILED receiver didn't signal it has received the data
- save_SAVESAVERFAILED your 'filesaver' function signalled an error
- save_SAVERAMFAILED your 'ramsaver' function signalled an error
-
- 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.
-
- If you want to implement a 'Selection' button in the save window, you should
- register a separate handler for event_CLICK on the 'Selection' button in the
- save window, and when it is pressed, modify the saveblock previously
- returned by Save_InitSaveWindowHandler, so that save_saveblock.ref points to
- the selction data. You could also change the writable icon contents and the
- 'file/ramsave' functions etc etc.
-
- ****************************************************************************
- */
-
-
-
- void Save_ReleaseSaveHandlers(save_saveblock *saveblock);
- /* You shouldn't need this normally because menu/window closing is detected
- * by SaveBoxHandler, 'cos it detects message_MENUSDELEATED and event_CLOSE.
- * NB, in RO2, there is no message_MENUSDELEATED, so you will have to call
- * this function when you next open a menu, or something...
- *
- * Also, if you want to close a free-standing (i.e. not in a menu)
- * save-window when <Escape> is pressed, you will need this function.
- */
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif
-
-