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

#ifndef _SCX_XLIB_H
#define _SCX_XLIB_H

#ifdef HAVE_CONFIG_H
#include <sysdep.h>
#endif

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include <pthread.h>
#include <errno.h>

#ifndef NeedFunctionPrototypes          /* Kludge */
 #error "X11 Release 3 (or earlier) no longer supported"
#endif

#if XlibSpecificationRelease >= 5
#  define XLIB_RELEASE_5_OR_LATER
#endif

#if XlibSpecificationRelease >= 6
#  define XLIB_RELEASE_6_OR_LATER
#endif

#define NO_OLD_FFI 1
#include <scheme48.h>

extern char* mc_extract_string(s48_call_t call, s48_ref_t s);
#define s48_enter_string s48_enter_string_latin_1_2
#define s48_extract_string(c, s) mc_extract_string(c, s)

extern s48_ref_t s48_checked_record_ref_2(s48_call_t call, s48_ref_t value,
                                        int i, s48_ref_t rectype);

#define S48_EXTRACT_ENUM(c, x, type) \
  s48_extract_long_2(c, s48_checked_record_ref_2(c, x, 1, type))

#define S48_ENTER_ENUM(c, index, vvector) \
  s48_vector_ref_2(c, s48_shared_binding_ref_2(c, vvector), index)

#define S48_EXTRACT_ENUM_SET(c, x, type) s48_extract_enum_set(c, x, type)
extern unsigned long s48_extract_enum_set(s48_call_t call, s48_ref_t v, s48_ref_t type);
extern s48_ref_t s48_enter_enum_set(s48_call_t call, unsigned long v, s48_ref_t type);

/*** Extraction-Macros for the XIDs ********************************/

#define scx_extract_window(c, x) (Window)s48_extract_long_2(c, x)
#define scx_enter_window(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_drawable(c, x) (Drawable)s48_extract_long_2(c, x)
#define scx_enter_drawable(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_font(c, x) (Font)s48_extract_long_2(c, x)
#define scx_enter_font(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_pixmap(c, x) (Pixmap)s48_extract_long_2(c, x)
#define scx_enter_pixmap(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_cursor(c, x) (Cursor)s48_extract_long_2(c, x)
#define scx_enter_cursor(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_colormap(c, x) (Colormap)s48_extract_long_2(c, x)
#define scx_enter_colormap(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_gcontext(c, x) (GContext)s48_extract_long_2(c, x)
#define scx_enter_gcontext(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_keysym(c, x) (GContext)s48_extract_long_2(c, x)
#define scx_enter_keysym(c, x) s48_enter_long_2(c, (long)x)

/* other CARD32 */

#define scx_enter_atom(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_atom(c, x) (Atom)s48_extract_long_2(c, x)
#define scx_enter_visualid(c, x) s48_enter_long_2(c, (long)x)
#define scx_extract_visualid(c, x) (VisualID)s48_extract_long_2(c, x)
#define scx_enter_time(c, x) s48_enter_long_2(c, x)
#define scx_extract_time(c, x) (Time)s48_extract_long_2(c, x)

/* other ints */

#define scx_enter_keycode(c, x) s48_enter_long_as_fixnum_2(c, x)
#define scx_extract_keycode(c, x) (KeyCode)s48_extract_long_2(c, x)
#define scx_extract_pixel(c, x) (Pixel)s48_extract_long_2(c, x)
#define scx_enter_pixel(c, x) s48_enter_long_2(c, (long)x)

/* records */

#define scx_extract_region(c, x) (Region)s48_extract_pointer_2(c, x)
#define scx_enter_region(c, r) s48_enter_pointer_2(c, r)

typedef struct node_ scx_node;
struct node_
{
  void *content;
  struct node_ *next;
};

typedef struct {
  pthread_t *event_thread;
  Display *display;
  pthread_mutex_t event_list_access_lock;
  pthread_mutex_t close_display_lock;
  scx_node *temp_events;
  long event_uid;
} scx_event_bundle;

extern s48_ref_t scx_display;

extern Display* scx_extract_display(s48_call_t call, s48_ref_t dpy);
extern s48_ref_t scx_enter_display(s48_call_t call,
				   scx_event_bundle *display_bundle);
//extern s48_ref_t scx_enter_display(s48_call_t call, Display* dpy);
extern scx_event_bundle * scx_get_display_bundle(s48_call_t call, Display *dpy);
extern scx_event_bundle* scx_extract_display_bundle(s48_call_t call,  s48_ref_t dpy);
#define SCX_DISPLAY_AFTER_FUNCTION(c, d) \
  s48_checked_record_ref_2(c, d, 14, scx_display)

extern s48_ref_t scx_color;
extern void scx_extract_color(s48_call_t call, s48_ref_t v, XColor* c);
extern void scx_copy_color(s48_call_t call, const XColor* c, s48_ref_t v);
extern s48_ref_t scx_enter_color(s48_call_t call, const XColor* c);

extern s48_ref_t scx_gc;
#define scx_extract_gc(c, x) \
  (GC)s48_extract_pointer_2(c, s48_checked_record_ref_2(c, x, 0, scx_gc))
