/* $Id: ps_events.c,v 1.3 90/11/30 09:01:41 altenhof Exp $ */

/*
 * Copyright (C) 1990 by Digital Equipment Corporation.
 * 
 * Author: Michael P. Altenhofen, CEC Karlsruhe e-mail:
 * Altenhofen@kampus.enet.dec.com
 * 
 * This file ist part of Shared X
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation without fee is hereby granted, but only for non-profit  use
 * and distribution,  and provided  that the copyright notice and this notice
 * is preserved on all copies.
 * 
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

#define PUBLIC extern

#define _USE_STRUCTS_
#define _USE_MASKS_
#define _USE_PROTO_
#define NEED_EVENTS

#include "glob.h"

#include "utils.h"
#include "io.h"
#include "table.h"

#undef PUBLIC


#include "filter.h"		/* -- map event type -> event masks -- */
#include "X11EventMaskNames.h"	/* -- map event mask -> event mask name -- */
#include "X11EventNames.h"	/* -- map event type -> event name -- */

/* -- frequently used macros -- */

#define MAPID( result , id , map , from_where )\
          if( ( result = MapID( id , map , from_where ) ) == InvalidID ) \
          {\
	      ErrorF( "Can't process event (ID map failure)!\n" ) ;\
	      return ;\
	  }

/* -- local definitions for hashing -- */
#define HASHSIZE 73

/* -- hash function : ( window ID ) modulo HASHSIZE ) -- */

#define HashID( id )   ( int ) ( (id ) % HASHSIZE )


#define NullEventMapPtr  ( EventMapPtr ) ( 0 )

typedef struct _EventMapEntry {	/* the things we need to dispatch events */

  XID window;			/* the key to this entry : the window ID */
  Mask exclusion_mask;		/* the events selected by  XmuX and NOT */
  /* by the client */
  struct _EventMapEntry *next;	/* we use hashing with collision resolution
				 * by linking */
} EventMapEntry, *EventMapPtr;

static EventMapPtr *WindowEventMap[MAXSOCKS];	/* one event map per client */

#define MAX_MAPS  10

static EventMapPtr *FreeMaps[MAX_MAPS];	/* list of allocated but unused hash
					 * tables */

static int free_index = -1;

static EventMapPtr FreeEntries = NullEventMapPtr; /* list of allocated but
						   * unused map entries */

static void
FreeEntry (entry)
  EventMapPtr entry;
{
  entry->next = FreeEntries;
  FreeEntries = entry;
  entry = NullEventMapPtr;
}


static EventMapPtr *
AllocEventMap ()
{
  EventMapPtr *map;
  register int i;

  if (free_index < 0) {
    free_index = -1;
    if ((map =
	 (EventMapPtr *) Xmalloc (HASHSIZE * sizeof (EventMapPtr))) ==
	(EventMapPtr *) NULL)
      FatalError ("Out of memory (Can't allocate new event map!)\n");
  }
  else
    map = FreeMaps[free_index--];

  for (i = 0; i < HASHSIZE; i++)
    map[i] = NullEventMapPtr;

  return (map);
}

static EventMapPtr
AllocEntry ()
{
  EventMapPtr new_entry;

  if (FreeEntries == NullEventMapPtr)
    new_entry = (EventMapPtr) Xmalloc (sizeof (EventMapEntry));
  else {
    new_entry = FreeEntries;
    FreeEntries = FreeEntries->next;
  }
  new_entry->next = NullEventMapPtr;
  new_entry->exclusion_mask = 0L;
  return (new_entry);
}

static void
InstallEventMap (client_fd)
  int client_fd;
{
  register int i;

  if ((WindowEventMap[client_fd] = AllocEventMap ()) ==
      (EventMapPtr *) NULL)
    FatalError ("Can't install event map for client %d!\n", client_fd);

  for (i = 0; i < HASHSIZE; i++)
    WindowEventMap[client_fd][i] = NullEventMapPtr;
}

static EventMapPtr
GetWindowEntry (window, client_fd)
  Window window;
  int client_fd;
{
  EventMapPtr entry;

  if (WindowEventMap[client_fd] == (EventMapPtr *) NULL)
    return (NullEventMapPtr);

  entry = WindowEventMap[client_fd][HashID (window)];

  while (entry != NullEventMapPtr)
    if (entry->window == window)
      break;
    else
      entry = entry->next;

  return (entry);
}

void
RemoveEventExclusionMask (window, client_fd)
  Window window;
  int client_fd;
{
  EventMapPtr *bucket, pred_entry, curr_entry;

  if (WindowEventMap[client_fd] == (EventMapPtr *) NULL) {
    return;
  }
  /* find the right place */
  bucket = WindowEventMap[client_fd] + HashID (window);
  pred_entry = curr_entry = *bucket;

  debug (_debug_events, "removed mask (clean up):\n");
  /* there's no entry at all */
  if (curr_entry == NullEventMapPtr)
    return;
  /* try to find the entry for the specified window */
  /* special case: remove the head of the list */
  if (curr_entry->window == window) {
    *bucket = curr_entry->next;
    curr_entry->next = NullEventMapPtr;
    FreeEntry (curr_entry);
    return;
  }
  /* search through the list */
  for (curr_entry = curr_entry->next;
       curr_entry != NullEventMapPtr;
       pred_entry = curr_entry, curr_entry = curr_entry->next)
    if (curr_entry->window == window) {
      pred_entry->next = curr_entry->next;
      curr_entry->next = NullEventMapPtr;
      FreeEntry (curr_entry);
      return;
    }
  return;
}


