/* Copyright 2001-2003 by Norbert Freudemann, David Frese */

#include "xlib.h"

#define EENTER(c, i, n, f) s48_record_set_2(c, e, i, f(c, xe->n))

#define EENTER_START(c, rtype, dbundle) \
  s48_ref_t e = s48_make_record_2(c, rtype); \
  EENTER(c, 0, type, scx_enter_event_type); \
  EENTER(c, 1, serial, s48_enter_long_2); \
  EENTER(c, 2, send_event, s48_enter_boolean_2); \
  s48_record_set_2(c, e, 3, scx_enter_display(c, dbundle));

#define EENTER_END() \
  return e

s48_ref_t scx_key_event_binding = NULL;

s48_ref_t scx_enter_key_event(s48_call_t call, XKeyEvent* xe,
			      scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_key_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, root, scx_enter_window);
  EENTER(call, 6, subwindow, scx_enter_window);
  EENTER(call, 7, time, scx_enter_time);
  EENTER(call, 8, x, s48_enter_long_2);
  EENTER(call, 9, y, s48_enter_long_2);
  EENTER(call, 10, x_root, s48_enter_long_2);
  EENTER(call, 11, y_root, s48_enter_long_2);
  EENTER(call, 12, state, scx_enter_state_set);
  EENTER(call, 13, keycode, scx_enter_keycode);
  EENTER(call, 14, same_screen, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_button_event_binding = NULL;

s48_ref_t scx_enter_button_event(s48_call_t call, XButtonEvent* xe,
				 scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_button_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, root, scx_enter_window);
  EENTER(call, 6, subwindow, scx_enter_window);
  EENTER(call, 7, time, scx_enter_time);
  EENTER(call, 8, x, s48_enter_long_2);
  EENTER(call, 9, y, s48_enter_long_2);
  EENTER(call, 10, x_root, s48_enter_long_2);
  EENTER(call, 11, y_root, s48_enter_long_2);
  EENTER(call, 12, state, scx_enter_state_set);
  EENTER(call, 13, button, scx_enter_button);
  EENTER(call, 14, same_screen, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_motion_event_binding = NULL;

s48_ref_t scx_enter_motion_event(s48_call_t call, XMotionEvent* xe,
				 scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_motion_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, root, scx_enter_window);
  EENTER(call, 6, subwindow, scx_enter_window);
  EENTER(call, 7, time, scx_enter_time);
  EENTER(call, 8, x, s48_enter_long_2);
  EENTER(call, 9, y, s48_enter_long_2);
  EENTER(call, 10, x_root, s48_enter_long_2);
  EENTER(call, 11, y_root, s48_enter_long_2);
  EENTER(call, 12, state, scx_enter_state_set);
  EENTER(call, 13, is_hint, s48_enter_boolean_2);
  EENTER(call, 14, same_screen, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_crossing_event_binding = NULL;

s48_ref_t scx_enter_crossing_event(s48_call_t call, XCrossingEvent* xe,
				   scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_crossing_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, root, scx_enter_window);
  EENTER(call, 6, subwindow, scx_enter_window);
  EENTER(call, 7, time, scx_enter_time);
  EENTER(call, 8, x, s48_enter_long_2);
  EENTER(call, 9, y, s48_enter_long_2);
  EENTER(call, 10, x_root, s48_enter_long_2);
  EENTER(call, 11, y_root, s48_enter_long_2);
  EENTER(call, 12, mode, scx_enter_notify_mode);
  EENTER(call, 13, detail, scx_enter_notify_detail);
  EENTER(call, 14, same_screen, s48_enter_boolean_2);
  EENTER(call, 15, focus, s48_enter_boolean_2);
  EENTER(call, 16, state, scx_enter_state_set);
  EENTER_END();
}

s48_ref_t scx_focus_change_event_binding = NULL;

s48_ref_t scx_enter_focus_change_event(s48_call_t call, XFocusChangeEvent* xe,
				       scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_focus_change_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, mode, scx_enter_notify_mode);
  EENTER(call, 6, detail, scx_enter_notify_detail);
  EENTER_END();
}

s48_ref_t scx_expose_event_binding = NULL;

s48_ref_t scx_enter_expose_event(s48_call_t call, XExposeEvent* xe,
				 scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_expose_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, x, s48_enter_long_2);
  EENTER(call, 6, y, s48_enter_long_2);
  EENTER(call, 7, width, s48_enter_long_2);
  EENTER(call, 8, height, s48_enter_long_2);
  EENTER(call, 9, count, s48_enter_long_2);
  EENTER_END();
}

s48_ref_t scx_graphics_expose_event_binding = NULL;

