/* $Id: demo.c,v 1.4 2004/11/11 15:18:22 cegger Exp $
 * demo.c - Author 1999 Andreas Beck   becka@ggi-project.org
 *
 * This is a demonstration of LibGII's functions and can be used as a
 * reference programming example.
 *
 *   This software is placed in the public domain and can be used freely
 *   for any purpose. It comes without any kind of warranty, either
 *   expressed or implied, including, but not limited to the implied
 *   warranties of merchantability or fitness for a particular purpose.
 *   Use it at your own risk. the author is not responsible for any damage
 *   or consequences raised by use or inability to use this program.
 */

#include <ggi/gic.h>

/* We use that to show the names of all recognizers bound to a feature.
 */
static void showRecognizers(gic_handle_t hand, gic_feature *feature)
{
	int x;
	gic_recognizer *rec;
	char buffer[256];

	for(x=0;;x++) {
		if (NULL==(rec=gicFeatureGetRecognizer(hand, feature,x)))
			break;
		gicRecognizerGetName(hand, rec,buffer,sizeof(buffer));
		printf("Rec#%d: '%s'\n",x+1,buffer);
	}
}

/* First we define to "actions". Actions are called, whenever a LibGIC
 * "feature" (that is something you want to control) changes state.
 *
 * Depending on your programming model, you will either directly use that
 * for callback functions or rather map the actions to a function that
 * posts program-events.
 *
 */
static void my_action(gic_handle_t hand, gic_actionlist *action,
		gic_feature *feature, gic_state newstate,gic_flag flag,int recnum)
{
	printf("my_action(%s) called with newstate=0x%x, privdata=%p, flag=%x.\n",
		action->name,newstate,action->privdata,flag);
	showRecognizers(hand, feature);
	return;
}

static void my_action2(gic_handle_t hand, gic_actionlist *action,
		gic_feature *feature, gic_state newstate,gic_flag flag,int recnum)
{
	printf("my_action2(%s) called with newstate=0x%x, pridata=%p, flag=%x.\n",
		action->name,newstate,action->privdata,flag);
	showRecognizers(hand, feature);
	return;
}

/* As one cannot reliably save function mappings, you need a table for 
 * mapping between action-names (like "mynextaction") and the functions
 * (like my_action()) you want to be called and their "privdata" argument
 * which can be used to distinguish multiple different features, that
 * essentially call the same action function.
 */

gic_actionlist actionmapping[]= {
	{NULL,"mynextaction",	my_action,	NULL},
	{NULL,"myprevaction",	my_action2,	(void *)0x12345678},
	{NULL,NULL,NULL,NULL}
};

#if 0	/* Defined, but unused */
static void training(gic_handle_t hand)
{
	int error;
	gic_recognizer	*trainresult,*trainremain;
	gii_event	event;
	gic_feature	bla;

	trainresult=NULL;
	error=gicRecognizerTrainStart(hand, &trainresult);
	printf("gicRecognizerTrain init returned: %d,%p.\n",error,trainresult);

	event.any.type=evKeyPress;
	event.key.sym=0x41;
	event.key.label=0x40;
	error=gicRecognizerTrain(hand, &trainresult,&event);
	printf("gicRecognizerTrain event returned: %d,%p.\n",error,trainresult);

	event.any.type=evKeyRelease;
	event.key.sym=0x41;
	event.key.label=0x40;
	error=gicRecognizerTrain(hand, &trainresult,&event);
	printf("gicRecognizerTrain event returned: %d,%p.\n",error,trainresult);

	trainremain=trainresult->next;
	error=gicFeatureAttachRecognizer(hand, &bla,trainresult);
	printf("Attached found recognizer to prev: %d.\n",error);

	error=gicRecognizerTrainStop(hand, &trainremain);
	printf("gicRecognizerTrain init (freeing unused entries ...) returned: %d,%p.\n",error,trainremain);

}
#endif


/* Now for the main routine, which just demonstrates how a LibGIC using
 * program looks like.
 */
int main(void)
{
	/* gic_handle_t is an opaque handle to any instance of LibGIC running.
	 */
	gic_handle_t	handle;

	/* gic_head is a type that stores a collection of different
	 * "contexts". A typical application will have several contexts,
	 * as you will want different actions to be invoked, when you
	 * are using the cursors inside say the game engine or in a
	 * configuration menu.
	 */
	gic_head	*head;

	/* This demo features two such contexts:
	 */
	gic_context	*menu,*game;

	/* The "real" LibGIC configuration info is read from a file.
	 * Note, that LIbGIC configuration info is human-readable, line
	 * oriented, and you can detected LibGIC generated lines by the
	 * "gic:" prefix. This should allow you to insert LibGIC data
	 * in about any style configuration file. Remember, that LibGIC
	 * configuration data size is variable, as you can add/delete
	 * bindings.
	 */
	FILE		*config;
	
	/* LibGIC is designed to get input from gii_events. In case you 
	 * are not using LibGII for input (why ?), you'll need to convert
	 * to LibGII event format. The recognizers need to understand
	 * the shall parse ...
	 */
	gii_event	event;

	/* Initialize LibGIC
	 */
	gicInit();

	/* Open a default LibGIC instance.
	 */
	handle=gicOpen(NULL);

	/* Read in the config file. Yes it is that simple.
	 */
	config=fopen("demo.gic","r");
	head=gicHeadRead(handle,config);
	fclose(config);

	/* For demonstration purposes, dump the read data to stdout.
	 */
	gicHeadWrite(handle,head,stdout);
	
	/* Now look up the contexts in the head. You could as well store 
	 * individual contexts, but this is much more convenient.
	 */
	menu=gicHeadLookupContext(handle,head,"Menu context");
	game=gicHeadLookupContext(handle,head,"Game context");
	printf("Looked up contexts game=%p menu=%p.\n",
		(void *)game, (void *)menu);

	/* We have the structure, but actions are not completely mapped yet,
	 * as there is no way to portably store function addresses and contents
	 * of "void *privdata". Use the mapping table shown above to re-
	 * establish those.
	 */
	printf("(Re)mapping all events.\n");
	gicHeadMapActions(handle,head,actionmapping);

	/* Now we are set. We would now use LibGII to get events and send 
	 * them to LibGIC. For demonstration purposes, we just make up the
	 * events ourselves.
	 */
	printf("Context handling events.\n");

	/* First a hopefully unmatched event.
	 */
	printf(" sending evCommand - don't think someone matches that ...\n");
	event.any.type=evCommand;
	gicContextHandleEvent(handle,menu, &event);

	printf(" sending evKeyPress (sym='A', label='@')\n");
	event.any.type=evKeyPress;
	event.key.sym=0x41;
	event.key.label=0x40;
	gicContextHandleEvent(handle,menu, &event);

	printf(" sending evKeyPress (sym='A', label='A')\n");
	event.any.type=evKeyPress;
	event.key.label=0x41;
	gicContextHandleEvent(handle,menu, &event);

	printf(" sending evKeyRelease (sym='A', label='A')\n");
	event.any.type=evKeyRelease;
	gicContextHandleEvent(handle,menu, &event);
	
	gicClose(handle);
	gicExit();
	return 0;
}

