#include MUT_H
#include MPH_H
#include "mbk_extern.h"
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>

#include "g_visu.h"
#include "v_view.h"
#include "v_menu.h"
#include "v_extern.h"
#include "v_drv.h"
#include "e_edit.h"
#include "e_menu.h"
#include "g_global.c"
#include "m_mes_id.h"
#include "v_icon.h"
#ident "@(#)GenView is very beautifull, ain't it ?"

static void getparam();
static void connection();
static void usage();
static void about();

/* Now getting to the point...  */
int
	main(argc, argv)
int argc;
char **argv;
{
char hello[50];            /* filename */
XSizeHints hv, he, htrace; /* good for winman when not overstuffed */
XWMHints wmh;              /* for iconifing purposes */
int i;
extern jmp_buf sjbuf;      /* when a problem arise...  */
Pixmap gIcon;
static int args_not_ok;    /* just once, for parameters, not for signals trap */
char *layout = NULL;       /* loading a layout */
char *c_file = NULL;       /* loading a C source file */
int pid = getpid();
char fargs[6][20];
XSetWindowAttributes window_stuff;
extern char *D_compilerPath;
extern char *E_fontname;
	
	mbkenv();           /* prepare mbk globals */
	if ((D_compilerPath = getenv("GENVIEW_GCC_PATH")) == NULL)
		D_compilerPath = GCC_PATH;

	hv.min_width = 410;
	hv.min_height = YMENU + 10;
	he.min_width = 440;
	he.min_height = 64;
	htrace.min_width = 440;
	htrace.min_height = 48;
	hv.flags = he.flags = htrace.flags = PPosition | PSize | PMinSize;
	getparam(argc, argv, &hv, &he, &htrace, &layout, &c_file, &E_fontname);
	alliancebanner("GenVieW", GENVIEW,
						"procedural Generator VieWer", "90-93", ALC);
	V_getColors(); 				/* now choosing and allocating colors */

	strcpy(hello, "View "); 	/* Creating what's necessary for watching */
	V_window = XCreateSimpleWindow(display, DefaultRootWindow(display),
			hv.x, hv.y, hv.width, hv.height, 5,
			V_colors[COLOR_FGND], V_colors[COLOR_BGND]);
	/* auto backup in case of overlap
	window_stuff.save_under = True;
	XChangeWindowAttributes(display, V_window, CWSaveUnder, &window_stuff); */

	V_PixSave = XCreatePixmap(display, V_window,
						hv.width, hv.height, V_depth);

	gIcon =  XCreateBitmapFromData(display, V_window, pvb, 32, 32);

	XSetStandardProperties(display, V_window, hello,
										"Watch it", gIcon, NULL, 0, &hv);
	wmh.initial_state = NormalState;
	wmh.flags = StateHint;
	XSetWMHints(display, V_window, &wmh);
	V_xWin = hv.x;
	V_yWin = hv.y + YMENU;
	dxWin = hv.width;
	dyWin = hv.height - YMENU;

	XSelectInput(display, V_window, ButtonReleaseMask | ButtonPressMask
			| KeyPressMask | ExposureMask | Button1MotionMask | LeaveWindowMask
			| PointerMotionMask | StructureNotifyMask | VisibilityChangeMask);

	V_getFonts();
	V_setGc();
	C_InitGc();
	C_getDiskInfo(); /* default configuration values for setup window */

	/* clearing the pixmap used for screen saving purposes */
	XSetForeground(display, V_gcCao[GC_FGND], V_colors[COLOR_BGND]);
	XFillRectangle(display, V_PixSave, V_gcCao[GC_FGND],
						0, 0, hv.width, hv.height);
	XSetForeground(display, V_gcCao[GC_FGND], V_colors[COLOR_FGND]);
	/* end of watching initialisation */

	/* Creating what's necessary for edit */
	E_Set_Font_Edit();
	strcpy(hello, "Edit ");
	E_window = XCreateSimpleWindow(display, DefaultRootWindow(display),
												he.x, he.y, he.width, he.height, 5,
												V_colors[COLOR_TEXT], 
												V_colors[COLOR_M_BGND]);

	XSetStandardProperties(display, E_window, hello, "Edit", gIcon, 
									NULL, 0, &he);
	wmh.initial_state = NormalState;
	wmh.flags = StateHint;
	XSetWMHints(display, E_window, &wmh);

	XSelectInput(display, E_window, ButtonReleaseMask | ButtonPressMask
			| StructureNotifyMask | KeyPressMask | KeyReleaseMask | ExposureMask);
	E_Init_Edit();
	E_maxligne =(he.height) / E_interligne;

	E_setMenu();

	/* end of edit initialisation */
	/* Creating what's necessary for trace */

	strcpy(hello, "Trace ");
	T_window = XCreateSimpleWindow(display, DefaultRootWindow(display),
			htrace.x, htrace.y, htrace.width, htrace.height, 5,
			V_colors[COLOR_TEXT], V_colors[COLOR_M_BGND]);

	XSetStandardProperties(display, T_window, hello, "Trace", gIcon, 
									NULL, 0, &htrace);
	wmh.initial_state = NormalState;
	wmh.flags = StateHint;
	XSetWMHints(display, T_window, &wmh);
	XSelectInput(display, T_window, ButtonReleaseMask | ButtonPressMask
			| KeyPressMask | ExposureMask);
	T_std(); /* opens standard streams for me */
	T_setMenu();
	/*	end of trace initialisation */

#ifdef PWET
	/* here begins the fork for ctrl-c catching :
	   fork genview, exec the process, and keep on going smoothly.
	   Launch the process now! */
	if ((i = fork()) == -1) {
		(void)fprintf(stderr, "Genview : can't fork\nExiting ...\n");
		exit(1);
	} else if (i == 0) { /* we're in the child, so let's run ctrlc */
		sprintf(fargs[0], "%s", "sigint");
		sprintf(fargs[1], "%s", DisplayString(display));
		sprintf(fargs[2], "%d", V_window);
		sprintf(fargs[3], "%d", E_window);
		sprintf(fargs[4], "%d", T_window);
		sprintf(fargs[5], "%d", pid);
		execlp("watchdog",
					fargs[0], fargs[1], fargs[2], fargs[3],
					fargs[4], fargs[5], (char *)0);
	} /* in the parent process :
	     Do not wait((char *)NULL); as we want watchdog to run in background */
#endif

	I_window = C_window = M_window = 0;
	V_createCursor(); /*	declaring the home made cursors */
	/*	mapping and raising the windows */
	XMapRaised(display, V_window);
	XRaiseWindow(display, V_window);
	XMapRaised(display, E_window);
	XRaiseWindow(display, E_window);
	XMapRaised(display, T_window);
	XRaiseWindow(display, T_window);
	M_id = M_GENVIEW;
	M_open();
	XMapRaised(display, M_window);
	XRaiseWindow(display, M_window);
	for (i = 0; i <= DEFAULT_LAYER; i++) /* xcache init */
		visu_db[i] = NULL;

	if (!xvisufig) {
		xscreen = yscreen = 0;
		dxscreen = dxWin;
		dyscreen = dyWin;
		scale = 1;
		zoomTrack.x = xscreen;
		zoomTrack.y = yscreen;
		zoomTrack.dx = dxscreen;
		zoomTrack.dy = dyscreen;
		zoomTrack.scale = scale;
	}


	unix_trap();   /* avoid exiting when mbk terminates */
	setjmp(sjbuf); /* come back here on failure */

	if (!args_not_ok) {
		args_not_ok = 1;
		if (c_file != NULL)
			E_load(c_file);

		if (layout != NULL) {
			if (M_isOnDisk(layout)) {
			extern char run_mode;
				run_mode = RUN;
				load_fig(layout);
				if (xvisufig) {
					fit();
					run_mode = STEP;
					update_AB();
				}
			} 
		}
	}

	while (1) { /* infinite event loop */
		XNextEvent(display, &V_event);
		allEvent();
	}
}

