/* %Z%%M% %I% %E% */

/*
 * Copyright (c) 1994, 1995 by Wayne C. Gramlich.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * for any purpose is hereby granted without fee provided that the above
 * copyright notice and this permission are retained.  The author makes
 * no representations about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 */

/*
 * This file provide a bunch of interface routines for dealing with
 * Xlib events.
 */

#ifndef XLIB_H
#include "xlib.h"
#endif

extern unsigned xlib_event_tag__key_press;
extern unsigned xlib_event_tag__key_release;
extern unsigned xlib_event_tag__button_press;
extern unsigned xlib_event_tag__button_release;
extern unsigned xlib_event_tag__motion_notify;
extern unsigned xlib_event_tag__enter_notify;
extern unsigned xlib_event_tag__leave_notify;
extern unsigned xlib_event_tag__focus_in;
extern unsigned xlib_event_tag__focus_out;
extern unsigned xlib_event_tag__keymap_notify;
extern unsigned xlib_event_tag__expose;
extern unsigned xlib_event_tag__graphics_expose;
extern unsigned xlib_event_tag__no_expose;
extern unsigned xlib_event_tag__visibility_notify;
extern unsigned xlib_event_tag__create_notify;
extern unsigned xlib_event_tag__destory_notify;
extern unsigned xlib_event_tag__unmap_notify;
extern unsigned xlib_event_tag__map_notify;
extern unsigned xlib_event_tag__map_request;
extern unsigned xlib_event_tag__reparent_notify;
extern unsigned xlib_event_tag__configure_notify;
extern unsigned xlib_event_tag__configure_request;
extern unsigned xlib_event_tag__gravity_notify;
extern unsigned xlib_event_tag__resize_request;
extern unsigned xlib_event_tag__circulate_notify;
extern unsigned xlib_event_tag__circulate_request;
extern unsigned xlib_event_tag__property_notify;
extern unsigned xlib_event_tag__selection_clear;
extern unsigned xlib_event_tag__selection_clear;
extern unsigned xlib_event_tag__selection_request;
extern unsigned xlib_event_tag__selection_notify;
extern unsigned xlib_event_tag__colormap_notify;
extern unsigned xlib_event_tag__client_message;
extern unsigned xlib_event_tag__mapping_notify;


/* The initial object: */
Xlib_event_struct xlib_event___initial_object = {
    &xlib_display___initial_object
}; /* default rest to zeros */
Xlib_event xlib_event___initial = &xlib_event___initial_object;

/*
 * xlib_event___bogus(event)
 *	This routine will append a event bogus message to the errors object.
 */
void
xlib_event___bogus(
    Xlib_event event)
{
    xlib_errors___add(event->display->errors, "Bogus field access in event");
}

/*
 * xlib_event__address_get(event)
 *	This routine will return the address of {event}.
 */
unsigned
xlib_event__address_get(
    Xlib_event event)
{
    return (unsigned)event;
}

/*
 * xlib_event__button_get(event)
 *	This routine will return the number of the button pressed or released
 *	in {event}.
 */
unsigned
xlib_event__button_get(
    Xlib_event event)
{
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case ButtonPress:
	case ButtonRelease:
	    return x_event->xbutton.button;
	default:
	    xlib_event___bogus(event);
    }
    return 0;
}

/*
 * xlib_event__count_get(event)
 *	This routine will return the count field of {event}.
 */
unsigned
xlib_event__count_get(
    Xlib_event event)
{
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case Expose:
	    return x_event->xexpose.count;
	default:
	    xlib_event___bogus(event);
    }
    return 0;
}

/*
 * xlib_event__create(display)
 *	This routine will create and return a new {xlib_event} object
 *	and associated with {display}.
 */
Xlib_event
xlib_event__create(
    Xlib_display display)
{
    Xlib_event event;

    event = (Xlib_event)malloc(sizeof(*event));
    event->display = display;
    event->event.type = 0;
    return event;
}

/*
 * xlib_event__external__initialize()
 *	This routine will "initialize" the {xlib_event} external
 *	code.
 */
void
xlib_event__external__initialize(void)
{
    /* Do nothing! */
}

/*
 * xlib_event__height_get(event)
 *	This routine will return the height field of {event}.
 */
unsigned
xlib_event__height_get(
    Xlib_event event)
{
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case ConfigureNotify:
	    return x_event->xconfigure.height;
	case Expose:
	    return x_event->xexpose.height;
	default:
	    xlib_event___bogus(event);
    }
    return 0;
}

/*
 * xlib_event__next(event)
 *	This routine will fetch the next event into {event}.
 */
void
xlib_event__next(
    Xlib_event event)
{
    Xlib_display display;

    display = event->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else {
	XNextEvent(display->display, &event->event);
    }
}

/*
 * xlib_event__pointer_query(event)
 *	This routine will determine the current position of the pointer.
 */
void
xlib_event__pointer_query(
    Xlib_event event)
{
    Window child_window;
    Xlib_display display;
    unsigned mask;
    Window root_window;
    int root_x;
    int root_y;
    XEvent *x_event;

    x_event = &event->event;
    assert(x_event->type == MotionNotify);
    display = event->display;
    if (display->closed) {
	xlib_display___closed(display);
	return;
    }
    (void)XQueryPointer(display->display, x_event->xmotion.window,
      &root_window, &child_window, &root_x, &root_y,
      &x_event->xmotion.x, &x_event->xmotion.y, &mask);
    
}

