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

#include "xlib.h"

s48_ref_t scx_Reparent_Window(s48_call_t call ,s48_ref_t display, 
			      s48_ref_t window, s48_ref_t parent, 
			      s48_ref_t x, s48_ref_t y) {
  XReparentWindow(scx_extract_display(call, display),
		  scx_extract_window(call, window),
		  scx_extract_window(call, parent),
		  (int)s48_extract_long_2(call, x), 
      (int)s48_extract_long_2(call, y));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Install_Colormap(s48_call_t call, s48_ref_t display, 
                              s48_ref_t colormap) {
  XInstallColormap(scx_extract_display(call, display),
		   scx_extract_colormap(call, colormap));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Uninstall_Colormap(s48_call_t call, s48_ref_t display, 
                                 s48_ref_t colormap) {
  XUninstallColormap(scx_extract_display(call, display), 
		     scx_extract_colormap(call, colormap));
  return s48_unspecific_2(call);
}

s48_ref_t scx_List_Installed_Colormaps(s48_call_t call, 
            s48_ref_t display, s48_ref_t window) {
  int i, n;
  Colormap *ret;
  s48_ref_t l = s48_null_2(call);

  ret = XListInstalledColormaps(scx_extract_display(call, display),
				scx_extract_window(call, window),
				&n);
  for (i = n-1; i >= 0; i--)
    l = s48_cons_2(call, scx_enter_colormap(call, ret[i]), l);
  XFree((char*)ret);
  return l;
}

s48_ref_t scx_revert_to_binding = NULL;
s48_ref_t scx_revert_tos_binding = NULL;
#define scx_extract_revert_to(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_revert_to_binding)
#define scx_enter_revert_to(c, x) \
  S48_ENTER_ENUM(c, x, scx_revert_tos_binding)

s48_ref_t scx_Set_Input_Focus(s48_call_t call, s48_ref_t display, 
			       s48_ref_t window, s48_ref_t revert_to, 
			      s48_ref_t time) {
  XSetInputFocus(scx_extract_display(call, display), 
		 scx_extract_window(call, window),
		 scx_extract_revert_to(call, revert_to),
		 scx_extract_time(call, time));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Get_Input_Focus(s48_call_t call, s48_ref_t display) {
  Window win;
  int revert_to;
  s48_ref_t v = s48_false_2(call);
  
  XGetInputFocus(scx_extract_display(call, display), &win, &revert_to);
  v = scx_enter_revert_to(call, revert_to);
  v = s48_cons_2(call, scx_enter_window(call, win), v);
  return v;
}

s48_ref_t scx_Warp_Pointer(s48_call_t call, s48_ref_t dpy, s48_ref_t src, 
         s48_ref_t dst, s48_ref_t srcx, s48_ref_t srcy, 
         s48_ref_t srcw, s48_ref_t srch, s48_ref_t dstx, s48_ref_t dsty) {
  XWarpPointer(scx_extract_display(call, dpy), 
	       scx_extract_window(call, src), scx_extract_window(call, dst),
	       (int)s48_extract_long_2(call, srcx), 
	       (int)s48_extract_long_2(call, srcy), 
	       (int)s48_extract_long_2(call, srcw),
	       (int)s48_extract_long_2(call, srch), 
	       (int)s48_extract_long_2(call, dstx), 
	       (int)s48_extract_long_2(call, dsty));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Bell(s48_call_t call, s48_ref_t display, s48_ref_t percent) {
  XBell(scx_extract_display(call, display), s48_extract_long_2(call, percent));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Set_Access_Control(s48_call_t call, s48_ref_t display, 
				 s48_ref_t on) {
  XSetAccessControl(scx_extract_display(call, display), 
		    !s48_false_p_2(call, on));
  return s48_unspecific_2(call);
}

s48_ref_t scx_save_set_binding = NULL;
#define scx_extract_save_set(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_save_set_binding)

s48_ref_t scx_Change_Save_Set(s48_call_t call, s48_ref_t display, 
			       s48_ref_t win, s48_ref_t mode) {
  XChangeSaveSet(scx_extract_display(call, display), 
		 scx_extract_window(call, win),
		 scx_extract_save_set(call, mode));
  return s48_unspecific_2(call);
}

s48_ref_t scx_close_down_mode_binding = NULL;
#define scx_extract_close_down_mode(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_close_down_mode_binding)

s48_ref_t scx_Set_Close_Down_Mode(s48_call_t call, 
            s48_ref_t display, s48_ref_t mode) {
  XSetCloseDownMode(scx_extract_display(call, display),
		    scx_extract_close_down_mode(call, mode));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Kill_Client(s48_call_t call, s48_ref_t display, s48_ref_t xid) {
  XKillClient(scx_extract_display(call, display), 
              (XID)s48_extract_long_2(call, xid));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Get_Pointer_Mapping(s48_call_t call, s48_ref_t display) {
  unsigned char map[256];
  int i, n;
  s48_ref_t ret = s48_false_2(call);

  n = XGetPointerMapping (scx_extract_display(call, display), map, 256);
  ret = s48_make_vector_2(call, n, s48_null_2(call));
  for (i = 0; i < n; i++)
    s48_vector_set_2(call, ret, i, s48_enter_long_2(call, map[i]));
  return ret;
}

s48_ref_t scx_Set_Pointer_Mapping(s48_call_t call, s48_ref_t display, 
                                  s48_ref_t map) {
  int i, n = s48_vector_length_2(call, map);
  unsigned char p[n];
  int ret;

  for (i = 0; i < n; i++)
    p[i] = (int)s48_extract_long_2(call, s48_vector_ref_2(call, map, i));

  ret = XSetPointerMapping(scx_extract_display(call, display), p, n);
  return (ret == MappingSuccess) ? s48_true_2(call) : s48_false_2(call);
}

void scx_init_wm(void) { 
  scx_revert_to_binding = s48_get_imported_binding_2("scx-revert-to");
  scx_revert_tos_binding = s48_get_imported_binding_2("scx-revert-tos");
  scx_save_set_binding = s48_get_imported_binding_2("scx-save-set");
  scx_close_down_mode_binding = 
    s48_get_imported_binding_2("scx-close-down-mode");

  S48_EXPORT_FUNCTION(scx_Reparent_Window);
  S48_EXPORT_FUNCTION(scx_Install_Colormap);
  S48_EXPORT_FUNCTION(scx_Uninstall_Colormap);
  S48_EXPORT_FUNCTION(scx_List_Installed_Colormaps);
  S48_EXPORT_FUNCTION(scx_Set_Input_Focus);
  S48_EXPORT_FUNCTION(scx_Get_Input_Focus);
  S48_EXPORT_FUNCTION(scx_Warp_Pointer);
  S48_EXPORT_FUNCTION(scx_Bell);
  S48_EXPORT_FUNCTION(scx_Set_Access_Control);
  S48_EXPORT_FUNCTION(scx_Change_Save_Set);
  S48_EXPORT_FUNCTION(scx_Set_Close_Down_Mode);
  S48_EXPORT_FUNCTION(scx_Kill_Client);
  S48_EXPORT_FUNCTION(scx_Get_Pointer_Mapping);
  S48_EXPORT_FUNCTION(scx_Set_Pointer_Mapping);
}