int
	allEvent()
{
static unsigned char answer; /* answer from event requested window */

	if (V_event.xany.window == V_window) {
		if (M_window && M_id != M_MAP && V_event.type != Expose)
			return;
		answer = V_view_event();
		XFlush(display);
		if (answer == OPEN_WINDOW_SETUP)
			if (!C_window)
				C_open();
			else
				XRaiseWindow(display, C_window);
		else if (answer == OPEN_WINDOW_INSPECT) {
			if (!I_window)
				 I_open();
			else {
				 I_out(1);
				 i_free();
				 XDestroyWindow(display, I_window);
				 I_window = 0;
				 I_open();
			 }
		} else if (answer == OPEN_WINDOW_MESSAGE) {
			if (!M_window)
				M_open();
			else {
				XDestroyWindow(display, M_window);
				M_window = 0;
				M_open();
			}
		}
	} else if (V_event.xany.window == I_window) {
		if (M_window && M_id != M_MAP && V_event.type != Expose)
			return;
		answer = I_event();
		XFlush(display);
		if (answer == CLOSE_WINDOW) {
			I_window = 0;
			answer = 0;
		}
	} else if (V_event.xany.window == C_window) {
		if (M_window && M_id != M_MAP && V_event.type != Expose)
			return;
		answer = C_event();
		XFlush(display);
		if ((answer & WINDOW_MASK) == CLOSE_WINDOW) {
			XFlush(display); /* avoid two redraws */
			C_window = 0;
			if ((answer & REFRESH_MASK) == REFRESH_ALL) {
				while (XCheckTypedWindowEvent(display, V_window, Expose, &V_event));
				V_refresh();
			}
			answer = 0;
		}
	} else if (V_event.xany.window == M_window) {
		answer = M_event();
		XFlush(display);
		if (answer == CLOSE_WINDOW) {
			M_window = 0;
			answer = 0;
		} else if (answer == CLOSE_GENVIEW) {
			unlink("var.tmp.dat");
			XFreePixmap(display, V_PixSave);
			XFreeColormap(display, V_cmap);
			XDestroyWindow(display, V_window);
			XDestroyWindow(display, T_window);
			XDestroyWindow(display, E_window);
			XDestroyWindow(display, M_window);
			XCloseDisplay(display);
			exit(0);
		} 
	} else if (V_event.xany.window == E_window) {
		if (M_window && M_id != M_MAP && V_event.type != Expose)
			return;
		answer = E_event();
		XFlush(display);
		if (answer == OPEN_WINDOW_MESSAGE) {
			if (!M_window)
				M_open();
			else {
				XDestroyWindow(display, M_window);
				M_window = 0;
				M_open();
			}
		}
	} else if (V_event.xany.window == T_window) {
		if (M_window && M_id != M_MAP && V_event.type != Expose)
			return;
		T_event();
	}
}