s48_ref_t scx_enter_graphics_expose_event(s48_call_t call, XGraphicsExposeEvent* xe,
					  scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_graphics_expose_event_binding, display_bundle);
  EENTER(call, 4, drawable, scx_enter_drawable);
  EENTER(call, 5, x, s48_enter_long_2);
  EENTER(call, 6, y, s48_enter_long_2);
  EENTER(call, 7, width, s48_enter_long_2);
  EENTER(call, 8, height, s48_enter_long_2);
  EENTER(call, 9, count, s48_enter_long_2);
  EENTER(call, 10, major_code, s48_enter_long_2);
  EENTER(call, 11, minor_code, s48_enter_long_2);
  EENTER_END();
}

s48_ref_t scx_no_expose_event_binding = NULL;

s48_ref_t scx_enter_no_expose_event(s48_call_t call, XNoExposeEvent* xe,
				    scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_no_expose_event_binding, display_bundle);
  EENTER(call, 4, drawable, scx_enter_drawable);
  EENTER(call, 5, major_code, s48_enter_long_2);
  EENTER(call, 6, minor_code, s48_enter_long_2);
  EENTER_END();
}

s48_ref_t scx_visibility_event_binding = NULL;

s48_ref_t scx_enter_visibility_event(s48_call_t call, XVisibilityEvent* xe,
				     scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_visibility_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, state, scx_enter_visibility_state);
  EENTER_END();
}

s48_ref_t scx_create_window_event_binding = NULL;

s48_ref_t scx_enter_create_window_event(s48_call_t call, XCreateWindowEvent* xe,
					scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_create_window_event_binding, display_bundle);
  EENTER(call, 4, parent, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, x, s48_enter_long_2);
  EENTER(call, 7, y, s48_enter_long_2);
  EENTER(call, 8, width, s48_enter_long_2);
  EENTER(call, 9, height, s48_enter_long_2);
  EENTER(call, 10, border_width, s48_enter_long_2);
  EENTER(call, 11, override_redirect, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_destroy_window_event_binding = NULL;

s48_ref_t scx_enter_destroy_window_event(s48_call_t call, XDestroyWindowEvent* xe,
					 scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_destroy_window_event_binding, display_bundle);
  EENTER(call, 4, event, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER_END();
}

s48_ref_t scx_unmap_event_binding = NULL;

s48_ref_t scx_enter_unmap_event(s48_call_t call, XUnmapEvent* xe,
				scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_unmap_event_binding, display_bundle);
  EENTER(call, 4, event, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, from_configure, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_map_event_binding = NULL;

s48_ref_t scx_enter_map_event(s48_call_t call, XMapEvent* xe,
			      scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_map_event_binding, display_bundle);
  EENTER(call, 4, event, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, override_redirect, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_map_request_event_binding = NULL;

s48_ref_t scx_enter_map_request_event(s48_call_t call, XMapRequestEvent* xe,
				      scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_map_request_event_binding, display_bundle);
  EENTER(call, 4, parent, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER_END();
}

s48_ref_t scx_reparent_event_binding = NULL;

s48_ref_t scx_enter_reparent_event(s48_call_t call, XReparentEvent* xe,
				   scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_reparent_event_binding, display_bundle);
  EENTER(call, 4, event, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, parent, scx_enter_window);
  EENTER(call, 7, x, s48_enter_long_2);
  EENTER(call, 8, y, s48_enter_long_2);
  EENTER(call, 9, override_redirect, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_configure_event_binding = NULL;

s48_ref_t scx_enter_configure_event(s48_call_t call, XConfigureEvent* xe,
				    scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_configure_event_binding, display_bundle);
  EENTER(call, 4, event, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, x, s48_enter_long_2);
  EENTER(call, 7, y, s48_enter_long_2);
  EENTER(call, 8, width, s48_enter_long_2);
  EENTER(call, 9, height, s48_enter_long_2);
  EENTER(call, 10, border_width, s48_enter_long_2);
  EENTER(call, 11, above, scx_enter_window);
  EENTER(call, 12, override_redirect, s48_enter_boolean_2);
  EENTER_END();
}

s48_ref_t scx_gravity_event_binding = NULL;

s48_ref_t scx_enter_gravity_event(s48_call_t call, XGravityEvent* xe,
				  scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_gravity_event_binding, display_bundle);
  EENTER(call, 4, event, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, x, s48_enter_long_2);
  EENTER(call, 7, y, s48_enter_long_2);
  EENTER_END();
}

s48_ref_t scx_resize_request_event_binding = NULL;

s48_ref_t scx_enter_resize_request_event(s48_call_t call, XResizeRequestEvent* xe,
					 scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_resize_request_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, width, s48_enter_long_2);
  EENTER(call, 6, height, s48_enter_long_2);
  EENTER_END();
}

s48_ref_t scx_configure_request_event_binding = NULL;

s48_ref_t scx_enter_configure_request_event(s48_call_t call, XConfigureRequestEvent* xe,
					    scx_event_bundle *display_bundle) {
  XWindowChanges WC;
  EENTER_START(call, scx_configure_request_event_binding, display_bundle);
  EENTER(call, 4, parent, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  WC.x = xe->x;
  WC.y = xe->y;
  WC.width = xe->width;
  WC.height = xe->height;
  WC.border_width = xe->border_width;
  WC.sibling = xe->above;
  WC.stack_mode = xe->detail;
  s48_record_set_2(call, e, 6, 
		   scx_enter_window_changes(call, &WC, xe->value_mask));
  EENTER_END();
}

s48_ref_t scx_circulate_event_binding = NULL;

s48_ref_t scx_enter_circulate_event(s48_call_t call, XCirculateEvent* xe,
				    scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_circulate_event_binding, display_bundle);
  EENTER(call, 4, event, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, place, scx_enter_place);
  EENTER_END();
}

s48_ref_t scx_circulate_request_event_binding = NULL;

s48_ref_t scx_enter_circulate_request_event(s48_call_t call, 
					    XCirculateRequestEvent* xe,
					    scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_circulate_request_event_binding, display_bundle);
  EENTER(call, 4, parent, scx_enter_window);
  EENTER(call, 5, window, scx_enter_window);
  EENTER(call, 6, place, scx_enter_place);
  EENTER_END();
}