void
InsertEventExclusionMask (window, client_fd, exclusion_mask)
  Window window;
  int client_fd;
  Mask exclusion_mask;		/* the events selected by XmuX and NOT by the
				 * client */
{
  register int known_win;
  EventMapPtr *bucket, entry;
  void _PrintMask ();

  known_win = FALSE;

  if (WindowEventMap[client_fd] == (EventMapPtr *) NULL)
    /* create it */
    InstallEventMap (client_fd);

  /* find the right place */
  bucket = WindowEventMap[client_fd] + HashID (window);

  entry = *bucket;
  _PrintMask (window, exclusion_mask, _debug_requests, 1);

  /* is there already an entry for this window */
  while (entry != NullEventMapPtr) {
    if (entry->window == window) {
      /* there's already an entry for this window */
      known_win = TRUE;
      break;
    }
    else
      entry = entry->next;
  }

  /* it's the first time for this window --> create a new entry */
  if (entry == NullEventMapPtr)
    if ((entry = AllocEntry ()) == NullEventMapPtr)
      FatalError ("Out of memory! Can't insert a new entry in the event table ( window ID 0x%lx)\n", window);

  /* fill in the values */
  entry->window = window;
  entry->exclusion_mask = exclusion_mask;
  entry->next = NullEventMapPtr;

  /* it was an unknown window , so link it */
  if (!known_win) {
    entry->next = *bucket;
    *bucket = entry;
  }
}

void
_PrintMask (win, mask, print_it, exclusion)
  XID win;
  Mask mask;
  int print_it;
  Bool exclusion;
{
  register long bit, bit_set;

  if (!print_it)
    return;
  if (exclusion)
    debug (print_it, "XmuX exclusive events on window 0x%lx :\n", win);
  else
    debug (print_it, "Window 0x%lx wants events :\n", win);

  for (bit = 0, bit_set = 1; bit < sizeof (long) * 8;
       bit++, bit_set <<= 1)
    if (mask & bit_set)
      debug (print_it, "==>%s\n", _EventMaskNames[bit].name);
}

void
FreeEventMap (client_fd)
  int client_fd;
{
  EventMapPtr *map;
  register int i;

  /* nothing to do ? */
  if ((map = WindowEventMap[client_fd]) == (EventMapPtr *) NULL)
    return;

  for (i = 0; i < HASHSIZE; i++)
    if (map[i] != NullEventMapPtr) {
      FreeEntry (map[i]);
      map[i] = NullEventMapPtr;
    }
  if (++free_index > MAX_MAPS - 1) {
    free_index = MAX_MAPS - 1;
    Xfree ((char *) map);
  }
  else
    FreeMaps[free_index] = map;
}

void
FreeEventMaps ()
{
  register int i;

  for (i = 0; i < MAXSOCKS; i++) {
    if (WindowEventMap[i] != (EventMapPtr *) NULL)
      FreeEventMap (i);
    WindowEventMap[i] = (EventMapPtr *) NULL;
  }
}

Mask
GetEventExclusionMask (window, client_fd)
  Window window;
  int client_fd;
{
  EventMapPtr entry;

  if ((entry = GetWindowEntry (window, client_fd)) == NullEventMapPtr)
    return (0L);
  else
    return (entry->exclusion_mask);
}

void
DeliverEvent (client, event, window)
  ClientPtr client;
  xEvent *event;		/* XXX an event of type xEvent cf.
				 * Xproto.h ! */
  XID window;
{
  EventMapPtr bucket;
  int client_fd;
  Bool delivered;

  debug (_debug_events, " (w=0x%lx)...", window);

  if (!client) {
    ErrorF ("Invalid client!\n");
    return;
  }
  delivered = FALSE;

  client_fd = ClientConnection (client);

  if (window == None) {
    /* always reported */
    WriteToClient (client, sizeof (xEvent), (char *) event);
    return;
  }
  if ((bucket = GetWindowEntry (window, client_fd)) == NullEventMapPtr) {
    /* may be the root window or something else --> send it */
    WriteToClient (client, sizeof (xEvent), (char *) event);
    return;
  }

  /*
   * let's see if this event was selected by X
   * XXX -- take care of send events ( type |= 0x80 ) !
   */
  if (bucket->exclusion_mask & filter[event->u.u.type & ~0x80])
    debug (_debug_events, "exclusive X event ( NOT delivered) !\n");
  else {
    WriteToClient (client, sizeof (xEvent), (char *) event);
    debug (_debug_events, "delivered\n");
  }
}

void
HandleOneServer (dpy, flush)
  Display *dpy;
  Bool flush;
{
  XEvent event;
  register int pending, which_events;

  if (flush) {
    /* 
     * find out whether server connection has gone
     */
    XNoOp (dpy);
    XFlush (dpy);
    which_events = QueuedAfterFlush;
  }
  else
    which_events = QueuedAlready;

  while (XEventsQueued (dpy, which_events)) {
    XNextEvent (dpy, &event);
    /* was the last event an error ? */
    if (clientErrorValue)
      Oops (ClientFromDisplay (dpy),
	    clientErrorRequest, 0, clientErrorValue);
    else
      /* don't do anything if no client attached to that display */
    if (ClientFromDisplay (dpy))
      (void) (*(Event_ProcVector[event.type]))
	(dpy, &event);
  }
  if (flush)
    FlushAllOutput ();
}

void
ProcessServerInput (selected)
  Bool selected;
{
  register long mask;
  register int index, base;
  Display *dpy;

  for (base = 0; base < mskcnt; base++) {
    mask = (selected == ALLSERVERS) ? BITS (AllServers)[base]
      : BITS (ReadyServers)[base];
    while (mask) {
      index = ffs (mask) - 1 + ((long) base << 5);
      mask &= ~lowbit (mask);
      dpy = DisplayFromFd (index);
      HandleOneServer (dpy, TRUE);
    }
  }
}

int
UnknownWireEvent (dpy, re, event)
  Display *dpy;
  XEvent *re;
  xEvent *event;
{

  ErrorF ("Unhandled wire event ! event number = %d , display = %d\n",
	  event->u.u.type, ConnectionNumber (dpy));
  DeliverEvent (ClientFromDisplay (dpy), event, None);
}

/*
 * Reformat a wire event into an XEvent structure of the right type.
 * Taken from XlibInt.c augmented by ID mapping
 */

