/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <fredde at shapeshifter dot se> wrote this file. As long as you retain this 
 * notice you can do whatever you want with this stuff. If we meet some day, 
 * and you think this stuff is worth it, you can buy me a beer in return. 
 * Fredrik Lindberg
 * ----------------------------------------------------------------------------
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

#include <time.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "xwlans.h"

u_char flg_run = 1;

int
main(int argc, char *argv[])
{
	int i, geo_mask = NoValue, opt_fork = 1;
	char *iface = 0;

	struct xw_t xw;
	struct opt_t *opts; 
	pid_t pid;

	xw.opt_shadow = 0;

	opts = _malloc(sizeof(struct opt_t));
	memset(opts, 0, sizeof(struct opt_t));

	for (i = 1; i < argc; i++)
	{
		if (strcmp(argv[i], "-h") == 0) {
			usage(argv[0]);
			exit(EXIT_SUCCESS);
		}
		else if (strcmp(argv[i], "-i") == 0) {
			iface = argv[++i];
		}
		else if (strcmp(argv[i], "-g") == 0) {
			geo_mask = XParseGeometry(argv[++i], &opts->x, &opts->y, &opts->width, &opts->height); 
		}
		else if (strcmp(argv[i], "-f") == 0) {
			opts->fname = argv[++i];
		}
		else if (strcmp(argv[i], "-ct") == 0) {
			opts->tcolor = argv[++i];
		}
		else if (strcmp(argv[i], "-cb") == 0) {
			opts->bcolor = argv[++i];
		}
		else if (strcmp(argv[i], "-cs") == 0) {
			xw.opt_shadow = 1;
			opts->scolor = argv[++i];
		}
		else if (strcmp(argv[i], "-nf") == 0) {
			opt_fork = 0;	
		}
		else if (strcmp(argv[i], "-display") == 0) {
			opts->dispn = argv[++i];
		}
		else if (strcmp(argv[i], "-b") == 0) {
			opts->bmax = argv[++i];	
		}
		else if (strcmp(argv[i], "-n") == 0) {
			opts->interval = argv[++i];
		}
		else if (strcmp(argv[i], "-d") == 0) {
			opts->dynamic = 1;
		}
		else if (strcmp(argv[i], "-m") == 0) {
			opts->measure = argv[++i];
		}
		else
		{
			fprintf(stderr, "Unknown option: %s\n", argv[i]);
			exit(EXIT_FAILURE);
		}
	} 

	/* no use to continue without an interface */
	if (iface == 0) {
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}


	xw.display = (opts->dispn != 0) ? opts->dispn : NULL; 
	if (init_win(&xw) != 0)
		exit(EXIT_FAILURE);

	xw.x = (geo_mask & XValue) ? opts->x : DEF_X;
	xw.y = (geo_mask & YValue) ? opts->y : DEF_Y;

	xw.x += (geo_mask & XNegative) ? DisplayWidth(xw.disp, xw.screen) : 0; 
	xw.y += (geo_mask & YNegative) ? DisplayHeight(xw.disp, xw.screen) : 0;

	xw.width = (geo_mask & WidthValue) ? opts->width : DEF_WIDTH;
	xw.height = (geo_mask & HeightValue) ? opts->height : DEF_HEIGHT;

	xw.font = XLoadFont(xw.disp, (opts->fname != 0) ? opts->fname : DEF_FONT);	
	XSetFont(xw.disp, xw.winGC, xw.font);
	xw.xfs = XQueryFont(xw.disp, xw.font);
	xw.f_height = xw.xfs->max_bounds.ascent + xw.xfs->max_bounds.descent;

	xw.c_text = get_color(&xw, (opts->tcolor != 0) ? opts->tcolor : DEF_TC);
	xw.c_bar = get_color(&xw, (opts->bcolor != 0) ? opts->bcolor : DEF_BC);
	xw.c_shadow = get_color(&xw, (opts->scolor != 0) ? opts->scolor : DEF_SC);

	xw.bmax = (opts->bmax != 0) ? atoi(opts->bmax) : DEF_BMAX;
	xw.interval = (opts->interval != 0) ? atoi(opts->interval) : DEF_INTERVAL;

	xw.opt_dyn = (opts->dynamic != 0) ? 1 : 0;

	if (opts->measure != 0) {
		xw.opt_measure = atoi(opts->measure);
		xw.opt_measure = ((xw.opt_measure >= 0) && (xw.opt_measure <= 1)) ? 
			xw.opt_measure : DEF_MEASURE;
	}
	else {
		xw.opt_measure = DEF_MEASURE;
	}

	free(opts);

	if (opt_fork == 1)
	{
		pid = fork();

		if (pid > 0) 
			exit(EXIT_SUCCESS);
		else if (pid == -1)
			fprintf(stderr, "Unable to fork into background: %s\n", strerror(errno));
	}

	signal(SIGHUP,  (void *)set_flg);
	signal(SIGINT,  (void *)set_flg);
	signal(SIGKILL, (void *)set_flg);
	signal(SIGTERM, (void *)set_flg);
	signal(SIGQUIT, (void *)set_flg);

	main_loop(&xw, iface);

	close_win(&xw);

	return 0;
}