/*
 * xlib_event__print(event, out_stream)
 *	This routine will output {event} to {out_stream}.
 */
void
xlib_event__print(
    Xlib_event event,
    Out_stream out_stream)
{
    extern void unsigned__print(unsigned, Out_stream);

    /* This is pretty cheesy: */
    unsigned__print((unsigned)event, out_stream);
}

/*
 * xlib_event__state_get(event)
 *	This procedure will return the state field associated with {event}.
 */
unsigned
xlib_event__state_get(
    Xlib_event event)
{
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case KeyPress:
	case KeyRelease:
	    return x_event->xkey.state;
	default:
	    xlib_event___bogus(event);
    }
    return 0;
}

/*
 * xlib_event__tag_get(event)
 *	This routine will return the tag field associated with {event}.
 */
unsigned
xlib_event__tag_get(
    Xlib_event event)
{
    switch (event->event.type) {
      case KeyPress:
	return xlib_event_tag__key_press;
      case KeyRelease:
	return xlib_event_tag__key_release;
      case ButtonPress:
	return xlib_event_tag__button_press;
      case ButtonRelease:
	return xlib_event_tag__button_release;
      case MotionNotify:
	return xlib_event_tag__motion_notify;
      case EnterNotify:
	return xlib_event_tag__enter_notify;
      case LeaveNotify:
	return xlib_event_tag__leave_notify;
      case FocusIn:
	return xlib_event_tag__focus_in;
      case FocusOut:
	return xlib_event_tag__focus_out;
      case KeymapNotify:
	return xlib_event_tag__keymap_notify;
      case Expose:
	return xlib_event_tag__expose;
      case GraphicsExpose:
	return xlib_event_tag__graphics_expose;
      case NoExpose:
	return xlib_event_tag__no_expose;
      case VisibilityNotify:
	return xlib_event_tag__visibility_notify;
      case CreateNotify:
	return xlib_event_tag__create_notify;
      case DestroyNotify:
	return xlib_event_tag__destory_notify;
      case UnmapNotify:
	return xlib_event_tag__unmap_notify;
      case MapNotify:
	return xlib_event_tag__map_notify;
      case MapRequest:
	return xlib_event_tag__map_request;
      case ReparentNotify:
	return xlib_event_tag__reparent_notify;
      case ConfigureNotify:
	return xlib_event_tag__configure_notify;
      case ConfigureRequest:
	return xlib_event_tag__configure_request;
      case GravityNotify:
	return xlib_event_tag__gravity_notify;
      case ResizeRequest:
	return xlib_event_tag__resize_request;
      case CirculateNotify:
	return xlib_event_tag__circulate_notify;
      case CirculateRequest:
	return xlib_event_tag__circulate_request;
      case PropertyNotify:
	return xlib_event_tag__property_notify;
      case SelectionClear:
	return xlib_event_tag__selection_clear;
      case SelectionRequest:
	return xlib_event_tag__selection_request;
      case SelectionNotify:
	return xlib_event_tag__selection_notify;
      case ColormapNotify:
	return xlib_event_tag__colormap_notify;
      case ClientMessage:
	return xlib_event_tag__client_message;
      case MappingNotify:
	return xlib_event_tag__mapping_notify;
    }
    xlib_event___bogus(event);
    return 0;
}

/*
 * xlib_event__width_get(event)
 *	This routine will return the width field of {event}.
 */
unsigned
xlib_event__width_get(
    Xlib_event event)
{
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case ConfigureNotify:
	    return x_event->xconfigure.width;
	case Expose:
	    return x_event->xexpose.width;
	default:
	    xlib_event___bogus(event);
    }
    return 0;
}

/*
 * xlib_event__x_c_key_sym_get(event)
 *	This routine will return the {KeySym} associated with event.
 */
KeySym
xlib_event__x_c_key_sym_get(
    Xlib_event event)
{
    char buffer[100];
    XComposeStatus compose;
    KeySym keysym;
    int length;
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case KeyPress:
	case KeyRelease:
	    length = XLookupString(&x_event->xkey,
	      buffer, sizeof(buffer), &keysym, &compose);
	    return keysym;
	default:
	    xlib_event___bogus(event);
    }
    return 0;
}

/*
 * xlib_event__x_get(event)
 *	This routine will return the x field of {event}.
 */
unsigned
xlib_event__x_get(
    Xlib_event event)
{
    int x;
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case ButtonPress:
	case ButtonRelease:
	    x = x_event->xbutton.x;
	    break;
	case Expose:
	    x = x_event->xexpose.x;
	    break;
	case MotionNotify:
	    x = x_event->xmotion.x;
	    break;
	default:
	    xlib_event___bogus(event);
    }
    if (x < 0) {
	x = 0;
    }
    return x;
}

/*
 * xlib_event__y_get(event)
 *	This routine will return the y field of {event}.
 */
unsigned
xlib_event__y_get(
    Xlib_event event)
{
    int y;
    XEvent *x_event;

    x_event = &event->event;
    switch (x_event->type) {
	case ButtonPress:
	case ButtonRelease:
	    y = x_event->xbutton.y;
	    break;
	case Expose:
	    y = x_event->xexpose.y;
	    break;
	case MotionNotify:
	    y = x_event->xmotion.y;
	    break;
	default:
	    xlib_event___bogus(event);
    }
    if (y < 0) {
	y = 0;
    }
    return y;
}



