Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
AG_EVENT(3)		    Library Functions Manual		   AG_EVENT(3)

NAME
       AG_Event	-- agar	event handlers / virtual functions

SYNOPSIS
       #include	<agar/core.h>

DESCRIPTION
       The AG_Event (or	AG_Function) type represents an	event handler (or more
       generally  a  virtual  function)	 under an AG_Object(3).	 It provides a
       general-purpose,	thread-safe message passing system.  It	is used	to im-
       plement virtual functions in objects.  The AG_Event structure  contains
       an  optional name identifier (a string of up to AG_EVENT_NAME_MAX char-
       acters long).  Event Handlers are declared as follows:

       void MyEventHandler(AG_Event *event)

       The final stack of arguments passed to MyEventHandler()	contains  both
       the arguments from the initial AG_SetEvent() call followed by any extra
       arguments  appended by subsequent AG_PostEvent()	calls.	See the	"EVENT
       ARGUMENTS" section for details and examples.

       An AG_Event may store up	to AG_EVENT_ARGS_MAX arguments.	 The arguments
       contained in an AG_Event	can be accessed	by the event handler either by
       index or	by name.

EVENT PROCESSING
       AG_Event	 *  AG_SetEvent(AG_Object  *obj,  const	  char	 *name,	  void
       (*fn)(AG_Event *event), const char *fmt,	...)

       AG_Event	  *   AG_AddEvent(AG_Object   *obj,  const  char  *name,  void
       (*fn)(AG_Event *event), const char *fmt,	...)

       AG_Event	* AG_FindEventHandler(AG_Object	*obj, const char *name)

       void AG_UnsetEvent(AG_Object *obj, const	char *name)

       void AG_UnsetEventByPtr(AG_Object *obj, AG_Event	*event)

       void AG_PostEvent(AG_Object *obj, const char *name,  const  char	 *fmt,
       ...)

       void  AG_PostEventByPtr(AG_Object  *obj,	 AG_Event  *event,  const char
       *fmt, ...)

       int AG_SchedEvent(AG_Object *obj, Uint32	ticks, const char *name, const
       char *fmt, ...)

       The AG_SetEvent() function sets an event	handler	to service  events  of
       type  name.   If	 a handler of the given	name already exists, it	is re-
       placed.	The AG_AddEvent() variant preserves any	 pre-existing  handler
       (such  that  multiple  handlers will be invoked by the event).  fn is a
       pointer to the event handler  function.	 fmt  is  an  optional	format
       string which specifies following	arguments (see "EVENT ARGUMENTS").

       AG_FindEventHandler() searches for an event handler by name and returns
       a pointer to its	AG_Event structure on success or NULL if not found.

       AG_UnsetEvent()	and  AG_UnsetEventByPtr()  delete the given event han-
       dler.

       AG_PostEvent() raises the event identified by name  under  object  obj.
       fmt  is	an  optional format string specifying following	arguments that
       will be passed to the event handler function.  The event	 handler  will
       see  the	 arguments  added  by AG_SetEvent() followed by	those added by
       AG_PostEvent().

       The AG_PostEventByPtr() variant accepts a pointer to an	AG_Event  ele-
       ment as opposed to looking up the event handler by name.

       AG_SchedEvent()	provides an interface similar to AG_PostEvent()	except
       that the	event is scheduled to occur in	the  given  number  of	ticks.
       AG_SchedEvent()	returns	 0  on success or -1 if	the timer could	not be
       created.	 When an AG_Object(3) is  detached  or	destroyed,  any	 event
       scheduled  for  execution  is automatically cancelled.  A more flexible
       interface for timers is described in AG_Timer(3)	(which AG_SchedEvent()
       uses internally).