static void
	getparam(argc, argv, shv, she, sht, layout, source, fontname)
int argc;
char **argv;
XSizeHints *shv, *she, *sht;
char **layout, **source, **fontname;
{
int i;
char *dn = NULL, *ge = NULL, *gt = NULL, *gv = NULL, *ft = NULL;

	for (i = 1; i < argc; i++) {
	char *arg = argv[i];
		if (*arg == '-') {
			switch (*++arg) {
				case 'a':
					about();
					continue;
				case 's':
					if (++i >= argc) 
						usage(argv[0]);
					*source = argv[i];
					continue;
				case 'd':
					if (++i >= argc) 
						usage(argv[0]);
					dn = argv[i];
					continue;
				case 'l':
					if (++i >= argc) 
						usage(argv[0]);
					*layout = argv[i];
					continue;
				case 'f':
					if (++i >= argc) 
						usage(argv[0]);
					*fontname = ft = argv[i];
					continue;
				case 'g':
					if (++i >= argc) 
						usage(argv[0]);
					*++arg;
					if (*arg == 'e')
						ge = argv[i];
					else if (*arg == 't')
						gt = argv[i];
					else if (*arg == 'v')
						gv = argv[i];
					else
						usage(argv[0]);
					continue;
				default:
					usage(argv[0]);
			}
		} else
			usage(argv[0]);
	}
	connection(dn, argv[0]); /* connect with appropriate server */
	shv->x =(V_width - 1) / 2 + 2;
	shv->y = 2;
	shv->width = V_width / 2 - 10;
	shv->height = V_height - 39;
	she->x = 2;
	she->y = 2;
	she->width =(V_width - 1) / 2 - 10;
	she->height = 3 *((V_height - 1) / 4) - 33;
	sht->x = 2;
	sht->y = 3 *((V_height - 1) / 4);
	sht->width =(V_width - 1) / 2 - 10;
	sht->height =(V_height - 1) / 4 - 33;
	if (!ft)
		if ((ft = XGetDefault(display, argv[0], "font")) != NULL)
			*fontname = ft;
		else
			*fontname = "7x13";
	if (!gv) {
		if ((gv = XGetDefault(display, argv[0], "gv")) != NULL) 
			XParseGeometry(gv,&(shv->x),&(shv->y),&(shv->width),&(shv->height));
	} else
		XParseGeometry(gv,&(shv->x),&(shv->y),&(shv->width),&(shv->height));

	if (!ge) {
		if ((ge = XGetDefault(display, argv[0], "ge")) != NULL)
			XParseGeometry(ge,&(she->x),&(she->y),&(she->width),&(she->height));
	} else
		XParseGeometry(ge,&(she->x),&(she->y),&(she->width),&(she->height));

	if (!gt) {
		if ((gt = XGetDefault(display, argv[0], "gt")) != NULL)
			XParseGeometry(gt,&(sht->x),&(sht->y),&(sht->width),&(sht->height));
	} else
		XParseGeometry(gt,&(sht->x),&(sht->y),&(sht->width),&(sht->height));

	if (shv->width < shv->min_width)
		shv->width = shv->min_width;
	if (she->width < she->min_width)
		she->width = she->min_width;
	if (sht->width < sht->min_width)
		sht->width = sht->min_width;
}

static void
	connection(displayName, progName)
char *displayName, *progName;
{
	if (!(display = XOpenDisplay(displayName))) {
		fprintf(stderr, "%s: unable to connect with server '%s'\n", progName,
					XDisplayName(NULL));
		exit(-1);
	}
	V_screen = DefaultScreen(display);
	V_depth = DefaultDepth(display, V_screen);
	V_width = DisplayWidth(display, V_screen);
	V_height = DisplayHeight(display, V_screen);
	V_vis = DefaultVisual(display, V_screen);
	V_class = V_vis->class;
	V_cmap = DefaultColormap(display, V_screen); /* create colormap */
}

static void
	usage(progName)
char *progName;
{
	fprintf(stderr, "usage : %s [-s source] [-l layout] [-ge <height>x<width>[{+}x{+}y]]",
							progName);
	fprintf(stderr, " [-gv <height>x<width>[{+}x{+}y]]");
	fprintf(stderr, " [-gt <height>x<width>[{+}x{+}y]]");
	fprintf(stderr, " [-fn fixed-width-fonts-for-editing]\n");
	exit(-1);
}

static void
	about()
{
	fprintf(stdout, "Hello, world\n");
}
