/* $Id: confmgrdemo.c,v 1.3 2005/06/20 06:55:01 cegger Exp $
 * confmgrdemo.c
 *
 * 1999 Andrew Apted  <andrew@ggi-project.org>
 *
 * This is a demonstration of LibGIC's config manager functionality 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>
#include <ggi/gic_confmgr.h>
#include <ggi/ggi.h>


static ggi_visual_t vis;
static ggi_mode     mode;

static ggi_pixel black, grey, white, br_white,
		 red, br_red, blue, br_blue,
		 green, br_green, cyan, br_cyan,
		 yellow, br_yellow;


static ggi_pixel map_color(int r, int g, int b)
{
	ggi_color col;

	col.r = r;  col.g = g;  col.b = b;

	return ggiMapColor(vis, &col);
}

static void setup_colors(void)
{
	black     = map_color(0x0000, 0x0000, 0x0000);
	grey      = map_color(0x5555, 0x5555, 0x5555);
	white     = map_color(0xaaaa, 0xaaaa, 0xaaaa);
	br_white  = map_color(0xffff, 0xffff, 0xffff);
	red       = map_color(0xaaaa, 0x0000, 0x0000);
	br_red    = map_color(0xffff, 0x0000, 0x0000);
	blue      = map_color(0x0000, 0x0000, 0xaaaa);
	br_blue   = map_color(0x0000, 0x0000, 0xffff);
	cyan      = map_color(0x0000, 0xaaaa, 0xaaaa);
	br_cyan   = map_color(0x0000, 0xffff, 0xffff);
	green     = map_color(0x0000, 0xaaaa, 0x0000);
	br_green  = map_color(0x0000, 0xffff, 0x0000);
	yellow    = map_color(0xaaaa, 0xaaaa, 0x0000);
	br_yellow = map_color(0xffff, 0xffff, 0x0000);
}


static int my_read_event(confmgr_info *info, gii_event *event, 
			 struct timeval *timeout)
{
	if (ggiEventPoll(vis, emAll, timeout)) {
		ggiEventRead(vis, event, emAll);
		return 1;
	}

	return 0;
}

static void my_set_color(confmgr_style style, int is_box)
{
	ggi_pixel bg, fg;

	switch (style) {
	
	    case CONFMGR_STYLE_BACKGROUND:
	    case CONFMGR_STYLE_SECTION_BACKGROUND:
	    case CONFMGR_STYLE_TEST_BACKGROUND:
	    	bg = fg = black;
		break;

	    case CONFMGR_STYLE_HEADING_TEXT:
	        bg = black; fg = white;
		break;

	    case CONFMGR_STYLE_HEADING_HIGHLIGHT:
	        bg = black; fg = br_yellow;
		break;

	    case CONFMGR_STYLE_ITEM_TEXT:
	    	bg = grey; fg = white;
		break;

	    case CONFMGR_STYLE_ITEM_CURRENT:
	    	bg = red; fg = br_white;
		break;

	    case CONFMGR_STYLE_ITEM_HIGHLIGHT:
	    	bg = green; fg = br_white;
		break;

	    case CONFMGR_STYLE_BINDING_TEXT:
	    	bg = blue; fg = white;
		break;

	    case CONFMGR_STYLE_BINDING_HIGHLIGHT:
	    	bg = cyan; fg = br_white;
		break;

	    default:
	        bg = grey; fg = white;
		break;
	}

	if (is_box) {
		ggiSetGCForeground(vis, bg);
	} else {
		ggiSetGCBackground(vis, bg);
		ggiSetGCForeground(vis, fg);
	}
}

static void my_draw_box(confmgr_info *info,
                        confmgr_style style,
			int x, int y, int w, int h)
{
	my_set_color(style, 1);

	ggiDrawBox(vis, x, y, w, h);
}

static void my_draw_text(confmgr_info *info,
                         confmgr_style style,
                         confmgr_font font,
			 int x, int y, const char *text)
{
	my_set_color(style, 0);

	ggiPuts(vis, x, y, text);
}

static void my_draw_bar(confmgr_info *info,
			gic_state state,
			int x, int y, int w, int h)
{
	float frac;
	int part;

	if (state == GIC_NOACTION) {
		ggiSetGCForeground(vis, blue);
		ggiDrawBox(vis, x, y, w, h);
		return;
	}

	frac = (float) (state - GIC_STATE_MIN) /
	       (float) (GIC_STATE_MAX - GIC_STATE_MIN);
	
	part = (int) (frac * (float) w);
	
	ggiSetGCForeground(vis, red);
	ggiDrawBox(vis, x, y, w, h);

	if (part > 0) {
		ggiSetGCForeground(vis, br_yellow);
		ggiDrawBox(vis, x, y, part, h);
	}
}

static void my_flush(confmgr_info *info)
{
	ggiFlush(vis);
}

static void my_make_sound(confmgr_info *info,
                          confmgr_sound sound)
{
	switch (sound) {

	    /* ... */

	    default:
	    	/* silence */
		break;
	}
}


