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

#include "xlib.h"
#include <sys/select.h>
#include <errno.h>

s48_ref_t scx_queued_mode_binding = NULL;
#define scx_extract_queued_mode(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_queued_mode_binding)

s48_ref_t scx_Events_Queued(s48_call_t call, s48_ref_t display, s48_ref_t mode) {
  int r;
  r = XEventsQueued(scx_extract_display(call, display),
		    scx_extract_queued_mode(call, mode));
  return s48_enter_long_2(call, r);
}

s48_ref_t scx_Events_Pending(s48_call_t call, s48_ref_t display) {
  return s48_enter_long_2(call,
			  XPending(scx_extract_display(call, display)));
}


s48_ref_t scx_Next_Event(s48_call_t call, s48_ref_t display) {
  XEvent e;
  XNextEvent(scx_extract_display(call, display), &e);
  return scx_enter_event(call, &e, scx_extract_display_bundle(call, display));
} 

s48_ref_t scx_Peek_Event(s48_call_t call, s48_ref_t display) {
  XEvent e;
  XPeekEvent(scx_extract_display(call, display), &e);
  return scx_enter_event(call, &e, scx_extract_display_bundle(call, display));
}

s48_ref_t scx_Get_Motion_Events(s48_call_t call, s48_ref_t display,
	   s48_ref_t window, s48_ref_t from, s48_ref_t to) {
  int n,i;
  XTimeCoord *p;
  s48_ref_t l = s48_null_2(call), t = s48_false_2(call);
  p = XGetMotionEvents(scx_extract_display(call, display),
		       scx_extract_window(call, window),
		       scx_extract_time(call, from),
		       scx_extract_time(call, to),
		       &n);

  for (i = n-1; i >= 0; i--) {
    t = s48_cons_2(call, s48_enter_long_as_fixnum_2(call, p[i].x),
		   s48_enter_long_as_fixnum_2(call, p[i].y));
    t = s48_cons_2(call, scx_enter_time(call, p[i].time), t);
    l = s48_cons_2(call, t, l);
  }
  XFree((char*)p);

  return l;
}

s48_ref_t scx_Send_Event(s48_call_t call, s48_ref_t display, s48_ref_t window,
	     s48_ref_t propagate, s48_ref_t event_mask, s48_ref_t event) {
  XEvent e;
  Status r;
  scx_extract_event(call, event, &e);

  r = XSendEvent(scx_extract_display(call, display),
		 scx_extract_window(call, window),
		 s48_extract_boolean_2(call, propagate),
		 scx_extract_event_mask(call, event_mask),
		 &e);
  return (r ? s48_true_2(call) : s48_false_2(call));
}

void scx_init_event(void) {
  scx_queued_mode_binding = s48_get_imported_binding_2("scx-queued-mode");
  S48_EXPORT_FUNCTION(scx_Events_Queued);
  S48_EXPORT_FUNCTION(scx_Events_Pending);
  S48_EXPORT_FUNCTION(scx_Next_Event);
  S48_EXPORT_FUNCTION(scx_Peek_Event);
  S48_EXPORT_FUNCTION(scx_Get_Motion_Events);
  S48_EXPORT_FUNCTION(scx_Send_Event);
}
