/*
 * AUTHOR: Jay Schmidgall <jay.schmidgall@spdbump.sungardss.com>
 *
 * $Id: fifteen.c,v 1.1 1999/08/04 21:24:11 danny Exp $
 */
#ifdef HAVE_CONFIG_H
#include <XbaeConfig.h>
#endif

#include <stdio.h>
#include <string.h>

#include <Xbae/Matrix.h>

#include <Xm/Form.h>
#include <Xm/TextF.h>

typedef struct {
    int row, column, count;
    Widget text;
} Empty;

void
LoadMatrix(w)
Widget w;
{
    String *cells[4];
    static String rows[4][4] = {
	{ "3",	"1",	"6",	"2"},
	{ "5",  "7",	"15",   "13"},
	{ "4",  "11",	"8",    "9"},
	{ "14", "10",	"12",   ""}
    };

    cells[0] = &rows[0][0];
    cells[1] = &rows[1][0];
    cells[2] = &rows[2][0];
    cells[3] = &rows[3][0];
    
    XtVaSetValues(w, XmNcells, cells, NULL);
}


#define REDRAW_VALUE 0x0

void
cbSelect(w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
    XbaeMatrixSelectCellCallbackStruct *cbs =
	(XbaeMatrixSelectCellCallbackStruct *) call;
    unsigned char **shadows;
    String **cells;
    Empty *empty;

    XtVaGetValues(w,
		  XmNcellShadowTypes, &shadows,
		  XmNuserData, (XtPointer) &empty,
		  XmNcells, &cells,
		  NULL);
    if ( ( (cbs->row == empty->row) &&
	   ( (cbs->column == empty->column - 1) ||
	     (cbs->column == empty->column + 1) ) ) ||
	 ( (cbs->column == empty->column) &&
	   ( (cbs->row == empty->row - 1) ||
	     (cbs->row == empty->row + 1) ) ) )
    {
	char buf[20];
	String cell = XbaeMatrixGetCell(w, cbs->row, cbs->column);
	
	shadows[cbs->row][cbs->column] = XmSHADOW_IN;
	shadows[empty->row][empty->column] = XmSHADOW_OUT;

	/* Note: if we set cbs->row, cbs->column first, then
	 * the value that 'cell' points to becomes the empty
	 * string! */
	XbaeMatrixSetCell(w, empty->row, empty->column, cell);
	XbaeMatrixSetCell(w, cbs->row, cbs->column, "");
	
	empty->row = cbs->row;
	empty->column = cbs->column;

	empty->count++;

	/* Check if won */
	if ( (0 == strcmp(cells[0][0], "1")) &&
	     (0 == strcmp(cells[0][1], "2")) &&
	     (0 == strcmp(cells[0][2], "3")) &&
	     (0 == strcmp(cells[0][3], "4")) &&
	     (0 == strcmp(cells[1][0], "5")) &&
	     (0 == strcmp(cells[1][1], "6")) &&
	     (0 == strcmp(cells[1][2], "7")) &&
	     (0 == strcmp(cells[1][3], "8")) &&
	     (0 == strcmp(cells[2][0], "9")) &&
	     (0 == strcmp(cells[2][1], "10")) &&
	     (0 == strcmp(cells[2][2], "11")) &&
	     (0 == strcmp(cells[2][3], "12")) &&
	     (0 == strcmp(cells[3][0], "13")) &&
	     (0 == strcmp(cells[3][1], "14")) &&
	     (0 == strcmp(cells[3][2], "15")) )
	{
	    XtRemoveCallback(w, XmNselectCellCallback, cbSelect, (XtPointer) NULL);
	    sprintf(buf, "Move %d WINS!", empty->count);
	}
	else
	    sprintf(buf, "Move %d", empty->count);
	XmTextFieldSetString(empty->text, buf);
    }
}


int
main(argc, argv)
int argc;
char *argv[];
{
    XtAppContext app;
    Widget toplevel, form, mw;
    unsigned char **cell_shadows;
    int rows, columns, m;
    Empty *empty = XtNew(Empty);
#ifdef USE_EDITRES
    extern void _XEditResCheckMessages();
#endif

    toplevel = XtVaAppInitialize(&app, "Fifteen",
				 NULL, 0,
				 &argc, argv,
				 NULL,
				 NULL);
#ifdef USE_EDITRES
    XtAddEventHandler( toplevel, (EventMask)0, True,
                       _XEditResCheckMessages, NULL);
#endif

    form = XtVaCreateWidget("form", xmFormWidgetClass, toplevel,
			    NULL);
    
    mw = XtVaCreateManagedWidget("mw", xbaeMatrixWidgetClass, form,
				 XmNtopOffset,	    4,
				 XmNtopAttachment,  XmATTACH_FORM,
				 XmNleftOffset,     4,
				 XmNleftAttachment, XmATTACH_FORM,
				 XmNrightOffset,    4,
				 XmNrightAttachment,XmATTACH_FORM,
				 XmNuserData,	    (XtPointer) empty,
				 NULL);

    empty->text = XtVaCreateManagedWidget(
	"text", xmTextFieldWidgetClass, form,
	XmNvalue,		    "Move 0",
	XmNeditable,		    False,
	XmNcursorPositionVisible, False,
	XmNcolumns,		    8,
	XmNtopOffset,		    4,
	XmNtraversalOn,	    False,
	XmNmarginWidth,	    2,
	XmNmarginHeight,	    2,
	XmNtopWidget,		    mw,
	XmNtopAttachment,	    XmATTACH_WIDGET,
	XmNleftWidget,	    mw,
	XmNleftAttachment,	    XmATTACH_OPPOSITE_WIDGET,
	XmNrightOffset,	    4,
	XmNrightAttachment,	    XmATTACH_FORM,
	XmNbottomOffset,	    4,
	XmNbottomAttachment,	    XmATTACH_FORM,
	NULL);
    
    XtVaGetValues(mw, XmNrows, &rows, XmNcolumns, &columns, NULL);

    cell_shadows = (unsigned char **) XtMalloc(sizeof(unsigned char *) * rows);
    for (m = 0; m < rows; m++)
    {
	cell_shadows[m] = (unsigned char *) XtMalloc(
	    sizeof(unsigned char) * columns);
	memset((void*) cell_shadows[m], XmSHADOW_OUT,
	       sizeof(unsigned char) * columns);
    }
    cell_shadows[rows-1][columns-1] = XmSHADOW_IN;
    empty->row = rows-1;
    empty->column = columns - 1;
    empty->count = 0;
    XtVaSetValues(mw, XmNcellShadowTypes, cell_shadows, NULL);
    for (m = 0; m < rows; m++)
	XtFree((XtPointer) cell_shadows[m]);
    XtFree((XtPointer) cell_shadows);

    XtAddCallback(mw, XmNselectCellCallback, cbSelect, (XtPointer) NULL);
    
    LoadMatrix(mw);

    XtManageChild(form);
    XtRealizeWidget(toplevel);
    XtAppMainLoop(app);
    /*NOTREACHED*/
    return 0;
}