s48_ref_t scx_property_event_binding = NULL;

s48_ref_t scx_enter_property_event(s48_call_t call, XPropertyEvent* xe,
				  scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_property_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, atom, scx_enter_atom);
  EENTER(call, 6, time, scx_enter_time);
  EENTER(call, 7, state, scx_enter_property_state);
  EENTER_END();
}

s48_ref_t scx_selection_clear_event_binding = NULL;

s48_ref_t scx_enter_selection_clear_event(s48_call_t call, 
					  XSelectionClearEvent* xe,
					  scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_selection_clear_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, selection, scx_enter_atom);
  EENTER(call, 6, time, scx_enter_time);
  EENTER_END();
}

s48_ref_t scx_selection_request_event_binding = NULL;

s48_ref_t scx_enter_selection_request_event(s48_call_t call, 
					    XSelectionRequestEvent* xe,
					    scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_selection_request_event_binding, display_bundle);
  EENTER(call, 4, owner, scx_enter_window);
  EENTER(call, 5, requestor, scx_enter_window);
  EENTER(call, 6, selection, scx_enter_atom);
  EENTER(call, 7, target, scx_enter_atom);
  EENTER(call, 8, property, scx_enter_atom);
  EENTER(call, 9, time, scx_enter_time);
  EENTER_END();
}

s48_ref_t scx_selection_event_binding = NULL;

s48_ref_t scx_enter_selection_event(s48_call_t call, XSelectionEvent* xe,
				    scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_selection_event_binding, display_bundle);
  EENTER(call, 4, requestor, scx_enter_window);
  EENTER(call, 5, selection, scx_enter_atom);
  EENTER(call, 6, target, scx_enter_atom);
  EENTER(call, 7, property, scx_enter_atom);
  EENTER(call, 8, time, scx_enter_time);
  EENTER_END();
}

s48_ref_t scx_colormap_event_binding = NULL;

s48_ref_t scx_enter_colormap_event(s48_call_t call, XColormapEvent* xe,
				   scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_colormap_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, colormap, scx_enter_colormap);
  EENTER(call, 6, new, s48_enter_boolean_2);
  EENTER(call, 7, state, scx_enter_colormap_state);
  EENTER_END();
}

s48_ref_t scx_client_message_event_binding = NULL;

s48_ref_t scx_enter_client_message_event(s48_call_t call, 
					 XClientMessageEvent* xe,scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_client_message_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  s48_record_set_2(call, e, 5, scx_enter_property(call, xe->message_type,
					  xe->format,
					  xe->data.b,
					  (20 / (xe->format >> 3))));
  EENTER_END();
}

s48_ref_t scx_mapping_event_binding = NULL;

s48_ref_t scx_enter_mapping_event(s48_call_t call, XMappingEvent* xe,
				  scx_event_bundle *display_bundle) {
  EENTER_START(call, scx_mapping_event_binding, display_bundle);
  EENTER(call, 4, window, scx_enter_window);
  EENTER(call, 5, request, scx_enter_mapping_request);
  EENTER(call, 6, first_keycode, scx_enter_keycode);
  EENTER(call, 7, count, s48_enter_long_2);
  EENTER_END();
}

s48_ref_t scx_keymap_event_binding = NULL;

s48_ref_t scx_enter_keymap_event(s48_call_t call, XKeymapEvent* xe,
				 scx_event_bundle *display_bundle) {
  s48_ref_t temp; int i;
  EENTER_START(call, scx_keymap_event_binding, display_bundle);
  temp = s48_make_vector_2(call, 32*8, s48_enter_long_as_fixnum_2(call, 0));
  for (i = 0; i < 32; i++) {
    int j; char b = xe->key_vector[i];
    for (j = 0; j < 8; j++)
      s48_vector_set_2(call, temp, i*8 + j, 
	   s48_enter_long_as_fixnum_2(call, (b & (1 << j)) ? 1 : 0));
  }
  s48_record_set_2(call, e, 4, temp);
  EENTER_END();
}

