changeset 1883:c347bc6e2cb3

[xemacs-hg @ 2004-01-27 13:13:42 by stephent] gtk button fix <87isixo7sl.fsf_-_@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Tue, 27 Jan 2004 13:13:45 +0000
parents 01dce9d37966
children 3d25fd3d9ac4
files src/ChangeLog src/ui-gtk.c
diffstat 2 files changed, 289 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Jan 27 13:00:42 2004 +0000
+++ b/src/ChangeLog	Tue Jan 27 13:13:45 2004 +0000
@@ -1,3 +1,10 @@
+2004-01-16  Malcolm Purvis  <malcolmpurvis@optushome.com.au>
+
+	* ui-gtk.c (__internal_callback_marshal): Marshalling data to
+	return to GTK requires a different API to marshalling data to use
+	as GTK parameters.
+	* ui-gtk.c (lisp_to_gtk_ret_type): New. 
+
 2004-01-23  Stephen J. Turnbull  <stephen@xemacs.org>
 
 	* specifier.c (Fvalid_specifier_type_p): Fix docstring typo.
--- a/src/ui-gtk.c	Tue Jan 27 13:00:42 2004 +0000
+++ b/src/ui-gtk.c	Tue Jan 27 13:13:45 2004 +0000
@@ -37,6 +37,7 @@
 
 Lisp_Object gtk_type_to_lisp (GtkArg *arg);
 int lisp_to_gtk_type (Lisp_Object obj, GtkArg *arg);
+int lisp_to_gtk_ret_type (Lisp_Object obj, GtkArg *arg);
 #if 0
 void describe_gtk_arg (GtkArg *arg);
 #endif
@@ -1042,7 +1043,7 @@
   signal_fake_event ();
 
   if (args[n_args].type != GTK_TYPE_NONE)
-    lisp_to_gtk_type (rval, &args[n_args]);
+    lisp_to_gtk_ret_type (rval, &args[n_args]);
 
   UNGCPRO;
 }
@@ -1807,6 +1808,286 @@
   return (0);
 }
 