EVENT ARGUMENTS
       The AG_SetEvent(), AG_AddEvent()	and AG_PostEvent() routines  accept  a
       special	fnArgs	format	string	specifying  a  list of arguments to be
       passed to the event handler  function.	For  example,  "%s,%p,%i"  (or
       "%s%p%i") says that the following arguments are a string, a pointer and
       an  integer.   An  event	 handler  routine  will	typically use accessor
       macros to extract argument values out of	the event structure:

	     void
	     MyEventHandler(AG_Event *event)
	     {
		     char *s = AG_STRING(1);
		     void *p = AG_PTR(2);
		     int i   = AG_INT(3);

		     /*	... */
	     }

       It is customary for Agar	 object	 classes  to  define  accessor	macros
       AG_<T>_PTR()  (for  accessing  arguments	by index), AG_<T>_NAMED() (for
       accessing arguments by name), and AG_<T>_SELF() (for accessing argument
       0, equivalent to	"AG_<T>_PTR(0)").  Arguments marked constant  must  be
       accessed	with AG_c<T>_PTR() and AG_c<T>_SELF().

       Here is an example using	Agar-GUI widget	classes:

	     static void
	     PushedOK(AG_Event *event)
	     {
		     AG_Button *button = AG_BUTTON_SELF();
		     AG_Radio *radio   = AG_RADIO_PTR(1);
		     AG_Button *button = AG_BUTTON_PTR(2);
		     const AG_Checkbox *cb = AG_cCHECKBOX_PTR(3);

	     /*	     cb->invert	= 1;		  <- Incorrect (cb is const) */
	     /*	     AG_WidgetDisable(cb);	  <- Incorrect (cb is const) */
		     AG_WidgetDisable(radio);  /* <- OK	*/
		     AG_WidgetDisable(button); /* <- OK	*/
	     }

	     AG_Window *win = AG_WindowNew(0);
	     AG_Checkbox *radio	= AG_RadioNew(window, 0, NULL);
	     AG_Button *button = AG_ButtonNew(window, 0, "OK");
	     AG_Checkbox *checkbox = AG_CheckboxNew(window, 0, "Some option");

	     AG_SetEvent(button, "button-pushed",
		 PushedOK, "%p,%Cp", radio, checkbox);

       Arguments  are  optionally  named  (tagged with a string) and retrieved
       with AG_<TYPE>_NAMED():

	     static void
	     CopySomeData(AG_Event *event)
	     {
		     const void	*src = AG_cPTR_NAMED("src");
		     void *dst = AG_PTR_NAMED("dst");
		     long offs = AG_LONG_NAMED("offs");

		     /*	... */
	     }

	     void *src,	*dst;
	     long offs = 0;

	     AG_SetEvent(obj, "some-event",
		 CopySomeData, "%Cp(src),%p(dst),%li(offs)",
		 src, dst, offs);

       The following argument specifiers are accepted:

       %p    A pointer to data:	void *.
       %Cp   A pointer to const	data: const void *.
       %i    Signed integer: int.
       %u    Unsigned integer: Uint.
       %li   Signed long integer: long.	 Not in	AG_SMALL.
       %lu   Unsigned long integer: Ulong.  Not	in AG_SMALL.
       %f    Real number: float.  Requires AG_HAVE_FLOAT.
       %d    Real number: double.  Requires AG_HAVE_FLOAT.
       %s    C string (NUL-terminated):	char *.

       The following macros extract the	arguments  contained  in  an  AG_Event
       structure.  If Agar is compiled with either --enable-debug or --enable-
       type-safety, they also check for	potential accesses to incorrect	types.

       AG_Object * AG_SELF(void)

       const AG_Object * AG_cSELF(void)

       void * AG_PTR(int index)

       const void * AG_cPTR(int	index)

       AG_Object * AG_OBJECT(int index,	const char *hierarchy)

       const AG_Object * AG_cOBJECT(int	index, const char *hierarchy)

       char * AG_STRING(int index)

       int AG_INT(int index)

       Uint AG_UINT(int	index)

       long AG_LONG(int	index)

       Ulong AG_ULONG(int index)

       float AG_FLOAT(int index)

       double AG_DOUBLE(int index)

       void * AG_PTR_NAMED(const char *key)

       const void * AG_cPTR_NAMED(const	char *key)

       AG_Object * AG_OBJECT_NAMED(const char *key, const char *hierarchy)

       const   AG_Object   *  AG_cOBJECT_NAMED(const  char  *key,  const  char
       *hierarchy)

       char * AG_STRING_NAMED(const char *key)

       int AG_INT_NAMED(const char *key)

       Uint AG_UINT_NAMED(const	char *key)

       long AG_LONG_NAMED(const	char *key)

       Ulong AG_ULONG_NAMED(const char *key)

       float AG_FLOAT_NAMED(const char *key)

       double AG_DOUBLE_NAMED(const char *key)

       The AG_SELF()  and  AG_cSELF()  macros  expand  to  a  pointer  to  the
       AG_Object(3)   receiving	  the	event  (the  obj  argument  passed  to
       AG_PostEvent()).	 They are equivalent to	AG_PTR(0) and AG_cPTR(0),  re-
       spectively.

       The  following  macros return a specific	item in	the list of arguments.
       When  retrieving	 arguments  by	index,	note  that  the	 arguments  to
       AG_PostEvent()  follow  the arguments to	AG_SetEvent() (i.e., the argu-
       ments to	AG_SetEvent() are pushed first onto the	argument  stack,  fol-
       lowed by	the arguments to AG_PostEvent(), if any).  These macros	ensure
       type  safety  if	Agar is	compiled with --enable-debug or	--enable-type-
       safety.

       AG_PTR()	returns	a pointer (a  `%p'  argument).	 AG_cPTR()  returns  a
       const pointer (a	`%Cp' argument).

       AG_OBJECT() returns a pointer to	an AG_Object(3)	(a `%p'	argument).  In
       debug  mode, assert that	the argument points to a valid AG_Object(3) by
       performing  a  validity	test,  and  a  class  membership  test.	   The
       AG_cOBJECT()  variant  asserts  that  the pointer is a const pointer (a
       `%Cp' argument).

       AG_STRING() returns a pointer to	a string (a `%s' argument).

       AG_INT(), AG_UINT(), AG_LONG() and AG_ULONG() return a natural or  long
       integer (a `%i',	`%u', `%li' or `%lu' argument, respectively).

       AG_FLOAT()  and	AG_DOUBLE()  return the	given floating-point number (a
       `%f' for	a float	or `%d'	for a double argument).

       The AG_*_NAMED()	macros retrieve	the given argument by name instead  of
       by  index.  If there is no argument matching the	name, a	fatal error is
       raised.

ARGUMENT MANIPULATION
       In some cases it	is desirable for functions to accept a list  of	 event
       handler	arguments  like	AG_SetEvent(), and possibly manipulate its en-
       tries directly.	For example, the AG_MenuAction(3) function of the  GUI
       widget  AG_Menu(3) accepts a pointer to an event	handler	function, fol-
       lowed by	an AG_SetEvent() style format string and a  variable  list  of
       arguments.  The following functions allow such manipulations.

       void AG_EventInit(AG_Event *ev)

       void AG_EventArgs(AG_Event *ev, const char *fmt,	...)

       void AG_EventCopy(AG_Event *dst,	const AG_Event *src)

       AG_Event	* AG_EventDup(const AG_Event *src)

       void AG_EVENT_DUMP(const	AG_Event *ev)

       void AG_EventPushPointer(AG_Event *ev, const char *key, void *val)

       void AG_EventPushConstPointer(AG_Event *ev, const char *key, const void
       *val)

       void AG_EventPushString(AG_Event	*ev, const char	*key, char *val)

       void AG_EventPushInt(AG_Event *ev, const	char *key, int val)

       void AG_EventPushUint(AG_Event *ev, const char *key, Uint val)

       void AG_EventPushLong(AG_Event *ev, const char *key, long val)

       void AG_EventPushUlong(AG_Event *ev, const char *key, Ulong val)

       void AG_EventPushFloat(AG_Event *ev, const char *key, float val)

       void AG_EventPushDouble(AG_Event	*ev, const char	*key, double val)

       void AG_EVENT_PUSH_ARG(va_list ap, char formatChar, AG_Event *ev)

       void * AG_EventPopPointer(AG_Event *ev)

       const void * AG_EventPopConstPointer(AG_Event *ev)

       char * AG_EventPopString(AG_Event *ev)

       int AG_EventPopInt(AG_Event *ev)

       Uint AG_EventPopUint(AG_Event *ev)

       long AG_EventPopLong(AG_Event *ev)

       Ulong AG_EventPopUlong(AG_Event *ev)

       float AG_EventPopFloat(AG_Event *ev)

       double AG_EventPopDouble(AG_Event *ev)

       AG_EventInit() initializes an AG_Event structure	with no	arguments.

       AG_EventArgs()  initializes  ev	and also specifies a list of arguments
       (in the same format as AG_SetEvent()).

       AG_EventCopy() copies the  function  pointer  and  arguments  from  one
       AG_Event	 to  another.	AG_EventDup() returns a	newly-allocated	dupli-
       cate.

       The AG_EVENT_DUMP() macro produces a listing of the arguments of	ev  on
       the console via AG_Debug(3).

       The  AG_EventPush*() routines put a new argument	on top of the argument
       stack, incrementing the argument	count.	AG_EventPop*()	decrement  the
       argument	count, returning a copy	of the data of the last	element.

       The AG_EVENT_PUSH_ARG() macro insert an argument	on the argument	stack,
       determining  the	 type  from formatChar and the data from the following
       va_arg(3) arguments.  The supported  formatChar	characters  are	 docu-
       mented in the "EVENT ARGUMENTS" section.

EVENT QUEUES
       Under  some circumstances, it is	useful to gather AG_Event objects into
       a simple	 queue.	  For  example,	 a  custom  event  loop	 routine  (see
       AG_EventLoop(3))	 or  a	low-level  Agar	 driver	(see AG_Driver(3)) may
       gather events from input	devices	and later process them.

STRUCTURE DATA
       For the AG_Event	structure:

       char * name	   String identifier for the event.
       int argc		   Argument count.
       AG_Variable *argv   Argument data (see AG_Variable(3)).

EXAMPLES
       The following code fragment demonstrates	a typical  AG_Event  usage  in
       the  Agar-GUI  library.	 We  bind an action to the button press	event,
       which is	called `button-pushed'.	  This	event  is  documented  in  the
       AG_Button(3) manual, and	so are the arguments it	appends	to the list of
       arguments passed	to the event handler (in this case, a single int).

	     void
	     SayHello(AG_Event *event)
	     {
		     char *s   = AG_STRING(1);	/* From	AG_SetEvent() */
		     int state = AG_INT(2);	/* From	later AG_PostEvent() */

		     AG_TextMsg(AG_MSG_INFO, "Hello, %s! (state=%d)", s, state);
	     }

	     AG_Button *btn;

	     btn = AG_ButtonNew(NULL, 0, "Say hello");
	     AG_SetEvent(btn, "button-pushed", SayHello, "%s", "World");

       The   AG_Button	 API   provides	  a   shorthand	 constructor  routine,
       AG_ButtonNewFn(), which accepts the `button-pushed'  event  handler  as
       argument:

	     AG_ButtonNewFn(NULL, 0, "Say hello", SayHello, "%s", "World");

       The following code fragment is equivalent:

	     AG_Button *btn;
	     AG_Event *ev;

	     btn = AG_ButtonNew(NULL, 0, "Say hello");
	     ev	= AG_SetEvent(btn, "button-pushed", SayHello, NULL);
	     AG_EventPushString(ev, NULL, "World");

       The following code fragment invokes a handler routine artificially:

	     void
	     SayHello(AG_Event *event)
	     {
		     char *s = AG_STRING(1);
		     int   i = AG_INT(2);
	     }

	     AG_Event ev;

	     AG_EventArgs(&ev, "%s,%d",	"Foo string", 1234);
	     SayHello(&ev);

SEE ALSO
       AG_EventLoop(3),	AG_Intro(3), AG_Object(3), AG_Timer(3),	AG_Variable(3)

HISTORY
       The  AG_Event mechanism first appeared in Agar 1.0.  The	AG_Variable(3)
       structure was first used	to represent event handler arguments  in  Agar
       1.3.4.	Agar 1.6.0 added the const argument accessor macros and	intro-
       duced validity and class	membership tests for object pointers in	 event
       handler	    arguments.	     AG_EventCopy(),	 AG_EventDup()	   and
       AG_UnsetEventByPtr() appeared in	Agar 1.6.0.

Agar 1.7		       December	21, 2022		   AG_EVENT(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=AG_Event&sektion=3&manpath=FreeBSD+Ports+14.3.quarterly>

home | help