int
WireToEvent (dpy, re, event)
  Display *dpy;			/* pointer to display structure */
  XEvent *re;			/* pointer to where event should be
				 * reformatted */
  xEvent *event;		/* wire protocol event */
{
  register int idmap = ConnectionNumber (dpy);	/* idmap */


  re->type = event->u.u.type & 0x7f;
  ((XAnyEvent *) re)->serial = event->u.u.sequenceNumber;
  ((XAnyEvent *) re)->send_event = ((event->u.u.type & 0x80) != 0);
  ((XAnyEvent *) re)->display = dpy;

  /*
   * Ignore the leading bit of the event type since it is set when a
   * client sends an event rather than the server.
   */

  switch (event->u.u.type & 0177) {
  case KeyPress:
  case KeyRelease:
    {
      register XKeyEvent *ev = (XKeyEvent *) re;

      ev->root = MapID (event->u.keyButtonPointer.root, idmap,
			FromClient);
      ev->window = MapID (event->u.keyButtonPointer.event, idmap,
			  FromClient);
      ev->subwindow = MapID (event->u.keyButtonPointer.child, idmap,
			     FromClient);

      ev->time = event->u.keyButtonPointer.time;
      ev->x = event->u.keyButtonPointer.eventX;
      ev->y = event->u.keyButtonPointer.eventY;
      ev->x_root = event->u.keyButtonPointer.rootX;
      ev->y_root = event->u.keyButtonPointer.rootY;
      ev->state = event->u.keyButtonPointer.state;
      ev->same_screen = event->u.keyButtonPointer.sameScreen;
      ev->keycode =  event->u.u.detail;
    }
    break;

  case ButtonPress:
  case ButtonRelease:
    {
      register XButtonEvent *ev = (XButtonEvent *) re;

      ev->root = MapID (event->u.keyButtonPointer.root, idmap,
			FromClient);
      ev->window = MapID (event->u.keyButtonPointer.event, idmap,
			  FromClient);
      ev->subwindow = MapID (event->u.keyButtonPointer.child, idmap,
			     FromClient);

      ev->time = event->u.keyButtonPointer.time;
      ev->x = event->u.keyButtonPointer.eventX;
      ev->y = event->u.keyButtonPointer.eventY;
      ev->x_root = event->u.keyButtonPointer.rootX;
      ev->y_root = event->u.keyButtonPointer.rootY;
      ev->state = event->u.keyButtonPointer.state;
      ev->same_screen = event->u.keyButtonPointer.sameScreen;
      ev->button = event->u.u.detail;
    }
    break;

  case MotionNotify:
    {
      register XMotionEvent *ev = (XMotionEvent *) re;

      ev->root = MapID (event->u.keyButtonPointer.root, idmap,
			FromClient);
      ev->window = MapID (event->u.keyButtonPointer.event, idmap,
			  FromClient);
      ev->subwindow = MapID (event->u.keyButtonPointer.child, idmap,
			     FromClient);
      ev->time = event->u.keyButtonPointer.time;
      ev->x = event->u.keyButtonPointer.eventX;
      ev->y = event->u.keyButtonPointer.eventY;
      ev->x_root = event->u.keyButtonPointer.rootX;
      ev->y_root = event->u.keyButtonPointer.rootY;
      ev->state = event->u.keyButtonPointer.state;
      ev->same_screen = event->u.keyButtonPointer.sameScreen;
      ev->is_hint = event->u.u.detail;
    }
    break;

  case EnterNotify:
  case LeaveNotify:
    {
      register XCrossingEvent *ev = (XCrossingEvent *) re;

      ev->root = MapID (event->u.enterLeave.root, idmap,
			FromClient);
      ev->window = MapID (event->u.enterLeave.event, idmap,
			  FromClient);
      ev->subwindow = MapID (event->u.enterLeave.child, idmap,
			     FromClient);

      ev->time = event->u.enterLeave.time;
      ev->x = event->u.enterLeave.eventX;
      ev->y = event->u.enterLeave.eventY;
      ev->x_root = event->u.enterLeave.rootX;
      ev->y_root = event->u.enterLeave.rootY;
      ev->state = event->u.enterLeave.state;
      ev->mode = event->u.enterLeave.mode;
      ev->same_screen = (event->u.enterLeave.flags &
			 ELFlagSameScreen) && True;
      ev->focus = (event->u.enterLeave.flags &
		   ELFlagFocus) && True;
      ev->detail = event->u.u.detail;
    }
    break;

  case FocusIn:
  case FocusOut:
    {
      register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;

      ev->window = MapID (event->u.focus.window, idmap,
			  FromClient);

      ev->mode = event->u.focus.mode;
      ev->detail = event->u.u.detail;
    }
    break;

  case KeymapNotify:
    {
      register XKeymapEvent *ev = (XKeymapEvent *) re;

      ev->window = MapID (dpy->current, idmap, FromClient);

      bcopy ((char *) ((xKeymapEvent *) event)->map,
	     &ev->key_vector[1],
	     sizeof (((xKeymapEvent *) event)->map));
    }
    break;

  case Expose:
    {
      register XExposeEvent *ev = (XExposeEvent *) re;

      ev->window = MapID (event->u.expose.window, idmap, FromClient);

      ev->x = event->u.expose.x;
      ev->y = event->u.expose.y;
      ev->width = event->u.expose.width;
      ev->height = event->u.expose.height;
      ev->count = event->u.expose.count;
    }
    break;

  case GraphicsExpose:
    {
      register XGraphicsExposeEvent *ev = (XGraphicsExposeEvent *) re;

      ev->drawable = MapID (event->u.graphicsExposure.drawable, idmap,
			    FromClient);

      ev->x = event->u.graphicsExposure.x;
      ev->y = event->u.graphicsExposure.y;
      ev->width = event->u.graphicsExposure.width;
      ev->height = event->u.graphicsExposure.height;
      ev->count = event->u.graphicsExposure.count;
      ev->major_code = event->u.graphicsExposure.majorEvent;
      ev->minor_code = event->u.graphicsExposure.minorEvent;
    }
    break;

  case NoExpose:
    {
      register XNoExposeEvent *ev = (XNoExposeEvent *) re;

      ev->drawable = MapID (event->u.noExposure.drawable, idmap,
			    FromClient);

      ev->major_code = event->u.noExposure.majorEvent;
      ev->minor_code = event->u.noExposure.minorEvent;
    }
    break;

  case VisibilityNotify:
    {
      register XVisibilityEvent *ev = (XVisibilityEvent *) re;

      ev->window = MapID (event->u.visibility.window, idmap,
			  FromClient);

      ev->state = event->u.visibility.state;
    }
    break;

  case CreateNotify:
    {
      register XCreateWindowEvent *ev = (XCreateWindowEvent *) re;

      ev->window = MapID (event->u.createNotify.window, idmap,
			  FromClient);

      ev->parent = MapID (event->u.createNotify.parent, idmap,
			  FromClient);

      ev->x = event->u.createNotify.x;
      ev->y = event->u.createNotify.y;
      ev->width = event->u.createNotify.width;
      ev->height = event->u.createNotify.height;
      ev->border_width = event->u.createNotify.borderWidth;
      ev->override_redirect = event->u.createNotify.override;
    }
    break;

  case DestroyNotify:
    {
      register XDestroyWindowEvent *ev = (XDestroyWindowEvent *) re;

      ev->window = MapID (event->u.destroyNotify.window, idmap,
			  FromClient);
      ev->event = MapID (event->u.destroyNotify.event, idmap,
			 FromClient);
    }
    break;

  case UnmapNotify:
    {
      register XUnmapEvent *ev = (XUnmapEvent *) re;

      ev->window = MapID (event->u.unmapNotify.window, idmap,
			  FromClient);
      ev->event = MapID (event->u.unmapNotify.event, idmap,
			 FromClient);
      ev->from_configure = event->u.unmapNotify.fromConfigure;
    }
    break;

  case MapNotify:
    {
      register XMapEvent *ev = (XMapEvent *) re;

      ev->window = MapID (event->u.mapNotify.window, idmap,
			  FromClient);
      ev->event = MapID (event->u.mapNotify.event, idmap,
			 FromClient);

      ev->override_redirect = event->u.mapNotify.override;
    }
    break;

  case MapRequest:
    {
      register XMapRequestEvent *ev = (XMapRequestEvent *) re;

      ev->window = MapID (event->u.mapRequest.window, idmap,
			  FromClient);
      ev->parent = MapID (event->u.mapRequest.parent, idmap,
			  FromClient);
    }
    break;

  case ReparentNotify:
    {
      register XReparentEvent *ev = (XReparentEvent *) re;

      ev->event = MapID (event->u.reparent.event, idmap,
			 FromClient);
      ev->window = MapID (event->u.reparent.window, idmap,
			  FromClient);
      ev->parent = MapID (event->u.reparent.parent, idmap,
			  FromClient);

      ev->x = event->u.reparent.x;
      ev->y = event->u.reparent.y;
      ev->override_redirect = event->u.reparent.override;
    }
    break;

  case ConfigureNotify:
    {
      register XConfigureEvent *ev = (XConfigureEvent *) re;

      ev->event = MapID (event->u.configureNotify.event, idmap,
			 FromClient);
      ev->window = MapID (event->u.configureNotify.window, idmap,
			  FromClient);
      ev->above = MapID (event->u.configureNotify.aboveSibling, idmap,
			 FromClient);

      ev->x = event->u.configureNotify.x;
      ev->y = event->u.configureNotify.y;
      ev->width = event->u.configureNotify.width;
      ev->height = event->u.configureNotify.height;
      ev->border_width = event->u.configureNotify.borderWidth;
      ev->override_redirect = event->u.configureNotify.override;

    }
    break;

  case ConfigureRequest:
    {
      register XConfigureRequestEvent *ev = (XConfigureRequestEvent *) re;

      ev->window = MapID (event->u.configureRequest.window,
			  idmap, FromClient);
      ev->parent = MapID (event->u.configureRequest.parent,
			  idmap, FromClient);
      ev->above = MapID (event->u.configureRequest.sibling,
			 idmap, FromClient);

      ev->x = event->u.configureRequest.x;
      ev->y = event->u.configureRequest.y;
      ev->width = event->u.configureRequest.width;
      ev->height = event->u.configureRequest.height;
      ev->border_width = event->u.configureRequest.borderWidth;
      ev->value_mask = event->u.configureRequest.valueMask;
      ev->detail = event->u.u.detail;
    }
    break;

  case GravityNotify:
    {
      register XGravityEvent *ev = (XGravityEvent *) re;

      ev->window = MapID (event->u.gravity.window, idmap,
			  FromClient);
      ev->event = MapID (event->u.gravity.event, idmap,
			 FromClient);

      ev->x = event->u.gravity.x;
      ev->y = event->u.gravity.y;
    }
    break;

  case ResizeRequest:
    {
      register XResizeRequestEvent *ev = (XResizeRequestEvent *) re;

      ev->window = MapID (event->u.resizeRequest.window,
			  idmap, FromClient);

      ev->width = event->u.resizeRequest.width;
      ev->height = event->u.resizeRequest.height;
    }
    break;

  case CirculateNotify:
    {
      register XCirculateEvent *ev = (XCirculateEvent *) re;

      ev->window = MapID (event->u.circulate.window, idmap,
			  FromClient);
      ev->event = MapID (event->u.circulate.event, idmap,
			 FromClient);

      ev->place = event->u.circulate.place;
    }
    break;

  case CirculateRequest:
    {
      register XCirculateRequestEvent *ev = (XCirculateRequestEvent *) re;

      ev->window = MapID (event->u.circulate.window, idmap,
			  FromClient);
      ev->parent = MapID (event->u.circulate.event, idmap,
			  FromClient);

      ev->place = event->u.circulate.place;
    }
    break;

  case PropertyNotify:
    {
      register XPropertyEvent *ev = (XPropertyEvent *) re;

      ev->window = MapID (event->u.property.window, idmap,
			  FromClient);
      ev->atom = event->u.property.atom;
      ev->time = event->u.property.time;
      ev->state = event->u.property.state;
    }
    break;

  case SelectionClear:
    {
      register XSelectionClearEvent *ev = (XSelectionClearEvent *) re;

      ev->window = MapID (event->u.selectionClear.window,
			  idmap, FromClient);

      ev->selection = event->u.selectionClear.atom;
      ev->time = event->u.selectionClear.time;
    }
    break;

  case SelectionRequest:
    {
      register XSelectionRequestEvent *ev = (XSelectionRequestEvent *) re;

      ev->owner = MapID (event->u.selectionRequest.owner,
			 idmap, FromClient);
      ev->requestor = MapID (event->u.selectionRequest.requestor,
			     idmap, FromClient);

      ev->selection = event->u.selectionRequest.selection;
      ev->target = event->u.selectionRequest.target;
      ev->property = event->u.selectionRequest.property;
      ev->time = event->u.selectionRequest.time;
    }
    break;

  case SelectionNotify:
    {
      register XSelectionEvent *ev = (XSelectionEvent *) re;

      ev->requestor = MapID (event->u.selectionNotify.requestor,
			     idmap, FromClient);

      ev->selection = event->u.selectionNotify.selection;
      ev->target = event->u.selectionNotify.target;
      ev->property = event->u.selectionNotify.property;
      ev->time = event->u.selectionNotify.time;
    }
    break;

  case ColormapNotify:
    {
      register XColormapEvent *ev = (XColormapEvent *) re;

      ev->window = MapID (event->u.colormap.window, idmap,
			  FromClient);
      ev->colormap = MapID (event->u.colormap.colormap, idmap,
			    FromClient);

      ev->new = event->u.colormap.new;
      ev->state = event->u.colormap.state;
    }
    break;

  case ClientMessage:
    {
      register int i;
      register XClientMessageEvent *ev = (XClientMessageEvent *) re;

      ev->window = MapIDTryHard (event->u.clientMessage.window,
				 FromClient);
      ev->format = event->u.u.detail;
      switch (ev->format) {
      case 8:
	ev->message_type = event->u.clientMessage.u.b.type;
	for (i = 0; i < 20; i++)
	  ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
	break;

      case 16:
	ev->message_type = event->u.clientMessage.u.s.type;
	ev->data.s[0] = event->u.clientMessage.u.s.shorts0;
	ev->data.s[1] = event->u.clientMessage.u.s.shorts1;
	ev->data.s[2] = event->u.clientMessage.u.s.shorts2;
	ev->data.s[3] = event->u.clientMessage.u.s.shorts3;
	ev->data.s[4] = event->u.clientMessage.u.s.shorts4;
	ev->data.s[5] = event->u.clientMessage.u.s.shorts5;
	ev->data.s[6] = event->u.clientMessage.u.s.shorts6;
	ev->data.s[7] = event->u.clientMessage.u.s.shorts7;
	ev->data.s[8] = event->u.clientMessage.u.s.shorts8;
	ev->data.s[9] = event->u.clientMessage.u.s.shorts9;
	break;

      case 32:
	ev->message_type = event->u.clientMessage.u.l.type;
	ev->data.l[0] = event->u.clientMessage.u.l.longs0;
	ev->data.l[1] = event->u.clientMessage.u.l.longs1;
	ev->data.l[2] = event->u.clientMessage.u.l.longs2;
	ev->data.l[3] = event->u.clientMessage.u.l.longs3;
	ev->data.l[4] = event->u.clientMessage.u.l.longs4;
	break;

      default:			/* XXX should never occur */
	break;
      }
    }
    break;

  case MappingNotify:
    {
      register XMappingEvent *ev = (XMappingEvent *) re;

      ev->first_keycode = event->u.mappingNotify.firstKeyCode;
      ev->request = event->u.mappingNotify.request;
      ev->count = event->u.mappingNotify.count;
    }
    break;

  default:
    return (_XUnknownWireEvent (dpy, re, event));
  }

  return (1);
}

