#include <X11/Intrinsic.h>
#include <X11/Label.h>
#include <X11/List.h>
#include <X11/Form.h>
#include <X11/StringDefs.h>
#include <stdio.h>

#define	 NO_OF_FRAGMENTS	9
char	 *fragment []	=	{"->",
				 "&",
				 "v",
				 "~",
				 "o",
				 "t",
				 "f",
				 "T",
				 "F",};
Widget	fragment_widget [NO_OF_FRAGMENTS];

void make_fragment (parent_widget, 
		label_widget, fragment_form,
		left_neighbour, left_distance, top_neighbour, top_distance)

Widget	parent_widget, *label_widget, *fragment_form,
	left_neighbour, top_neighbour;
int	left_distance, top_distance;

{
	int	i;
	extern	void
		fragment_action (), make_switch ();
	Arg	label_args [30], form_args [30];
	char	fragment_name [NO_OF_FRAGMENTS][256];
	static	XtCallbackRec
		fragment_calls [] = {{fragment_action, NULL}, {NULL, NULL},};

	/*
	**	Create the label first
	*/

	i = 0;
	XtSetArg (label_args [i], XtNlabel, (XtArgVal) "fragment:");
	i++;
	XtSetArg (label_args [i], XtNborderWidth, (XtArgVal) 0);
	i++;
	XtSetArg (label_args [i], XtNfromVert, (XtArgVal) top_neighbour);
	i++;
	XtSetArg (label_args [i], XtNvertDistance, (XtArgVal) top_distance);
	i++;
	XtSetArg (label_args [i], XtNfromHoriz, (XtArgVal) left_neighbour);
	i++;
	XtSetArg (label_args [i], XtNhorizDistance, (XtArgVal) left_distance);
	i++;

	*label_widget = XtCreateManagedWidget ("fragment_label",
				labelWidgetClass, parent_widget, label_args,
				i);
	
	/*
	**	Now create the form, which will house the uni-lists
	*/

	i = 0;
	XtSetArg (form_args [i], XtNfromVert, (XtArgVal) *label_widget);
	i++;
	XtSetArg (form_args [i], XtNfromHoriz, (XtArgVal) left_neighbour);
	i++;
	XtSetArg (form_args [i], XtNhorizDistance, (XtArgVal) left_distance);
	i++;
	XtSetArg (form_args [i], XtNdefaultDistance, (XtArgVal) 2);
	i++;
	*fragment_form = XtCreateManagedWidget ("fragment_form",
				formWidgetClass, parent_widget, form_args, i);

	/*
	**	Now create the uni-lists themselves
	*/

	sprintf (&(fragment_name [0][0]), "fragment_%d", 0);
	make_switch (*fragment_form,
		&fragment_widget [0], &(fragment_name [0] [0]),
		&(fragment [0]), fragment_calls, True, NULL, 3, NULL, 1);
	for (i = 1; i < NO_OF_FRAGMENTS; i++) {
		sprintf (&(fragment_name [i] [0]), "fragment_%d", i);
		make_switch (*fragment_form, 
			&fragment_widget [i], &(fragment_name [i][0]),
			&(fragment [i]), fragment_calls, True, 
			fragment_widget [i-1], 3, NULL, 1);
	}

/*	XtSetSensitive (fragment_widget [0], False); */
}

int	fragment_state [NO_OF_FRAGMENTS] = {1,1,1,1,1,1,1,1,1};
char	fragment_string [256];

void fragment_action (the_switch, client_data, the_item)

Widget			the_switch;
caddr_t			client_data;
XtListReturnStruct	*the_item;

{
	int	i;
	char	the_string [256], answer [6];
	extern	void 
		send_to_magic ();
	extern 	int
		receive_all ();

	for (i = 0; i < NO_OF_FRAGMENTS; i++) {
		if (strcmp (the_item->string, fragment [i]) == 0) {
			if (fragment_state [i] == 0) {
				XtListHighlight (the_switch, 
				  the_item->list_index);
				fragment_state [i] = 1;
				if (i == 1 || i == 2) {
				  fragment_state [1] = 1;
				  fragment_state [2] = 1;
				}
			}
			else {
				XtListUnhighlight (the_switch);
				fragment_state [i] = 0;
				if (i == 1 || i == 2) {
				  fragment_state [1] = 0;
				  fragment_state [2] = 0;
				}

			}
		}
	}

	if (fragment_state [3] == 1)
		answer [0] = 'y';
	else
		answer [0] = 'n';
	if (fragment_state [1] == 1 || fragment_state [2] == 1)
		answer [1] = 'y';
	else
		answer [1] = 'n';
	if (fragment_state [5] == 1)
		answer [2] = 'y';
	else
		answer [2] = 'n';
	if (fragment_state [7] == 1)
		answer [3] = 'y';
	else
		answer [3] = 'n';
	if (fragment_state [8] == 1)
		answer [4] = 'y';
	else
		answer [4] = 'n';
	if (fragment_state [4] == 1)
		answer [5] = 'y';
	else
		answer [5] = 'n';

	sprintf (the_string, "F\n%c\n%c\n%c\n%c\n%c\n%c\n",
		answer [0], answer [1], answer [2], answer [3],
		answer [4], answer [5]);
	send_to_magic (the_string);
	receive_all ();
}

/*
**	update_fragment is called by receive_all only
*/

void	update_fragment ()
{
	int i;

	for (i = 0; i < NO_OF_FRAGMENTS; fragment_state [i++] = 0);
	for (i = 16; fragment_string [i] != '\0' && i < 256; i++)
		switch (fragment_string [i]) {
			case '>': fragment_state [0] = 1;
				  break;
			case '&': fragment_state [1] = 1;
				  break;
			case 'v': fragment_state [2] = 1;
				  break;
			case '~': fragment_state [3] = 1;
				  break;
			case 'o': fragment_state [4] = 1;
				  break;
			case 't': fragment_state [5] = 1;
				  break;
			case 'f': fragment_state [6] = 1;
				  break;
			case 'T': fragment_state [7] = 1;
				  break;
			case 'F': fragment_state [8] = 1;
				  break;
		}
	for (i = 0; i < NO_OF_FRAGMENTS; i++)
		if (fragment_state [i] == 1)
			XtListHighlight (fragment_widget [i], 0);
		else
			XtListUnhighlight (fragment_widget [i]);
}
