/*
**	conns.c
*/

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Form.h>
#include <X11/Dialog.h>
#include <X11/List.h>
#include <X11/Command.h>
#include <stdio.h>

Widget		global_connectives_shell;
static Widget	global_con_button;

Boolean		conns_up = False;

void con_action (button, client_data, call_data)

Widget		button;
caddr_t		client_data, call_data;

{
	global_con_button = button;
	XtSetSensitive (button, False);
	XtPopup (global_connectives_shell, XtGrabNone);
	conns_up = True;
}

static Widget	symbol_dialog, define_list, define_button,
		disp_list;
static Widget	define_dialog, con_list;
static char	define_string [256];
static char	*disp_string []	= 
			{"        ", 
			 NULL,};
       char	*con_string [] = 
		{"                                                         ",
	  	 "                                                         ",
		 "                                                         ",
		 "                                                         ",
		 "                                                         ",
		 "                                                         ",
	 	 NULL,};
#define	NO_OF_CONNS	6

void make_connectives (the_shell)

Widget		the_shell;

{
	int		i;
	Widget		the_form, close_button, con_label;
	extern Widget	define_button;
	static char	symbol_string [256];
	extern char	define_string [256];
	static char	*list_string [] = {"const", 
					   "unary", 
					   "binary", 
					   NULL,};
	extern void	symbol_action (), list_action (), define_action (),
			close_action (), disp_action (), make_switch (),
			make_dialog (), make_button (), make_list ();
	static XtCallbackRec
			symbol_calls [] =
				{{symbol_action, NULL},
				 {NULL, NULL},},
			list_calls []	=
				{{list_action, NULL},
				 {NULL, NULL},},
			define_calls []	=
				{{define_action, NULL},
				 {NULL, NULL},},
			close_calls []	=
				{{close_action, NULL},
				 {NULL, NULL},},
			disp_calls []	=
				{{disp_action, NULL},
				 {NULL, NULL},};
	static Arg	list_args [30], disp_args [30];

/*
**	Initialize symbol_string and define_string to empty
*/
	symbol_string [0] = '\0';
	define_string [0] = '\0';

	the_form = XtCreateManagedWidget ("con_form",
			formWidgetClass, the_shell, NULL, 0);
	make_dialog (the_form, &symbol_dialog, "symbol_dialog",
		"symbol:", symbol_string, True, 0,
		"accept", symbol_calls, NULL, NULL, NULL, NULL,
		NULL, 4, NULL, 4);
	make_switch (the_form, 
		&disp_list, "display_list", &(disp_string [0]), disp_calls, 
		True, symbol_dialog, 9, NULL, 34);
	make_dialog (the_form, &define_dialog, "define_dialog",
		"define connective:                  ", 
		define_string, True, 0,
		NULL, NULL, NULL, NULL, NULL, NULL,
		disp_list, 0, NULL, 4);
	XtSetSensitive (define_dialog, False);

	i = 0;
	XtSetArg (list_args [i], XtNcallback, (XtArgVal) list_calls);
	i++;
	XtSetArg (list_args [i], XtNverticalList, (XtArgVal) False);
	i++;
	XtSetArg (list_args [i], XtNdefaultColumns, (XtArgVal) 3);
	i++;
	XtSetArg (list_args [i], XtNlist, (XtArgVal) list_string);
	i++;
	XtSetArg (list_args [i], XtNfromHoriz, (XtArgVal) symbol_dialog);
	i++;
	XtSetArg (list_args [i], XtNhorizDistance, (XtArgVal) 8 );
	i++;
	XtSetArg (list_args [i], XtNfromVert, (XtArgVal) define_dialog);
	i++;
	XtSetArg (list_args [i], XtNvertDistance, (XtArgVal) 0);
	i++;
	define_list = XtCreateManagedWidget ("define_list",
			listWidgetClass, the_form, list_args, i);
	XtSetSensitive (define_list, False);

	make_button (the_form, &define_button, "define_button",
		"accept", define_calls, 
		define_list, 14, define_dialog, 0);
	XtSetSensitive (define_button, False);
	make_button (the_form, &close_button, "close_button",
		"close window", close_calls,
		define_button, 14, define_dialog, 0);
	make_list (the_form, &con_label, "con_label", "defined connectives:",
		&con_list, "con_list", con_string, disp_calls, 1,
		NULL, 8, define_list, 4);

}

static	char 	the_symbol;
static	int	arity_index = 0;

static void symbol_action (button, client_data, call_data)

Widget		button;
caddr_t		client_data, call_data;