s48_ref_t scx_enter_event(s48_call_t call, XEvent* e, 
			  scx_event_bundle* bundle) {
  switch (e->type) {
  case KeyPress : case KeyRelease :
    return scx_enter_key_event(call, (XKeyEvent*)e, bundle);
  case ButtonPress : case ButtonRelease :
    return scx_enter_button_event(call, (XButtonEvent*)e, bundle);
  case MotionNotify :
    return scx_enter_motion_event(call, (XMotionEvent*)e, bundle);
  case EnterNotify : case LeaveNotify :
    return scx_enter_crossing_event(call, (XCrossingEvent*)e, bundle);
  case FocusIn : case FocusOut :
    return scx_enter_focus_change_event(call, (XFocusChangeEvent*)e, bundle);
  case KeymapNotify :
    return scx_enter_keymap_event(call, (XKeymapEvent*)e, bundle);
  case Expose :
    return scx_enter_expose_event(call, (XExposeEvent*)e, bundle);
  case GraphicsExpose :
    return scx_enter_graphics_expose_event(call, (XGraphicsExposeEvent*)e, bundle);
  case NoExpose :
    return scx_enter_no_expose_event(call, (XNoExposeEvent*)e, bundle);
  case VisibilityNotify :
    return scx_enter_visibility_event(call, (XVisibilityEvent*)e, bundle);
  case CreateNotify :
    return scx_enter_create_window_event(call, (XCreateWindowEvent*)e, bundle);
  case DestroyNotify :
    return scx_enter_destroy_window_event(call, (XDestroyWindowEvent*)e, bundle);
  case UnmapNotify :
    return scx_enter_unmap_event(call, (XUnmapEvent*)e, bundle);
  case MapNotify :
    return scx_enter_map_event(call, (XMapEvent*)e, bundle);
  case MapRequest :
    return scx_enter_map_request_event(call, (XMapRequestEvent*)e, bundle);
  case ReparentNotify :
    return scx_enter_reparent_event(call, (XReparentEvent*)e, bundle);
  case ConfigureNotify :
    return scx_enter_configure_event(call, (XConfigureEvent*)e, bundle);
  case ConfigureRequest :
    return scx_enter_configure_request_event(call, (XConfigureRequestEvent*)e, bundle);
  case GravityNotify :
    return scx_enter_gravity_event(call, (XGravityEvent*)e, bundle);
  case ResizeRequest :
    return scx_enter_resize_request_event(call, (XResizeRequestEvent*)e, bundle);
  case CirculateRequest :
    return scx_enter_circulate_request_event(call, (XCirculateRequestEvent*)e, bundle);
  case PropertyNotify :
    return scx_enter_property_event(call, (XPropertyEvent*)e, bundle);
  case SelectionClear :
    return scx_enter_selection_clear_event(call, (XSelectionClearEvent*)e, bundle);
  case SelectionRequest :
    return scx_enter_selection_request_event(call, (XSelectionRequestEvent*)e, bundle);
  case SelectionNotify :
    return scx_enter_selection_event(call, (XSelectionEvent*)e, bundle);
  case ColormapNotify :
    return scx_enter_colormap_event(call, (XColormapEvent*)e, bundle);
  case ClientMessage :
    return scx_enter_client_message_event(call, (XClientMessageEvent*)e, bundle);
  case MappingNotify :
    return scx_enter_mapping_event(call, (XMappingEvent*)e, bundle);
  default: return s48_false_2(call);
  } /* switch end */
}

/*** extraction ****************************************************/

#define EEXTRACT(c, i, name, f) xe->name = f(c, s48_record_ref_2(c, e, i))
#define EEXTRACT_START(c, rtype) \
  s48_check_record_type_2(c, e, rtype); \
  EEXTRACT(c, 0, type, scx_extract_event_type); \
  EEXTRACT(c, 1, serial, s48_extract_long_2); \
  EEXTRACT(c, 2, send_event, s48_extract_boolean_2); \
  EEXTRACT(c, 3, display, scx_extract_display)
  
void scx_extract_key_event(s48_call_t call, s48_ref_t e, XKeyEvent* xe) {
  EEXTRACT_START(call, scx_key_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, root, scx_extract_window);
  EEXTRACT(call, 6, subwindow, scx_extract_window);
  EEXTRACT(call, 7, time, scx_extract_time);
  EEXTRACT(call, 8, x, s48_extract_long_2);
  EEXTRACT(call, 9, y, s48_extract_long_2);
  EEXTRACT(call, 10, x_root, s48_extract_long_2);
  EEXTRACT(call, 11, y_root, s48_extract_long_2);
  EEXTRACT(call, 12, state, scx_extract_state_set);
  EEXTRACT(call, 13, keycode, scx_extract_keycode);
  EEXTRACT(call, 14, same_screen, s48_extract_boolean_2);
 
}

