/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Dialog2.h
    Author:  Copyright  1994 Julian Smith
    Version: 1.03 (13 Mar 1995)
    Purpose: Dialogue box handling
    Mods:    25 Feb 1995 - JPS - Added okfn which is called when program should
                                 read the dialog's contents
             13 Mar 1995 - JPS - Split up source a bit more so that less code
                                 would be linked in.
                                 Bugfix: Desk_Event_ReleaseWindow now called when
                                 window isn't deleted.
             10 Apr 1995 - JPS - Modified to support DLLs with the global
                                 variable '*Desk_dialog2_menublock'.
*/


#ifndef __Desk_Dialog2_h
#define __Desk_Dialog2_h

#ifdef __cplusplus
	extern "C" {
#endif


#ifndef __Desk_Wimp_h
	#include "Wimp.h"
#endif

#ifndef __Desk_Window_h
	#include "Window.h"
#endif



typedef enum	{
	Desk_dialog2_type_CLOSED	= 0,
	Desk_dialog2_type_MENULEAF,
	Desk_dialog2_type_MENU,
	Desk_dialog2_type_STATIC
	}
	Desk_dialog2_dialog2type;


typedef struct Desk_dialog2_block *Desk_dialog2_blockptr;

typedef void (*Desk_dialog2_openfn)( Desk_dialog2_blockptr);
typedef void (*Desk_dialog2_okfn)( Desk_dialog2_blockptr);


typedef struct Desk_dialog2_block	{

	void		*reference;	/* This is supplied by you.		*/
	const char	*templatename;	/* Name in the Templates file of the 	*/
					/* window associated with this dialog2	*/
	Desk_window_handle	window;		/* This is NULL whenever the window has been deleted.	*/

	Desk_dialog2_openfn	openfn;		/* Your function, called whenever a dialog2 is opened.	*/
	Desk_dialog2_okfn	okfn;		/* Called when OK is clicked, or return-in-last-icon	*/
					/* ie whenver the dialog's contents need acting on.	*/
	union	{
		int	value;
		struct	{
			unsigned int	type		:  2;	/* A Desk_dialog2_dialog2type	*/
			unsigned int	keepwindow	:  1;
			unsigned int	notifyclose	:  1;
			int		okbutton	:  9;
			int		cancelbutton	:  9;
			int		maxtitlesize	: 10;
			}
			data;
		}
		flags;
	}
	Desk_dialog2_block;
/*

This structure holds all the information about a particular dialog box.
All the fields are all set initially by Desk_Dialog2_CreateDialogBlock - you
shouldn't need to change them normally.

If you do have to change things yourself, you should *not* change any
fields directly, as some need to be modified only by internal Desk_Dialog2_
functions. There are a few macros/functions below which give you as much
access as is good for you! See the end of this file for details of what
the fields mean.

*/ 



/* Here come the functions:	*/

Desk_dialog2_block	*Desk_Dialog2_CreateDialogBlock( 
	const char		*templatename, 
	Desk_icon_handle	okbutton,
	Desk_icon_handle	cancelbutton,
	Desk_dialog2_openfn	openfn,
	Desk_dialog2_okfn	okfn,
	void			*reference
	);
/* 

This creates a dialog box information block. Store the returned pointer
and pass it to Desk_Dialog2_OpenDialogStatic, Desk_Dialog2_OpenDialogMenu or
Desk_Dialog2_OpenDialogMenuLeaf as/when the dialog box is required.

'templatename' should be the name of the dialog window in your templates
file.  Desk_Dialog2_CreateDialogBlock doesn't copy this string, it just
stores the address of the start of the string, so the string you pass
should be a permanent one, eg Desk_Dialog2_CreateDialogBlock( "infowindow"...).

'okbutton' and 'cancelbutton' should be the icon handles of the OK and
cancel buttons in the window. Use -1 if these aren't present. The
Dialog2 library will claim Desk_event_CLICKs, and call Desk_Dialog2_CloseDialog if
there is a  SELECT click on either of these two buttons. It will also
claim Desk_event_KEY and fake  a SELECT click on ok/cancel when Return/Escape
is pressed (assuming that the validation strings for writable icons are
set up properly - this is done automatically in !TemplEd, for example).


'openfn' is called whenever the dialog box is opened (unless 'openfn' is
NULL). This is done after the type (menu, menuleaf, static) has been
set, so 'openfn' will know what sort of dialog is being opened. 'openfn'
should call Desk_Event_Claim for mouse-clicks etc so that your application
can deal with clicks/keypresses in the dialog window. Note that all
Desk_event_ handlers for the dialog window are released using Desk_Window_Delete
when a dialog is closed (unless 'keepwindow' is set - see below), so 
you can't be sure of getting dialog-window events unless you claim them
in openfn  each time the dialog is opened.

'openfn' should have a prototype like:
void MyOpenDialog2Function( Desk_dialog2_block *dialog2);

The 'reference' passed to Desk_Dialog2_CreateDialogBlock will be in
dialog2->reference.

Note.
-----

If (as is normal) you claim Desk_event_CLICK in your 'openfn' (see below),
you will  hear about clicks *before* the Dialog2 function, because
Dialog2 calls Desk_Event_Claim  before calling 'openfn', and the Event module
sends events to more recent  claiments first (also, the claim is for any
icon on the window, so has lower  priority than specific-icon claims).
Hence the dialog2 will be closed *after* you have dealt with OK/cancel
clicks, which is what should happen.

If the auto-handling of OK/Cancel and Return/Escape bothers you, just
pass -1 for the  two button handles, and Dialog2 will not interfere with
button clicks or key-presses at all. You are then responsible for
calling Desk_Dialog2_CloseDialog when an 'OK' or  'Cancel' button is clicked,
or when Return/Escape is pressed.

*/



/* The next few functions return ERROR or NOERROR.	*/
/* See DeskLib:Core.h) for #defines of (NO)ERROR.	*/

void	Desk_Dialog2_OpenDialogMenuLeaf( Desk_event_pollblock *event, Desk_dialog2_block *dialog2);
/* 
Opens the dialog2 as the leaf of the current menu. This should be done
in response  to a Desk_message_MENUWARN - the Desk_event_pollblock should be the
one which is a Desk_message_MENUWARN.
*/

void	Desk_Dialog2_OpenDialogMenu( Desk_dialog2_block *dialog2, Desk_window_openpos openpos);
/*
Opens the dialog2 as a menu-dialogue - ie clicking outside it will
make it disappear. This uses Desk_Wimp_CreateMenu.
*/

void	Desk_Dialog2_OpenDialogStatic( Desk_dialog2_block *dialog2, Desk_window_openpos openpos);
/*
Opens the dialog2 as a static dialog - ie a proper window. Returns
NOERROR if succesful, or ERROR if unable to open the dialog2.
*/

void	Desk_Dialog2_CloseDialog( Desk_dialog2_block *dialog2);
/*
Closes the dialog. Can be called from (for eg) Desk_event_CLICK-handling code
for a 'Cancel' button in the dialog2's window.

If dialog2->flags.data.keepwindow == 0 (the default), the dialog window
will be Desk_Window_Delete-ed, so all handlers for the window will be
released automatically.

If the dialog2 is part of a menu, the menu will be closed automaticlly.
*/


void	Desk_Dialog2_DeleteDialog( Desk_dialog2_block *dialog2);
/*
This closes dialog2, if it was open, and then removes the dialog2 block
completely, so you mustn't use 'dialog2' again after calling this
function. 

Call this if you will never need to open the dialog ever again.	
*/










/* 
********************************************************************
********************************************************************
**Other information which you won't need to know about normally...**
********************************************************************
********************************************************************
*/
/*
dialog2->openfn;
	This is a pointer to a function that is called whenever 
	the dialog2 is opened, to allow the application to register 
	Desk_Event_ handlers for mouse-clicks etc.
	This function will also be called when the dialog2 is closed, 
	if you set flags.value.notifyclose with Desk_Dialog2_SetNotifyClose.

dialog2->flags.data.type	: 2;
	Treat as a Desk_dialog2_dialog2type, ie it is one of:
	Desk_dialog2_type_CLOSED, Desk_dialog2_type_MENU, Desk_dialog2_type_MENULEAF
	and Desk_dialog2_type_STATIC.
	Useful if, for eg, you are thinging of opening a menu based 
	on the dialog2 window.
	You might not want to do this if the dialog2 box is already
	a menu, or part of a menu. Also tells you if the dialog2
	is closed.
	*Don't* change 'type' yourself.

dialog2->flags.data.keepwindow	: 1;
	If 0 (the default), Desk_Wimp_DeleteWindow will be called whenever 
	the dialog2 is closed and 'window' set to NULL. Desk_Window_Create 
	is called whenever the dialog2 is opened, with 'templatename'.
	Hence 'window' will only be a proper window-handle when the 
	dialog is open.
	
	If 1, the dialog2's window is left created at all times after 
	the first time the dialog is opened.
	
	You can change 'keepwindow' at any time you please - use
	the macro 'Desk_Dialog2_SetKeepWindow', #defined below.

	You should set 'keepwindow' if you want to have your own 
	event handlers permanently attatched to the dialog2 window, 
	without having to Desk_Event_Claim/Release every time the dialog2
	is opened/closed.

dialog2->flags.data.notifyclose	: 1;
	If 1, 'openfn' will also be called whenver the dialog
	is closed. 'openfn' will know whether the dialog is being
	opened/closed by looking at dialog2->flags.data.type, which 
	will be Desk_dialog2_type_CLOSED if the dialog2 is closing.
	
	The reason for this is that you might want to register 
	a non-window-specific event handler when the dialog2 is
	open - this won't be released when the dialog window is
	closed with Desk_Window_Delete().
	
	'notifyclose' is set to 0 initially by Desk_Dialog2_CreateDialogBox.
	You can change it whenever you like - use the macro
	'Desk_Dialog_SetNotifyClose' #defined below.

dialog2->flags.data.maxtitlesize	: 10;
	This is initially set to Desk_template_TITLEMIN, and is passed to
	Desk_Window_Create whenever the dialog2's window needes to be 
	created. If you need to change the title of a Dialog2 window
	to something longer than in the original templates file, you
	should do this before the Dialog2's window is created, with
	Desk_Dialog2_ChangeTitleSize.
*/


/* These next few prototypes are probably not all that much use normally...	*/




#ifdef Desk__using_SDLS
  extern Desk_dialog2_block	**Desk_Dialog2__Ref_menublock( void);
#endif

#if defined( Desk__using_SDLS) && !defined( Desk__making_Dialog2)
  #define Desk_dialog2_menublock (*Desk_Dialog2__Ref_menublock())
#else
  extern Desk_dialog2_block	*Desk_dialog2_menublock;
/* 
This will always point to the dialog2 which is open as part of a menu,
or be NULL. If you call Desk_Dialog2_CloseDialog( Desk_dialog2_menublock) whenever
you close a menu (ie a menu choice with Select or Menu), then this will
free the dialog2.							
*/
#endif




void	Desk_Dialog2_Window_GetWindowOpenPos( 
		Desk_wimp_point *pos, Desk_window_openpos openpos, Desk_window_handle window
		);
/* 
Makes 'pos' be the top-left of the window if it was opened with
Desk_Window_Show. This actually opens the window using Desk_Window_Show, reads
where the window was	opened, and closes the window.
*/

void	Desk_Dialog2_EnsureWindowHandle( Desk_dialog2_block *dialog2);
/*
Desk_Window_Create's a window for the Desk_dialog2_box if it hasn't got one already.

You can call this anytime - just be aware that Dialog2 will delete the
window whenver the dialog closes, unless you have called
Desk_Dialog2_KeepWindow.
*/

#define Desk_Dialog2_ChangeCloseNotification( dialog2, x)	(dialog2)->flags.data.notifyclose = (x)
#define Desk_Dialog2_NotifyClose( dialog2)		Desk_Dialog2_ChangeCloseNotification( dialog2, 1)
#define Desk_Dialog2_DontNotifyClose( dialog2)	Desk_Dialog2_ChangeCloseNotification( dialog2, 0)
/* 
Sets whether dialog2->openfn is called when the dialog is closed.

The default is not to do this. */


#define Desk_Dialog2_ChangeKeepWindow( dialog2, x)	(dialog2)->flags.data.keepwindow = (x)
#define Desk_Dialog2_KeepWindow( dialog2)		Desk_Dialog2_ChangeKeepWindow( dialog2, 1)
#define Desk_Dialog2_DontKeepWindow( dialog2)	Desk_Dialog2_ChangeKeepWindow( dialog2, 0)
/*
Sets whether the dialog2's window is not deleted whenever the dialog2 is
closed. The default is 0 - ie the window *is* deleted whenever the
dialog is closed. */

#define Desk_Dialog2_ChangeTitleSize( dialog2, x)	(dialog2)->flags.data.maxtitlesize = (x)
/*
flags.data.maxtitlesize is passed to Desk_Window_Create. See
DeskLib:Template.h for an explanation of what maxtitlesize is all
about...
*/

#ifdef __cplusplus
}
#endif


#endif