/*
 * Reformat an XEvent structure into a wire event of the right type. Taken
 * from XEvToWire.c and augmented by ID mapping
 */

/* ARGSUSED */

int
EventToWire (dpy, re, event)
  Display *dpy;
  XEvent *re;			/* pointer to where event should be
				 * reformatted */
  xEvent *event;		/* wire protocol event */
{
  register int idmap = ConnectionNumber (dpy);
  ClientPtr client;

  client = ClientFromDisplay (dpy);
  switch (event->u.u.type = re->type) {
  case KeyPress:
  case KeyRelease:
    {
      register XKeyEvent *ev = (XKeyEvent *) & re->xkey;

      event->u.keyButtonPointer.root = MapID (ev->root, idmap,
					      FromServer);
      event->u.keyButtonPointer.event = MapID (ev->window, idmap,
					       FromServer);
      event->u.keyButtonPointer.child = MapID (ev->subwindow, idmap,
					       FromServer);
      event->u.keyButtonPointer.time = ev->time;
      event->u.keyButtonPointer.eventX = ev->x;
      event->u.keyButtonPointer.eventY = ev->y;
      event->u.keyButtonPointer.rootX = ev->x_root;
      event->u.keyButtonPointer.rootY = ev->y_root;
      event->u.keyButtonPointer.state = ev->state;
      event->u.keyButtonPointer.sameScreen = ev->same_screen;
      event->u.u.detail = ev->keycode;
    }
    break;

  case ButtonPress:
  case ButtonRelease:
    {
      register XButtonEvent *ev = (XButtonEvent *) & re->xbutton;

      event->u.keyButtonPointer.root = MapID (ev->root, idmap,
					      FromServer);
      event->u.keyButtonPointer.event = MapID (ev->window, idmap,
					       FromServer);
      event->u.keyButtonPointer.child = MapID (ev->subwindow, idmap,
					       FromServer);
      event->u.keyButtonPointer.time = ev->time;
      event->u.keyButtonPointer.eventX = ev->x;
      event->u.keyButtonPointer.eventY = ev->y;
      event->u.keyButtonPointer.rootX = ev->x_root;
      event->u.keyButtonPointer.rootY = ev->y_root;
      event->u.keyButtonPointer.state = ev->state;
      event->u.keyButtonPointer.sameScreen = ev->same_screen;
      event->u.u.detail = ev->button;
    }
    break;

  case MotionNotify:
    {
      register XMotionEvent *ev = (XMotionEvent *) & re->xmotion;

      event->u.keyButtonPointer.root = MapID (ev->root, idmap,
					      FromServer);
      event->u.keyButtonPointer.event = MapID (ev->window, idmap,
					       FromServer);
      event->u.keyButtonPointer.child = MapID (ev->subwindow, idmap,
					       FromServer);
      event->u.keyButtonPointer.time = ev->time;
      event->u.keyButtonPointer.eventX = ev->x;
      event->u.keyButtonPointer.eventY = ev->y;
      event->u.keyButtonPointer.rootX = ev->x_root;
      event->u.keyButtonPointer.rootY = ev->y_root;
      event->u.keyButtonPointer.state = ev->state;
      event->u.keyButtonPointer.sameScreen = ev->same_screen;
      event->u.u.detail = ev->is_hint;


    }
    break;

  case EnterNotify:
  case LeaveNotify:
    {
      register XCrossingEvent *ev = (XCrossingEvent *) & re->xcrossing;

      event->u.enterLeave.root = MapID (ev->root, idmap,
					FromServer);
      event->u.enterLeave.event = MapID (ev->window, idmap,
					 FromServer);

      event->u.enterLeave.child = MapID (ev->subwindow, idmap,
					 FromServer);

      event->u.enterLeave.time = ev->time;
      event->u.enterLeave.eventX = ev->x;
      event->u.enterLeave.eventY = ev->y;
      event->u.enterLeave.rootX = ev->x_root;
      event->u.enterLeave.rootY = ev->y_root;
      event->u.enterLeave.state = ev->state;
      event->u.enterLeave.mode = ev->mode;
      event->u.enterLeave.flags = 0;
      if (ev->same_screen) {
	event->u.enterLeave.flags |= ELFlagSameScreen;
      }
      if (ev->focus) {
	event->u.enterLeave.flags |= ELFlagFocus;
      }
      event->u.u.detail = ev->detail;
    }
    break;

  case FocusIn:
  case FocusOut:
    {
      register XFocusChangeEvent *ev = (XFocusChangeEvent *) & re->xfocus;

      event->u.focus.window = MapID (ev->window, idmap,
				     FromServer);
      event->u.focus.mode = ev->mode;
      event->u.u.detail = ev->detail;
    }
    break;

  case KeymapNotify:
    {
      register XKeymapEvent *ev = (XKeymapEvent *) & re->xkeymap;

      bcopy (&ev->key_vector[1],
	     (char *) (((xKeymapEvent *) event)->map),
	     sizeof (((xKeymapEvent *) event)->map));
    }
    break;

  case Expose:
    {
      register XExposeEvent *ev = (XExposeEvent *) & re->xexpose;

      event->u.expose.window = MapID (ev->window, idmap,
				      FromServer);

      event->u.expose.x = ev->x;
      event->u.expose.y = ev->y;
      event->u.expose.width = ev->width;
      event->u.expose.height = ev->height;
      event->u.expose.count = ev->count;
    }
    break;

  case GraphicsExpose:
    {
      register XGraphicsExposeEvent *ev =
      (XGraphicsExposeEvent *) & re->xgraphicsexpose;

      event->u.graphicsExposure.drawable = MapID (ev->drawable,
						  idmap, FromServer);
      event->u.graphicsExposure.x = ev->x;
      event->u.graphicsExposure.y = ev->y;
      event->u.graphicsExposure.width = ev->width;
      event->u.graphicsExposure.height = ev->height;
      event->u.graphicsExposure.count = ev->count;
      event->u.graphicsExposure.majorEvent = ev->major_code;
      event->u.graphicsExposure.minorEvent = ev->minor_code;
    }
    break;

  case NoExpose:
    {
      register XNoExposeEvent *ev = (XNoExposeEvent *) & re->xnoexpose;

      event->u.noExposure.drawable = MapID (ev->drawable, idmap,
					    FromServer);
      event->u.noExposure.majorEvent = ev->major_code;
      event->u.noExposure.minorEvent = ev->minor_code;
    }
    break;

  case VisibilityNotify:
    {
      register XVisibilityEvent *ev = (XVisibilityEvent *) & re->xvisibility;

      event->u.visibility.window = MapID (ev->window, idmap,
					  FromServer);
      event->u.visibility.state = ev->state;
    }
    break;

  case CreateNotify:
    {
      register XCreateWindowEvent *ev =
      (XCreateWindowEvent *) & re->xcreatewindow;

      event->u.createNotify.window = MapID (ev->window, idmap,
					    FromServer);
      event->u.createNotify.parent = MapID (ev->parent, idmap,
					    FromServer);
      event->u.createNotify.x = ev->x;
      event->u.createNotify.y = ev->y;
      event->u.createNotify.width = ev->width;
      event->u.createNotify.height = ev->height;
      event->u.createNotify.borderWidth = ev->border_width;
      event->u.createNotify.override = ev->override_redirect;
    }
    break;

  case DestroyNotify:
    {
      register XDestroyWindowEvent *ev =
      (XDestroyWindowEvent *) & re->xdestroywindow;

      event->u.destroyNotify.window = MapID (ev->window, idmap,
					     FromServer);
      event->u.destroyNotify.event = MapID (ev->event, idmap,
					    FromServer);
    }
    break;

  case UnmapNotify:
    {
      register XUnmapEvent *ev = (XUnmapEvent *) & re->xunmap;

      event->u.unmapNotify.window = MapID (ev->window, idmap,
					   FromServer);
      event->u.unmapNotify.event = MapID (ev->event, idmap,
					  FromServer);
      event->u.unmapNotify.fromConfigure = ev->from_configure;
    }
    break;

  case MapNotify:
    {
      register XMapEvent *ev = (XMapEvent *) & re->xmap;

      event->u.mapNotify.window = MapID (ev->window, idmap,
					 FromServer);
      event->u.mapNotify.event = MapID (ev->event, idmap,
					FromServer);

      event->u.mapNotify.override = ev->override_redirect;
    }
    break;

  case MapRequest:
    {
      register XMapRequestEvent *ev = (XMapRequestEvent *) & re->xmaprequest;

      event->u.mapRequest.window = MapID (ev->window, idmap,
					  FromServer);
      event->u.mapRequest.parent = MapID (ev->parent, idmap,
					  FromServer);
    }
    break;

  case ReparentNotify:
    {
      register XReparentEvent *ev = (XReparentEvent *) & re->xreparent;

      event->u.reparent.window = MapID (ev->window, idmap,
					FromServer);
      event->u.reparent.event = MapID (ev->event, idmap,
				       FromServer);

      if ((event->u.reparent.parent = MapID (ev->parent, idmap,
					     FromServer)) == InvalidID) {
				/* a new ID (probably from the WM)
				 * -> register it */
	InsertID (ev->parent, ev->parent, idmap, FromClient);
	InsertID (ev->parent, ev->parent, idmap, FromServer);
	event->u.reparent.parent = ev->parent;
      }
      event->u.reparent.x = ev->x;
      event->u.reparent.y = ev->y;
      event->u.reparent.override = ev->override_redirect;
    }
    break;

  case ConfigureNotify:
    {
      register XConfigureEvent *ev = (XConfigureEvent *) & re->xconfigure;

      event->u.configureNotify.window = MapID (ev->window, idmap,
					       FromServer);
      event->u.configureNotify.event = MapID (ev->event, idmap,
					      FromServer);
      if ((event->u.configureNotify.aboveSibling =
	   MapID (ev->above, idmap, FromServer)) == InvalidID) {
				/* a new ID
				 * -> register it */
	InsertID (ev->above, ev->above, idmap, FromServer);
	InsertID (ev->above, ev->above, idmap, FromClient);
	event->u.configureNotify.aboveSibling = ev->above;
      }
      event->u.configureNotify.x = ev->x;
      event->u.configureNotify.y = ev->y;
      event->u.configureNotify.width = ev->width;
      event->u.configureNotify.height = ev->height;
      event->u.configureNotify.borderWidth = ev->border_width;
      event->u.configureNotify.override = ev->override_redirect;
    }
    break;

  case ConfigureRequest:
    {
      register XConfigureRequestEvent *ev =
      (XConfigureRequestEvent *) & re->xconfigurerequest;

      event->u.configureRequest.window = MapID (ev->window, idmap,
						FromServer);
      event->u.configureRequest.parent = MapID (ev->parent, idmap,
						FromServer);
      event->u.configureRequest.sibling = MapID (ev->above, idmap,
						 FromServer);
      event->u.configureRequest.x = ev->x;
      event->u.configureRequest.y = ev->y;
      event->u.configureRequest.width = ev->width;
      event->u.configureRequest.height = ev->height;
      event->u.configureRequest.borderWidth = ev->border_width;
      event->u.configureRequest.valueMask = ev->value_mask;
      event->u.u.detail = ev->detail;
    }
    break;

  case GravityNotify:
    {
      register XGravityEvent *ev = (XGravityEvent *) & re->xgravity;

      event->u.gravity.window = MapID (ev->window, idmap,
				       FromServer);
      event->u.gravity.event = MapID (ev->event, idmap,
				      FromServer);
      event->u.gravity.x = ev->x;
      event->u.gravity.y = ev->y;
    }
    break;

  case ResizeRequest:
    {
      register XResizeRequestEvent *ev =
      (XResizeRequestEvent *) & re->xresizerequest;

      event->u.resizeRequest.window = MapID (ev->window, idmap,
					     FromServer);
      event->u.resizeRequest.width = ev->width;
      event->u.resizeRequest.height = ev->height;
    }
    break;

  case CirculateNotify:
    {
      register XCirculateEvent *ev = (XCirculateEvent *) & re->xcirculate;

      event->u.circulate.window = MapID (ev->window, idmap,
					 FromServer);
      event->u.circulate.event = MapID (ev->event, idmap,
					FromServer);
      event->u.circulate.place = ev->place;
    }
    break;

  case CirculateRequest:
    {
      register XCirculateRequestEvent *ev =
      (XCirculateRequestEvent *) & re->xcirculaterequest;

      event->u.circulate.window = MapID (ev->window, idmap,
					 FromServer);
      event->u.circulate.event = MapID (ev->parent, idmap,
					FromServer);
      event->u.circulate.place = ev->place;
    }
    break;

  case PropertyNotify:
    {
      register XPropertyEvent *ev = (XPropertyEvent *) & re->xproperty;

      event->u.property.window = MapID (ev->window, idmap,
					FromServer);
      event->u.property.atom = ev->atom;
      event->u.property.time = ev->time;
      event->u.property.state = ev->state;
    }
    break;

  case SelectionClear:
    {
      register XSelectionClearEvent *ev =
      (XSelectionClearEvent *) & re->xselectionclear;

      event->u.selectionClear.window = MapID (ev->window, idmap,
					      FromServer);
      event->u.selectionClear.atom = ev->selection;
      event->u.selectionClear.time = ev->time;
    }
    break;

  case SelectionRequest:
    {
      register XSelectionRequestEvent *ev =
      (XSelectionRequestEvent *) & re->xselectionrequest;

      event->u.selectionRequest.owner = MapID (ev->owner, idmap,
					       FromServer);
      event->u.selectionRequest.requestor = MapID (ev->requestor, idmap,
						   FromServer);
      event->u.selectionRequest.selection = ev->selection;
      event->u.selectionRequest.target = ev->target;
      event->u.selectionRequest.property = ev->property;
      event->u.selectionRequest.time = ev->time;
    }
    break;

  case SelectionNotify:
    {
      register XSelectionEvent *ev =
      (XSelectionEvent *) & re->xselection;

      event->u.selectionNotify.requestor = MapID (ev->requestor,
						  idmap,
						  FromServer);
      event->u.selectionNotify.selection = ev->selection;
      event->u.selectionNotify.target = ev->target;
      event->u.selectionNotify.property = ev->property;
      event->u.selectionNotify.time = ev->time;
    }
    break;

  case ColormapNotify:
    {
      register XColormapEvent *ev = (XColormapEvent *) & re->xcolormap;

      event->u.colormap.window = MapID (ev->window, idmap,
					FromServer);
      event->u.colormap.colormap = MapID (ev->colormap, idmap,
					  FromServer);
      event->u.colormap.new = ev->new;
      event->u.colormap.state = ev->state;
    }
    break;

  case ClientMessage:
    {
      register int i;
      register XClientMessageEvent *ev =
      (XClientMessageEvent *) & re->xclient;

      event->u.clientMessage.window = MapID (ev->window, idmap,
					     FromServer);
      event->u.u.detail = ev->format;
      switch (ev->format) {
      case 8:
	event->u.clientMessage.u.b.type = ev->message_type;
	for (i = 0; i < 20; i++)
	  event->u.clientMessage.u.b.bytes[i] = ev->data.b[i];
	break;
      case 16:
	event->u.clientMessage.u.s.type = ev->message_type;
	event->u.clientMessage.u.s.shorts0 = ev->data.s[0];
	event->u.clientMessage.u.s.shorts1 = ev->data.s[1];
	event->u.clientMessage.u.s.shorts2 = ev->data.s[2];
	event->u.clientMessage.u.s.shorts3 = ev->data.s[3];
	event->u.clientMessage.u.s.shorts4 = ev->data.s[4];
	event->u.clientMessage.u.s.shorts5 = ev->data.s[5];
	event->u.clientMessage.u.s.shorts6 = ev->data.s[6];
	event->u.clientMessage.u.s.shorts7 = ev->data.s[7];
	event->u.clientMessage.u.s.shorts8 = ev->data.s[8];
	event->u.clientMessage.u.s.shorts9 = ev->data.s[9];
	break;
      case 32:
	event->u.clientMessage.u.l.type = ev->message_type;
	event->u.clientMessage.u.l.longs0 = ev->data.l[0];
	event->u.clientMessage.u.l.longs1 = ev->data.l[1];
	event->u.clientMessage.u.l.longs2 = ev->data.l[2];
	event->u.clientMessage.u.l.longs3 = ev->data.l[3];
	event->u.clientMessage.u.l.longs4 = ev->data.l[4];
	break;
      default:
	/* client passing bogus data, let server complain */
	break;
      }
    }
    break;

  case MappingNotify:
    {
      register XMappingEvent *ev = (XMappingEvent *) & re->xmapping;

      event->u.mappingNotify.firstKeyCode = ev->first_keycode;
      event->u.mappingNotify.request = ev->request;
      event->u.mappingNotify.count = ev->count;
    }
    break;

  default:
    return (0);
  }

  /*
   * Compute sequence number (except for KeymapNotify events).  We must
   * take into account that the server connection we use to talk to a real
   * X server is some numbers "ahead" (this amount is stored in a global
   * array "ServerAhead").  We want to avoid clients (Xlib respectively)
   * complaining "Xlib: sequence lost (x > y) in reply type z"
   */
  if (re->type != KeymapNotify)
    event->u.u.sequenceNumber = client->sequence;
  /* mark if event is a send event */
  if (((XAnyEvent *) re)->send_event)
    event->u.u.type |= 0x80;

  return (1);
}