void scx_extract_button_event(s48_call_t call, s48_ref_t e, XButtonEvent* xe) {
  EEXTRACT_START(call, scx_button_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, root, scx_extract_window);
  EEXTRACT(call, 6, subwindow, scx_extract_window);
  EEXTRACT(call, 7, time, scx_extract_time);
  EEXTRACT(call, 8, x, s48_extract_long_2);
  EEXTRACT(call, 9, y, s48_extract_long_2);
  EEXTRACT(call, 10, x_root, s48_extract_long_2);
  EEXTRACT(call, 11, y_root, s48_extract_long_2);
  EEXTRACT(call, 12, state, scx_extract_state_set);
  EEXTRACT(call, 13, button, scx_extract_button);
  EEXTRACT(call, 14, same_screen, s48_extract_boolean_2);
 
}

void scx_extract_motion_event(s48_call_t call, s48_ref_t e, XMotionEvent* xe) {
  EEXTRACT_START(call, scx_motion_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, root, scx_extract_window);
  EEXTRACT(call, 6, subwindow, scx_extract_window);
  EEXTRACT(call, 7, time, scx_extract_time);
  EEXTRACT(call, 8, x, s48_extract_long_2);
  EEXTRACT(call, 9, y, s48_extract_long_2);
  EEXTRACT(call, 10, x_root, s48_extract_long_2);
  EEXTRACT(call, 11, y_root, s48_extract_long_2);
  EEXTRACT(call, 12, state, scx_extract_state_set);
  EEXTRACT(call, 13, is_hint, s48_extract_boolean_2);
  EEXTRACT(call, 14, same_screen, s48_extract_boolean_2);
 
}

void scx_extract_crossing_event(s48_call_t call, s48_ref_t e, XCrossingEvent* xe) {
  EEXTRACT_START(call, scx_crossing_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, root, scx_extract_window);
  EEXTRACT(call, 6, subwindow, scx_extract_window);
  EEXTRACT(call, 7, time, scx_extract_time);
  EEXTRACT(call, 8, x, s48_extract_long_2);
  EEXTRACT(call, 9, y, s48_extract_long_2);
  EEXTRACT(call, 10, x_root, s48_extract_long_2);
  EEXTRACT(call, 11, y_root, s48_extract_long_2);
  EEXTRACT(call, 12, mode, scx_extract_notify_mode);
  EEXTRACT(call, 13, detail, scx_extract_notify_detail);
  EEXTRACT(call, 14, same_screen, s48_extract_boolean_2);
  EEXTRACT(call, 15, focus, s48_extract_boolean_2);
  EEXTRACT(call, 16, state, scx_extract_state_set);
 
}

void scx_extract_focus_change_event(s48_call_t call, s48_ref_t e, 
       XFocusChangeEvent* xe) {
  EEXTRACT_START(call, scx_focus_change_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, mode, scx_extract_notify_mode);
  EEXTRACT(call, 6, detail, scx_extract_notify_detail);
 
}

void scx_extract_expose_event(s48_call_t call, s48_ref_t e, XExposeEvent* xe) {
  EEXTRACT_START(call, scx_expose_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, x, s48_extract_long_2);
  EEXTRACT(call, 6, y, s48_extract_long_2);
  EEXTRACT(call, 7, width, s48_extract_long_2);
  EEXTRACT(call, 8, height, s48_extract_long_2);
  EEXTRACT(call, 9, count, s48_extract_long_2);
 
}

void scx_extract_graphics_expose_event(s48_call_t call, s48_ref_t e, 
       XGraphicsExposeEvent* xe) {
  EEXTRACT_START(call, scx_graphics_expose_event_binding);
  EEXTRACT(call, 4, drawable, scx_extract_drawable);
  EEXTRACT(call, 5, x, s48_extract_long_2);
  EEXTRACT(call, 6, y, s48_extract_long_2);
  EEXTRACT(call, 7, width, s48_extract_long_2);
  EEXTRACT(call, 8, height, s48_extract_long_2);
  EEXTRACT(call, 9, count, s48_extract_long_2);
  EEXTRACT(call, 10, major_code, s48_extract_long_2);
  EEXTRACT(call, 11, minor_code, s48_extract_long_2);
 
}

void scx_extract_no_expose_event(s48_call_t call, s48_ref_t e,
        XNoExposeEvent* xe) {
  EEXTRACT_START(call, scx_no_expose_event_binding);
  EEXTRACT(call, 4, drawable, scx_extract_drawable);
  EEXTRACT(call, 5, major_code, s48_extract_long_2);
  EEXTRACT(call, 6, minor_code, s48_extract_long_2);
 
}

void scx_extract_visibility_event(s48_call_t call, s48_ref_t e,
       XVisibilityEvent* xe) {
  EEXTRACT_START(call, scx_visibility_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, state, scx_extract_visibility_state);
 
}

