diff src/glyphs-widget.c @ 384:bbff43aa5eb7 r21-2-7

Import from CVS: tag r21-2-7
author cvs
date Mon, 13 Aug 2007 11:08:24 +0200
parents
children aabb7f5b1c81
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/glyphs-widget.c	Mon Aug 13 11:08:24 2007 +0200
@@ -0,0 +1,444 @@
+/* Widget-specific glyph objects.
+   Copyright (C) 1998 Andy Piper
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: Not in FSF. */
+
+#include <config.h>
+#include "lisp.h"
+#include "lstream.h"
+#include "console.h"
+#include "device.h"
+#include "faces.h"
+#include "glyphs.h"
+#include "objects.h"
+
+#include "window.h"
+#include "buffer.h"
+#include "frame.h"
+#include "insdel.h"
+#include "opaque.h"
+
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (button);
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (combo);
+Lisp_Object Qcombo;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (edit);
+Lisp_Object Qedit;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (scrollbar);
+Lisp_Object Qscrollbar;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (widget);
+#if 0
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (group);
+Lisp_Object Qgroup;
+#endif
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (label);
+Lisp_Object Qlabel;
+
+Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
+
+#define WIDGET_BORDER_HEIGHT 2
+#define WIDGET_BORDER_WIDTH 4
+
+/* TODO:
+   - more complex controls.
+   - tooltips for controls.
+   - images in controls.
+ */
+
+/* In windows normal windows work in pixels, dialog boxes work in
+   dialog box units. Why? sigh. We could reuse the metrics for dialogs
+   if this were not the case. As it is we have to position things
+   pixel wise. I'm not even sure that X has this problem at least for
+   buttons in groups. */
+Lisp_Object
+widget_face_font_info (Lisp_Object domain, Lisp_Object face,
+		       int *height, int *width)
+{
+  Lisp_Object font_instance = FACE_FONT (face, domain, Vcharset_ascii);
+
+  if (height)
+    *height = XFONT_INSTANCE (font_instance)->height;
+  if (width)
+    *width = XFONT_INSTANCE (font_instance)->width;
+  
+  return font_instance;
+}
+
+void
+widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face,
+				 int th, int tw,
+				 int* height, int* width)
+{
+  int ch=0, cw=0;
+  widget_face_font_info (domain, face, &ch, &cw);
+  if (height)
+    *height = th * (ch + 2 * WIDGET_BORDER_HEIGHT);
+  if (width)
+    *width = tw * cw + 2 * WIDGET_BORDER_WIDTH;
+}
+
+static int
+widget_possible_dest_types (void)
+{
+  return IMAGE_WIDGET_MASK;
+}
+
+#if 0 /* currently unused */
+static void
+check_valid_glyph (Lisp_Object data)
+{
+  if (SYMBOLP (data))
+    CHECK_BUFFER_GLYPH (XSYMBOL (data)->value);
+  else
+    CHECK_BUFFER_GLYPH (data);
+}
+#endif /* currently unused */
+
+static void
+check_valid_item_list (Lisp_Object data)
+{
+  Lisp_Object rest;
+  Lisp_Object items;
+  Fcheck_valid_plist (data);
+  
+  items = Fplist_get (data, Q_items, Qnil);
+
+  CHECK_LIST (items);
+  EXTERNAL_LIST_LOOP (rest, items)
+    {
+      CHECK_STRING (XCAR (rest));
+    }
+}
+
+/* wire widget property invocations to specific widgets ...  The
+ problem we are solving here is that when instantiators get converted
+ to instances they lose some type information (they just become
+ subwindows or widgets for example). For widgets we need to preserve
+ this type information so that we can do widget specific operations on
+ the instances. This is encoded in the widget type
+ field. widget_property gets invoked by decoding the primary type
+ (Qwidget), widget property then invokes based on the secondary type
+ (Qedit for example). It is debatable that we should wire things in this
+ generalised way rather than treating widgets specially in
+ image_instance_property. */
+static Lisp_Object 
+widget_property (Lisp_Object image_instance, Lisp_Object prop)
+{
+  struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+  struct image_instantiator_methods* meths;
+
+  /* first see if its a general property ... */
+  if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
+    return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
+
+  /* .. then try device specific methods ... */
+  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+				   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+				   ERROR_ME_NOT);
+  if (meths && HAS_IIFORMAT_METH_P (meths, property))
+    return IIFORMAT_METH (meths, property, (image_instance, prop));
+  /* ... then format specific methods ... */
+  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+				   ERROR_ME_NOT);
+  if (meths && HAS_IIFORMAT_METH_P (meths, property))
+    return IIFORMAT_METH (meths, property, (image_instance, prop));
+  /* ... then fail */
+  return Qunbound;
+}
+
+static Lisp_Object 
+widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object val)
+{
+  struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+  struct image_instantiator_methods* meths;
+  Lisp_Object ret;
+
+  /* try device specific methods first ... */
+  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+				   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+				   ERROR_ME_NOT);
+  if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
+      &&
+      !UNBOUNDP (ret = 
+		 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
+    {
+      return ret;
+    }
+  /* ... then format specific methods ... */
+  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+				   ERROR_ME_NOT);
+  if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
+      &&
+      !UNBOUNDP (ret = 
+		 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
+    {
+      return ret;
+    }
+  /* we didn't do any device specific properties, so shove the property in our plist */
+  IMAGE_INSTANCE_WIDGET_PROPS (ii)
+    = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
+  return val;
+}
+
+static void
+widget_validate (Lisp_Object instantiator)
+{
+  Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
+  struct gui_item gui;
+  if (NILP (desc))
+    signal_simple_error ("Must supply :descriptor", instantiator);
+
+  gui_parse_item_keywords (desc, &gui);
+
+  if (!NILP (find_keyword_in_vector (instantiator, Q_width))
+	     && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
+    signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
+
+  if (!NILP (find_keyword_in_vector (instantiator, Q_height))
+	     && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
+    signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator);
+}
+
+static void
+combo_validate (Lisp_Object instantiator)
+{
+  widget_validate (instantiator);
+  if (NILP (find_keyword_in_vector (instantiator, Q_properties)))
+    signal_simple_error ("Must supply item list", instantiator);
+}
+
+static void
+initialize_widget_image_instance (struct Lisp_Image_Instance *ii, Lisp_Object type)
+{
+  /*  initialize_subwindow_image_instance (ii);*/
+  IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
+  IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
+  IMAGE_INSTANCE_WIDGET_FACE (ii) = Vwidget_face;
+  gui_item_init (&IMAGE_INSTANCE_WIDGET_ITEM (ii));
+}
+
+/* Instantiate a button widget. Unfortunately instantiated widgets are
+   particular to a frame since they need to have a parent. It's not
+   like images where you just select the image into the context you
+   want to display it in and BitBlt it. So images instances can have a
+   many-to-one relationship with things you see, whereas widgets can
+   only be one-to-one (i.e. per frame) */
+static void
+widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
+		      Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		      int dest_mask, Lisp_Object domain, int default_textheight,
+		      int default_pixheight)
+{
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  struct gui_item* pgui = &IMAGE_INSTANCE_WIDGET_ITEM (ii);
+  Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
+  Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
+  Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
+  Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
+  Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
+  Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
+  int pw=0, ph=0, tw=0, th=0;
+  
+  /* this just does pixel type sizing */
+  subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
+			 dest_mask, domain);
+
+  if (!(dest_mask & IMAGE_WIDGET_MASK))
+    incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
+
+  initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
+
+  /* retrieve the fg and bg colors */
+  if (!NILP (face))
+    IMAGE_INSTANCE_WIDGET_FACE (ii) = Fget_face (face);
+  
+  /* data items for some widgets */
+  IMAGE_INSTANCE_WIDGET_PROPS (ii) = 
+    find_keyword_in_vector (instantiator, Q_properties);
+
+  /* retrieve the gui item information */
+  if (STRINGP (desc) || NILP (desc))
+    IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
+  else
+    gui_parse_item_keywords (find_keyword_in_vector (instantiator, Q_descriptor),
+			     pgui);
+
+  /* normalize size information */
+  if (!NILP (width))
+    tw = XINT (width);
+  if (!NILP (height))
+    th = XINT (height);
+  if (!NILP (pixwidth))
+    pw = XINT (pixwidth);
+  if (!NILP (pixheight))
+    ph = XINT (pixheight);
+
+  if (!tw && !pw && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+    tw = XSTRING_LENGTH (IMAGE_INSTANCE_WIDGET_TEXT (ii));
+  if (!th && !ph)
+    {
+      if (default_textheight)
+	th = default_textheight;
+      else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+	th = 1;
+      else
+	ph = default_pixheight;
+    }
+
+  if (tw !=0 || th !=0)
+    widget_text_to_pixel_conversion (domain,
+				     IMAGE_INSTANCE_WIDGET_FACE (ii),
+				     th, tw, th ? &ph : 0, tw ? &pw : 0);
+
+  IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = pw;
+  IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = ph;
+}
+
+static void
+widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+		    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		    int dest_mask, Lisp_Object domain)
+{
+  widget_instantiate_1 (image_instance, instantiator, pointer_fg,
+			       pointer_bg, dest_mask, domain, 1, 0);
+}
+
+static void
+combo_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+		   Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		   int dest_mask, Lisp_Object domain)
+{
+  Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
+				 Q_items, Qnil);
+  int len;
+  GET_LIST_LENGTH (data, len);
+  widget_instantiate_1 (image_instance, instantiator, pointer_fg,
+			pointer_bg, dest_mask, domain, len + 1, 0);
+}
+
+/* Instantiate a static control */
+static void
+static_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+		    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		    int dest_mask, Lisp_Object domain)
+{
+  widget_instantiate_1 (image_instance, instantiator, pointer_fg,
+			pointer_bg, dest_mask, domain, 0, 4);
+}
+
+
+/************************************************************************/
+/*                            initialization                            */
+/************************************************************************/
+
+void
+syms_of_glyphs_widget (void)
+{
+  defkeyword (&Q_descriptor, ":descriptor");
+  defkeyword (&Q_height, ":height");
+  defkeyword (&Q_width, ":width");
+  defkeyword (&Q_properties, ":properties");
+  defkeyword (&Q_items, ":items");
+}
+
+void
+image_instantiator_format_create_glyphs_widget (void)
+{
+  /* we only do this for properties */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
+  IIFORMAT_HAS_METHOD (widget, property);
+  IIFORMAT_HAS_METHOD (widget, set_property);
+
+  /* widget image-instantiator types - buttons */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
+  IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
+
+  IIFORMAT_VALID_KEYWORD (button, Q_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (button, Q_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (button, Q_pixel_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (button, Q_pixel_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (button, Q_face, check_valid_face);
+  IIFORMAT_VALID_KEYWORD (button, Q_descriptor, check_valid_vector);
+  /* edit fields */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit, "edit");
+  IIFORMAT_HAS_SHARED_METHOD (edit, validate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (edit, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (edit, instantiate, widget);
+
+  IIFORMAT_VALID_KEYWORD (edit, Q_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (edit, Q_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (edit, Q_pixel_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (edit, Q_pixel_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (edit, Q_face, check_valid_face);
+  IIFORMAT_VALID_KEYWORD (edit, Q_descriptor, check_valid_vector);
+  /* combo box */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo, "combo");
+  IIFORMAT_HAS_METHOD (combo, validate);
+  IIFORMAT_HAS_SHARED_METHOD (combo, possible_dest_types, widget);
+  IIFORMAT_HAS_METHOD (combo, instantiate);
+
+  IIFORMAT_VALID_KEYWORD (combo, Q_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (combo, Q_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (combo, Q_pixel_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (combo, Q_face, check_valid_face);
+  IIFORMAT_VALID_KEYWORD (combo, Q_descriptor, check_valid_vector);
+  IIFORMAT_VALID_KEYWORD (combo, Q_properties, check_valid_item_list);
+  /* scrollbar */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
+  IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
+
+  IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
+  IIFORMAT_VALID_KEYWORD (scrollbar, Q_descriptor, check_valid_vector);
+  /* labels */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
+  IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (label, instantiate, static);
+
+  IIFORMAT_VALID_KEYWORD (label, Q_pixel_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (label, Q_pixel_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (label, Q_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (label, Q_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (label, Q_face, check_valid_face);
+  IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
+#if 0
+  /* group */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (group, "group");
+  IIFORMAT_HAS_SHARED_METHOD (group, possible_dest_types, widget);
+  IIFORMAT_HAS_METHOD (group, instantiate);
+
+  IIFORMAT_VALID_KEYWORD (group, Q_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (group, Q_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (group, Q_pixel_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (group, Q_pixel_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (group, Q_face, check_valid_face);
+  IIFORMAT_VALID_KEYWORD (group, Q_background, check_valid_string);
+  IIFORMAT_VALID_KEYWORD (group, Q_descriptor, check_valid_string);
+#endif
+}
+
+void
+vars_of_glyphs_widget (void)
+{
+}