NotImplementedEvent (dpy, event)
  Display *dpy;
  XEvent *event;
{
  ErrorF ("Not implemented event !\n");
}

_ProcKeyEvent (dpy, event)	/* 2/3 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }

  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.keyButtonPointer.event);
}

_ProcButtonEvent (dpy, event)	/* 4/5 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.keyButtonPointer.event);
}

_ProcMotionNotifyEvent (dpy, event)	/* 6 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.keyButtonPointer.event);
}

_ProcEnterLeaveEvent (dpy, event)	/* 7/8 */
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.enterLeave.event);
}

_ProcFocusEvent (dpy, event)	/* 9/10 */
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event, ret_event.u.focus.window);
}

_ProcKeymapNotifyEvent (dpy, event)	/* 11 */
  XEvent *event;
{
  xKeymapEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }

  /*
   * We can't use DeliverEvent here, because casting ret_event to the
   * type xEvent yields an error
   */
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ((XAnyEvent *) event)->serial);
  WriteToClient (ClientFromDisplay (dpy),
		 sizeof (xKeymapEvent), (char *) &ret_event);
  debug (_debug_events, "delivered\n");
}

_ProcExposeEvent (dpy, event)	/* 12 */
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.expose.window);
}

_ProcGraphicsExposeEvent (dpy, event)	/* 13 */
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.graphicsExposure.drawable);
}