void scx_extract_create_window_event(s48_call_t call, s48_ref_t e, 
       XCreateWindowEvent* xe) {
  EEXTRACT_START(call, scx_create_window_event_binding);
  EEXTRACT(call, 4, parent, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, x, s48_extract_long_2);
  EEXTRACT(call, 7, y, s48_extract_long_2);
  EEXTRACT(call, 8, width, s48_extract_long_2);
  EEXTRACT(call, 9, height, s48_extract_long_2);
  EEXTRACT(call, 10, border_width, s48_extract_long_2);
  EEXTRACT(call, 11, override_redirect, s48_extract_boolean_2);
 
}

void scx_extract_destroy_window_event(s48_call_t call, s48_ref_t e, 
       XDestroyWindowEvent* xe) {
  EEXTRACT_START(call, scx_destroy_window_event_binding);
  EEXTRACT(call, 4, event, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
 
}

void scx_extract_unmap_event(s48_call_t call, s48_ref_t e, XUnmapEvent* xe) {
  EEXTRACT_START(call, scx_unmap_event_binding);
  EEXTRACT(call, 4, event, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, from_configure, s48_extract_boolean_2);
 
}

void scx_extract_map_event(s48_call_t call, s48_ref_t e, XMapEvent* xe) {
  EEXTRACT_START(call, scx_map_event_binding);
  EEXTRACT(call, 4, event, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, override_redirect, s48_extract_boolean_2);
 
}

void scx_extract_map_request_event(s48_call_t call, s48_ref_t e,
       XMapRequestEvent* xe) {
  EEXTRACT_START(call, scx_map_request_event_binding);
  EEXTRACT(call, 4, parent, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
 
}

void scx_extract_reparent_event(s48_call_t call, s48_ref_t e, 
       XReparentEvent* xe) {
  EEXTRACT_START(call, scx_reparent_event_binding);
  EEXTRACT(call, 4, event, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, parent, scx_extract_window);
  EEXTRACT(call, 7, x, s48_extract_long_2);
  EEXTRACT(call, 8, y, s48_extract_long_2);
  EEXTRACT(call, 9, override_redirect, s48_extract_boolean_2);
 
}

void scx_extract_configure_event(s48_call_t call, s48_ref_t e, 
       XConfigureEvent* xe) {
  EEXTRACT_START(call, scx_configure_event_binding);
  EEXTRACT(call, 4, event, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, x, s48_extract_long_2);
  EEXTRACT(call, 7, y, s48_extract_long_2);
  EEXTRACT(call, 8, width, s48_extract_long_2);
  EEXTRACT(call, 9, height, s48_extract_long_2);
  EEXTRACT(call, 10, border_width, s48_extract_long_2);
  EEXTRACT(call, 11, above, scx_extract_window);
  EEXTRACT(call, 12, override_redirect, s48_extract_boolean_2);
 
}

void scx_extract_gravity_event(s48_call_t call, s48_ref_t e, XGravityEvent* xe) {
  EEXTRACT_START(call, scx_gravity_event_binding);
  EEXTRACT(call, 4, event, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, x, s48_extract_long_2);
  EEXTRACT(call, 7, y, s48_extract_long_2);
 
}

void scx_extract_resize_request_event(s48_call_t call, s48_ref_t e, 
       XResizeRequestEvent* xe) {
  EEXTRACT_START(call, scx_resize_request_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, width, s48_extract_long_2);
  EEXTRACT(call, 6, height, s48_extract_long_2);
 
}

void scx_extract_configure_request_event(s48_call_t call, s48_ref_t e,
					 XConfigureRequestEvent* xe) {
  XWindowChanges WC;
  EEXTRACT_START(call, scx_configure_request_event_binding);
  EEXTRACT(call, 4, parent, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  xe->value_mask = scx_extract_window_changes(call, 
        s48_record_ref_2(call, e, 6), &WC);
  xe->x = WC.x;
  xe->y = WC.y;
  xe->width = WC.width;
  xe->height = WC.height;
  xe->border_width = WC.border_width;
  xe->above = WC.sibling;
  xe->detail = WC.stack_mode;
 
}

void scx_extract_circulate_event(s48_call_t call, s48_ref_t e, 
       XCirculateEvent* xe) {
  EEXTRACT_START(call, scx_circulate_event_binding);
  EEXTRACT(call, 4, event, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, place, scx_extract_place);
 
}

void scx_extract_circulate_request_event(s48_call_t call, s48_ref_t e,
					 XCirculateRequestEvent* xe) {
  EEXTRACT_START(call, scx_circulate_request_event_binding);
  EEXTRACT(call, 4, parent, scx_extract_window);
  EEXTRACT(call, 5, window, scx_extract_window);
  EEXTRACT(call, 6, place, scx_extract_place);
 
}

void scx_extract_property_event(s48_call_t call, s48_ref_t e, 
       XPropertyEvent* xe) {
  EEXTRACT_START(call, scx_property_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, atom, scx_extract_atom);
  EEXTRACT(call, 6, time, scx_extract_time);
  EEXTRACT(call, 7, state, scx_extract_property_state);
 
}

void scx_extract_selection_clear_event(s48_call_t call, s48_ref_t e, 
       XSelectionClearEvent* xe) {
  EEXTRACT_START(call, scx_selection_clear_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, selection, scx_extract_atom);
  EEXTRACT(call, 6, time, scx_extract_time);
 
}

void scx_extract_selection_request_event(s48_call_t call, s48_ref_t e,
       XSelectionRequestEvent* xe) {
  EEXTRACT_START(call, scx_selection_request_event_binding);
  EEXTRACT(call, 4, owner, scx_extract_window);
  EEXTRACT(call, 5, requestor, scx_extract_window);
  EEXTRACT(call, 6, selection, scx_extract_atom);
  EEXTRACT(call, 7, target, scx_extract_atom);
  EEXTRACT(call, 8, property, scx_extract_atom);
  EEXTRACT(call, 9, time, scx_extract_time);
 
}

void scx_extract_selection_event(s48_call_t call, s48_ref_t e, 
       XSelectionEvent* xe) {
  EEXTRACT_START(call, scx_selection_event_binding);
  EEXTRACT(call, 4, requestor, scx_extract_window);
  EEXTRACT(call, 5, selection, scx_extract_atom);
  EEXTRACT(call, 6, target, scx_extract_atom);
  EEXTRACT(call, 7, property, scx_extract_atom);
  EEXTRACT(call, 8, time, scx_extract_time);
 
}

void scx_extract_colormap_event(s48_call_t call, s48_ref_t e, 
       XColormapEvent* xe) {
  EEXTRACT_START(call, scx_colormap_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, colormap, scx_extract_colormap);
  EEXTRACT(call, 6, new, s48_extract_boolean_2);
  EEXTRACT(call, 7, state, scx_extract_colormap_state);
 
}

void scx_extract_client_message_event(s48_call_t call, s48_ref_t e, 
       XClientMessageEvent* xe) {
  int nelements, i;
  char* data; int bytes;
  EEXTRACT_START(call, scx_client_message_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  scx_extract_property(call, s48_record_ref_2(call, e, 5), 
           &xe->message_type, &xe->format,
		       &data, &nelements);
  if (xe->format == 32) bytes = nelements * 4;
  else if (xe->format == 16) bytes = nelements * 2;
  else bytes = nelements;
  for (i = 0; i < 20; i++)
    if (i < bytes)
      xe->data.b[i] = data[i];
    else
      xe->data.b[i] = 0;
  free(data);
 
}

void scx_extract_mapping_event(s48_call_t call, s48_ref_t e, XMappingEvent* xe) {
  EEXTRACT_START(call, scx_mapping_event_binding);
  EEXTRACT(call, 4, window, scx_extract_window);
  EEXTRACT(call, 5, request, scx_extract_mapping_request);
  EEXTRACT(call, 6, first_keycode, scx_extract_keycode);
  EEXTRACT(call, 7, count, s48_extract_long_2);
 
}

void scx_extract_keymap_event(s48_call_t call, s48_ref_t e, XKeymapEvent* xe) 
{
  s48_ref_t temp; int i;
  EEXTRACT_START(call, scx_keymap_event_binding);
  xe->window = (Window)0;
  temp = s48_record_ref_2(call, e, 4);
  for (i = 0; i < 32; i++) {
    int j; char* b = &xe->key_vector[i];
    for (j = 0; j < 8; j++)
      *b |= (s48_extract_long_2(call, s48_vector_ref_2(call, temp, i*8 + j))
	     == 0 ? 0 : 1) << j;
  }
 
}

void scx_extract_event(s48_call_t call, s48_ref_t se, XEvent* e) {
  int t;
  t = scx_extract_event_type(call, s48_record_ref_2(call, se, 0));
  switch (t) {
  case KeyPress : case KeyRelease :
    scx_extract_key_event(call, se, (XKeyEvent*)e); break;
  case ButtonPress : case ButtonRelease :
    scx_extract_button_event(call, se, (XButtonEvent*)e); break;
  case MotionNotify :
    scx_extract_motion_event(call, se, (XMotionEvent*)e); break;
  case EnterNotify : case LeaveNotify :
    scx_extract_crossing_event(call, se, (XCrossingEvent*)e); break;
  case FocusIn : case FocusOut :
    scx_extract_focus_change_event(call, se, (XFocusChangeEvent*)e); break;
  case KeymapNotify :
    scx_extract_keymap_event(call, se, (XKeymapEvent*)e); break;
  case Expose :
    scx_extract_expose_event(call, se, (XExposeEvent*)e); break;
  case GraphicsExpose :
    scx_extract_graphics_expose_event(call, se, (XGraphicsExposeEvent*)e); break;
  case NoExpose :
    scx_extract_no_expose_event(call, se, (XNoExposeEvent*)e); break;
  case VisibilityNotify :
    scx_extract_visibility_event(call, se, (XVisibilityEvent*)e); break;
  case CreateNotify :
    scx_extract_create_window_event(call, se, (XCreateWindowEvent*)e); break;
  case DestroyNotify :
    scx_extract_destroy_window_event(call, se, (XDestroyWindowEvent*)e); break;
  case UnmapNotify :
    scx_extract_unmap_event(call, se, (XUnmapEvent*)e); break;
  case MapNotify :
    scx_extract_map_event(call, se, (XMapEvent*)e); break;
  case MapRequest :
    scx_extract_map_request_event(call, se, (XMapRequestEvent*)e); break;
  case ReparentNotify :
    scx_extract_reparent_event(call, se, (XReparentEvent*)e); break;
  case ConfigureNotify :
    scx_extract_configure_event(call, se, (XConfigureEvent*)e); break;
  case ConfigureRequest :
    scx_extract_configure_request_event(call, se, (XConfigureRequestEvent*)e); break;
  case GravityNotify :
    scx_extract_gravity_event(call, se, (XGravityEvent*)e); break;
  case ResizeRequest :
    scx_extract_resize_request_event(call, se, (XResizeRequestEvent*)e); break;
  case CirculateRequest :
    scx_extract_circulate_request_event(call, se, (XCirculateRequestEvent*)e); break;
  case PropertyNotify :
    scx_extract_property_event(call, se, (XPropertyEvent*)e); break;
  case SelectionClear :
    scx_extract_selection_clear_event(call, se, (XSelectionClearEvent*)e); break;
  case SelectionRequest :
    scx_extract_selection_request_event(call, se, (XSelectionRequestEvent*)e); break;
  case SelectionNotify :
    scx_extract_selection_event(call, se, (XSelectionEvent*)e); break;
  case ColormapNotify :
    scx_extract_colormap_event(call, se, (XColormapEvent*)e); break;
  case ClientMessage :
    scx_extract_client_message_event(call, se, (XClientMessageEvent*)e); break;
  case MappingNotify :
    scx_extract_mapping_event(call, se, (XMappingEvent*)e); break;
  }
}

void scx_init_event_types() {
  scx_key_event_binding = s48_get_imported_binding_2("scx-key-event");
  scx_button_event_binding = s48_get_imported_binding_2("scx-button-event");
  scx_motion_event_binding = s48_get_imported_binding_2("scx-motion-event");
  scx_crossing_event_binding = s48_get_imported_binding_2("scx-crossing-event");
  scx_focus_change_event_binding = 
    s48_get_imported_binding_2("scx-focus-change-event");
  scx_expose_event_binding = s48_get_imported_binding_2("scx-expose-event");
  scx_graphics_expose_event_binding = 
    s48_get_imported_binding_2("scx-graphics-expose-event");
  scx_no_expose_event_binding = s48_get_imported_binding_2("scx-no-expose-event");
  scx_visibility_event_binding = s48_get_imported_binding_2("scx-visibility-event");
  scx_create_window_event_binding = 
    s48_get_imported_binding_2("scx-create-window-event");
  scx_destroy_window_event_binding = 
    s48_get_imported_binding_2("scx-destroy-window-event");
  scx_unmap_event_binding = s48_get_imported_binding_2("scx-unmap-event");
  scx_map_event_binding = s48_get_imported_binding_2("scx-map-event");
  scx_map_request_event_binding = 
    s48_get_imported_binding_2("scx-map-request-event");
  scx_reparent_event_binding = s48_get_imported_binding_2("scx-reparent-event");
  scx_configure_event_binding = s48_get_imported_binding_2("scx-configure-event");
  scx_gravity_event_binding = s48_get_imported_binding_2("scx-gravity-event");
  scx_resize_request_event_binding = 
    s48_get_imported_binding_2("scx-resize-request-event");
  scx_configure_request_event_binding = 
    s48_get_imported_binding_2("scx-configure-request-event");
  scx_circulate_event_binding = s48_get_imported_binding_2("scx-circulate-event");
  scx_circulate_event_binding = 
    s48_get_imported_binding_2("scx-circulate-request-event");
  scx_property_event_binding = s48_get_imported_binding_2("scx-property-event");
  scx_selection_clear_event_binding = 
    s48_get_imported_binding_2("scx-selection-clear-event");
  scx_selection_request_event_binding = 
    s48_get_imported_binding_2("scx-selection-request-event");
  scx_selection_event_binding = s48_get_imported_binding_2("scx-selection-event");
  scx_colormap_event_binding = s48_get_imported_binding_2("scx-colormap-event");
  scx_client_message_event_binding = 
    s48_get_imported_binding_2("scx-client-message-event");
  scx_mapping_event_binding = s48_get_imported_binding_2("scx-mapping-event");
  scx_keymap_event_binding = s48_get_imported_binding_2("scx-keymap-event");
}
