GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
AG_EVENT(3) FreeBSD Library Functions Manual AG_EVENT(3)

AG_Eventagar event handlers / virtual functions

#include <agar/core.h>

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 implement virtual functions in objects. The AG_Event structure contains an optional name identifier (a string of up to AG_EVENT_NAME_MAX characters long). Event Handlers are declared as follows:


void
(AG_Event *event);

The final stack of arguments passed to () 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.

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


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


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


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


void
(AG_Object *obj, AG_Event *event);


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


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


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

The () function sets an event handler to service events of type name. If a handler of the given name already exists, it is replaced. 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).

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

() and AG_UnsetEventByPtr() delete the given event handler.

() 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 () variant accepts a pointer to an AG_Event element as opposed to looking up the event handler by name.

() 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).

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 () (for accessing arguments by index), () (for accessing arguments by name), and () (for accessing argument 0, equivalent to "AG_<T>_PTR(0)"). Arguments marked must be accessed with () and ().

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 (tagged with a string) and retrieved with ():

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 *
(void);


const AG_Object *
(void);


void *
(int index);


const void *
(int index);


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


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


char *
(int index);


int
(int index);


Uint
(int index);


long
(int index);


Ulong
(int index);


float
(int index);


double
(int index);


void *
(const char *key);


const void *
(const char *key);


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


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


char *
(const char *key);


int
(const char *key);


Uint
(const char *key);


long
(const char *key);


Ulong
(const char *key);


float
(const char *key);


double
(const char *key);

The () 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), respectively.

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

() returns a pointer (a ‘%p’ argument). AG_cPTR() returns a const pointer (a ‘%Cp’ argument).

() 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).

() returns a pointer to a string (a ‘%s’ argument).

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

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

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

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


void
(AG_Event *ev);


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


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


AG_Event *
(const AG_Event *src);


void
(const AG_Event *ev);


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


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


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


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


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


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


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


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


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


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


void *
(AG_Event *ev);


const void *
(AG_Event *ev);


char *
(AG_Event *ev);


int
(AG_Event *ev);


Uint
(AG_Event *ev);


long
(AG_Event *ev);


Ulong
(AG_Event *ev);


float
(AG_Event *ev);


double
(AG_Event *ev);

() initializes an AG_Event structure with no arguments.

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

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

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

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

The () 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 documented in the EVENT ARGUMENTS section.

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.

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)).

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);

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

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 introduced 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.

December 21, 2022 Agar 1.7

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.