#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include "g_visu.h"
#include "v_view.h"
#include "c_menu.h"
#include "v_extern.h"

extern GC V_gcBox;

#define s_width 16
#define s_height 16

static Pixmap pattern[GC_FGND + 1];

static char pattern_bits[GC_FGND + 1][0x20] = {
	{ /* bulk */
   	0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
	{ /* bulk */
   	0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
	{ /* dif */
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb,
   	0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee,
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee},
	{ /* dif */
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb,
   	0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee,
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee},
	{ /* dif */
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb,
   	0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee,
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee},
	{ /* dif */
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb,
   	0xdd, 0xdd, 0xee, 0xee, 0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee,
   	0x77, 0x77, 0xbb, 0xbb, 0xdd, 0xdd, 0xee, 0xee},
	{ /* gate */
   	0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
   	0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
   	0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55},
	{ /* poly */
   	0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
		0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
		0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa},
	{ /* poly */
   	0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
		0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
		0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa},
	{ /* alu1 */
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44,
   	0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11,
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11},
	{ /* alu1 */
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44,
   	0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11,
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11},
	{ /* contats */
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff},
	{ /* contats */
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff},
	{ /* contats */
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff},
	{ /* contats */
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff},
	{ /* contats */
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff},
	{ /* alu2 */
   	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
   	0x44, 0x44, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
   	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00},
	{ /* alu2 */
   	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
   	0x44, 0x44, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
   	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00},
	{ /* contats */
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff},
	{ /* alu3 */
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44,
   	0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11,
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11},
	{ /* alu3 */
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44,
   	0x22, 0x22, 0x11, 0x11, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11,
   	0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11},
	{ /* contats */
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff,
   	0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff},
	{ /* reference, filled */
   	0xaa, 0xaa, 0x11, 0x11, 0xaa, 0xaa, 0x44, 0x44, 0xaa, 0xaa, 0x11, 0x11,
   	0xaa, 0xaa, 0x44, 0x44, 0xaa, 0xaa, 0x11, 0x11, 0xaa, 0xaa, 0x44, 0x44,
   	0xaa, 0xaa, 0x11, 0x11, 0xaa, 0xaa, 0x44, 0x44},
	{ /* instance, filled */
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
	{ /* default, filled */
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
	{ /* foreground, filled */
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
};

static Cursor sleep, arrow;
static char wait[] = {0x00, 0x00, 0x80, 0x03, 0xdf, 0xf7, 0x0f, 0xc1, 0xe7, 
								0xa7, 0x3b, 0x98, 0x19, 0x11, 0x0c, 0x21, 0x0c, 0x21, 
								0x0c, 0x21, 0x0c, 0x22, 0x0c, 0x24, 0x18, 0x10, 0x30, 
								0x08, 0xf0, 0x1f, 0xf8, 0x3f};

void V_createCursor()
{
/*
Pixmap pw;

	pw = XCreatePixmapFromBitmapData(display, V_window, wait, 16,16,
											V_colors[COLOR_FGND], V_colors[COLOR_BGND],1);
	sleep = XCreatePixmapCursor(display, pw, pw, V_colors[COLOR_FGND],
											V_colors[COLOR_BGND], 1,1);
*/
	sleep = XCreateFontCursor(display, XC_watch);
	arrow = XCreateFontCursor(display, XC_left_ptr);
	XDefineCursor(display, V_window, arrow);
	XDefineCursor(display, T_window, arrow);
	XDefineCursor(display, E_window, arrow);
}

void M_createCursor()
{
	XDefineCursor(display, M_window, arrow);
}

void M_changeCursor(i)
int i; 
{
	if (i)
		XDefineCursor(display, M_window, arrow);
	else
		XDefineCursor(display, M_window, sleep);
}

void V_changeCursor(i)
int i; 
{
	
	if (i) {
		XDefineCursor(display, V_window, arrow);
		XDefineCursor(display, T_window, arrow);
		XDefineCursor(display, E_window, arrow);
	} else {
		XDefineCursor(display, V_window, sleep);
		XDefineCursor(display, T_window, sleep);
		XDefineCursor(display, E_window, sleep);
	}
}
	
void V_getColors()
{
XColor def, forget_it;
register int i;

	XFreeColormap (display, V_cmap);

	for (i = 0; i < CMAPSIZE; i++) {
		if (!XAllocNamedColor(display,V_cmap,V_colorName[i],&def,&forget_it)) {
		 fprintf (stderr, "colorname '%s' is not in X11 database.\n\
							 Exiting in getColors.\n",
		 V_colorName[i]);
			exit (-1);
		}
		V_colors[i] = def.pixel;
	}
}

static void useStipple(stip, map, s_w, s_h)
Pixmap *stip;
unsigned int s_w, s_h;
char *map;
{
	if ((*stip = XCreateBitmapFromData(display, V_window, map, s_w, s_h)) == NULL) {
		(void)fprintf(stderr, "cannot allocate stipple. Not enough core.\n\
					Exiting in useStipple.\n");
		exit(-1);
	}
}

void V_setGc()
{
XGCValues vGC;
register int i;

	/* the loop is strongly dependant of the #define in .h file, take care */
	for (i = GC_BLKN; i <= GC_FGND; i++) {
		useStipple (&pattern[i], pattern_bits[i], s_width, s_height);
		vGC.stipple = pattern[i];
		vGC.fill_style = FillStippled;
		vGC.foreground = V_colors[i];
		vGC.background = V_colors[COLOR_BGND];
		vGC.plane_mask = AllPlanes;
		vGC.font = V_menuFont;
		V_gcCao[i] = XCreateGC (display, V_window,
			(GCStipple | GCForeground | GCBackground | GCFillStyle | GCPlaneMask),
			&vGC);
	}

	/* used to draw in, peek strechable box */
	vGC.fill_style = FillSolid;
	vGC.foreground = 1;
	vGC.background = 1;
	vGC.plane_mask = 0x0F;
	V_gcBox = XCreateGC (display, V_window,
			(GCForeground | GCBackground | GCFillStyle | GCPlaneMask),
			&vGC);
	XSetFunction (display, V_gcBox, GXxor);
}

void V_getFonts ()
{
register int i;

	for (i = 0; i <= 5; i++)
		if ((V_vr[i] = XLoadFont (display, V_fontName[i])) == 0) {
			fprintf (stderr, "font %s not available from X11 database.\n\
							Exiting in getFonts!\n", V_fontName[i]);
			exit (-1);
		}
	if ((V_menuFont = XLoadFont (display, "6x10")) == 0) {
			fprintf (stderr, "font 6x10 not available from X11 database.\n\
						Exiting in getFonts!\n");
			exit (-1);
	}
}

void C_InitGc ()
{
register int i;
XGCValues vGC;
extern GC C_gcV1, C_gcV2;
extern GC C_ObjectGc[];

	C_gcBgnd = XCreateGC (display, V_window, 0, 0);
	XSetBackground (display, C_gcBgnd, V_colors[COLOR_M_BGND]);
	XSetForeground (display, C_gcBgnd, V_colors[COLOR_M_BGND]);
	XSetFont (display, C_gcBgnd, V_menuFont);

	C_gcIconInv = XCreateGC (display, V_window, 0, 0);
	XSetBackground (display, C_gcIconInv, V_colors[COLOR_ICON_INV]);
	XSetForeground (display, C_gcIconInv, V_colors[COLOR_ICON_INV]);
	XSetFont (display, C_gcIconInv, V_menuFont);

	C_gcIcon = XCreateGC (display, V_window, 0, 0);
	XSetBackground (display, C_gcIcon, V_colors[COLOR_ICON]);
	XSetForeground (display, C_gcIcon, V_colors[COLOR_ICON]);
	XSetFont (display, C_gcIcon, V_menuFont);

	C_gcIconTextInv = XCreateGC (display, V_window, 0, 0);
	XSetBackground (display, C_gcIconTextInv, V_colors[COLOR_ICON_INV]);
	XSetForeground (display, C_gcIconTextInv, V_colors[COLOR_ICON_TEXT_INV]);
	XSetFont (display, C_gcIconTextInv, V_menuFont);

	C_gcIconText = XCreateGC (display, V_window, 0, 0);
	XSetBackground (display, C_gcIconText, V_colors[COLOR_ICON]);
	XSetForeground (display, C_gcIconText, V_colors[COLOR_ICON_TEXT]);
	XSetFont (display, C_gcIconText, V_menuFont);

	C_gcText = XCreateGC (display, V_window, 0, 0);
	XSetBackground (display, C_gcText, V_colors[COLOR_M_BGND]);
	XSetForeground (display, C_gcText, V_colors[COLOR_TEXT]);
	XSetFont (display, C_gcText, V_menuFont);

	C_gcTextPop = XCreateGC (display, V_window, 0, 0);
	XSetBackground (display, C_gcTextPop, V_colors[COLOR_BGND]);
	XSetForeground (display, C_gcTextPop, V_colors[COLOR_ICON_TEXT]);
	XSetFont (display, C_gcTextPop, V_menuFont);

	C_gcV1 = XCreateGC (display, V_window, 0, 0);
	XSetForeground (display, C_gcV1, V_colors[COLOR_BUTTON1]);

	C_gcV2 = XCreateGC (display, V_window, 0, 0);
	XSetForeground(display, C_gcV2, V_colors[COLOR_BUTTON2]);

	/* Creation d'autant de GraphicsContext que d'objets a afficher */
	/* obtention d'un simili inverse video */

	for (i = 0; i <= C_NB_OBJECT; i++) {
		vGC.foreground = V_colors[COLOR_BGND];
		vGC.background = i <= GC_REF ? V_colors[i] : V_colors[COLOR_FGND];
		vGC.font = V_menuFont;
		C_ObjectGc[i] = XCreateGC (display, V_window,
			(GCForeground | GCBackground | GCFont), &vGC);
	}
}
