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

    File:    Event.h
    Author:  Copyright  1992 Jason Williams (for code by John Winters)
    Version: 1.01 (14 Jul 1993)
    Purpose: High-level WIMP event dispatch to a hierarchy of user event
             handling functions.
    Mods:    14 July 1993 - Added Desk_Event_Initialise3
             20 Mar 1995  - JPS Added veneers for global vars for use with DLLs
             22 Jul 1996  - JPS Added Desk_Event_MessagesClaim and
                                Desk_Event_MessagesRelease.
*/


#ifndef __Desk_Event_h
#define __Desk_Event_h

#ifdef __cplusplus
	extern "C" {
#endif


#ifndef __Desk_Core_h
	#include "Desk.Core.h"
#endif

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



/*  NOTES
 *  =====
 *
 *  Event supplies a set of high-level functions for proper handling of WIMP
 *  events.
 *  It polls the WIMP for you, and then passes the resulting event to one of
 *  your designated handler routines. Events are cascaded down through your
 *  handlers until one of them returns Desk_bool_TRUE, indicating that the event has
 *  been successfully dealt with. This allows you to have application-wide
 *  defaults for certain event types, with occasional overrides of that
 *  default for specific windows or icons.
 *
 *  Handlers can be registered for the following (priority-ordered) things:
 *
 *    Specific window, specific icon, specific event.
 *    Specific window, specific icon, any event.
 *    Specific window, any icon, specific event.
 *    Specific window, any icon, any event.
 *    Any window, specific event.
 *    Any window, any event.
 *
 *  When an non window-related event occurs, the order is as follows:
 *
 *    Any window, specific event.
 *    Any window, any event.
 *
 *  A set of default handlers is also provided (handlers.c): You can copy
 *  the code for the handlers you need into your own program as a base event
 *  handling system.
 *
 *  Any event which has no registered handlers will automatically be masked
 *  out in subsequent Desk_Wimp_Polls. (Except for "Quit" messages)
 *
 *  NULL events are treated (slightly) specially compared to other events.
 *  After registering handler(s) for NULL events they will be turned on.
 *  (They will NOT be turned on if you request a handler for ALL events. To
 *  enable NULL events, you must specifically register a handler for
 *  Desk_event_NULL events.)
 *  As a default, Desk_Wimp_Poll will be used, but functions are supplied for
 *  you to set a minimum return time (as in Desk_Wimp_PollIdle) if NULL events
 *  are wanted less frequently 
 *  TWO options for NULL event handling are open to you:
 *    Each NULL event is passed to ALL registered handlers,
 *      (To allow you to do important things as often as possible)
 *    Each handler gets one NULL event in turn, in a round-robin fashion.
 *      (To allow you to multitask several "subtask" functions alongside
 *       each other with ease)
 */



typedef Desk_bool (*Desk_event_handler) ( Desk_event_pollblock *Desk_poll_block, void *reference);
/* 
User Desk_event_handler function. Return Desk_bool_TRUE if the event has been handled.
 */


/* JS 01 Apr 1995, 10 Apr 1995 */
/* Added function veneers for globals which must be  */
/* used if compiling for use with DeskLib DLLs.       */

#ifdef Desk__using_SDLS
  extern Desk_event_pollmask  *Desk_Event__Ref_mask( void);
  extern int             *Desk_Event__Ref_taskhandle( void);
  extern unsigned int    *Desk_Event__Ref_wimpversion( void);
  extern char            *Desk_Event__Ref_taskname( void);
  extern Desk_event_pollblock *Desk_Event__Ref_lastevent( void);
#endif

#if defined( Desk__using_SDLS) && !defined( Desk__making_Event)
  #define Desk_Event_mask        (*Desk_Event__Ref_mask())
  #define Desk_Event_taskhandle  (*Desk_Event__Ref_taskhandle())
  #define Desk_Event_wimpversion (*Desk_Event__Ref_wimpversion())
  #define Desk_Event_taskname    (Desk_Event__Ref_taskname())
  #define Desk_Event_lastevent   (*Desk_Event__Ref_lastevent())
#else
  extern Desk_event_pollmask  Desk_Event_mask;         /* Mask used by Desk_event_ FNs for Desk_Wimp_Poll */
  extern int             Desk_Event_taskhandle;   /* WIMP task-handle of this application  */
  extern unsigned int    Desk_Event_wimpversion;  /* Wimp version number * 100             */
  extern const char*     Desk_Event_taskname; /* Application name                      */
  extern Desk_event_pollblock	Desk_Event_lastevent;    /* Last event received by Desk_event_()       */
#endif



extern Desk_bool Desk_Event_Claim(Desk_event_type eventtype,
                        Desk_window_handle window,  Desk_icon_handle icon,
                        Desk_event_handler handler, void *reference);
/*
 * Call this function to claim an event. This attaches the given handler
 * function to the given event for all future event processing.
 *    eventtype should be Desk_event_ANY  - to handle all events, or
 *              an event type        - to handle a specific event
 *    window    should be Desk_event_ANY  - if not window-specific, or
 *              a window handle      - to attach ONLY to that window
 *    icon      should be Desk_event_ANY  - if not icon-specific, or
 *              an icon handle       - to attach ONLY to that icon
 *              (NOTE: if icon != Desk_event_ANY, window MUST be defined)
 *
 *    handler   is the address of your handler function
 *    reference is a handle for any user-data you want passed to the
 *              function whenever it is called.
 */


extern Desk_bool Desk_Event_Release(Desk_event_type event,
                          Desk_window_handle  window, Desk_icon_handle icon,
                          Desk_event_handler handler, void *reference);
/*
 * This will release your claim on an event, removing the given handler
 * from further usage.
 * The parameters passed in should be the same as those passed to 
 * Desk_Event_Claim.
 */


extern void Desk_Event_ReleaseWindow(Desk_window_handle window);
/*
 * This is similar to Desk_Event_Release, but rather than delinking ONE handler
 * it delinks ALL handlers attached to the given window. This should be done
 * if you close/delete the window using low-level routines. (It is done
 * automatically if you use Desk_Window_ calls to remove the window)
 */



extern void Desk_Event_Process(Desk_event_pollblock *event);
/*
 * Call this to process a Desk_Wimp_Poll event. It will cascade the event down
 * through the event-handler hierarchy until one of your event handlers
 * returns Desk_bool_TRUE to indicate succesful handling of the message.
 * NOTE that Desk_Event_Poll calls Desk_Wimp_Poll and Desk_Event_Process for you.
 */


extern void Desk_Event_Poll(void);
/*
 * Main event poll routine. Use as in:
 * while (Desk_bool_TRUE)
 *   Desk_Event_Poll();
 */


extern void Desk_Event_Initialise( const char *taskname);
/*
 * Call this once to initialise the Wimp and the event manager
 * **** This call is obsolescent, and should only be used if you still need
 *      RISC OS 2 compatability - see Desk_Event_InitialisePlus, below.
 */


extern void Desk_Event_Initialise3( const char *taskname, int version, const int *messages);
/*
 * Extended version of Desk_Event_Initialise which allows the wimp version
 * number to be set and the list of acceptable messages to be passed
 *
 * This function should only be used for version numbers of 300 or greater
 * (i.e. for tasks which will only run on RISC OS 3 or later versions).
 */


extern void Desk_Event_CloseDown(void);
/*
 * Call this to CloseDown (quit) the application
 */




typedef Desk_bool (*Desk_event_claimorreleasefn)( 
		Desk_event_type	eventtype, 
		Desk_window_handle	window, 
		Desk_icon_handle	icon, 
		Desk_event_handler	handler, 
		void	*reference
		);
/*
This is the function-type of the Desk_Event_Claim and Desk_Event_Release
functions. Useful for writing functions which accept a pointer to either
of these functions, in order to claim or release a set of events
consistently
*/


void	Desk_Event_MessagesClaim( Desk_event_handler handler, void* reference);
/*
Claims all message events - Desk_event_USERMESSAGE,
Desk_event_USERMESSAGERECORDED, Desk_event_ACK.

Release with Desk_Event_MessagesRelease.
 */

void	Desk_Event_MessagesRelease( Desk_event_handler handler, void* reference);
/*
Releases message events - see Desk_Event_MessagesClaim.
 */



void	Desk_Event_PollIdle3( void* pollword);
/*
Use instead of Desk_Event_Poll whenever Desk_Event_ClaimNullIdle has
been used.

Calls Desk_Wimp_PollIdle3 with 'earliest' being the time of the earliest
handler registered with Desk_Event_ClaimNullIdle.

When a null event is returned from Wimp_Poll, the internal handler calls
all handlers registered  with Desk_Event_ClaimNullIdle who asked to be
called back earlier than the time of the null event until one of these
handlers returns Desk_bool_TRUE.

The internal null handler returns whatever the last idle handler
returned, so will not prevent any conventional null handlers being
called. However, conventional null handlers could cause the internal
handler to be not called if they return Desk_bool_TRUE.
 */


#define	Desk_Event_PollIdle()	Desk_Event_PollIdle3( NULL)
/*
Use instead of Desk_Event_Poll whenever Desk_Event_ClaimNullIdle has
been used.
 */

void	Desk_Event_ClaimNullIdle( Desk_event_handler handler, unsigned int earliest, void* reference);
/*
'handler' will be called after time 'earliest', as measured using
Desk_Time_Monotonic(). 

Desk_Event_ClaimNullIdle can be called multiple times, and
Desk_Event_PollIdle and Desk_Event_PollIdle3 will use the earliest
registered handler when calling Wimp_PollIdle.

Things are a lot simpler if you don't call Desk_Event_Claim( event_NULL,
...) as well as Desk_Event_ClaimNullIdle.

If you want to be called regularly, your handler should call
Desk_Event_ClaimNullIdle() each time it runs.

Note that if Desk_Event_ClaimNullIdle is called from within a handler
previously set up with a call to Desk_Event_ClaimNullIdle, the nullidle claim
will be internally marked as inactive until all relevent nullidle
handlers have been called. This avoids infinite loops when handlers call
Desk_Event_ClaimNullIdle() (eg so that they are polled continuously).
 */


void	Desk_Event_ClaimNullIdleInterval( Desk_event_handler handler, int interval, void* reference);
/*
As Desk_Event_ClaimNullIdle, except that takes an interval from the
current time, instead of an absolute time.
 */

void	Desk_Event_ReleaseNullIdle( Desk_event_handler handler, void* reference);





#ifdef __cplusplus
}
#endif


#endif
