/* xtmines: game where you try to cross a minefield */
/* Written by Timothy Tsai  April 13, 1992 */

#include "xtmines.h"

/* handle_event: given an event, it will perform some action based on what */
/*               the event is and where is occurred;  the function is just */
/*               one big switch statement;  thus, this is the main         */
/*               contolling loop                                           */
void handle_event(eventptr)
XEvent *eventptr;
{
	/* To avoid having to use eventptr, copy contents of *evenptr */
	/*    to event */
	XEvent			event=*eventptr;

	/* Both of the following are filled in once the event.type */
	/*    has been determined */
	XButtonPressedEvent	*eventbp;
	XKeyPressedEvent	*eventkp;

	/* Used by XLookupString;  this is used to check for control, */
	/*    shifted, or other special keys */
	KeySym			ksym;

	/* Used by XLookupString;  this is used to check for actual */
	/*    keyboard commands not picked up by KeySym */
	char			s;
	char			str[MAXSTRLEN];

	/* Both vx and vy are passed to setvxvy() to determine the virtual */
	/*   position of the event */
	int			vx,vy;

      	switch(event.type) {

	   case GraphicsExpose:
	   case NoExpose:
		break;
	   case Expose:
		refresh(); break;

	/*---Check for button events first-----------------------------*/

	   case ButtonPress:
		eventbp = (XButtonPressedEvent *) &event;	

		/* quit, but add and show scores first */
		if (eventbp->window==wind[quit_wind])
			show_and_add_scores();

		/* toggle pause status */
		else if (eventbp->window==wind[pause_wind])
			do_pause();

		/* toggle show status; showfig to showman, or vice versa */
		/* also update show_wind and man bitmap or fig */
		else if (eventbp->window==wind[show_wind]) {
		   show = (show==sh_man) ? sh_fig : sh_man;
		   if (show==sh_fig)
			used_showfig = TRUE;
		   if (used_showfig)
			sprintf(str,"Show = *%s",
				(show==sh_man) ? "man" : "fig");
		   else
			sprintf(str,"Show = %s",
				(show==sh_man) ? "man" : "fig");
		   WindPrint(show_wind,str);
		   draw(bm_man,manvx,manvy);
		}

		/* throw grenade */
		else if (eventbp->window==wind[tgrenade_wind])
			throw_grenade();

		/* surrender */
		else if (eventbp->window==wind[giveup_wind]) {
		   show_all_bombs();
		   dead = TRUE;
		}

		/* toggle automark;  also update automark_wind   */
		/*    therefore, also turn off extended_automark */
		else if (eventbp->window==wind[automark_wind]) {
		   automark = (automark ? FALSE : TRUE);
		   sprintf(str,"Automark = %s",automark ? "on" : "off");
		   WindPrint(automark_wind,str);
		   if (!automark) {
			extended_automark = FALSE;
			WindPrint(eautomark_wind,"ExtAmark = off");
		   }
		   if (automark && (bomb_status(manvx,manvy)==0))
			mark_allaround_ok(manvx,manvy,0);
		}

		/* toggle sanity check;  also update sanitycheck_wind */
		else if (eventbp->window==wind[sanitycheck_wind]) {
		   sanity = (sanity ? FALSE : TRUE);
		   if (sanity)
			used_sanity = TRUE;
		   if (used_sanity)
		   	sprintf(str,"Sanity = *%s",sanity ? "on" : "off");
		   else
		   	sprintf(str,"Sanity = %s",sanity ? "on" : "off");
		   WindPrint(sanitycheck_wind,str);
		   if (sanity)
			do_sanity_check(manvx,manvy);
		}

		/* toggle extended automark;  also update eautomark_wind */
		else if (eventbp->window==wind[eautomark_wind]) {
		   /* automark must be on for extended_automark to be on */
		   if (!automark) {
			print_status("Must turn automark on first!");
			XBell(disp,0);
		   }
		   else if (level < MIN_EXTENDED_MARK_LEVEL) {
			sprintf(str,
				"Minimum level for extended_automark is %s",
				num_rank_to_words(MIN_EXTENDED_MARK_LEVEL));
			WindPrint(status,str);
			XBell(disp,0);
		   }
		   else {
			extended_automark = (extended_automark ? FALSE : TRUE);
			if (extended_automark)
				used_eautomark = TRUE;
			if (used_eautomark)
			   sprintf(str,"ExtAmark = *%s",
				extended_automark ? "on" : "off");
			else
			   sprintf(str,"ExtAmark = %s",
				extended_automark ? "on" : "off");
			WindPrint(eautomark_wind,str);
			if (extended_automark && (bomb_status(manvx,manvy)==0))
				mark_allaround_ok(manvx,manvy,0);
		   }
		}

		/* do refresh */
		else if (eventbp->window==wind[refresh_wind])
   			refresh();

		/* otherwise, it must be a move or mark */
		/*    BUTTON1 (left)   : move man */
		/*    BUTTON2 (middle) : mark unsafe (as bomb */
		/*    BUTTON3 (right)  : mark safe */
		/* If a mark is desired, and the square is already marked */
		/*    as the desired mark, then the square will be unmarked */
		else if (eventbp->window==field)
		   if (setvxvy(eventbp->x,eventbp->y,&vx,&vy)!=OUT_OF_RANGE) {
		   switch (eventbp->button) {
			case BUTTON1 :	move_man(vx,vy);
					break;
			case BUTTON2 :	if (FIELD[vx][vy].m == fm_bomb)
					     remove_mark(vx,vy);
					else
					     mark_bomb(vx,vy);
					break;
			case BUTTON3 :	if (FIELD[vx][vy].m == fm_safe)
					     remove_mark(vx,vy);
					else
					     mark_ok(vx,vy);
					break;
			default      :	fprintf(stderr,
						"Error: Illegal button\n");
					exit(3);
		   } /* switch */
		   if (sanity)
			do_sanity_check(manvx,manvy);
		   }
		break;

	/*---Now check for keyboard events-----------------------------*/

	   case KeyPress:
		eventkp = (XKeyPressedEvent *) &event;
   		XLookupString(&event,&s,1,&ksym,NULL);
   		switch (ksym) {
		/* Ignore the following;  otherwise, control-l is */
		/*    interpreted as two keystrokes */
		   case XK_Control_L:
		   case XK_Shift_L:
		   case XK_Shift_R:
		   case XK_Caps_Lock:
		   case XK_Meta_L:
		   case XK_Meta_R:
		   case XK_Alt_L:
		   case XK_Alt_R:
			break;
   		   default:
   			switch (s) {
   			   case '':			/* refresh */
   				refresh(); break;
			   case 'p':
			   case 'P':
				do_pause();
				break;
			   case 'q':
			   case 'Q':			/* quit */
				show_and_add_scores();
			   case ' ':			/* mark allaround */
				mark_allaround_ok(manvx,manvy,-1);
				if (sanity)
					do_sanity_check(manvx,manvy);
				break;
			   default:
				print_status("Illegal keyboard input");
				XBell(disp,0); break;
			} /* switch (s) */
			break;
		} /* switch (ksym) */
		break;
	   default:
		fprintf(stderr,"Error: Illegal event\n");
		exit(4);
	} /* switch (event.type) */
}
