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

#include "xlib.h"

s48_ref_t scx_Draw_Image_String(s48_call_t call, s48_ref_t display, 
        s48_ref_t drawable, s48_ref_t gc, s48_ref_t x, s48_ref_t y,
				s48_ref_t string) {
  XDrawImageString(scx_extract_display(call, display),
		   scx_extract_drawable(call, drawable),
		   scx_extract_gc(call, gc),
		   s48_extract_long_2(call, x),
		   s48_extract_long_2(call, y),
		   s48_extract_string(call, string),
		   s48_string_length_2(call, string));
  return s48_unspecific_2(call);
}

s48_ref_t scx_Draw_Image_String_16(s48_call_t call, s48_ref_t display, 
           s48_ref_t drawable, s48_ref_t gc, s48_ref_t x, s48_ref_t y,
				   s48_ref_t string) {
  int i, len = s48_extract_long_2(call, s48_length_2(call, string));
  XChar2b chars[len];
  for (i = 0; i < len; i++) {
    chars[i].byte1 = 
      s48_extract_char_2(call, s48_car_2(call, s48_car_2(call, string)));
    chars[i].byte2 = 
      s48_extract_char_2(call, s48_cdr_2(call, s48_car_2(call, string)));
    string = s48_cdr_2(call, string);
  }
  XDrawImageString16(scx_extract_display(call, display),
		     scx_extract_drawable(call, drawable),
		     scx_extract_gc(call, gc),
		     s48_extract_long_2(call, x),
		     s48_extract_long_2(call, y),
		     chars, len);
  
  return s48_unspecific_2(call);
}

s48_ref_t scx_text_item = NULL;

void scx_extract_text_item(s48_call_t call, s48_ref_t v, XTextItem* ti) {
  s48_check_record_type_2(call, v, scx_text_item);
  if (!s48_false_p_2(call, s48_record_ref_2(call, v, 0))) {
    ti->nchars = s48_string_length_2(call, s48_record_ref_2(call, v, 0));
    ti->chars = (char*)malloc(ti->nchars);
    strncpy(ti->chars, 
            s48_extract_string(call, s48_record_ref_2(call, v, 0)), 
            ti->nchars);
  } else {
    ti->chars = NULL;
    ti->nchars = 0;
  }
  ti->delta = (int)s48_extract_long_2(call, s48_record_ref_2(call, v, 1));
  ti->font = scx_extract_font(call, s48_record_ref_2(call, v, 2));
  /* Free all chars arrays! */
}

void scx_extract_text_item_16(s48_call_t call, s48_ref_t v, XTextItem16* ti) {
  s48_ref_t l = s48_null_2(call);
  s48_check_record_type_2(call, v, scx_text_item);
  {
    if (!s48_false_p_2(call, s48_record_ref_2(call, v, 0))) {
      int i, n;
      XChar2b* s;
      l = s48_record_ref_2(call,v, 0);
      n = s48_extract_long_2(call, s48_length_2(call, l));

      s = (XChar2b*)malloc(n * sizeof(XChar2b));
      for (i = n-1; i >= 0; i--) {
	ti->chars[i].byte1 = 
	  s48_extract_long_2(call, s48_car_2(call, s48_car_2(call, l)));
	ti->chars[i].byte2 = 
	  s48_extract_long_2(call, s48_cdr_2(call, s48_car_2(call, l)));
      }
      ti->nchars = n;
    } else {
      ti->chars = NULL;
      ti->nchars = 0;
    }
    ti->delta = (int)s48_extract_long_2(call, s48_record_ref_2(call, v, 1));
    ti->font = scx_extract_font(call, s48_record_ref_2(call, v, 2));
  }
  /* Free all chars arrays! */
}

s48_ref_t scx_Draw_Text(s48_call_t call, s48_ref_t display, s48_ref_t drawable,
			s48_ref_t gc, s48_ref_t x, s48_ref_t y,
			s48_ref_t items) {
  int i, len = s48_extract_long_2(call, s48_length_2(call, items));

  XTextItem parts[len];
  for (i = 0; i < len; i++) {
    scx_extract_text_item(call, s48_car_2(call, items), &parts[i]);
    items = s48_cdr_2(call, items);
  }
  XDrawText(scx_extract_display(call, display),
	    scx_extract_drawable(call, drawable),
	    scx_extract_gc(call, gc),
	    s48_extract_long_2(call, x),
	    s48_extract_long_2(call, y),
	    parts, len);
  for (i = 0; i < len; i++)
    free(parts[i].chars);
  return s48_unspecific_2(call);
}

s48_ref_t scx_Draw_Text_16(s48_call_t call, s48_ref_t display, 
           s48_ref_t drawable, s48_ref_t gc, s48_ref_t x, s48_ref_t y,
	   s48_ref_t items) {
  int i, len = s48_extract_long_2(call, s48_length_2(call, items));

  XTextItem16 parts[len];
  for (i = 0; i < len; i++) {
    scx_extract_text_item_16(call, s48_car_2(call, items), &parts[i]);
    items = s48_cdr_2(call, items);
  }
  
  XDrawText16(scx_extract_display(call, display),
	      scx_extract_drawable(call, drawable),
	      scx_extract_gc(call, gc),
	      s48_extract_long_2(call, x),
	      s48_extract_long_2(call, y),
	      parts, len);
  for (i = 0; i < len; i++)
    free(parts[i].chars);
  return s48_unspecific_2(call);
}

s48_ref_t scx_Text_Extents(s48_call_t call, s48_ref_t font_struct, 
			   s48_ref_t string) {
  XCharStruct overall;
  int dir, ascent, descent;
  XTextExtents(scx_extract_fontstruct(call, font_struct),
	       s48_extract_string(call, string),
	       s48_string_length_2(call, string),
	       &dir, &ascent, &descent,
	       &overall);
  return scx_enter_charstruct(call, &overall);
}

s48_ref_t scx_Text_Extents_16(s48_call_t call, s48_ref_t font_struct, 
			      s48_ref_t string) {
  XCharStruct overall;
  int dir, ascent, descent;

  int i, len = s48_extract_long_2(call, s48_length_2(call, string));

  XChar2b chars[len];
  for (i = 0; i < len; i++) {
    chars[i].byte1 = 
      s48_extract_char_2(call, s48_car_2(call, s48_car_2(call, string)));
    chars[i].byte2 = 
      s48_extract_char_2(call, s48_cdr_2(call, s48_car_2(call, string)));
    string = s48_cdr_2(call, string);
  }
  XTextExtents16(scx_extract_fontstruct(call, font_struct),
		 chars, len,
		 &dir, &ascent, &descent,
		 &overall);
  return scx_enter_charstruct(call, &overall);
}

void scx_init_text(void) {
  scx_text_item = s48_get_imported_binding_2("scx-text-item");
  
  S48_EXPORT_FUNCTION(scx_Draw_Image_String);
  S48_EXPORT_FUNCTION(scx_Draw_Image_String_16);
  S48_EXPORT_FUNCTION(scx_Draw_Text);
  S48_EXPORT_FUNCTION(scx_Draw_Text_16);
  S48_EXPORT_FUNCTION(scx_Text_Extents);
  S48_EXPORT_FUNCTION(scx_Text_Extents_16);
}