{
	extern char	the_symbol, define_string [256];

	if (sscanf (XtDialogGetValueString (symbol_dialog), "%1s", 
						&the_symbol) > 0) {
		XtSetSensitive (define_dialog, True);
		XtSetSensitive (define_list, True);
		XtSetSensitive (define_button, True);
		switch (arity_index) {
			case 0:	sprintf 
				(disp_string [0], "%c = ", the_symbol);
				break;
			case 1:	sprintf
				(disp_string [0], "%c a = ", the_symbol);
				break;
			case 2: sprintf
				(disp_string [0], "a %c b = ", the_symbol);
				break;
		}
		XawListChange (disp_list, disp_string, 1, 0, False);
		XtListHighlight (define_list, arity_index);
	}
}

static void list_action (the_list, client_data, arity)

Widget		the_list;
caddr_t		client_data;
XtListReturnStruct
		*arity;

{
	extern char	the_symbol, define_string [256];

	switch (arity->list_index) {
		case 0:	sprintf (disp_string [0], "%c = ", the_symbol);
			arity_index = 0;
			break;
		case 1: sprintf (disp_string [0], "%c a = ", the_symbol);
			arity_index = 1;
			break;
		case 2: sprintf (disp_string [0], "a %c b = ", the_symbol);
			arity_index = 2;
			break;
	}
	XawListChange (disp_list, disp_string, 1, 0, False);
}

static 	int	con_count = 0;

#define	OK	0
#define	NO_FAIR	1
#define F_LOGIC	2
#define ILLEGAL	3
#define	ACCEPTD	4

Display	    *display_ptr;

static void define_action (button, client_data, call_data)

Widget		button;
caddr_t		client_data, call_data;

{
	static char	c;
	static char	the_string [256], the_con_string [256];
	extern char	the_symbol;
	extern int	receive_all ();
	extern void	ring ();


	strcpy (the_con_string, XtDialogGetValueString (define_dialog));
	if (sscanf (the_con_string, "%1s", &c) > 0) {

		sprintf (the_string, "C\n%c\n", the_symbol);
		send_to_magic (the_string);
#ifdef DEBUG
		fprintf (stderr, the_string); fflush (stderr);
#endif
		if (receive_all () == NO_FAIR) {
			/*
			**	Bad symbol was used to define the
			**	connective - send new line 
			**	deactivate the definition window
			**	and get out.
			*/
			ring ();
			XtSetSensitive (define_dialog, False);
			XtSetSensitive (define_list, False);
			XtSetSensitive (define_button, False);
			send_to_magic ("\n");
			receive_all ();
		}
		else {
			sprintf (the_string, "%d\n%s\n", arity_index,
				 the_con_string);
			send_to_magic (the_string);
#ifdef DEBUG
			fprintf (stderr, the_string); fflush (stderr);
#endif
			if (receive_all () == ILLEGAL) {
				/*
				**	The definition sent to magic
				**	is rubbish - send 'N' followed by
				**	new line and get out
				*/
				ring ();
				send_to_magic ("N\n");
				receive_all ();
			}
			else {

				XtSetSensitive (define_dialog, False);
				XtSetSensitive (define_list, False);
				XtSetSensitive (define_button, False);

/*				sprintf (con_string [con_count], 
**				   "%s%s\0", disp_string [0], the_con_string);
**				XtListChange (con_list, con_string, 
**				   NO_OF_CONNS, 0, True);
*/
				con_count++;
				if (con_count >= NO_OF_CONNS)
					XtSetSensitive (symbol_dialog, False);
			}
		}
	}
	else
		ring ();
}

static void close_action (button, client_data, call_data)

Widget		button;
caddr_t		client_data, call_data;

{
	XtPopdown (global_connectives_shell);
	XtSetSensitive (global_con_button, True);
}

static void disp_action (list, client_data, item)

Widget		list;
XtListReturnStruct
		*item;

{
	XtListUnhighlight (list);
}

void ring ()
{
	extern Display *display_ptr;

	XBell (display_ptr, 100);
	XBell (display_ptr, 50);
	XBell (display_ptr, 100);
}

void reset_conns ()
{
	int	i;

	/*
	**	clean up the defined connectives first
	*/

	for (i = 0; i < NO_OF_CONNS; strcpy (con_string [i++], "      "));
	XawListChange (con_list, con_string, NO_OF_CONNS, 0, True);
	con_count = 0;
	XtSetSensitive (symbol_dialog, True);
}

void getsymbol (widget, event, params, num_params)
Widget		widget;
XEvent		*event;
String		*params;
Cardinal	*num_params;
{
	symbol_action (widget, (XtPointer) NULL, (XtPointer) NULL);
}

void getdefine (widget, event, params, num_params)
Widget          widget;
XEvent          *event;
String          *params;
Cardinal        *num_params;
{
	define_action (widget, (XtPointer) NULL, (XtPointer) NULL);
}

void update_def_list ()
{
	XawListChange (con_list, con_string, NO_OF_CONNS, 0, True);
}