static confmgr_info my_info =
{
	NULL,		 /* handle: filled in later */

	NULL,		 /* head: filled in later */

	NULL, NULL,	 /* private stuff */

	{ -1, -1 },	 /* screen & char sizes: filled in later */
	{ -1, -1 },
	{ -1, -1 },

	19, 19, 11, 11,  /* max lengths */
	
	{  1,  1 },	 /* gaps (last two filled in later) */
	{ -1, -1 },
	{ -1, -1 },

	{ 0, 0, 0, 0 },  /* borders */
	{ 0, 0, 0, 0 },
	{ 0, 0, 0, 0 },

	{ 0, 0, 0, 0 },  /* boxes */
	{ 0, 0, 0, 0 },
	{ 0, 0, 0, 0 },

	0,	/* flags */

	&my_read_event,    /* callback API */
	&my_draw_box,
	&my_draw_text,
	&my_draw_bar,
	&my_flush,
	&my_make_sound
};


int main(int argc, char **argv)
{
	FILE *fp;

	int err;

	const char *filename = "confmgrdemo.gic";
	gic_handle_t handle;

	
	/* handle args */

	if (argc > 1) {
		filename = argv[1];
	}
	
	/* initialize */

	if (gicInit() < 0) {
		ggiPanic("Couldn't init GIC\n");
	}
	handle=gicOpen(NULL);
	my_info.handle=handle;

	if (ggiInit() < 0) {
		ggiPanic("Couldn't init GGI\n");
	}


	/* read in config file */

	fp = fopen(filename, "r");

	if (fp == NULL) {
		ggiPanic("Couldn't open config file.\n");
	}
	
	my_info.head = gicHeadRead(handle, fp);
	fclose(fp);
	
	if (my_info.head == NULL) {
		ggiPanic("Error reading config file.\n");
	}
	

	/* now open a LibGGI visual */

	vis = ggiOpen(NULL);
	
	ggiSetFlags(vis, GGIFLAG_ASYNC);

	ggiParseMode("", &mode);

	if (ggiSetMode(vis, &mode) != 0) {
		ggiPanic("Unable to set mode.\n");
	}
	
	ggiSetColorfulPalette(vis);

	setup_colors();

	my_info.screen_size.x = mode.virt.x;
	my_info.screen_size.y = mode.virt.y;
	
	ggiGetCharSize(vis, &my_info.small_size.x,
	                    &my_info.small_size.y);

	my_info.big_size    = my_info.small_size;
	my_info.item_gap    = my_info.small_size;
	my_info.binding_gap = my_info.small_size;


	/* Invoke the config manager */
	
	err = gicConfigManager(&my_info);

	if (err) {
		fprintf(stderr, "ERROR (%d) from config manager.\n", err);
	}


	/* clean up */

	ggiClose(vis);

	ggiExit();
	gicClose(handle);
	gicExit();

	return 0;
}
