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

#include "xlib.h"

s48_ref_t scx_display = NULL;
s48_ref_t scx_color = NULL;
s48_ref_t scx_gc = NULL;
s48_ref_t scx_fontstruct = NULL;
s48_ref_t scx_screenformat = NULL;
s48_ref_t scx_visual = NULL;
s48_ref_t scx_screen = NULL;
s48_ref_t scx_event_mask_binding = NULL;
s48_ref_t scx_gc_value_binding = NULL;
s48_ref_t scx_gc_values_binding = NULL;
s48_ref_t scx_byte_order_binding = NULL;
s48_ref_t scx_byte_orders_binding = NULL;
s48_ref_t scx_bit_order_binding = NULL;
s48_ref_t scx_bit_orders_binding = NULL;
s48_ref_t scx_bit_gravity_binding = NULL;
s48_ref_t scx_bit_gravities_binding = NULL;
s48_ref_t scx_win_gravity_binding = NULL;
s48_ref_t scx_win_gravities_binding = NULL;
s48_ref_t scx_event_type_binding = NULL;
s48_ref_t scx_event_types_binding = NULL;
s48_ref_t scx_font_direction_binding = NULL;
s48_ref_t scx_font_directions_binding = NULL;
s48_ref_t scx_state_binding = NULL;
s48_ref_t scx_states_binding = NULL;
s48_ref_t scx_state_set_binding = NULL;
s48_ref_t scx_button_binding = NULL;
s48_ref_t scx_buttons_binding = NULL;
s48_ref_t scx_notify_mode_binding = NULL;
s48_ref_t scx_notify_modes_binding = NULL;
s48_ref_t scx_notify_detail_binding = NULL;
s48_ref_t scx_notify_details_binding = NULL;
s48_ref_t scx_visibility_state_binding = NULL;
s48_ref_t scx_visibility_states_binding = NULL;
s48_ref_t scx_place_binding = NULL;
s48_ref_t scx_places_binding = NULL;
s48_ref_t scx_property_state_binding = NULL;
s48_ref_t scx_property_states_binding = NULL;
s48_ref_t scx_colormap_state_binding = NULL;
s48_ref_t scx_colormap_states_binding = NULL;
s48_ref_t scx_mapping_request_binding = NULL;
s48_ref_t scx_mapping_requests_binding = NULL;
s48_ref_t scx_backing_store_binding = NULL;
s48_ref_t scx_backing_stores_binding = NULL;
s48_ref_t scx_map_state_binding = NULL;
s48_ref_t scx_map_states_binding = NULL;
s48_ref_t scx_window_class_binding = NULL;
s48_ref_t scx_window_classes_binding = NULL;
s48_ref_t scx_stack_mode_binding = NULL;
s48_ref_t scx_stack_modes_binding = NULL;
s48_ref_t scx_window_change_binding = NULL;
s48_ref_t scx_window_changes_binding = NULL;

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

  return s48_unsafe_record_ref_2(call, value, i);
}

s48_ref_t scx_enum_set_type_binding = NULL;

extern unsigned long s48_extract_enum_set(s48_call_t call, s48_ref_t v, 
                       s48_ref_t type) {
  s48_check_record_type_2(call, v, scx_enum_set_type_binding);
  if (!(s48_eq_p_2(call, s48_unsafe_shared_binding_ref_2(call, type),
		   s48_unsafe_record_ref_2(call, v, 0))))
    s48_assertion_violation_2(call, "s48_extract_enum_set", 
			      "Wrong argument type", 0);
  return s48_extract_long_2(call, s48_unsafe_record_ref_2(call, v, 1));
}

s48_ref_t s48_enter_enum_set(s48_call_t call, unsigned long v, s48_ref_t type) {
  s48_ref_t r = s48_make_record_2(call, scx_enum_set_type_binding);
  s48_record_set_2(call, r, 0, s48_shared_binding_ref_2(call, type));
  s48_record_set_2(call, r, 1, s48_enter_long_2(call, v));
  return r;
}

s48_ref_t scx_struct_cache_ref(s48_call_t call, void* cpointer, 
			       s48_ref_t the_list) {
  s48_ref_t list = s48_copy_local_ref(call, the_list);

  while (s48_pair_p_2(call, list)) {
    s48_ref_t temp = list;

    if (s48_extract_pointer_2(call, s48_car_2(call, s48_car_2(call, list))) == 
	cpointer)
      return s48_weak_pointer_ref_2(call, 
				    s48_cdr_2(call, s48_car_2(call, list)));
    
    list = s48_cdr_2(call, list);
    s48_free_local_ref(call, temp);
  }
  
  return s48_false_2(call);
}