void
main_loop(struct xw_t *xw, char *iface)
{
	XEvent xev;
	int tmpval = 0, maxval = 0; 
	char flg_update = 1;
	time_t timeval = time(NULL);

	while(flg_run == 1)
	{
		if (flg_update == 1)
		{
			tmpval = get_strength(iface, xw->opt_measure);
			maxval = (tmpval > maxval) ? tmpval : maxval;

			if (xw->opt_dyn == 1)
				xw->bmax = maxval;

			flg_update = 0;
			timeval = time(NULL);
			clear_win(xw);
			redraw(xw, tmpval, maxval); 
			XSync(xw->disp, False);
		}
			
		while(XPending(xw->disp))
		{
			XNextEvent(xw->disp, &xev);
			if (xev.type == Expose)
			{
				/* Did the exposure happen inside our drawing area? */
				if (((xev.xexpose.x >= xw->x) && (xev.xexpose.x <= (xw->x + xw->width))) ||
					((xev.xexpose.y >= xw->y) && (xev.xexpose.y <= (xw->y + xw->height))))
				{
					redraw(xw, tmpval, maxval); 
					XSync(xw->disp, False);
				}
				/* The whole screen was exposed */
				else if ((xev.xexpose.x == 0) && (xev.xexpose.y == 0))
				{
					redraw(xw, tmpval, maxval); 
					XSync(xw->disp, False);
				}

			}
		}

		usleep(1000);

		if ((time(NULL) - timeval) >= xw->interval)
			flg_update = 1;
	}
}

void
set_flg()
{

	flg_run = 0;
}

void
usage(char *exec)
{

	printf("X WaveLan Strength monitor %s\n", VERSION);
	printf("Usage %s -i <interface> [options]\n", exec);
	printf("Options:\n");
	printf(" -display disp \t Displayname\n"); 
	printf(" -g geometry \t [<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>]\n");
	printf(" -f font \t Font name (default fixed)\n");
	printf(" -ct color \t Text color (default rgb:ff/ff/ff)\n"); 
	printf(" -cb color \t Bar color (default rgb:ff/ff/ff)\n");
	printf(" -cs color \t Shadow color\n");
	printf(" -b int \t Maximum measureable dBm value (default 110)\n");
	printf(" -d \t\t Dynamic maximum measureable dBm value (overrides -b)\n");
	printf(" -n seconds \t Update interval (default 3)\n");
	printf(" -m 0/1 \t What to measure, 0 = Quality, 1 = Signal (default Signal)\n");
	printf(" -nf \t\t Don't fork into background\n");
}



syntax highlighted by Code2HTML, v. 0.9.1