extern s48_ref_t scx_enter_gc(s48_call_t call, GC gc);

extern s48_ref_t scx_fontstruct;
#define scx_extract_fontstruct(c, x)\
  (XFontStruct*)s48_extract_pointer_2(c, s48_checked_record_ref_2(c, x, 0,\
							   scx_fontstruct))
extern s48_ref_t scx_enter_charstruct(s48_call_t call, XCharStruct* cs);
extern s48_ref_t scx_enter_fontstruct(s48_call_t call, XFontStruct* fs);

extern s48_ref_t scx_screenformat;
#define scx_extract_screenformat(c, x)\
  (ScreenFormat*)s48_extract_long_2(c, s48_checked_record_ref_2(c, x, 0,\
							   scx_screenformat))
extern s48_ref_t scx_enter_screenformat(s48_call_t call, ScreenFormat* sf);

extern s48_ref_t scx_visual;
#define scx_extract_visual(c, x)\
  (Visual*)s48_extract_pointer_2(c, s48_checked_record_ref_2(c, x, 0,\
						      scx_visual))
extern s48_ref_t scx_enter_visual(s48_call_t call, Visual* vis);

extern s48_ref_t scx_screen;
#define scx_extract_screen(c, x)\
  (Screen*)s48_extract_pointer_2(c, s48_checked_record_ref_2(c, x, 0,\
						      scx_screen))
extern s48_ref_t scx_enter_screen(s48_call_t call, Screen* scr);

extern void scx_extract_property(s48_call_t call, s48_ref_t p, Atom* type, int* format,
				 char** data, int* nelements);
extern s48_ref_t scx_enter_property(s48_call_t call, Atom type, int format, char* data,
				    int nelements);

extern s48_ref_t scx_enter_window_changes(s48_call_t call, 
         XWindowChanges* WC, unsigned long mask);
extern unsigned long scx_extract_window_changes(s48_call_t call,
         s48_ref_t changes, XWindowChanges* WC);

extern s48_ref_t scx_enter_x_error(s48_call_t call, XErrorEvent* xe);
extern void scx_extract_x_error(s48_call_t call, s48_ref_t e, XErrorEvent* xe);

/* more types */

extern s48_ref_t scx_event_mask_binding;
#define scx_extract_event_mask(c, x) \
  S48_EXTRACT_ENUM_SET(c, x, scx_event_mask_binding)
#define scx_enter_event_mask(c, x) s48_enter_enum_set(c, x, scx_event_mask_binding)

extern s48_ref_t scx_gc_value_binding;
extern s48_ref_t scx_gc_values_binding;
#define scx_extract_gc_value(c, x) S48_EXTRACT_ENUM(c, x, scx_gc_value_binding)
#define scx_enter_gc_value(c, x) S48_ENTER_ENUM(c, x, scx_gc_values_binding)

extern s48_ref_t scx_byte_order_binding;
extern s48_ref_t scx_byte_orders_binding;
#define scx_extract_byte_order(c, x) S48_EXTRACT_ENUM(c, x, scx_byte_order_binding)
#define scx_enter_byte_order(c, x)  S48_ENTER_ENUM(c, x, scx_byte_orders_binding)

extern s48_ref_t scx_bit_order_binding;
extern s48_ref_t scx_bit_orders_binding;
#define scx_extract_bit_order(c, x) S48_EXTRACT_ENUM(c, x, scx_bit_order_binding)
#define scx_enter_bit_order(c, x) S48_ENTER_ENUM(c, x, scx_bit_orders_binding)

extern s48_ref_t scx_bit_gravity_binding;
extern s48_ref_t scx_bit_gravities_binding;
#define scx_extract_bit_gravity(c, x) S48_EXTRACT_ENUM(c, x, scx_bit_gravity_binding)
#define scx_enter_bit_gravity(c, x) S48_ENTER_ENUM(c, x, scx_bit_gravities_binding)

extern s48_ref_t scx_win_gravity_binding;
extern s48_ref_t scx_win_gravities_binding;
#define scx_extract_win_gravity(c, x) S48_EXTRACT_ENUM(c, x, scx_win_gravity_binding)
#define scx_enter_win_gravity(c, x) S48_ENTER_ENUM(c, x, scx_win_gravities_binding)

extern s48_ref_t scx_event_type_binding;
extern s48_ref_t scx_event_types_binding;
#define scx_extract_event_type(c, x) S48_EXTRACT_ENUM(c, x, scx_event_type_binding)
#define scx_enter_event_type(c, x) S48_ENTER_ENUM(c, x, scx_event_types_binding)

extern s48_ref_t scx_font_direction_binding;
extern s48_ref_t scx_font_directions_binding;
#define scx_extract_font_direction(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_font_direction_binding)
#define scx_enter_font_direction(c, x) \
  S48_ENTER_ENUM(c, x, scx_font_directions_binding)

extern s48_ref_t scx_state_binding;
extern s48_ref_t scx_states_binding;
#define scx_extract_state(c, x) S48_EXTRACT_ENUM(c, x, scx_state_binding)
#define scx_enter_state(c, x) S48_ENTER_ENUM(c, x, scx_states_binding)