void scx_struct_cache_set(s48_call_t call, void* cpointer, 
      s48_ref_t* l, s48_ref_t v) {
  s48_ref_t list = s48_copy_local_ref(call, *l);//s48_make_local_ref(call, s48_deref(*l));
  s48_ref_t previous = s48_false_2(call);
  s48_ref_t pair = s48_false_2(call);

  /* create the new entry */
  pair = s48_make_weak_pointer_2(call, v);// s48_local_to_global_ref(s48_make_weak_pointer_2(call, v));
  pair = s48_cons_2(call, s48_enter_pointer_2(call, cpointer), pair);
    // s48_local_to_global_ref(s48_cons_2(call, 
    //			       s48_local_to_global_ref(s48_enter_pointer_2(call, cpointer)), pair));

  *l = s48_local_to_global_ref(s48_cons_2(call, pair, list));//s48_local_to_global_ref(s48_cons_2(call, pair, *l));
  previous = s48_make_local_ref(call, s48_deref(*l));

  /* remove all empty and duplicate entries */
  while (!s48_null_p_2(call, list)) {
    s48_ref_t entry = s48_car_2(call, list);
    if ((s48_false_p_2(call, s48_weak_pointer_ref_2(call, s48_cdr_2(call, entry)))) ||
        (s48_extract_pointer_2(call, s48_car_2(call, entry)) == cpointer))
      s48_set_cdr_2(call, previous, s48_local_to_global_ref(s48_cdr_2(call, list)));
    else
      previous = list;
    
    list = s48_local_to_global_ref(s48_cdr_2(call, list));
  }

  *l = s48_local_to_global_ref(previous);
 }

void scx_init_types(void) {
  scx_enum_set_type_binding = s48_get_imported_binding_2("s48-enum-set-type");
  scx_display = s48_get_imported_binding_2("scx-display");
  scx_color = s48_get_imported_binding_2("scx-color");
  scx_gc = s48_get_imported_binding_2("scx-gc");
  scx_fontstruct = s48_get_imported_binding_2("scx-fontstruct");
  scx_screenformat = s48_get_imported_binding_2("scx-screenformat");
  scx_visual = s48_get_imported_binding_2("scx-visual");
  scx_screen = s48_get_imported_binding_2("scx-screen");

  scx_event_mask_binding = s48_get_imported_binding_2("scx-event-mask");
  scx_gc_value_binding = s48_get_imported_binding_2("scx-gc-value");
  scx_gc_values_binding = s48_get_imported_binding_2("scx-gc-values");
  scx_byte_order_binding = s48_get_imported_binding_2("scx-byte-order");
  scx_byte_orders_binding = s48_get_imported_binding_2("scx-byte-orders");
  scx_bit_order_binding = s48_get_imported_binding_2("scx-bit-order");
  scx_bit_orders_binding = s48_get_imported_binding_2("scx-bit-orders");
  scx_bit_gravity_binding = s48_get_imported_binding_2("scx-bit-gravity");
  scx_bit_gravities_binding = s48_get_imported_binding_2("scx-bit-gravities");
  scx_win_gravity_binding = s48_get_imported_binding_2("scx-win-gravity");
  scx_win_gravities_binding = s48_get_imported_binding_2("scx-win-gravities");
  scx_event_type_binding = s48_get_imported_binding_2("scx-event-type");
  scx_event_types_binding = s48_get_imported_binding_2("scx-event-types");
  scx_font_direction_binding = s48_get_imported_binding_2("scx-font-direction");
  scx_font_directions_binding = s48_get_imported_binding_2("scx-font-directions");
  scx_state_binding = s48_get_imported_binding_2("scx-state");
  scx_states_binding = s48_get_imported_binding_2("scx-states");
  scx_state_set_binding = s48_get_imported_binding_2("scx-state-set");
  scx_button_binding = s48_get_imported_binding_2("scx-button");
  scx_buttons_binding = s48_get_imported_binding_2("scx-buttons");
  scx_notify_mode_binding = s48_get_imported_binding_2("scx-notify-mode");
  scx_notify_modes_binding = s48_get_imported_binding_2("scx-notify-modes");
  scx_notify_detail_binding = s48_get_imported_binding_2("scx-notify-detail");
  scx_notify_details_binding = s48_get_imported_binding_2("scx-notify-details");
  scx_visibility_state_binding = s48_get_imported_binding_2("scx-visibility-state");
  scx_visibility_states_binding = s48_get_imported_binding_2("scx-visibility-states");
  scx_place_binding = s48_get_imported_binding_2("scx-place");
  scx_places_binding = s48_get_imported_binding_2("scx-places");
  scx_property_state_binding = s48_get_imported_binding_2("scx-property-state");
  scx_property_states_binding = s48_get_imported_binding_2("scx-property-states");
  scx_colormap_state_binding = s48_get_imported_binding_2("scx-colormap-state");
  scx_colormap_state_binding = s48_get_imported_binding_2("scx-colormap-states");
  scx_mapping_request_binding = s48_get_imported_binding_2("scx-mapping-request");
  scx_mapping_requests_binding = s48_get_imported_binding_2("scx-mapping-requests");
  scx_backing_store_binding = s48_get_imported_binding_2("scx-backing-store");
  scx_backing_stores_binding = s48_get_imported_binding_2("scx-backing-stores");
  scx_map_state_binding = s48_get_imported_binding_2("scx-map-state");
  scx_map_states_binding = s48_get_imported_binding_2("scx-map-states");
  scx_window_class_binding = s48_get_imported_binding_2("scx-window-class");
  scx_window_classes_binding = s48_get_imported_binding_2("scx-window-classes");
  scx_stack_mode_binding = s48_get_imported_binding_2("scx-stack-mode");
  scx_stack_modes_binding = s48_get_imported_binding_2("scx-stack-modes");
  scx_window_change_binding = s48_get_imported_binding_2("scx-window-change");
  scx_window_changes_binding = s48_get_imported_binding_2("scx-window-changes");
}
