/*
 * DISPAT.H
 *
 * $Id: dispat.h,v 1.1 1993/08/27 17:08:43 munro Exp $
 *
 * Declare generic dispatcher routines for event driven programs
 *
 */
/*    Copyright (c) 1994.  The Regents of the University of California.
                    All rights reserved.  */

#ifndef DISPAT_H
#define DISPAT_H

/* A program may need to handle input events from several different
   devices-- stdin, one or more connections to X servers, UNIX pipelines,
   and the like.  A true event loop should:
     1) dispatch any events which have been read but not processed
        (pending events) BEFORE entering the loop, then loop:
     2) flush any pending output to the devices and
        pause until input arrives on any device,
     3) dispatch input to the appropriate event handler for each device
        on which input has arrived.

   Some devices, such as a connection to an X server, may require
   multiple additional handlers-- in the case of X, to distribute events
   to the handler for the toolkit which owns the window.

   A program creates a Dispatcher for each input connection for which it
   wants to receive events.  The program then calls DispatchEvents to
   enter a perpetual loop in which the Dispatch method for each Dispatcher
   is called as input becomes available on its file descriptor.
 */

/* Create a new dispatcher and add it to the list of active Dispatchers.
   The Pending or Flush methods may be 0 to skip those operations.
   Returns non-zero if the memory manager fails.  Any existing Dispatcher
   for the same file descriptor is replaced.
     Pending should handle any events which have already been read.  Its
      return values are the same as for Dispatch.
     Flush should flush output, if appropriate.
     Dispatch should read and process all available input, but must not
      block by attempting to read more than is available.  It should
      process all input that is read, then return 0.  If Dispatch
      returns >0, DispatchEvents returns immediately.  If Dispatch
      returns <0, DispatchEvents will return unless another Dispatcher
      exists which did not return -1 the last time it was invoked
      (this branch exists to prevent an infinite loop when the only
      input source is a terminal and the process is in the background).  */
extern int AddDispatcher(int fd, void *context, int (*Pending)(void *),
			 void (*Flush)(void *), int (*Dispatch)(void *));

/* Remove the dispatcher associated with the given file descriptor.
   RemoveDispatcher returns the context passed to AddDispatcher.  */
extern void *RemoveDispatcher(int fd);

/* Loop until some Dispatch returns non-0.  Note that Dispatchers may
   be created and removed within the DispatchEvents loop; if there are
   no active Dispatchers, DispatchEvents returns to its caller, as if
   a Dispatch returned non-0.  */
extern void DispatchEvents(void);

/* Loop until some Dispatch returns non-0, or until no more input events
   are available.  Same as DispatchEvents, but won't block.  */
extern void MaybeDispatch(void);

/* The DispatchWorker (if non-0) will be called if no input is available
   for any of the active Dispatchers.  It will be called repeatedly,
   checking for input between calls, until it returns 0.  */
extern int (*DispatchWorker)(void);

/* Test whether this file descriptor already has a Dispatcher.  */
extern int HasDispatcher(int fd);

/* The DispatchNext function is like DispatchEvents, but it only
   dispatches one event, returning the file descriptor for that event.
   Returns -1 if DispatchEvent would have exited without dispatching
   any events, -2 if a Dispatch returned >0, and -3 if a Pending
   returned >0.  */
extern int DispatchNext(void);

/* Replace DispatchError with routine of your choice to get non-default
   error behavior.  By default (DispatchError=0), a message is printed
   to stderr and processing continues.  If DispatchError returns non-zero,
   DispatchEvents will return to its caller, otherwise its loop
   continues.  */
extern int (*DispatchError)(void);

#endif
