#include <stdio.h>

#include "widget.h"


static void ClassInitialize (void);
static void Initialize (Widget, Widget, ArgList, Cardinal *);
static void Realize (Widget, XtValueMask *, XSetWindowAttributes *);
static void Destroy (Widget);
static void Resize (Widget);
static void HandleExpose (Widget, XEvent *, Region);
static Boolean SetValues (Widget, Widget, Widget, ArgList, Cardinal *);
static Boolean TakeFocus (Widget, Time *);


extern void MoveLeft (MyWidget w, XEvent *event,
		      String *params, Cardinal *num_params);
extern void MoveRight (MyWidget w, XEvent *event,
		       String *params, Cardinal *num_params);
extern void Jump (MyWidget w, XEvent *event,
		  String *params, Cardinal *num_params);
static void Enter (MyWidget w, XEvent *event,
		   String *params, Cardinal *num_params);
static void Leave (MyWidget w, XEvent *event,
		   String *params, Cardinal *num_params);


/*
 * Definition of a new Widget.
 */

static XtActionsRec actions[] = {
    {"moveleft",	(XtActionProc) MoveLeft},
    {"moveright",	(XtActionProc) MoveRight},
    {"jump",		(XtActionProc) Jump},
    {"enterwin",	(XtActionProc) Enter},
    {"leavewin",	(XtActionProc) Leave},
#if 0
    {"putplayer",	(XtActionProc) PutPlayer},
#endif
};


static char translations[] =
    "<Key>comma:	moveleft()\n\
     <KeyUp>comma:	moveleft()\n\
     <Key>z:		moveleft()\n\
     <KeyUp>z:		moveleft()\n\
     <Key>o:		moveleft()\n\
     <KeyUp>o:		moveleft()\n\
     <Key>j:		moveleft()\n\
     <KeyUp>j:		moveleft()\n\
     <Key>Left:		moveleft()\n\
     <KeyUp>Left:	moveleft()\n\
     <Key>period:	moveright()\n\
     <KeyUp>period:	moveright()\n\
     <Key>x:		moveright()\n\
     <KeyUp>x:		moveright()\n\
     <Key>p:		moveright()\n\
     <KeyUp>p:		moveright()\n\
     <Key>l:		moveright()\n\
     <KeyUp>l:		moveright()\n\
     <Key>Right:	moveright()\n\
     <KeyUp>Right:	moveright()\n\
     <Key>space:	jump()\n\
     <KeyUp>space:	jump()\n\
     <Key>Up:		jump()\n\
     <KeyUp>Up:		jump()\n\
     <Key>k:		jump()\n\
     <KeyUp>k:		jump()\n\
     <EnterNotify>:	enterwin()\n\
     <LeaveNotify>:	leavewin()";



MyClassRec myClassRec = {
	{
/* core_class fields */
    /* superclass		*/	(WidgetClass) &widgetClassRec,
    /* class_name		*/	"My",
    /* widget_size		*/	sizeof (MyRec),
    /* class_initialize		*/	ClassInitialize,
    /* class_part_initialize	*/	NULL,
    /* class_inited		*/	False,
    /* initialize		*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	Realize,
    /* actions			*/	actions,
    /* num_actions		*/	XtNumber (actions),
    /* resources		*/	NULL, /* resources */
    /* num_resources		*/	0, /* XtNumber(resources) */
    /* xrm_class		*/	NULLQUARK,
    /* compress_motion		*/	True,
    /* compress_exposure	*/	False,
    /* compress_enterleave	*/	True,
    /* visible_interest		*/	False,
    /* destroy			*/	Destroy,
    /* resize			*/	Resize,
    /* expose			*/	HandleExpose,
    /* set_values		*/	SetValues,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	NULL,
    /* get_values_hook		*/	NULL,
    /* accept_focus		*/	TakeFocus,
    /* version			*/	XtVersion,
    /* callback_private		*/	NULL,
    /* tm_table			*/	translations,
    /* query_geometry		*/	NULL,
    /* display_accelerator	*/	NULL,
    /* extension		*/	NULL,
  },{
/* my_class field */
    /* dummy			*/	0      	   /* Make C compiler happy. */
  }
};