extern s48_ref_t scx_state_set_binding;
#define scx_extract_state_set(c, x) S48_EXTRACT_ENUM_SET(c, x, scx_state_set_binding)
#define scx_enter_state_set(c, x) s48_enter_enum_set(c, x, scx_state_set_binding)

extern s48_ref_t scx_button_binding;
extern s48_ref_t scx_buttons_binding;
#define scx_extract_button(c, x) S48_EXTRACT_ENUM(c, x, scx_button_binding)
#define scx_enter_button(c, x) S48_ENTER_ENUM(c, x, scx_buttons_binding)

extern s48_ref_t scx_notify_mode_binding;
extern s48_ref_t scx_notify_modes_binding;
#define scx_extract_notify_mode(c, x) S48_EXTRACT_ENUM(c, x, scx_notify_mode_binding)
#define scx_enter_notify_mode(c, x) S48_ENTER_ENUM(c, x, scx_notify_modes_binding)

extern s48_ref_t scx_notify_detail_binding;
extern s48_ref_t scx_notify_details_binding;
#define scx_extract_notify_detail(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_notify_detail_binding)
#define scx_enter_notify_detail(c, x) \
  S48_ENTER_ENUM(c, x, scx_notify_details_binding)

extern s48_ref_t scx_visibility_state_binding;
extern s48_ref_t scx_visibility_states_binding;
#define scx_extract_visibility_state(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_visibility_state_binding)
#define scx_enter_visibility_state(c, x) \
  S48_ENTER_ENUM(c, x, scx_visibility_states_binding)

extern s48_ref_t scx_place_binding;
extern s48_ref_t scx_places_binding;
#define scx_extract_place(c, x) S48_EXTRACT_ENUM(c, x, scx_place_binding)
#define scx_enter_place(c, x) S48_ENTER_ENUM(c, x, scx_places_binding)

extern s48_ref_t scx_property_state_binding;
extern s48_ref_t scx_property_states_binding;
#define scx_extract_property_state(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_property_state_binding)
#define scx_enter_property_state(c, x) \
  S48_ENTER_ENUM(c, x, scx_property_states_binding)

extern s48_ref_t scx_colormap_state_binding;
extern s48_ref_t scx_colormap_states_binding;
#define scx_extract_colormap_state(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_colormap_state_binding)
#define scx_enter_colormap_state(c, x) \
  S48_ENTER_ENUM(c, x, scx_colormap_states_binding)

extern s48_ref_t scx_mapping_request_binding;
extern s48_ref_t scx_mapping_requests_binding;
#define scx_extract_mapping_request(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_mapping_request_binding)
#define scx_enter_mapping_request(c, x) \
  S48_ENTER_ENUM(c, x, scx_mapping_requests_binding)

extern s48_ref_t scx_backing_store_binding;
extern s48_ref_t scx_backing_stores_binding;
#define scx_extract_backing_store(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_backing_store_binding)
#define scx_enter_backing_store(c, x) \
  S48_ENTER_ENUM(c, x, scx_backing_stores_binding)

extern s48_ref_t scx_map_state_binding;
extern s48_ref_t scx_map_states_binding;
#define scx_extract_map_state(c, x) S48_EXTRACT_ENUM(c, x, scx_map_state_binding)
#define scx_enter_map_state(c, x) S48_ENTER_ENUM(c, x, scx_map_states_binding)

extern s48_ref_t scx_window_class_binding;
extern s48_ref_t scx_window_classes_binding;
#define scx_extract_window_class(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_window_class_binding)
#define scx_enter_window_class(c, x) \
  S48_ENTER_ENUM(c, x, scx_window_classes_binding)

extern s48_ref_t scx_stack_mode_binding;
extern s48_ref_t scx_stack_modes_binding;
#define scx_extract_stack_mode(c, x) S48_EXTRACT_ENUM(c, x, scx_stack_mode_binding)
#define scx_enter_stack_mode(c, x) S48_ENTER_ENUM(c, x, scx_stack_modes_binding)

extern s48_ref_t scx_window_change_binding;
extern s48_ref_t scx_window_changes_binding;
#define scx_extract_window_change(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_window_change_binding)
#define scx_enter_window_change(c, x) \
  S48_ENTER_ENUM(c, x, scx_window_changes_binding)

extern s48_ref_t scx_struct_cache_ref(s48_call_t call, 
                                      void* cpointer, s48_ref_t list);
extern s48_ref_t scx_enter_event(s48_call_t call, XEvent* e,
				 scx_event_bundle* bundle);
extern s48_call_t s48_get_current_call (void);
extern void scx_struct_cache_set(s48_call_t call, void* cpointer, s48_ref_t* l, s48_ref_t v);
extern void scx_extract_event(s48_call_t call, s48_ref_t se, XEvent* e);
extern void scx_extract_key_event(s48_call_t call, s48_ref_t e, XKeyEvent* xe);
extern void scx_extract_mapping_event(s48_call_t call, s48_ref_t e, XMappingEvent* xe);
#endif