_ProcNoExposeEvent (dpy, event)	/* 14 */
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.noExposure.drawable);
}

_ProcVisibilityNotifyEvent (dpy, event)	/* 15 */
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.visibility.window);
}

_ProcCreateNotifyEvent (dpy, event)	/* 16 */
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  /* the parent window has to be informed about the creation */
  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.createNotify.parent);
}

_ProcDestroyNotifyEvent (dpy, event)	/* 17 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event, event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.destroyNotify.event);
}

_ProcUnmapNotifyEvent (dpy, event)	/* 18 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.unmapNotify.event);
}

_ProcMapNotifyEvent (dpy, event)/* 19 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.mapNotify.event);
}

_ProcMapRequestEvent (dpy, event)	/* 20 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.mapRequest.window);
}

_ProcReparentNotifyEvent (dpy, event)	/* 21 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.reparent.event);
}

_ProcConfigureNotifyEvent (dpy, event)	/* 22 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.configureNotify.event);
}

_ProcConfigureRequestEvent (dpy, event)	/* 23 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.configureRequest.window);
}

_ProcGravityNotifyEvent (dpy, event)	/* 24 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.gravity.event);
}

_ProcResizeRequestEvent (dpy, event)	/* 25 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.resizeRequest.window);
}

_ProcCirculateNotifyEvent (dpy, event)	/* 26 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.circulate.event);
}

_ProcCirculateRequestEvent (dpy, event)	/* 27 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  /* event field is the parent when this is used as a CirculateRequest */
  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.circulate.parent);
}

_ProcPropertyNotifyEvent (dpy, event)	/* 28 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.property.window);
}

_ProcSelectionClearEvent (dpy, event)	/* 29 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.selectionClear.window);
}

_ProcSelectionRequestEvent (dpy, event)	/* 30 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.selectionRequest.requestor);
}

_ProcSelectionNotifyEvent (dpy, event)	/* 31 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.selectionNotify.requestor);
}

_ProcColormapNotifyEvent (dpy, event)	/* 32 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.colormap.window);
}

_ProcClientMessageEvent (dpy, event)	/* 33 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event,
		ret_event.u.clientMessage.window);
}

_ProcMappingNotifyEvent (dpy, event)	/* 34 */
  Display *dpy;
  XEvent *event;
{
  xEvent ret_event;

  if (!EventToWire (dpy, event, &ret_event)) {
    ErrorF ("Unknown event type %d!\n", event->type);
    return;
  }
  debug (_debug_events, "%s...(# 0x%lx)...", X11EventNames[event->type],
	 ret_event.u.u.sequenceNumber);

  DeliverEvent (ClientFromDisplay (dpy), &ret_event, None);
}