+/* Convert lisp types to GTK return types.  This is identical to
+   lisp_to_gtk_type() except that the macro used to set the value is
+   different.
+
+   ### There should be some way of combining these two functions.
+*/
+int lisp_to_gtk_ret_type (Lisp_Object obj, GtkArg *arg)
+{
+  switch (GTK_FUNDAMENTAL_TYPE (arg->type))
+    {
+      /* flag types */
+    case GTK_TYPE_NONE:
+      return (0);
+    case GTK_TYPE_CHAR:
+      {
+	Ichar c;
+
+	CHECK_CHAR_COERCE_INT (obj);
+	c = XCHAR (obj);
+	*(GTK_RETLOC_CHAR (*arg)) = c;
+      }
+      break;
+    case GTK_TYPE_UCHAR:
+      {
+	Ichar c;
+
+	CHECK_CHAR_COERCE_INT (obj);
+	c = XCHAR (obj);
+	*(GTK_RETLOC_CHAR (*arg)) = c;
+      }
+      break;
+    case GTK_TYPE_BOOL:
+      *(GTK_RETLOC_BOOL (*arg)) = NILP (obj) ? FALSE : TRUE;
+      break;
+    case GTK_TYPE_INT:
+    case GTK_TYPE_UINT:
+      if (NILP (obj) || EQ (Qt, obj))
+	{
+	  /* For we are a kind mistress and allow sending t/nil for
+             1/0 to stupid GTK functions that say they take guint or
+             gint in the header files, but actually treat it like a
+             bool.  *sigh*
+	  */
+	  *(GTK_RETLOC_INT(*arg)) = NILP (obj) ? 0 : 1;
+	}
+      else
+	{
+	  CHECK_INT (obj);
+	  *(GTK_RETLOC_INT(*arg)) = XINT (obj);
+	}
+      break;
+    case GTK_TYPE_LONG:
+    case GTK_TYPE_ULONG:
+      abort();
+    case GTK_TYPE_FLOAT:
+      CHECK_INT_OR_FLOAT (obj);
+      *(GTK_RETLOC_FLOAT(*arg)) = extract_float (obj);
+      break;
+    case GTK_TYPE_DOUBLE:
+      CHECK_INT_OR_FLOAT (obj);
+      *(GTK_RETLOC_DOUBLE(*arg)) = extract_float (obj);
+      break;
+    case GTK_TYPE_STRING:
+      if (NILP (obj))
+	*(GTK_RETLOC_STRING (*arg)) = NULL;
+      else
+	{
+	  CHECK_STRING (obj);
+	  *(GTK_RETLOC_STRING (*arg)) = (char *) XSTRING_DATA (obj);
+	}
+      break;
+    case GTK_TYPE_ENUM:
+    case GTK_TYPE_FLAGS:
+      /* Convert a lisp symbol to a GTK enum */
+      *(GTK_RETLOC_ENUM(*arg)) = lisp_to_flag (obj, arg->type);
+      break;
+    case GTK_TYPE_BOXED:
+      if (NILP (obj))
+	{
+	  *(GTK_RETLOC_BOXED(*arg)) = NULL;
+	}
+      else if (GTK_BOXEDP (obj))
+	{
+	  *(GTK_RETLOC_BOXED(*arg)) = XGTK_BOXED (obj)->object;
+	}
+      else if (arg->type == GTK_TYPE_STYLE)
+	{
+	  obj = Ffind_face (obj);
+	  CHECK_FACE (obj);
+	  *(GTK_RETLOC_BOXED(*arg)) = face_to_style (obj);
+	}
+      else if (arg->type == GTK_TYPE_GDK_GC)
+	{
+	  obj = Ffind_face (obj);
+	  CHECK_FACE (obj);
+	  *(GTK_RETLOC_BOXED(*arg)) = face_to_gc (obj);
+	}
+      else if (arg->type == GTK_TYPE_GDK_WINDOW)
+	{
+	  if (GLYPHP (obj))
+	    {
+	      Lisp_Object window = Fselected_window (Qnil);
+	      Lisp_Object instance =
+		glyph_image_instance (obj, window, ERROR_ME_DEBUG_WARN, 1);
+	      struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (instance);
+
+	      switch (XIMAGE_INSTANCE_TYPE (instance))
+		{
+		case IMAGE_TEXT:
+		case IMAGE_POINTER:
+		case IMAGE_SUBWINDOW:
+		case IMAGE_NOTHING:
+		  *(GTK_RETLOC_BOXED(*arg)) = NULL;
+		  break;
+
+		case IMAGE_MONO_PIXMAP:
+		case IMAGE_COLOR_PIXMAP:
+		  *(GTK_RETLOC_BOXED(*arg)) = IMAGE_INSTANCE_GTK_PIXMAP (p);
+		  break;
+		}
+	    }
+	  else if (GTK_OBJECTP (obj) && GTK_IS_WIDGET (XGTK_OBJECT (obj)->object))
+	    {
+	      *(GTK_RETLOC_BOXED(*arg)) = GTK_WIDGET (XGTK_OBJECT (obj))->window;
+	    }
+	  else
+	    {
+	      invalid_argument ("Don't know how to convert object to GDK_WINDOW", obj);
+	    }
+	  break;
+	}
+      else if (arg->type == GTK_TYPE_GDK_COLOR)
+	{
+	  if (COLOR_SPECIFIERP (obj))
+	    {
+	      /* If it is a specifier, we just convert it to an
+                 instance, and let the ifs below handle it.
+	      */
+	      obj = Fspecifier_instance (obj, Qnil, Qnil, Qnil);
+	    }
+	  
+	  if (COLOR_INSTANCEP (obj))
+	    {
+	      /* Easiest one */
+	      *(GTK_RETLOC_BOXED(*arg)) = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (obj));
+	    }
+	  else if (STRINGP (obj))
+	    {
+	      invalid_argument ("Please use a color specifier or instance, not a string", obj);
+	    }
+	  else
+	    {
+	      invalid_argument ("Don't know how to convert to GdkColor", obj);
+	    }
+	}
+      else if (arg->type == GTK_TYPE_GDK_FONT)
+	{
+	  if (SYMBOLP (obj))
+	    {
+	      /* If it is a symbol, we treat that as a face name */
+	      obj = Ffind_face (obj);
+	    }
+
+	  if (FACEP (obj))
+	    {
+	      /* If it is a face, we just grab the font specifier, and
+                 cascade down until we finally reach a FONT_INSTANCE
+	      */
+	      obj = Fget (obj, Qfont, Qnil);
+	    }
+
+	  if (FONT_SPECIFIERP (obj))
+	    {
+	      /* If it is a specifier, we just convert it to an
+                 instance, and let the ifs below handle it
+	      */
+	      obj = Fspecifier_instance (obj, Qnil, Qnil, Qnil);
+	    }
+
+	  if (FONT_INSTANCEP (obj))
+	    {
+	      /* Easiest one */
+	      *(GTK_RETLOC_BOXED(*arg)) = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (obj));
+	    }
+	  else if (STRINGP (obj))
+	    {
+	      invalid_argument ("Please use a font specifier or instance, not a string", obj);
+	    }
+	  else
+	    {
+	      invalid_argument ("Don't know how to convert to GdkColor", obj);
+	    }
+	}
+      else
+	{
+	  /* Unknown type to convert to boxed */
+	  stderr_out ("Don't know how to convert to boxed!\n");
+	  *(GTK_RETLOC_BOXED(*arg)) = NULL;
+	}
+      break;
+
+    case GTK_TYPE_POINTER:
+      if (NILP (obj))
+	*(GTK_RETLOC_POINTER(*arg)) = NULL;
+      else
+	*(GTK_RETLOC_POINTER(*arg)) = LISP_TO_VOID (obj);
+      break;
+
+      /* structured types */
+    case GTK_TYPE_SIGNAL:
+    case GTK_TYPE_ARGS: /* This we can do as a list of values */
+    case GTK_TYPE_C_CALLBACK:
+    case GTK_TYPE_FOREIGN:
+      stderr_out ("Do not know how to convert `%s' from lisp!\n", gtk_type_name (arg->type));
+      return (-1);
+
+#if 0
+      /* #### BILL! */
+      /* This is not used, and does not work with union type */
+    case GTK_TYPE_CALLBACK:
+      {
+	GUI_ID id;
+
+	id = new_gui_id ();
+	obj = Fcons (Qnil, obj); /* Empty data */
+	obj = Fcons (make_int (id), obj);
+
+	gcpro_popup_callbacks (id, obj);
+
+	*(GTK_RETLOC_CALLBACK(*arg)).marshal = __internal_callback_marshal;
+	*(GTK_RETLOC_CALLBACK(*arg)).data = (gpointer) obj;
+	*(GTK_RETLOC_CALLBACK(*arg)).notify = __internal_callback_destroy;
+      }
+      break;
+#endif
+
+      /* base type of the object system */
+    case GTK_TYPE_OBJECT:
+      if (NILP (obj))
+	*(GTK_RETLOC_OBJECT (*arg)) = NULL;
+      else
+	{
+	  CHECK_GTK_OBJECT (obj);
+	  if (XGTK_OBJECT (obj)->alive_p)
+	    *(GTK_RETLOC_OBJECT (*arg)) = XGTK_OBJECT (obj)->object;
+	  else
+	    invalid_argument ("Attempting to pass dead object to GTK function", obj);
+	}
+      break;
+
+    default:
+      if (GTK_FUNDAMENTAL_TYPE (arg->type) == GTK_TYPE_ARRAY)
+	{
+	  if (NILP (obj))
+	    *(GTK_RETLOC_POINTER(*arg)) = NULL;
+	  else
+	    {
+	      xemacs_list_to_array (obj, arg);
+	    }
+	}
+      else if (GTK_FUNDAMENTAL_TYPE (arg->type) == GTK_TYPE_LISTOF)
+	{
+	  if (NILP (obj))
+	    *(GTK_RETLOC_POINTER(*arg)) = NULL;
+	  else
+	    {
+	      xemacs_list_to_gtklist (obj, arg);
+	    }
+	}
+      else
+	{
+	  stderr_out ("Do not know how to convert `%s' from lisp!\n", gtk_type_name (arg->type));
+	  abort();
+	}
+      break;
+    }
+
+  return (0);
+}
+
 /* This is used in glyphs-gtk.c as well */
 static Lisp_Object
 get_enumeration (GtkType t)