WidgetClass myWidgetClass = (WidgetClass) &myClassRec;


/****************************************************/

/*
 * Procedures
 */


static void ClassInitialize ()
{
    /* fprintf (stderr, "-- Class Initialize\n"); */
}


static void Initialize (Widget request, Widget w, ArgList al, Cardinal *cp)
{
    /* fprintf (stderr, "-- Initialize\n"); */
}


static void Realize (Widget ww, XtValueMask *valueMask,
		     XSetWindowAttributes *attributes)
{
    MyWidget w = (MyWidget) ww;
    XWindowAttributes watr;
    XGCValues gcv;
    GC gc;
    Display *disp;
    Window win;
    Pixmap store;

    /* fprintf (stderr, "-- Realize\n"); */

    if (w->core.width == 0)
	w->core.width = 1;
    if (w->core.height == 0)
	w->core.height = 1;
    disp = XtDisplay (w);
    XtCreateWindow ((Widget) w, InputOutput,
		    DefaultVisual (disp, DefaultScreen (disp)),
		    *valueMask, attributes);
    win = XtWindow (w);
    XGetWindowAttributes (disp, win, &watr);
    store = XCreatePixmap (disp, win, watr.width, watr.height, watr.depth);
    w->my.store = store;
    gcv.foreground = WhitePixel (disp, DefaultScreen (disp));
    gc = XCreateGC (disp, store, GCForeground, &gcv);
    w->my.gc = gc;
    XFillRectangle (disp, store, gc, 0, 0, watr.width, watr.height);
}


static void HandleExpose (Widget ww, XEvent *event, Region r)
{
    MyWidget w = (MyWidget) ww;
    /* fprintf (stderr, "-- Handle Expose\n"); */

    XCopyArea (XtDisplay (w), w->my.store, w->core.window,
	       w->my.gc,
	       event->xexpose.x, event->xexpose.y,
	       event->xexpose.width, event->xexpose.height,
	       event->xexpose.x, event->xexpose.y);
}


extern void set_colormaps (int on);
extern MyWidget canvas_widget;

static void Leave (w, event, params, num_params)
    MyWidget w;
    XEvent *event;
    String *params;
    Cardinal *num_params;
{
    if (w == canvas_widget)
	set_colormaps (0);
    XAutoRepeatOn (XtDisplay (w));
}

static void Enter (w, event, params, num_params)
    MyWidget w;
    XEvent *event;
    String *params;
    Cardinal *num_params;
{
    extern int goleft, goright, dojump;

    if (w == canvas_widget)
	set_colormaps (1);
    XAutoRepeatOff (XtDisplay (w));
    goleft = 0;
    goright = 0;
    dojump = 0;
}



static void Destroy (Widget w)
{
    /* fprintf (stderr, "-- Destroy\n"); */
}

static void Resize (Widget w)
{
    /* fprintf (stderr, "-- Resize\n"); */
}


static Boolean SetValues (Widget w1, Widget w2, Widget w3, ArgList al, Cardinal *cp)
{
    /* fprintf (stderr, "-- Set Values\n"); */
}

static Boolean TakeFocus(Widget w, Time *time)
{
    /* fprintf (stderr, "-- Take Focus\n"); */

    XSetInputFocus (XtDisplay (w), w->core.window, RevertToPointerRoot,
		    CurrentTime);
    return True;
}




/*********** User procedures ***********/




void Update_Screen (MyWidget w)
{
    XCopyArea (XtDisplay (w), w->my.store, w->core.window,
	       w->my.gc,
	       0, 0, w->core.width, w->core.height, 0, 0);
}

void Update_Zone (MyWidget w, int x, int y, int width, int height)
{
    XCopyArea (XtDisplay (w), w->my.store, w->core.window,
	       w->my.gc,
	       x, y, width, height, x, y);
}


