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

#include "xlib.h"

s48_ref_t scx_visual_class_binding = NULL;
#define scx_extract_visual_class(c, x) \
  S48_EXTRACT_ENUM(c, x, scx_visual_class_binding)
s48_ref_t scx_visual_classes_binding = NULL;
#define scx_enter_visual_class(c, x) \
  S48_ENTER_ENUM(c, x, scx_visual_classes_binding)

s48_ref_t scx_enter_visual(s48_call_t call, Visual* vis) {
  s48_ref_t v = s48_make_record_2(call, scx_visual);
  s48_record_set_2(call, v, 0, s48_enter_pointer_2(call, vis));
  return v;
}

s48_ref_t scx_visual_info_binding = NULL;

s48_ref_t scx_enter_visual_info(s48_call_t call, XVisualInfo* vi) {
  s48_ref_t v = s48_make_record_2(call, scx_visual_info_binding);
  s48_record_set_2(call, v, 0, scx_enter_visual(call, vi->visual));
  s48_record_set_2(call, v, 1, scx_enter_visualid(call, vi->visualid));
  s48_record_set_2(call, v, 2, s48_enter_long_2(call, vi->screen));
  s48_record_set_2(call, v, 3, s48_enter_long_2(call, vi->depth));
  s48_record_set_2(call, v, 4, scx_enter_visual_class(call, vi->class));
  s48_record_set_2(call, v, 5, s48_enter_long_2(call, vi->red_mask));
  s48_record_set_2(call, v, 6, s48_enter_long_2(call, vi->green_mask));
  s48_record_set_2(call, v, 7, s48_enter_long_2(call, vi->blue_mask));
  s48_record_set_2(call, v, 8, s48_enter_long_2(call, vi->bits_per_rgb));
  s48_record_set_2(call, v, 9, s48_enter_long_2(call, vi->colormap_size));
  return v;
}

unsigned int scx_extract_visual_info(s48_call_t call, s48_ref_t v, 
				     XVisualInfo* vi) {
  unsigned long mask = 0;

  s48_check_record_type_2(call, v, scx_visual_info_binding);
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 0)))
    vi->visual = scx_extract_visual(call, s48_record_ref_2(call, v, 0));
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 1))) {
    vi->visualid = scx_extract_visualid(call, s48_record_ref_2(call, v, 1));
    mask |= VisualIDMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 2))) {
    vi->screen = s48_extract_long_2(call, s48_record_ref_2(call, v, 2));
    mask |= VisualScreenMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 3))) {
    vi->depth = s48_extract_long_2(call, s48_record_ref_2(call, v, 4));
    mask |= VisualDepthMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 4))) {
    vi->class = scx_extract_visual_class(call, s48_record_ref_2(call, v, 5));
    mask |= VisualClassMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 5))) {
    vi->red_mask = s48_extract_long_2(call, s48_record_ref_2(call, v, 6));
    mask |= VisualRedMaskMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 6))) {
    vi->green_mask = s48_extract_long_2(call, s48_record_ref_2(call, v, 7));
    mask |= VisualGreenMaskMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 7))) {
    vi->blue_mask = s48_extract_long_2(call, s48_record_ref_2(call, v, 8));
    mask |= VisualBlueMaskMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 8))) {
    vi->bits_per_rgb = s48_extract_long_2(call, s48_record_ref_2(call, v, 9));
    mask |= VisualBitsPerRGBMask;
  }
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 9))) {
    vi->colormap_size = s48_extract_long_2(call, s48_record_ref_2(call, v, 10));
    mask |= VisualColormapSizeMask;
  }
  return mask;
}

s48_ref_t scx_Get_Visual_Info(s48_call_t call, s48_ref_t display, 
			      s48_ref_t template) {
  XVisualInfo templ;
  unsigned long mask = scx_extract_visual_info(call, template, &templ);
  XVisualInfo* vis;
  int n, i;
  s48_ref_t l = s48_null_2(call);

  vis = XGetVisualInfo(scx_extract_display(call, display),
		       mask, &templ, &n);

  for (i = n-1; i >= 0; i--)
    l = s48_cons_2(call, scx_enter_visual_info(call, &vis[i]), l);

  return l;
}

s48_ref_t scx_Match_Visual_Info(s48_call_t call, s48_ref_t display, 
	    s48_ref_t scrnum, s48_ref_t depth, s48_ref_t class) {
  XVisualInfo vi;
  
  if (! XMatchVisualInfo(scx_extract_display(call, display),
			 s48_extract_long_2(call, scrnum),
			 s48_extract_long_2(call, depth),
			 scx_extract_visual_class(call, class),
			 &vi) )
    return s48_false_2(call);
  else
    return scx_enter_visual_info(call, &vi);
}

s48_ref_t scx_VisualIDFromVisual(s48_call_t call, s48_ref_t visual) {
  return s48_enter_long_2(call, 
	    XVisualIDFromVisual(scx_extract_visual(call, visual)));
}

void scx_init_visual(void) {
  scx_visual_class_binding = s48_get_imported_binding_2("scx-visual-class");
  scx_visual_classes_binding = s48_get_imported_binding_2("scx-visual-classes");
  scx_visual_info_binding = s48_get_imported_binding_2("scx-visual-info");

  S48_EXPORT_FUNCTION(scx_Get_Visual_Info);
  S48_EXPORT_FUNCTION(scx_Match_Visual_Info);
  S48_EXPORT_FUNCTION(scx_VisualIDFromVisual);
}
