changeset 7363:c31e5dab4f85

[project @ 2008-01-12 08:21:57 by jwe]
author jwe
date Sat, 12 Jan 2008 08:21:57 +0000
parents 94f66d813b2d
children 0e07f78369d1
files src/ChangeLog src/Makefile.in src/genprops.awk src/graphics.cc src/graphics.h.in
diffstat 5 files changed, 1756 insertions(+), 2600 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sat Jan 12 08:00:38 2008 +0000
+++ b/src/ChangeLog	Sat Jan 12 08:21:57 2008 +0000
@@ -1,3 +1,11 @@
+2008-01-12  Michael Goffioul <michael.goffioul@gmail.com>
+
+	* Makefile.in (distclean): Delete graphics-props.cc.
+
+	* genprops.awk: Handle new graphics property classes.
+
+	* graphics.h.in, graphics.cc: Adapt for new specific property types.
+
 2008-01-12  John W. Eaton  <jwe@octave.org>
 
 	* toplev.cc (octave_config_info): Add GNUPLOT to the struct.
--- a/src/Makefile.in	Sat Jan 12 08:00:38 2008 +0000
+++ b/src/Makefile.in	Sat Jan 12 08:21:57 2008 +0000
@@ -525,7 +525,7 @@
 distclean: clean
 	rm -f Makefile octave$(EXEEXT) .fname so_locations oct-errno.cc
 	rm -f stamp-prereq stamp-liboctave-prereq
-	rm -f doc-files gendoc.cc graphics.h mxarray.h DOCSTRINGS
+	rm -f doc-files gendoc.cc graphics.h graphics-props.cc mxarray.h DOCSTRINGS
 .PHONY: distclean
 
 maintainer-clean: distclean
--- a/src/genprops.awk	Sat Jan 12 08:00:38 2008 +0000
+++ b/src/genprops.awk	Sat Jan 12 08:21:57 2008 +0000
@@ -109,174 +109,420 @@
 ## The 'o' and 'O' qualifiers are only useful when the the property type
 ## is something other than octave_value.
 
+## simple accessor
+
+function emit_get_accessor (i, rtype, faccess)
+{
+  printf ("  %s get_%s (void) const", rtype, name[i]);
+  
+  if (emit_get[i] == "definition")
+    printf (" { return %s.%s (); }\n", name[i], faccess);
+  else
+    printf (";\n");
+}
+
+## bool_property
+
+function emit_get_bool (i)
+{
+  printf ("  bool is_%s (void) const", name[i]);
+  
+  if (emit_get[i] == "definition")
+    printf (" { return %s.is_on (); }\n", name[i]);
+  else
+    printf (";\n");
+
+  emit_get_accessor(i, "std::string", "current_value");
+}
+
+## radio_property
+
+function emit_get_radio (i)
+{
+  printf ("  bool %s_is (const std::string& v) const", name[i]);
+  
+  if (emit_get[i] == "definition")
+    printf (" { return %s.is (v); }\n", name[i]);
+  else
+    printf (";\n");
+
+  emit_get_accessor(i, "std::string", "current_value");
+}
+
+## color_property
+
+function emit_get_color (i)
+{
+  printf ("  bool %s_is_rgb (void) const { return %s.is_rgb (); }\n", name[i], name[i]);
+
+  printf ("  bool %s_is (const std::string& v) const", name[i]);
+  
+  if (emit_get[i] == "definition")
+    printf (" { return %s.is (v); }\n", name[i]);
+  else
+    printf (";\n");
+  
+  printf ("  Matrix get_%s_rgb (void) const", name[i]);
+  
+  if (emit_get[i] == "definition")
+    printf (" { return (%s.is_rgb () ? %s.rgb () : Matrix ()); }\n", name[i], name[i]);
+  else
+    printf (";\n");
+
+  emit_get_accessor(i, "octave_value", "get");
+}
+
+## callback_property
+
+function emit_get_callback (i)
+{
+  printf ("  void execute_%s (void)", name[i]);
+  
+  if (emit_get[i] == "definition")
+    printf (" { %s.execute (); }\n", name[i]);
+  else
+    printf (";\n");
+
+  emit_get_accessor(i, "octave_value", "get");
+}
+
+## data_property
+
+function emit_get_data (i)
+{
+  emit_get_accessor(i, "NDArray", "array_value");
+
+  printf ("  data_property get_%s_property (void) const { return %s; }\n",
+          name[i], name[i]);
+}
+
+## common section
+
+function emit_common_declarations ()
+{
+  printf ("public:\n");
+  printf ("  properties (const graphics_handle& mh, const graphics_handle& p);\n\n");
+  printf ("  ~properties (void) { }\n\n");
+  printf ("  void set (const caseless_str& name, const octave_value& val);\n\n");
+  printf ("  octave_value get (void) const;\n\n");
+  printf ("  octave_value get (const caseless_str& name) const;\n\n");
+  printf ("  std::string graphics_object_name (void) const { return go_name; }\n\n");
+  printf ("  static property_list::pval_map_type factory_defaults (void);\n\n");
+  printf ("private:\n  static std::string go_name;\n\n");
+}
+
 function emit_declarations ()
 {
+  if (class_name)
+    emit_common_declarations();
+
   if (idx > 0)
-      print "private:\n";
+    print "private:\n";
 
   for (i = 1; i <= idx; i++)
-      printf ("  %s%s %s;\n", mutable[i] ? "mutable " : "", type[i], name[i]);
+    printf ("  %s%s %s;\n", mutable[i] ? "mutable " : "", type[i], name[i]);
 
   if (idx > 0)
-      print "\npublic:\n";
+    print "\npublic:\n";
 
   for (i = 1; i <= idx; i++)
   {
-      if (emit_get[i])
+    if (emit_get[i])
+    {
+      if (type[i] == "array_property" || type[i] == "any_property")
+        emit_get_accessor(i, "octave_value", "get");
+      else if (type[i] == "handle_property")
+        emit_get_accessor(i, "graphics_handle", "handle_value");
+      else if (type[i] == "string_property")
+        emit_get_accessor(i, "std::string", "string_value");
+      else if (type[i] == "double_property")
+        emit_get_accessor(i, "double", "double_value");
+      else if (type[i] == "data_property")
+        emit_get_data(i);
+      else if (type[i] == "bool_property")
+        emit_get_bool(i);
+      else if (type[i] == "radio_property")
+        emit_get_radio(i);
+      else if (type[i] == "color_property")
+        emit_get_color(i);
+      else if (type[i] == "callback_property")
+        emit_get_callback(i);
+      else
       {
-	  printf ("  %s get_%s (void) const", type[i], name[i]);
+        printf ("  %s get_%s (void) const", type[i], name[i]);
 
-	  if (emit_get[i] == "definition")
-	      printf (" { return %s; }\n", name[i]);
-	  else
-	      printf (";\n");
+        if (emit_get[i] == "definition")
+          printf (" { return %s; }\n", name[i]);
+        else
+          printf (";\n");
       }
+      printf ("\n");
+    }
   }
 
   if (idx > 0)
-      printf ("\n");
+    printf ("\n");
 
   for (i = 1; i <= idx; i++)
   {
-      if (emit_set[i])
-      {
-	  printf ("  void set_%s (const %s& val)", name[i], type[i]);
+    if (emit_set[i])
+    {
+      printf ("  void set_%s (const octave_value& val)", name[i], type[i]);
 
-	  if (emit_set[i] == "definition")
-	  {
-	      printf ("\n  {\n    if (! error_state)\n      {\n        %s = val;\n",
-		      name[i]);
-	      if (limits[i])
-		  printf ("        update_axis_limits (\"%s\");\n", name[i]);
-	      if (mode[i])
-		  printf ("        set_%smode (\"manual\");\n", name[i]);
-	      printf ("        mark_modified ();\n      }\n  }\n\n");
-	  }
-	  else
-	      printf (";\n");
+      if (emit_set[i] == "definition")
+      {
+        printf ("\n  {\n    if (! error_state)\n      {\n        %s = val;\n",
+          name[i]);
+        if (limits[i])
+          printf ("        update_axis_limits (\"%s\");\n", name[i]);
+        if (mode[i])
+          printf ("        set_%smode (\"manual\");\n", name[i]);
+        printf ("        mark_modified ();\n      }\n  }\n\n");
       }
+      else
+        printf (";\n\n");
+    }
 
-      if (emit_ov_set[i])
-      {
-	  printf ("  void set_%s (const octave_value& val)", name[i]);
-
-	  if (emit_ov_set[i] == "definition")
-	      printf (" { set_%s (%s (val)); }\n\n", name[i], type[i]);
-          else if (emit_ov_set[i] == "assignment")
-          {
-              printf ("\n  {\n    %s tmp (%s);\n    tmp = val;\n    set_%s (tmp);\n  };\n\n",
-		      type[i], name[i], name[i], name[i]);
-         }
-	  else
-	      printf (";\n");
-      }
+##    if (emit_ov_set[i])
+##    {
+##      printf ("  void set_%s (const octave_value& val)", name[i]);
+##
+##      if (emit_ov_set[i] == "definition")
+##        printf (" { set_%s (%s (val)); }\n\n", name[i], type[i]);
+##      else if (emit_ov_set[i] == "assignment")
+##      {
+##        printf ("\n  {\n    %s tmp (%s);\n    tmp = val;\n    set_%s (tmp);\n  };\n\n",
+##                type[i], name[i], name[i], name[i]);
+##      }
+##      else
+##        printf (";\n");
+##    }
   }
 
-  if (idx > 0)
-      print "\nprivate:";
+##  if (idx > 0)
+##    print "\nprivate:";
+}
+
+function emit_source ()
+{
+  if (class_name)
+  {
+    printf ("// ******** %s ********\n\n", class_name) >> filename;
+
+    ## constructor
+
+    printf ("%s::properties::properties (const graphics_handle& mh, const graphics_handle& p)\n", class_name) >> filename;
+    printf ("  : base_properties (go_name, mh, p),\n") >> filename;
+
+    for (i = 1; i <= idx; i++)
+    {
+      printf ("    %s (\"%s\", mh, %s)", name[i], name[i], default[i]) >> filename;
+      if (i < idx)
+        printf (",") >> filename;
+      printf ("\n") >> filename;
+    }
+
+    printf ("{\n  init ();\n") >> filename;
+
+##    for (i = 1; i <= idx; i++)
+##      printf ("  insert_static_property (\"%s\", %s);\n", name[i], name[i]) >> filename;
+
+    printf ("}\n\n") >> filename;
+
+    ## set method
+
+    printf ("void\n%s::properties::set (const caseless_str& name, const octave_value& val)\n{\n",
+            class_name) >> filename;
+
+    for (i = 1; i <= idx; i++)
+    {
+      printf ("  %sif (name.compare (\"%s\"))\n    set_%s (val);\n",
+              (i > 1 ? "else " : ""), name[i], name[i]) >> filename;
+    }
+
+    printf ("  else\n    base_properties::set (name, val);\n}\n\n") >> filename;
+
+    ## get "all" method
+
+    printf ("octave_value\n%s::properties::get (void) const\n{\n", class_name) >> filename;
+    printf ("  Octave_map m = base_properties::get ().map_value ();\n\n") >> filename;
+
+    for (i = 1; i <= idx; i++)
+    {
+      printf ("  m.assign (\"%s\", get_%s ()%s);\n", name[i], name[i],
+              (type[i] == "handle_property" ? ".as_octave_value ()" : "")) >> filename;
+    }
+
+    printf ("\n  return m;\n}\n\n") >> filename;
+    
+    ## get "one" method
+
+    printf ("octave_value\n%s::properties::get (const caseless_str& name) const\n{\n",
+            class_name) >> filename;
+    printf ("  octave_value retval;\n\n") >> filename;
+
+    for (i = 1; i<= idx; i++)
+    {
+      printf ("  %sif (name.compare (\"%s\"))\n",
+              (i > 1 ? "else " : ""), name[i]) >> filename;
+      printf ("    retval = get_%s ()%s;\n", name[i],
+              (type[i] == "handle_property" ? ".as_octave_value ()" : "")) >> filename;
+    }
+
+    printf ("  else\n    retval = base_properties::get (name);\n\n") >> filename;
+    printf ("  return retval;\n}\n\n") >> filename;
+
+    ## factory defaults method
+
+    printf ("property_list::pval_map_type\n%s::properties::factory_defaults (void)\n{\n",
+            class_name) >> filename;
+    printf ("  property_list::pval_map_type m;\n\n") >> filename;
+
+    for (i = 1; i <= idx; i++)
+    {
+      defval = default[i];
+      if (type[i] == "radio_property" || type[i] == "color_property")
+        defval = gensub (/^.*\{(.*)\}.*$/, "\"\\1\"", "g", defval);
+      if (! defval)
+        defval = "octave_value ()";
+      if (name[i] !~ /__.*/)
+        printf ("  m[\"%s\"] = %s%s;\n", name[i], defval,
+                (type[i] == "handle_property" ? ".as_octave_value ()" : "")) >> filename;
+    }
+
+    printf ("\n  return m;\n}\n\n") >> filename;
+
+    ## go_name static field
+
+    printf ("std::string %s::properties::go_name (\"%s\");\n\n",
+            class_name, class_name) >> filename;
+  }
 }
 
 BEGIN {
-    printf ("// DO NOT EDIT!  Generated automatically by genprops.awk.\n\n");
+  filename = "graphics-props.cc";
+  printf ("// DO NOT EDIT!  Generated automatically by genprops.awk.\n\n");
+  printf ("// DO NOT EDIT!  Generated automatically by genprops.awk.\n\n") > filename;
+}
+
+/BEGIN_PROPERTIES\(.*\)/ {
+  gather = 1;
+  idx = 0;
+  class_name = gensub (/^.*BEGIN_PROPERTIES\((.*)\)/, "\\1", "g");
+  next;
 }
 
 /BEGIN_PROPERTIES/ {
-    gather = 1;
-    idx = 0;
-    next;
+  gather = 1;
+  idx = 0;
+  class_name = "";
+  next;
 }
 
 /END_PROPERTIES/ {
-    emit_declarations();
-    gather = 0;
-    next;
+  emit_declarations();
+  emit_source();
+  gather = 0;
+  next;
 }
 
 {
   if (gather)
-    {
-      if (NF < 2 || NF > 4)
-	next;
+  {
+    if (NF < 2)
+      next;
 
-      idx++;
+    idx++;
 
-      field = 1;
+    field = 1;
 
-      if ($field == "mutable")
-      {
-	  mutable[idx] = 1;
-	  field++;
-      }
-      else
-	  mutable[idx] = 0;
+    if ($field == "mutable")
+    {
+      mutable[idx] = 1;
+      field++;
+    }
+    else
+      mutable[idx] = 0;
 
-      type[idx] = $(field++);
-      name[idx] = $(field++);
+    type[idx] = $(field++);
+    name[idx] = $(field++);
 
-      limits[idx] = 0;
-      mode[idx] = 0;
-      emit_get[idx] = "definition";
-      emit_set[idx] = "definition";
-      if (type[idx] == "octave_value")
-	  emit_ov_set[idx] = "";
-      else
-	  emit_ov_set[idx] = "definition";
+    limits[idx] = 0;
+    mode[idx] = 0;
+    emit_get[idx] = "definition";
+    emit_set[idx] = "definition";
+    default[idx] = "";
+##    if (type[idx] == "octave_value")
+##      emit_ov_set[idx] = "";
+##    else
+##      emit_ov_set[idx] = "definition";
 
-      if (NF == field)
-        {
-	    quals = $field;
-
-	    if (index (quals, "l"))
-		limits[idx] = 1;
+    if (NF >= field)
+    {
+      if ($field != ",")
+      {
+        quals = $(field++);
 
-	    if (index (quals, "m"))
-		mode[idx] = 1;
+        if (index (quals, "l"))
+          limits[idx] = 1;
 
-	    ## There is a custom inline definition for the get function,
-	    ## so we don't emit anything.
-	    if (index (quals, "g"))
-		emit_get[idx] = "";
+        if (index (quals, "m"))
+          mode[idx] = 1;
+
+        ## There is a custom inline definition for the get function,
+        ## so we don't emit anything.
+        if (index (quals, "g"))
+          emit_get[idx] = "";
 
-	    ## There is a custom extern definition for the get function,
-	    ## but we still emit the declaration.
-	    if (index (quals, "G"))
-		emit_get[idx] = "declaration";
+        ## There is a custom extern definition for the get function,
+        ## but we still emit the declaration.
+        if (index (quals, "G"))
+          emit_get[idx] = "declaration";
 
-	    ## There is a custom inline definition for the set function,
-	    ## so we don't emit anything.
-	    if (index (quals, "s"))
-		emit_set[idx] = "";
+        ## There is a custom inline definition for the set function,
+        ## so we don't emit anything.
+        if (index (quals, "s"))
+          emit_set[idx] = "";
 
-	    ## There is a custom extern definition for the set function,
-	    ## but we still emit the declaration.
-	    if (index (quals, "S"))
-		emit_set[idx] = "declaration";
-
-            ## emmit an asignment set function
-            if (index (quals, "a"))
-                emit_ov_set[idx] = "assignment";
+        ## There is a custom extern definition for the set function,
+        ## but we still emit the declaration.
+        if (index (quals, "S"))
+          emit_set[idx] = "declaration";
 
-	    if (type[idx] != "octave_value")
-	    {
-		## The 'o' and 'O' qualifiers are only useful when the
-		## the property type is something other than an
-		## octave_value.
-
-		## There is a custom inline definition for the
-		## octave_value version of the set function, so we
-		## don't emit anything.
-		if (index (quals, "o"))
-		    emit_ov_set[idx] = "";
+##        ## emmit an asignment set function
+##        if (index (quals, "a"))
+##          emit_ov_set[idx] = "assignment";
+##
+##        if (type[idx] != "octave_value")
+##        {
+##          ## The 'o' and 'O' qualifiers are only useful when the
+##          ## the property type is something other than an
+##          ## octave_value.
+##
+##          ## There is a custom inline definition for the
+##          ## octave_value version of the set function, so we
+##          ## don't emit anything.
+##          if (index (quals, "o"))
+##            emit_ov_set[idx] = "";
+##
+##          ## There is a custom extern definition for the
+##          ## octave_value version of the set function, but we
+##          ## still emit the declaration.
+##          if (index (quals, "O"))
+##            emit_ov_set[idx] = "declaration";
+##        }
+      }
 
-		## There is a custom extern definition for the
-		## octave_value version of the set function, but we
-		## still emit the declaration.
-		if (index (quals, "O"))
-		    emit_ov_set[idx] = "declaration";
-	    }
-        }
+      if (NF > field && $field == ",")
+      {
+        field++;
 
+        for (i = field; i <= NF; i++)
+          default[idx] = (default[idx] (i > field ? " " : "") $i);
+      }
     }
+
+  }
   else
-      print $0;
+    print $0;
 }
--- a/src/graphics.cc	Sat Jan 12 08:00:38 2008 +0000
+++ b/src/graphics.cc	Sat Jan 12 08:21:57 2008 +0000
@@ -50,6 +50,93 @@
   error ("set: invalid value for %s property", pname.c_str ());
 }
 
+static Matrix
+jet_colormap (void)
+{
+  Matrix cmap (64, 3, 0.0);
+
+  for (octave_idx_type i = 0; i < 64; i++)
+    {
+      // This is the jet colormap.  It would be nice to be able
+      // to feval the jet function but since there is a static
+      // property object that includes a colormap_property
+      // object, we need to initialize this before main is even
+      // called, so calling an interpreted function is not
+      // possible.
+
+      double x = i / 63.0;
+
+      if (x >= 3.0/8.0 && x < 5.0/8.0)
+        cmap(i,0) = 4.0 * x - 3.0/2.0;
+      else if (x >= 5.0/8.0 && x < 7.0/8.0)
+        cmap(i,0) = 1.0;
+      else if (x >= 7.0/8.0)
+        cmap(i,0) = -4.0 * x + 9.0/2.0;
+
+      if (x >= 1.0/8.0 && x < 3.0/8.0)
+        cmap(i,1) = 4.0 * x - 1.0/2.0;
+      else if (x >= 3.0/8.0 && x < 5.0/8.0)
+        cmap(i,1) = 1.0;
+      else if (x >= 5.0/8.0 && x < 7.0/8.0)
+        cmap(i,1) = -4.0 * x + 7.0/2.0;
+
+      if (x < 1.0/8.0)
+        cmap(i,2) = 4.0 * x + 1.0/2.0;
+      else if (x >= 1.0/8.0 && x < 3.0/8.0)
+        cmap(i,2) = 1.0;
+      else if (x >= 3.0/8.0 && x < 5.0/8.0)
+        cmap(i,2) = -4.0 * x + 5.0/2.0;
+    }
+
+  return cmap;
+}
+
+static Matrix
+default_colororder (void)
+{
+  Matrix retval (7, 3, 0.0);
+
+  retval(0,2) = 1.0;
+
+  retval(1,1) = 0.5;
+
+  retval(2,0) = 1.0;
+
+  retval(3,1) = 0.75;
+  retval(3,2) = 0.75;
+
+  retval(4,0) = 0.75;
+  retval(4,2) = 0.75;
+
+  retval(5,0) = 0.75;
+  retval(5,1) = 0.75;
+
+  retval(6,0) = 0.25;
+  retval(6,1) = 0.25;
+  retval(6,2) = 0.25;
+
+  return retval;
+}
+
+static Matrix
+default_lim (void)
+{
+  Matrix m (1, 2, 0);
+  m(1) = 1;
+  return m;
+}
+
+static Matrix
+default_data (void)
+{
+  Matrix retval (1, 2);
+
+  retval(0) = 0;
+  retval(1) = 1;
+
+  return retval;
+}
+
 // ---------------------------------------------------------------------
 
 radio_values::radio_values (const std::string& opt_string)
@@ -118,59 +205,14 @@
   if (retval)
     {
       for (int i = 0; i < 3; i++)
-	xrgb[i] = tmp_rgb[i];
+	xrgb(i) = tmp_rgb[i];
     }
 
   return retval;
 }
 
-color_property::color_property (const octave_value& val)
-  : radio_val (), current_val ()
-{
-  // FIXME -- need some error checking here.
-
-  if (val.is_string ())
-    {
-      std::string s = val.string_value ();
-
-      if (! s.empty ())
-	{
-	  color_values col (s);
-	  if (! error_state)
-	    {
-	      color_val = col;
-	      current_type = color_t;
-	    }
-	}
-      else
-	error ("invalid color specification");	  
-    }
-  else if (val.is_real_matrix ())
-    {
-      Matrix m = val.matrix_value ();
-
-      if (m.numel () == 3)
-	{
-	  color_values col (m (0), m (1), m(2));
-	  if (! error_state)
-	    {
-	      color_val = col;
-	      current_type = color_t;
-	    }
-	}
-      else
-	error ("invalid color specification");
-    }
-  else 
-    error ("invalid color specification");
-}
-
-// We also provide this assignment operator so that assignment from an
-// octave_value object can happen without wiping out list of possible
-// radio_values set in color_property constructor.
-
-color_property&
-color_property::operator = (const octave_value& val)
+void
+color_property::set (const octave_value& val)
 {
   if (val.is_string ())
     {
@@ -192,11 +234,13 @@
 		  current_type = color_t;
 		}
 	      else
-		error ("invalid color specification");	  
+		error ("invalid value for color property \"%s\" (value = %s)",
+               get_name ().c_str (), s.c_str ());
 	    }	
 	}
       else
-	error ("invalid color specification");	  
+	error ("invalid value for color property \"%s\"",
+           get_name ().c_str ());
     }
   else if (val.is_real_matrix ())
     {
@@ -212,14 +256,98 @@
 	    }
 	}
       else
-	error ("invalid color specification");
+	error ("invalid value for color property \"%s\"",
+           get_name ().c_str ());
     }
   else 
-    error ("invalid color specification");
-
-  return *this;
+    error ("invalid value for color property \"%s\"",
+           get_name ().c_str ());
 }
 
+bool
+array_property::validate (const octave_value& v)
+{
+  bool ok = false;
+
+  // FIXME: should we always support []?
+  if (v.is_empty () && v.is_double_type ())
+    return true;
+
+  // check value type
+  if (type_constraints.size () > 0)
+    {
+      for (std::list<std::string>::const_iterator it = type_constraints.begin ();
+           ! ok && it != type_constraints.end (); ++it)
+        if ((*it) == v.type_name ())
+          ok = true;
+    }
+  else
+    ok = v.is_double_type ();
+
+  if (ok)
+    {
+      dim_vector vdims = v.dims ();
+      int vlen = vdims.length ();
+
+      ok = false;
+
+      // check value size
+      if (size_constraints.size () > 0)
+        for (std::list<dim_vector>::const_iterator it = size_constraints.begin ();
+             ! ok && it != size_constraints.end (); ++it)
+          {
+            dim_vector itdims = (*it);
+
+            if (itdims.length () == vlen)
+              {
+                ok = true;
+
+                for (int i = 0; ok && i < vlen; i++)
+                  if (itdims(i) >= 0 && itdims(i) != vdims(i))
+                    ok = false;
+              }
+          }
+      else
+        return true;
+    }
+
+  return ok;
+}
+
+void
+handle_property::set (const octave_value& v)
+{
+  double dv = v.double_value ();
+
+  if (! error_state)
+    {
+      graphics_handle gh = gh_manager::lookup (dv);
+
+      if (xisnan (gh.value ()) || gh.ok ())
+        current_val = gh;
+      else
+        error ("set: invalid graphics handle (= %g) for property \"%s\"",
+            dv, get_name ().c_str ());
+    }
+  else
+    error ("set: invalid graphics handle for property \"%s\"",
+        get_name ().c_str ());
+}
+
+bool
+callback_property::validate (const octave_value& v) const
+{
+  // FIXME: implement this
+  return true;
+}
+
+void
+callback_property::execute (void)
+{
+  // FIXME: define correct signature and implement this
+}
+
+// ---------------------------------------------------------------------
 
 void
 property_list::set (const caseless_str& name, const octave_value& val)
@@ -686,6 +814,88 @@
     }
 }
 
+octave_value
+base_properties::get (const caseless_str& name) const
+{
+  octave_value retval;
+
+  if (name.compare ("tag"))
+    retval = get_tag ();
+  else if (name.compare ("type"))
+    retval = get_type ();
+  else if (name.compare ("__modified__"))
+    retval = is_modified ();
+  else if (name.compare ("parent"))
+    retval = get_parent ().as_octave_value ();
+  else if (name.compare ("children"))
+    retval = children;
+  else
+  {
+    std::map<caseless_str, property>::const_iterator it = all_props.find (name);
+
+    if (it != all_props.end ())
+      retval = it->second.get ();
+    else
+      error ("get: unknown property \"%s\"", name.c_str ());
+  }
+
+  return retval;
+}
+
+octave_value
+base_properties::get (void) const
+{
+  Octave_map m;
+
+  for (std::map<caseless_str, property>::const_iterator it = all_props.begin ();
+       it != all_props.end (); ++it)
+    m.assign (it->second.get_name (), it->second.get ());
+
+  m.assign ("tag", get_tag ());
+  m.assign ("type", get_type ());
+  m.assign ("__modified__", is_modified ());
+  m.assign ("parent", get_parent ().as_octave_value ());
+  m.assign ("children", children);
+
+  return m;
+}
+
+void
+base_properties::set (const caseless_str& name, const octave_value& val)
+{
+  if (name.compare ("tag"))
+    set_tag (val);
+  else if (name.compare ("__modified__"))
+    __modified__ = val;
+  else if (name.compare ("parent"))
+    set_parent (val);
+  else if (name.compare ("children"))
+    maybe_set_children (children, val);
+  else
+  {
+    std::map<caseless_str, property>::iterator it = all_props.find (name);
+
+    if (it != all_props.end ())
+      it->second.set (val);
+    else
+      error ("set: unknown property \"%s\"", name.c_str ());
+  }
+
+  if (! error_state && ! name.compare ("__modified__"))
+    mark_modified ();
+}
+
+property
+base_properties::get_property (const caseless_str& name) const
+{
+  std::map<caseless_str, property>::const_iterator it = all_props.find (name);
+
+  if (it == all_props.end ())
+    return property ();
+  else
+    return it->second;
+}
+
 void
 base_properties::remove_child (const graphics_handle& h)
 {
@@ -714,17 +924,6 @@
 }
 
 void
-base_properties::set_tag (const octave_value& val)
-{
-  std::string tmp = val.string_value ();
-
-  if (! error_state)
-    tag = tmp;
-  else
-    error ("set: expecting tag to be a character string");
-}
-
-void
 base_properties::set_parent (const octave_value& val)
 {
   double tmp = val.double_value ();
@@ -737,13 +936,13 @@
 
       if (new_parent.ok ())
 	{
-	  graphics_object parent_obj = gh_manager::get_object (parent);
+	  graphics_object parent_obj = gh_manager::get_object (get_parent ());
 
 	  parent_obj.remove_child (__myhandle__);
 
-	  parent = new_parent;
+	  parent = new_parent.as_octave_value ();
 
-	  ::adopt (parent, __myhandle__);
+	  ::adopt (parent.handle_value (), __myhandle__);
 	}
       else
 	error ("set: invalid graphics handle (= %g) for parent", tmp);
@@ -755,22 +954,22 @@
 void
 base_properties::mark_modified (void)
 {
-  __modified__ = true;
-  graphics_object parent_obj = gh_manager::get_object (parent);
+  __modified__ = "on";
+  graphics_object parent_obj = gh_manager::get_object (get_parent ());
   parent_obj.mark_modified ();
 }
 
 void
 base_properties::override_defaults (base_graphics_object& obj)
 {
-  graphics_object parent_obj = gh_manager::get_object (parent);
+  graphics_object parent_obj = gh_manager::get_object (get_parent ());
   parent_obj.override_defaults (obj);
 }
 
 void
 base_properties::update_axis_limits (const std::string& axis_type) const
 {
-  graphics_handle h = (type == "axes") ? __myhandle__ : parent;
+  graphics_handle h = (get_type () == "axes") ? __myhandle__ : get_parent ();
 
   graphics_object obj = gh_manager::get_object (h);
 
@@ -787,9 +986,17 @@
     gh_manager::free (children(i));
 }
 
+// ---------------------------------------------------------------------
+
+#include "graphics-props.cc"
+
+// ---------------------------------------------------------------------
+
 void
-root_figure::properties::set_currentfigure (const graphics_handle& val)
+root_figure::properties::set_currentfigure (const octave_value& v)
 {
+  graphics_handle val (v.double_value ());
+
   if (error_state)
     return;
 
@@ -797,86 +1004,22 @@
     {
       currentfigure = val;
 
-      gh_manager::push_figure (currentfigure);
+      gh_manager::push_figure (val);
     }
   else
     gripe_set_invalid ("currentfigure");
 }
 
-void
-root_figure::properties::set (const caseless_str& name,
-			      const octave_value& val)
-{
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("currentfigure"))
-    set_currentfigure (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("visible"))
-    set_visible (val);
-  else
-    warning ("set: invalid property `%s'", name.c_str ());
-}
-
-octave_value root_figure::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("currentfigure", currentfigure.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("visible", visible);
-
-  return m;
-}
-
-octave_value 
-root_figure::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = type;
-  else if (name.compare ("tag"))
-    retval = type;
-  else if (name.compare ("currentfigure"))
-    retval = currentfigure.as_octave_value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("visible"))
-    retval = visible;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
-}
-
 property_list
 root_figure::factory_properties = root_figure::init_factory_properties ();
 
-std::string root_figure::properties::go_name ("root figure");
-
 // ---------------------------------------------------------------------
 
-figure::properties::properties (const graphics_handle& mh,
-				const graphics_handle& p)
-  : base_properties (go_name, mh, p),
-    __plot_stream__ (Matrix ()),
-    __enhanced__ (false),
-    nextplot ("replace"),
-    closerequestfcn (make_fcn_handle ("closereq")),
-    currentaxes (octave_NaN),
-    colormap (),
-    visible ("on"),
-    paperorientation ("portrait"),
-    color ( color_values (1, 1, 1))
-{ }
+void
+figure::properties::set_currentaxes (const octave_value& v)
+{
+  graphics_handle val (v.double_value ());
 
-void
-figure::properties::set_currentaxes (const graphics_handle& val)
-{
   if (error_state)
     return;
 
@@ -901,117 +1044,13 @@
 }
 
 void
-figure::properties::set (const caseless_str& name, const octave_value& val)
-{
-  bool modified = true;
-
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("__modified__"))
-    {
-      __modified__ = val.bool_value ();
-      modified = false;
-    }
-  else if (name.compare ("__plot_stream__"))
-    set___plot_stream__ (val);
-  else if (name.compare ("__enhanced__"))
-    set___enhanced__ (val);
-  else if (name.compare ("nextplot"))
-    set_nextplot (val);
-  else if (name.compare ("closerequestfcn"))
-    set_closerequestfcn (val);
-  else if (name.compare ("currentaxes"))
-    set_currentaxes (val);
-  else if (name.compare ("colormap"))
-    set_colormap (val);
-  else if (name.compare ("visible"))
-    set_visible (val);
-  else if (name.compare ("paperorientation"))
-    set_paperorientation (val);
-  else if (name.compare ("color"))
-    set_color (val);
-  else
-    {
-      modified = false;
-      warning ("set: invalid property `%s'", name.c_str ());
-    }
-
-  if (modified)
-    mark_modified ();
-}
-
-octave_value
-figure::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("parent", parent.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("__modified__", __modified__);
-  m.assign ("__plot_stream__", __plot_stream__);
-  m.assign ("__enhanced__", __enhanced__);
-  m.assign ("nextplot", nextplot);
-  m.assign ("closerequestfcn", closerequestfcn);
-  m.assign ("currentaxes", currentaxes.as_octave_value ());
-  m.assign ("colormap", colormap);
-  m.assign ("visible", visible);
-  m.assign ("paperorientation", paperorientation);
-  m.assign ("color", color);
-
-  return m;
-}
-
-octave_value
-figure::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = tag;
-  else if (name.compare ("type"))
-    retval = type;
-  else if (name.compare ("parent"))
-    retval = parent.as_octave_value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("__modified__"))
-    retval = __modified__;
-  else if (name.compare ("__plot_stream__"))
-    retval = __plot_stream__;
-  else if (name.compare ("__enhanced__"))
-    retval = __enhanced__;
-  else if (name.compare ("nextplot"))
-    retval = nextplot;
-  else if (name.compare ("closerequestfcn"))
-    retval = closerequestfcn;
-  else if (name.compare ("currentaxes"))
-    retval = currentaxes.as_octave_value ();
-  else if (name.compare ("colormap"))
-    retval = colormap;
-  else if (name.compare ("visible"))
-    retval = visible;
-  else if (name.compare ("paperorientation"))
-    retval = paperorientation;
-  else if (name.compare ("color"))
-    retval = color;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
-}
-
-void
 figure::properties::close (void)
 {
-  if (! __plot_stream__.is_empty ())
+  if (! get___plot_stream__ ().is_empty ())
     {
       octave_value_list args;
       args(1) = "\nquit;\n";
-      args(0) = __plot_stream__;
+      args(0) = get___plot_stream__ ();
       feval ("fputs", args);
       args.resize (1);
       feval ("fflush", args);
@@ -1025,20 +1064,6 @@
   xset (0, "currentfigure", cf.value ());
 }
 
-property_list::pval_map_type
-figure::properties::factory_defaults (void)
-{
-  property_list::pval_map_type m;
-
-  m["nextplot"] = "replace";
-  // m["closerequestfcn"] = make_fcn_handle ("closereq");
-  m["colormap"] = colormap_property ();
-  m["visible"] = "on";
-  m["paperorientation"] = "portrait";
-  m["color"] = color_property (color_values (1, 1, 1));
-  return m;
-}
-
 octave_value
 figure::get_default (const caseless_str& name) const
 {
@@ -1055,335 +1080,70 @@
   return retval;
 }
 
-std::string figure::properties::go_name ("figure");
-
 // ---------------------------------------------------------------------
 
-static Matrix
-default_colororder (void)
+void
+axes::properties::set_title (const octave_value& v)
 {
-  Matrix retval (7, 3, 0.0);
-
-  retval(0,2) = 1.0;
-
-  retval(1,1) = 0.5;
-
-  retval(2,0) = 1.0;
-
-  retval(3,1) = 0.75;
-  retval(3,2) = 0.75;
-
-  retval(4,0) = 0.75;
-  retval(4,2) = 0.75;
-
-  retval(5,0) = 0.75;
-  retval(5,1) = 0.75;
-
-  retval(6,0) = 0.25;
-  retval(6,1) = 0.25;
-  retval(6,2) = 0.25;
-
-  return retval;
-}
+  graphics_handle val = ::reparent (v, "set", "title", __myhandle__, false);
 
-axes::properties::properties (const graphics_handle& mh,
-			      const graphics_handle& p)
-  : base_properties (go_name, mh, p),
-    position (Matrix ()),
-    title (octave_NaN),
-    box ("on"),
-    key ("off"),
-    keybox ("off"),
-    keypos (1),
-    colororder (default_colororder ()),
-    dataaspectratio (Matrix (1, 3, 1.0)),
-    dataaspectratiomode ("auto"),
-    layer (radio_values ("{bottom}|top")),
-    xlim (),
-    ylim (),
-    zlim (),
-    clim (),
-    xlimmode (radio_values ("{auto}|manual")),
-    ylimmode (radio_values ("{auto}|manual")),
-    zlimmode (radio_values ("{auto}|manual")),
-    climmode (radio_values ("{auto}|manual")),
-    xlabel (octave_NaN),
-    ylabel (octave_NaN),
-    zlabel (octave_NaN),
-    xgrid ("off"),
-    ygrid ("off"),
-    zgrid ("off"),
-    xminorgrid ("off"),
-    yminorgrid ("off"),
-    zminorgrid ("off"),
-    xtick (Matrix ()),
-    ytick (Matrix ()),
-    ztick (Matrix ()),
-    xtickmode ("auto"),
-    ytickmode ("auto"),
-    ztickmode ("auto"),
-    xticklabel (""),
-    yticklabel (""),
-    zticklabel (""),
-    xticklabelmode ("auto"),
-    yticklabelmode ("auto"),
-    zticklabelmode ("auto"),
-    color (color_values (0, 0, 0), radio_values ("flat|none|interp")),
-    xcolor (color_values (0, 0, 0)),
-    ycolor (color_values (0, 0, 0)),
-    zcolor (color_values (0, 0, 0)),
-    xscale (radio_values ("{linear}|log")),
-    yscale (radio_values ("{linear}|log")),
-    zscale (radio_values ("{linear}|log")),
-    xdir ("normal"),
-    ydir ("normal"),
-    zdir ("normal"),
-    xaxislocation ("bottom"),
-    yaxislocation ("left"),
-    view (),
-    visible ("on"),
-    nextplot ("replace"),
-    outerposition (),
-    activepositionproperty (radio_values ("{outerposition}|position")),
-    __colorbar__ (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside"))
-{
-  Matrix tlim (1, 2, 0.0);
-  tlim(1) = 1;
-  xlim = tlim;
-  ylim = tlim;
-  zlim = tlim;
-  Matrix cl (1, 2, 0);
-  cl(1) = 1;
-  clim = cl;
-
-  Matrix tview (1, 2, 0.0);
-  tview(1) = 90;
-  view = tview;
-
-  Matrix touterposition (1, 4, 0.0);
-  touterposition(2) = 1;
-  touterposition(3) = 1;
-  outerposition = touterposition;
-}
-
-void
-axes::properties::set_title (const graphics_handle& val)
-{
   if (! error_state)
     {
-      gh_manager::free (title);
+      gh_manager::free (title.handle_value ());
       title = val;
     }
 }
 
 void
-axes::properties::set_title (const octave_value& val)
+axes::properties::set_xlabel (const octave_value& v)
 {
-  set_title (::reparent (val, "set", "title", __myhandle__, false));
-}
+  graphics_handle val = ::reparent (v, "set", "xlabel", __myhandle__, false);
 
-void
-axes::properties::set_xlabel (const graphics_handle& val)
-{
   if (! error_state)
     {
-      gh_manager::free (xlabel);
+      gh_manager::free (xlabel.handle_value ());
       xlabel = val;
     }
 }
 
 void
-axes::properties::set_xlabel (const octave_value& val)
+axes::properties::set_ylabel (const octave_value& v)
 {
-  set_xlabel (::reparent (val, "set", "xlabel", __myhandle__, false));
-}
+  graphics_handle val = ::reparent (v, "set", "ylabel", __myhandle__, false);
 
-void
-axes::properties::set_ylabel (const graphics_handle& val)
-{
   if (! error_state)
     {
-      gh_manager::free (ylabel);
+      gh_manager::free (ylabel.handle_value ());
       ylabel = val;
     }
 }
 
 void
-axes::properties::set_ylabel (const octave_value& val)
+axes::properties::set_zlabel (const octave_value& v)
 {
-  set_ylabel (::reparent (val, "set", "ylabel", __myhandle__, false));
-}
+  graphics_handle val = ::reparent (v, "set", "zlabel", __myhandle__, false);
 
-void
-axes::properties::set_zlabel (const graphics_handle& val)
-{
   if (! error_state)
     {
-      gh_manager::free (zlabel);
+      gh_manager::free (zlabel.handle_value ());
       zlabel = val;
     }
 }
 
 void
-axes::properties::set_zlabel (const octave_value& val)
-{
-  set_zlabel (::reparent (val, "set", "zlabel", __myhandle__, false));
-}
-
-void
-axes::properties::set (const caseless_str& name, const octave_value& val)
-{
-  bool modified = true;
-
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("parent"))
-    set_parent (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("__modified__"))
-    {
-      __modified__ = val.bool_value ();
-      modified = false;
-    }
-  else if (name.compare ("position"))
-    set_position (val);
-  else if (name.compare ("title"))
-    set_title (val);
-  else if (name.compare ("box"))
-    set_box (val);
-  else if (name.compare ("key"))
-    set_key (val);
-  else if (name.compare ("keybox"))
-    set_keybox (val);
-  else if (name.compare ("keypos"))
-    set_keypos (val);
-  else if (name.compare ("colororder"))
-    set_colororder (val);
-  else if (name.compare ("dataaspectratio"))
-    set_dataaspectratio (val);
-  else if (name.compare ("dataaspectratiomode"))
-    set_dataaspectratiomode (val);
-  else if (name.compare ("layer"))
-    set_layer (val);
-  else if (name.compare ("xlim"))
-    set_xlim (val);
-  else if (name.compare ("ylim"))
-    set_ylim (val);
-  else if (name.compare ("zlim"))
-    set_zlim (val);
-  else if (name.compare ("clim"))
-    set_clim (val);
-  else if (name.compare ("xlimmode"))
-    set_xlimmode (val);
-  else if (name.compare ("ylimmode"))
-    set_ylimmode (val);
-  else if (name.compare ("zlimmode"))
-    set_zlimmode (val);
-  else if (name.compare ("climmode"))
-    set_climmode (val);
-  else if (name.compare ("xlabel"))
-    set_xlabel (val);
-  else if (name.compare ("ylabel"))
-    set_ylabel (val);
-  else if (name.compare ("zlabel"))
-    set_zlabel (val);
-  else if (name.compare ("xgrid"))
-    set_xgrid (val);
-  else if (name.compare ("ygrid"))
-    set_ygrid (val);
-  else if (name.compare ("zgrid"))
-    set_zgrid (val);
-  else if (name.compare ("xminorgrid"))
-    set_xminorgrid (val);
-  else if (name.compare ("yminorgrid"))
-    set_yminorgrid (val);
-  else if (name.compare ("zminorgrid"))
-    set_zminorgrid (val);
-  else if (name.compare ("xtick"))
-    set_xtick (val);
-  else if (name.compare ("ytick"))
-    set_ytick (val);
-  else if (name.compare ("ztick"))
-    set_ztick (val);
-  else if (name.compare ("xtickmode"))
-    set_xtickmode (val);
-  else if (name.compare ("ytickmode"))
-    set_ytickmode (val);
-  else if (name.compare ("ztickmode"))
-    set_ztickmode (val);
-  else if (name.compare ("xticklabel"))
-    set_xticklabel (val);
-  else if (name.compare ("yticklabel"))
-    set_yticklabel (val);
-  else if (name.compare ("zticklabel"))
-    set_zticklabel (val);
-  else if (name.compare ("xticklabelmode"))
-    set_xticklabelmode (val);
-  else if (name.compare ("yticklabelmode"))
-    set_yticklabelmode (val);
-  else if (name.compare ("zticklabelmode"))
-    set_zticklabelmode (val);
-  else if (name.compare ("color"))
-    set_color (val);
-  else if (name.compare ("xcolor"))
-    set_xcolor (val);
-  else if (name.compare ("ycolor"))
-    set_ycolor (val);
-  else if (name.compare ("zcolor"))
-    set_zcolor (val);
-  else if (name.compare ("xscale"))
-    set_xscale (val);
-  else if (name.compare ("yscale"))
-    set_yscale (val);
-  else if (name.compare ("zscale"))
-    set_zscale (val);
-  else if (name.compare ("xdir"))
-    set_xdir (val);
-  else if (name.compare ("ydir"))
-    set_ydir (val);
-  else if (name.compare ("zdir"))
-    set_zdir (val);
-  else if (name.compare ("xaxislocation"))
-    set_xaxislocation (val);
-  else if (name.compare ("yaxislocation"))
-    set_yaxislocation (val);
-  else if (name.compare ("view"))
-    set_view (val);
-  else if (name.compare ("visible"))
-    set_visible (val);
-  else if (name.compare ("nextplot"))
-    set_nextplot (val);
-  else if (name.compare ("outerposition"))
-    set_outerposition (val);
-  else if (name.compare ("activepositionproperty"))
-    set_activepositionproperty (val);
-  else if (name.compare ("__colorbar__"))
-    set___colorbar__ (val);
-  else
-    {
-      modified = false;
-      warning ("set: invalid property `%s'", name.c_str ());
-    }
-
-  if (modified)
-    mark_modified ();
-}
-
-void
 axes::properties::set_defaults (base_graphics_object& obj,
 				const std::string& mode)
 {
   position = Matrix ();
-  title = octave_NaN;
+  title = graphics_handle ();
   box = "on";
   key = "off";
   keybox = "off";
-  keypos = 1;
+  keypos = 1.0;
   colororder = default_colororder ();
   dataaspectratio = Matrix (1, 3, 1.0);
   dataaspectratiomode = "auto";
-  layer = radio_property (radio_values ("{bottom}|top"));
+  layer = "bottom";
 
   Matrix tlim (1, 2, 0.0);
   tlim(1) = 1;
@@ -1395,13 +1155,13 @@
   cl(1) = 1;
   clim = cl;
   
-  xlimmode = radio_property (radio_values ("{auto}|manual"));
-  ylimmode = radio_property (radio_values ("{auto}|manual"));
-  zlimmode = radio_property (radio_values ("{auto}|manual"));
-  climmode = radio_property (radio_values ("{auto}|manual"));
-  xlabel = octave_NaN;
-  ylabel = octave_NaN;
-  zlabel = octave_NaN;
+  xlimmode = "auto";
+  ylimmode = "auto";
+  zlimmode = "auto";
+  climmode = "auto";
+  xlabel = graphics_handle ();
+  ylabel = graphics_handle ();
+  zlabel = graphics_handle ();
   xgrid = "off";
   ygrid = "off";
   zgrid = "off";
@@ -1420,18 +1180,18 @@
   xticklabelmode = "auto";
   yticklabelmode = "auto";
   zticklabelmode = "auto";
-  color = color_property (color_values (0, 0, 0), radio_values("flat|none|interp"));
-  xcolor = color_property ("black");
-  ycolor = color_property ("black");
-  zcolor = color_property ("black");
-  xscale = radio_property (radio_values ("{linear}|log"));
-  yscale = radio_property (radio_values ("{linear}|log"));
-  zscale = radio_property (radio_values ("{linear}|log"));
+  color = octave_value (color_values (0, 0, 0));
+  xcolor = octave_value (color_values ("black"));
+  ycolor = octave_value (color_values ("black"));
+  zcolor = octave_value (color_values ("black"));
+  xscale = "linear";
+  yscale = "linear";
+  zscale = "linear";
   xdir = "normal";
   ydir = "normal";
   zdir = "normal";
-  xaxislocation = "left";
-  yaxislocation = "bottom";
+  yaxislocation = "left";
+  xaxislocation = "bottom";
 
   Matrix tview (1, 2, 0.0);
   tview(1) = 90;
@@ -1451,8 +1211,8 @@
       outerposition = touterposition;
     }
 
-  activepositionproperty = radio_property (radio_values ("{outerposition}|position"));
-  __colorbar__  = radio_property (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside"));
+  activepositionproperty = "outerposition";
+  __colorbar__  = "none";
 
   delete_children ();
 
@@ -1464,255 +1224,49 @@
 graphics_handle
 axes::properties::get_title (void) const
 {
-  if (! title.ok ())
+  if (! title.handle_value ().ok ())
     title = gh_manager::make_graphics_handle ("text", __myhandle__);
 
-  return title;
+  return title.handle_value ();
 }
 
 graphics_handle
 axes::properties::get_xlabel (void) const
 {
-  if (! xlabel.ok ())
+  if (! xlabel.handle_value ().ok ())
     xlabel = gh_manager::make_graphics_handle ("text", __myhandle__);
 
-  return xlabel;
+  return xlabel.handle_value ();
 }
 
 graphics_handle
 axes::properties::get_ylabel (void) const
 {
-  if (! ylabel.ok ())
+  if (! ylabel.handle_value ().ok ())
     ylabel = gh_manager::make_graphics_handle ("text", __myhandle__);
 
-  return ylabel;
+  return ylabel.handle_value ();
 }
 
 graphics_handle
 axes::properties::get_zlabel (void) const
 {
-  if (! zlabel.ok ())
+  if (! zlabel.handle_value ().ok ())
     zlabel = gh_manager::make_graphics_handle ("text", __myhandle__);
 
-  return zlabel;
-}
-
-octave_value
-axes::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("parent", parent.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("__modified__", __modified__);
-  m.assign ("position", position);
-  m.assign ("title", get_title().as_octave_value ());
-  m.assign ("box", box);
-  m.assign ("key", key);
-  m.assign ("keybox", keybox);
-  m.assign ("keypos", keypos);
-  m.assign ("colororder", colororder);
-  m.assign ("dataaspectratio", dataaspectratio);
-  m.assign ("dataaspectratiomode", dataaspectratiomode);
-  m.assign ("layer", layer);
-  m.assign ("xlim", xlim);
-  m.assign ("ylim", ylim);
-  m.assign ("zlim", zlim);
-  m.assign ("clim", clim);
-  m.assign ("xlimmode", xlimmode);
-  m.assign ("ylimmode", ylimmode);
-  m.assign ("zlimmode", zlimmode);
-  m.assign ("climmode", climmode);
-  m.assign ("xlabel", get_xlabel().as_octave_value ());
-  m.assign ("ylabel", get_ylabel().as_octave_value ());
-  m.assign ("zlabel", get_zlabel().as_octave_value ());
-  m.assign ("xgrid", xgrid);
-  m.assign ("ygrid", ygrid);
-  m.assign ("zgrid", zgrid);
-  m.assign ("xminorgrid", xminorgrid);
-  m.assign ("yminorgrid", yminorgrid);
-  m.assign ("zminorgrid", zminorgrid);
-  m.assign ("xtick", xtick);
-  m.assign ("ytick", ytick);
-  m.assign ("ztick", ztick);
-  m.assign ("xtickmode", xtickmode);
-  m.assign ("ytickmode", ytickmode);
-  m.assign ("ztickmode", ztickmode);
-  m.assign ("xticklabel", xticklabel);
-  m.assign ("yticklabel", yticklabel);
-  m.assign ("zticklabel", zticklabel);
-  m.assign ("xticklabelmode", xticklabelmode);
-  m.assign ("yticklabelmode", yticklabelmode);
-  m.assign ("zticklabelmode", zticklabelmode);
-  m.assign ("color", color);
-  m.assign ("xcolor", xcolor);
-  m.assign ("ycolor", ycolor);
-  m.assign ("zcolor", zcolor);
-  m.assign ("xscale", xscale);
-  m.assign ("yscale", yscale);
-  m.assign ("zscale", zscale);
-  m.assign ("xdir", xdir);
-  m.assign ("ydir", ydir);
-  m.assign ("zdir", zdir);
-  m.assign ("xaxislocation", xaxislocation);
-  m.assign ("yaxislocation", yaxislocation);
-  m.assign ("view", view);
-  m.assign ("visible", visible);
-  m.assign ("nextplot", nextplot);
-  m.assign ("outerposition", outerposition);
-  m.assign ("activepositionproperty", activepositionproperty);
-  m.assign ("__colorbar__", __colorbar__);
-
-  return m;
-}
-
-octave_value
-axes::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = tag;
-  else if (name.compare ("type"))
-    retval = type;
-  else if (name.compare ("parent"))
-    retval = parent.value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("__modified__"))
-    retval = __modified__;
-  else if (name.compare ("position"))
-    retval = position;
-  else if (name.compare ("title"))
-    retval = get_title().as_octave_value ();
-  else if (name.compare ("box"))
-    retval = box;
-  else if (name.compare ("key"))
-    retval = key;
-  else if (name.compare ("keybox"))
-    retval = keybox;
-  else if (name.compare ("keypos"))
-    retval = keypos;
-  else if (name.compare ("colororder"))
-    retval = colororder;
-  else if (name.compare ("dataaspectratio"))
-    retval = dataaspectratio;
-  else if (name.compare ("dataaspectratiomode"))
-    retval = dataaspectratiomode;
-  else if (name.compare ("layer"))
-    retval = layer;
-  else if (name.compare ("xlim"))
-    retval = xlim;
-  else if (name.compare ("ylim"))
-    retval = ylim;
-  else if (name.compare ("zlim"))
-    retval = zlim;
-  else if (name.compare ("clim"))
-    retval = clim;
-  else if (name.compare ("xlimmode"))
-    retval = xlimmode;
-  else if (name.compare ("ylimmode"))
-    retval = ylimmode;
-  else if (name.compare ("zlimmode"))
-    retval = zlimmode;
-  else if (name.compare ("climmode"))
-    retval = climmode;
-  else if (name.compare ("xlabel"))
-    retval = get_xlabel().as_octave_value ();
-  else if (name.compare ("ylabel"))
-    retval = get_ylabel().as_octave_value ();
-  else if (name.compare ("zlabel"))
-    retval = get_zlabel().as_octave_value ();
-  else if (name.compare ("xgrid"))
-    retval = xgrid;
-  else if (name.compare ("ygrid"))
-    retval = ygrid;
-  else if (name.compare ("zgrid"))
-    retval = zgrid;
-  else if (name.compare ("xminorgrid"))
-    retval = xminorgrid;
-  else if (name.compare ("yminorgrid"))
-    retval = yminorgrid;
-  else if (name.compare ("zminorgrid"))
-    retval = zminorgrid;
-  else if (name.compare ("xtick"))
-    retval = xtick;
-  else if (name.compare ("ytick"))
-    retval = ytick;
-  else if (name.compare ("ztick"))
-    retval = ztick;
-  else if (name.compare ("xtickmode"))
-    retval = xtickmode;
-  else if (name.compare ("ytickmode"))
-    retval = ytickmode;
-  else if (name.compare ("ztickmode"))
-    retval = ztickmode;
-  else if (name.compare ("xticklabel"))
-    retval = xticklabel;
-  else if (name.compare ("yticklabel"))
-    retval = yticklabel;
-  else if (name.compare ("zticklabel"))
-    retval = zticklabel;
-  else if (name.compare ("xticklabelmode"))
-    retval = xticklabelmode;
-  else if (name.compare ("yticklabelmode"))
-    retval = yticklabelmode;
-  else if (name.compare ("zticklabelmode"))
-    retval = zticklabelmode;
-  else if (name.compare ("color"))
-    retval = color;
-  else if (name.compare ("xcolor"))
-    retval = xcolor;
-  else if (name.compare ("ycolor"))
-    retval = ycolor;
-  else if (name.compare ("zcolor"))
-    retval = zcolor;
-  else if (name.compare ("xscale"))
-    retval = xscale;
-  else if (name.compare ("yscale"))
-    retval = yscale;
-  else if (name.compare ("zscale"))
-    retval = zscale;
-  else if (name.compare ("xdir"))
-    retval = xdir;
-  else if (name.compare ("ydir"))
-    retval = ydir;
-  else if (name.compare ("zdir"))
-    retval = zdir;
-  else if (name.compare ("xaxislocation"))
-    retval = xaxislocation;
-  else if (name.compare ("yaxislocation"))
-    retval = yaxislocation;
-  else if (name.compare ("view"))
-    retval = view;
-  else if (name.compare ("visible"))
-    retval = visible;
-  else if (name.compare ("nextplot"))
-    retval = nextplot;
-  else if (name.compare ("outerposition"))
-    retval = outerposition;
-  else if (name.compare ("activepositionproperty"))
-    retval = activepositionproperty;
-  else if (name.compare ("__colorbar__"))
-    retval = __colorbar__;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
+  return zlabel.handle_value ();
 }
 
 void
 axes::properties::remove_child (const graphics_handle& h)
 {
-  if (title.ok () && h == title)
+  if (title.handle_value ().ok () && h == title.handle_value ())
     title = gh_manager::make_graphics_handle ("text", __myhandle__);
-  else if (xlabel.ok () && h == xlabel)
+  else if (xlabel.handle_value ().ok () && h == xlabel.handle_value ())
     xlabel = gh_manager::make_graphics_handle ("text", __myhandle__);
-  else if (ylabel.ok () && h == ylabel)
+  else if (ylabel.handle_value ().ok () && h == ylabel.handle_value ())
     ylabel = gh_manager::make_graphics_handle ("text", __myhandle__);
-  else if (zlabel.ok () && h == zlabel)
+  else if (zlabel.handle_value ().ok () && h == zlabel.handle_value ())
     zlabel = gh_manager::make_graphics_handle ("text", __myhandle__);
   else
     base_properties::remove_child (h);
@@ -1723,95 +1277,10 @@
 {
   base_properties::delete_children ();
 
-  gh_manager::free (title);
-  gh_manager::free (xlabel);
-  gh_manager::free (ylabel);
-  gh_manager::free (zlabel);
-}
-
-property_list::pval_map_type
-axes::properties::factory_defaults (void)
-{
-  property_list::pval_map_type m;
-
-  m["position"] = Matrix ();
-  m["title"] = octave_NaN;
-  m["box"] = "on";
-  m["key"] = "off";
-  m["keybox"] = "off";
-  m["keypos"] = 1;
-  m["colororder"] = default_colororder ();
-  m["dataaspectratio"] = Matrix (1, 3, 1.0);
-  m["dataaspectratiomode"] = "auto";
-  m["layer"] = radio_property (radio_values ("{bottom}|top"));
-
-  Matrix tlim (1, 2, 0.0);
-  tlim(1) = 1;
-
-  m["xlim"] = tlim;
-  m["ylim"] = tlim;
-  m["zlim"] = tlim;
-  
-  Matrix cl(1, 2, 0);
-  cl(1) = 1;
-  
-  m["clim"] = cl;
-
-  m["xlimmode"] = radio_property (radio_values ("{auto}|manual"));
-  m["ylimmode"] = radio_property (radio_values ("{auto}|manual"));
-  m["zlimmode"] = radio_property (radio_values ("{auto}|manual"));
-  m["climmode"] = radio_property (radio_values ("{auto}|manual"));
-  m["xlabel"] = octave_NaN;
-  m["ylabel"] = octave_NaN;
-  m["zlabel"] = octave_NaN;
-  m["xgrid"] = "off";
-  m["ygrid"] = "off";
-  m["zgrid"] = "off";
-  m["xminorgrid"] = "off";
-  m["yminorgrid"] = "off";
-  m["zminorgrid"] = "off";
-  m["xtick"] = Matrix ();
-  m["ytick"] = Matrix ();
-  m["ztick"] = Matrix ();
-  m["xtickmode"] = "auto";
-  m["ytickmode"] = "auto";
-  m["ztickmode"] = "auto";
-  m["xticklabel"] = "";
-  m["yticklabel"] = "";
-  m["zticklabel"] = "";
-  m["xticklabelmode"] = "auto";
-  m["yticklabelmode"] = "auto";
-  m["zticklabelmode"] = "auto";
-  m["color"] = color_property (color_values (0, 0, 0), radio_values("flat|none|interp"));
-  m["xcolor"] = color_property ("black");
-  m["ycolor"] = color_property ("black");
-  m["zcolor"] = color_property ("black");
-  m["xscale"] = radio_property (radio_values ("{linear}|log"));
-  m["yscale"] = radio_property (radio_values ("{linear}|log"));
-  m["zscale"] = radio_property (radio_values ("{linear}|log"));
-  m["xdir"] = "normal";
-  m["ydir"] = "normal";
-  m["zdir"] = "normal";
-  m["xaxislocation"] = "bottom";
-  m["yaxislocation"] = "left";
-
-  Matrix tview (1, 2, 0.0);
-  tview(1) = 90;
-
-  m["view"] = tview;
-
-  m["visible"] = "on";
-  m["nextplot"] = "replace";
-
-  Matrix touterposition (1, 4, 0.0);
-  touterposition(2) = 1;
-  touterposition(3) = 1;
-
-  m["outerposition"] = touterposition;
-  m["activepositionproperty"] =  radio_property (radio_values ("{outerposition}|position"));
-  m["__colorbar__"] = radio_property (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside"));
-
-  return m;
+  gh_manager::free (title.handle_value ());
+  gh_manager::free (xlabel.handle_value ());
+  gh_manager::free (ylabel.handle_value ());
+  gh_manager::free (zlabel.handle_value ());
 }
 
 octave_value
@@ -1925,8 +1394,6 @@
   double max_val = -octave_Inf;
   double min_pos = octave_Inf;
 
-  radio_property tmp;
-
   char update_type = 0;
 
   Matrix limits;
@@ -1935,9 +1402,7 @@
       || axis_type == "xldata" || axis_type == "xudata"
       || axis_type == "xlimmode")
     {
-      tmp = xproperties.get_xlimmode ();
-
-      if (tmp.current_value () == "auto")
+      if (xproperties.xlimmode_is ("auto"))
 	{
 	  for (octave_idx_type i = 0; i < n; i++)
 	    {
@@ -1946,14 +1411,14 @@
 	      if (obj.isa ("line") || obj.isa ("image")
 		  || obj.isa ("patch") || obj.isa ("surface"))
 		{
-		  data_property xdata = obj.get_xdata ();
+		  data_property xdata = obj.get_xdata_property ();
 
 		  check_limit_vals (min_val, max_val, min_pos, xdata);
 
 		  if (obj.isa ("line"))
 		    {
-		      data_property xldata = obj.get_xldata ();
-		      data_property xudata = obj.get_xudata ();
+		      data_property xldata = obj.get_xldata_property ();
+		      data_property xudata = obj.get_xudata_property ();
 
 		      check_limit_vals (min_val, max_val, min_pos, xldata);
 		      check_limit_vals (min_val, max_val, min_pos, xudata);
@@ -1961,10 +1426,8 @@
 		}
 	    }
 
-	  tmp = xproperties.get_xscale ();
-
 	  limits = get_axis_limits (min_val, max_val, min_pos,
-				    tmp.current_value () == "log");
+				    xproperties.xscale_is ("log"));
 
 	  update_type = 'x';
 	}
@@ -1973,9 +1436,7 @@
 	   || axis_type == "ldata" || axis_type == "udata"
 	   || axis_type == "ylimmode")
     {
-      tmp = xproperties.get_ylimmode ();
-
-      if (tmp.current_value () == "auto")
+      if (xproperties.ylimmode_is ("auto"))
 	{
 	    for (octave_idx_type i = 0; i < n; i++)
 	    {
@@ -1984,14 +1445,14 @@
 	      if (obj.isa ("line") || obj.isa ("image")
 		|| obj.isa ("patch") || obj.isa ("surface"))
 		{
-		  data_property ydata = obj.get_ydata ();
+		  data_property ydata = obj.get_ydata_property ();
 
 		  check_limit_vals (min_val, max_val, min_pos, ydata);
 
 		  if (obj.isa ("line"))
 		    {
-		      data_property ldata = obj.get_ldata ();
-		      data_property udata = obj.get_udata ();
+		      data_property ldata = obj.get_ldata_property ();
+		      data_property udata = obj.get_udata_property ();
 
 		      check_limit_vals (min_val, max_val, min_pos, ldata);
 		      check_limit_vals (min_val, max_val, min_pos, udata);
@@ -1999,10 +1460,8 @@
 		}
 	    }
 
-	  tmp = xproperties.get_yscale ();
-
 	  limits = get_axis_limits (min_val, max_val, min_pos,
-				    tmp.current_value () == "log");
+				    xproperties.yscale_is ("log"));
 
 	  update_type = 'y';
 	}
@@ -2010,9 +1469,7 @@
   else if (axis_type == "zdata" || axis_type == "zscale"
 	   || axis_type == "zlimmode")
     {
-      tmp = xproperties.get_zlimmode ();
-
-      if (tmp.current_value () == "auto")
+      if (xproperties.zlimmode_is ("auto"))
 	{
 	  for (octave_idx_type i = 0; i < n; i++)
 	    {
@@ -2020,25 +1477,21 @@
 
 	      if (obj.isa ("line") || obj.isa ("patch") || obj.isa ("surface"))
 		{
-		  data_property zdata = obj.get_zdata ();
+		  data_property zdata = obj.get_zdata_property ();
 
 		  check_limit_vals (min_val, max_val, min_pos, zdata);
 		}
 	    }
 
-	  tmp = xproperties.get_zscale ();
-
 	  limits = get_axis_limits (min_val, max_val, min_pos,
-				    tmp.current_value () == "log");
+				    xproperties.zscale_is ("log"));
 
 	  update_type = 'z';
 	}
     }
   else if (axis_type == "cdata" || axis_type == "climmode")
     {
-      tmp = xproperties.get_climmode ();
-
-      if (tmp.current_value () == "auto")
+      if (xproperties.climmode_is ("auto"))
 	{
 	  for (octave_idx_type i = 0; i < n; i++)
 	    {
@@ -2046,7 +1499,7 @@
 
 	      if (obj.isa ("image") || obj.isa ("patch") || obj.isa ("surface"))
 		{
-		  data_property cdata = obj.get_cdata ();
+		  data_property cdata = obj.get_cdata_property ();
 
 		  check_limit_vals (min_val, max_val, min_pos, cdata);
 		}
@@ -2097,850 +1550,25 @@
   unwind_protect::run ();
 }
 
-std::string axes::properties::go_name ("axes");
+// ---------------------------------------------------------------------
+
+// Note: "line" code is entirely auto-generated
 
 // ---------------------------------------------------------------------
 
-static Matrix
-default_data (void)
-{
-  Matrix retval (1, 2);
-
-  retval(0) = 0;
-  retval(1) = 1;
-
-  return retval;
-}
-
-line::properties::properties (const graphics_handle& mh,
-			      const graphics_handle& p)
-  : base_properties (go_name, mh, p),
-    xdata (default_data ()),
-    ydata (default_data ()),
-    zdata (Matrix ()),
-    ldata (Matrix ()),
-    udata (Matrix ()),
-    xldata (Matrix ()),
-    xudata (Matrix ()),
-    color (),
-    linestyle ("-"),
-    linewidth (0.5),
-    marker ("none"),
-    markeredgecolor ("auto"),
-    markerfacecolor ("none"),
-    markersize (1),
-    keylabel (""),
-    interpreter (radio_values ("{tex}|none|latex"))
-{ }
-
-void
-line::properties::set (const caseless_str& name, const octave_value& val)
-{
-  bool modified = true;
-
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("parent"))
-    set_parent (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("__modified__"))
-    {
-      __modified__ = val.bool_value ();
-      modified = false;
-    }
-  else if (name.compare ("xdata"))
-    set_xdata (val);
-  else if (name.compare ("ydata"))
-    set_ydata (val);
-  else if (name.compare ("zdata"))
-    set_zdata (val);
-  else if (name.compare ("ldata"))
-    set_ldata (val);
-  else if (name.compare ("udata"))
-    set_udata (val);
-  else if (name.compare ("xldata"))
-    set_xldata (val);
-  else if (name.compare ("xudata"))
-    set_xudata (val);
-  else if (name.compare ("color"))
-    set_color (val);
-  else if (name.compare ("linestyle"))
-    set_linestyle (val);
-  else if (name.compare ("linewidth"))
-    set_linewidth (val);
-  else if (name.compare ("marker"))
-    set_marker (val);
-  else if (name.compare ("markeredgecolor"))
-    set_markeredgecolor (val);
-  else if (name.compare ("markerfacecolor"))
-    set_markerfacecolor (val);
-  else if (name.compare ("markersize"))
-    set_markersize (val);
-  else if (name.compare ("keylabel"))
-    set_keylabel (val);
-  else if (name.compare ("interpreter"))
-    set_interpreter (val);
-  else
-    {
-      modified = false;
-      warning ("set: invalid property `%s'", name.c_str ());
-    }
-
-  if (modified)
-    mark_modified ();
-}
-
-octave_value
-line::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("parent", parent.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("__modified__", __modified__);
-  m.assign ("xdata", xdata);
-  m.assign ("ydata", ydata);
-  m.assign ("zdata", zdata);
-  m.assign ("ldata", ldata);
-  m.assign ("udata", udata);
-  m.assign ("xldata", xldata);
-  m.assign ("xudata", xudata);
-  m.assign ("color", color);
-  m.assign ("linestyle", linestyle);
-  m.assign ("linewidth", linewidth);
-  m.assign ("marker", marker);
-  m.assign ("markeredgecolor", markeredgecolor);
-  m.assign ("markerfacecolor", markerfacecolor);
-  m.assign ("markersize", markersize);
-  m.assign ("keylabel", keylabel);
-  m.assign ("interpreter", interpreter);
-
-  return m;
-}
-
-octave_value
-line::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = tag;
-  else if (name.compare ("type"))
-    retval = type;
-  else if (name.compare ("parent"))
-    retval = parent.as_octave_value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("__modified__"))
-    retval = __modified__;
-  else if (name.compare ("xdata"))
-    retval = xdata;
-  else if (name.compare ("ydata"))
-    retval = ydata;
-  else if (name.compare ("zdata"))
-    retval = zdata;
-  else if (name.compare ("ldata"))
-    retval = ldata;
-  else if (name.compare ("udata"))
-    retval = udata;
-  else if (name.compare ("xldata"))
-    retval = xldata;
-  else if (name.compare ("xudata"))
-    retval = xudata;
-  else if (name.compare ("color"))
-    retval = color;
-  else if (name.compare ("linestyle"))
-    retval = linestyle;
-  else if (name.compare ("linewidth"))
-    retval = linewidth;
-  else if (name.compare ("marker"))
-    retval = marker;
-  else if (name.compare ("markeredgecolor"))
-    retval = markeredgecolor;
-  else if (name.compare ("markerfacecolor"))
-    retval = markerfacecolor;
-  else if (name.compare ("markersize"))
-    retval = markersize;
-  else if (name.compare ("keylabel"))
-    retval = keylabel;
-  else if (name.compare ("interpreter"))
-    retval = interpreter;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
-}
-
-property_list::pval_map_type
-line::properties::factory_defaults (void)
-{
-  property_list::pval_map_type m;
-
-  m["xdata"] = default_data ();
-  m["ydata"] = default_data ();
-  m["zdata"] = Matrix ();
-  m["ldata"] = Matrix ();
-  m["udata"] = Matrix ();
-  m["xldata"] = Matrix ();
-  m["xudata"] = Matrix ();
-  m["color"] = color_property ();
-  m["linestyle"] = "-";
-  m["linewidth"] = 0.5;
-  m["marker"] = "none";
-  m["markeredgecolor"] = "auto";
-  m["markerfacecolor"] = "none";
-  m["markersize"] = 1;
-  m["keylabel"] = "";
-  m["interpreter"] = radio_property (radio_values ("{tex}|none|latex"));
-
-  return m;
-}
-
-std::string line::properties::go_name ("line");
-
-// ---------------------------------------------------------------------
-
-text::properties::properties (const graphics_handle& mh,
-			      const graphics_handle& p)
-  : base_properties (go_name, mh, p),
-    string (""),
-    units ("data"),
-    position (Matrix (1, 3, 0.0)),
-    rotation (0),
-    horizontalalignment ("left"),
-    color (Matrix (1, 3, 0.0)),
-    fontname ("Helvetica"),
-    fontsize (10),
-    fontangle (radio_values ("{normal}|italic|oblique")),
-    fontweight (radio_values ("{normal}|bold|demi|light")),
-    interpreter (radio_values ("{tex}|none|latex"))
-{ }
-
-void
-text::properties::set (const caseless_str& name, const octave_value& val)
-{
-  bool modified = true;
-
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("parent"))
-    set_parent (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("__modified__"))
-    {
-      __modified__ = val.bool_value ();
-      modified = false;
-    }
-  else if (name.compare ("string"))
-    set_string (val);
-  else if (name.compare ("units"))
-    set_units (val);
-  else if (name.compare ("position"))
-    set_position (val);
-  else if (name.compare ("rotation"))
-    set_rotation (val);
-  else if (name.compare ("horizontalalignment"))
-    set_horizontalalignment (val);
-  else if (name.compare ("color"))
-    set_color (val);
-  else if (name.compare ("fontname"))
-    set_fontname (val);
-  else if (name.compare ("fontsize"))
-    set_fontsize (val);
-  else if (name.compare ("fontangle"))
-    set_fontangle (val);
-  else if (name.compare ("fontweight"))
-    set_fontweight (val);
-  else if (name.compare ("interpreter"))
-    set_interpreter (val);
-  else
-    {
-      modified = false;
-      warning ("set: invalid property `%s'", name.c_str ());
-    }
-
-  if (modified)
-    mark_modified ();
-}
-
-octave_value
-text::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("parent", parent.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("__modified__", __modified__);
-  m.assign ("string", string);
-  m.assign ("units", units);
-  m.assign ("position", position);
-  m.assign ("rotation", rotation);
-  m.assign ("horizontalalignment", horizontalalignment);
-  m.assign ("color", color);
-  m.assign ("fontname", fontname);
-  m.assign ("fontsize", fontsize);
-  m.assign ("fontangle", fontangle);
-  m.assign ("fontweight", fontweight);
-  m.assign ("interpreter", interpreter);
-
-  return m;
-}
-
-octave_value
-text::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = tag;
-  else if (name.compare ("type"))
-    retval = type;
-  else if (name.compare ("parent"))
-    retval = parent.as_octave_value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("__modified__"))
-    retval = __modified__;
-  else if (name.compare ("string"))
-    retval = string;
-  else if (name.compare ("units"))
-    retval = units;
-  else if (name.compare ("position"))
-    retval = position;
-  else if (name.compare ("rotation"))
-    retval = rotation;
-  else if (name.compare ("horizontalalignment"))
-    retval = horizontalalignment;
-  else if (name.compare ("color"))
-    retval = color;
-  else if (name.compare ("fontname"))
-    retval = fontname;
-  else if (name.compare ("fontsize"))
-    retval = fontsize;
-  else if (name.compare ("fontangle"))
-    retval = fontangle;
-  else if (name.compare ("fontweight"))
-    retval = fontweight;
-  else if (name.compare ("interpreter"))
-    retval = interpreter;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
-}
-
-property_list::pval_map_type
-text::properties::factory_defaults (void)
-{
-  property_list::pval_map_type m;
-
-  m["string"] = "";
-  m["units"] = "data";
-  m["position"] = Matrix (1, 3, 0.0);
-  m["rotation"] = 0;
-  m["horizontalalignment"] = "left";
-  m["color"] = Matrix (1, 3, 1.0);
-  m["fontname"] = "Helvetica";
-  m["fontsize"] = 10;
-  m["fontangle"] = radio_property (radio_values ("{normal}|italic|oblique"));
-  m["fontweight"] = radio_property (radio_values ("{normal}|bold|demi|light"));
-  m["interpreter"] = radio_property (radio_values ("{tex}|none|latex"));
-
-  return m;
-}
-
-std::string text::properties::go_name ("text");
+// Note: "text" code is entirely auto-generated
 
 // ---------------------------------------------------------------------
 
-image::properties::properties (const graphics_handle& mh,
-			       const graphics_handle& p)
-  : base_properties (go_name, mh, p),
-    xdata (Matrix ()),
-    ydata (Matrix ()),
-    cdata (Matrix ())
-{ }
-
-void
-image::properties::set (const caseless_str& name,
-			const octave_value& val)
-{
-  bool modified = true;
-
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("parent"))
-    set_parent (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("__modified__"))
-    {
-      __modified__ = val.bool_value ();
-      modified = false;
-    }
-  else if (name.compare ("xdata"))
-    set_xdata (val);
-  else if (name.compare ("ydata"))
-    set_ydata (val);
-  else if (name.compare ("cdata"))
-    set_cdata (val);
-  else
-    {
-      modified = false;
-      warning ("set: invalid property `%s'", name.c_str ());
-    }
-
-  if (modified)
-    mark_modified ();
-}
-
-octave_value
-image::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("parent", parent.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("__modified__", __modified__);
-  m.assign ("xdata", xdata);
-  m.assign ("ydata", ydata);
-  m.assign ("cdata", cdata);
-
-  return m;
-}
-
-octave_value
-image::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = tag;
-  else if (name.compare ("type"))
-    retval = type;
-  else if (name.compare ("parent"))
-    retval = parent.as_octave_value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("__modified__"))
-    retval = __modified__;
-  else if (name.compare ("xdata"))
-    retval = xdata;
-  else if (name.compare ("ydata"))
-    retval = ydata;
-  else if (name.compare ("cdata"))
-    retval = cdata;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
-}
-
-property_list::pval_map_type
-image::properties::factory_defaults (void)
-{
-  property_list::pval_map_type m;
-
-  m["xdata"] = Matrix ();
-  m["ydata"] = Matrix ();
-  m["cdata"] = Matrix ();
-
-  return m;
-}
-
-std::string image::properties::go_name ("image");
+// Note: "image" code is entirely auto-generated
 
 // ---------------------------------------------------------------------
 
-patch::properties::properties (const graphics_handle& mh,
-			       const graphics_handle& p)
-  : base_properties (go_name, mh, p),
-    xdata (Matrix ()),
-    ydata (Matrix ()),
-    zdata (Matrix ()),
-    cdata (Matrix ()),
-    faces (Matrix ()),
-    vertices (Matrix ()),
-    facecolor (radio_values ("{flat}|none|interp")),
-    facealpha (1.0),
-    edgecolor (color_values (0, 0, 0), radio_values ("flat|none|interp")),
-    linestyle ("-"),
-    linewidth (0.5),
-    marker ("none"),
-    markeredgecolor ("auto"),
-    markerfacecolor ("none"),
-    markersize (1),
-    keylabel (""),
-    interpreter (radio_values ("{tex}|none|latex"))
-{ }
-
-void
-patch::properties::set (const caseless_str& name,
-			const octave_value& val)
-{
-  bool modified = true;
-
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("parent"))
-    set_parent (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("__modified__"))
-    {
-      __modified__ = val.bool_value ();
-      modified = false;
-    }
-  else if (name.compare ("xdata"))
-    set_xdata (val);
-  else if (name.compare ("ydata"))
-    set_ydata (val);
-  else if (name.compare ("zdata"))
-    set_zdata (val);
-  else if (name.compare ("cdata"))
-    set_cdata (val);
-  else if (name.compare ("faces"))
-    set_faces (val);
-  else if (name.compare ("vertices"))
-    set_vertices (val);
-  else if (name.compare ("facecolor"))
-    set_facecolor (val);
-  else if (name.compare ("facealpha"))
-    set_facealpha (val);
-  else if (name.compare ("edgecolor"))
-    set_edgecolor (val);
-  else if (name.compare ("linestyle"))
-    set_linestyle (val);
-  else if (name.compare ("linewidth"))
-    set_linewidth (val);
-  else if (name.compare ("marker"))
-    set_marker (val);
-  else if (name.compare ("markeredgecolor"))
-    set_markeredgecolor (val);
-  else if (name.compare ("markerfacecolor"))
-    set_markerfacecolor (val);
-  else if (name.compare ("markersize"))
-    set_markersize (val);
-  else if (name.compare ("keylabel"))
-    set_keylabel (val);
-  else if (name.compare ("interpreter"))
-    set_interpreter (val);
-  else
-    {
-      modified = false;
-      warning ("set: invalid property `%s'", name.c_str ());
-    }
-
-  if (modified)
-    mark_modified ();
-}
-
-octave_value
-patch::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("parent", parent.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("__modified__", __modified__);
-  m.assign ("xdata", xdata);
-  m.assign ("ydata", ydata);
-  m.assign ("zdata", zdata);
-  m.assign ("cdata", cdata);
-  m.assign ("faces", faces);
-  m.assign ("vertices", vertices);
-  m.assign ("facecolor", facecolor);
-  m.assign ("facealpha", facealpha);
-  m.assign ("edgecolor", edgecolor);
-  m.assign ("linestyle", linestyle);
-  m.assign ("linewidth", linewidth);
-  m.assign ("marker", marker);
-  m.assign ("markeredgecolor", markeredgecolor);
-  m.assign ("markerface", markerfacecolor);
-  m.assign ("markersize", markersize);
-  m.assign ("keylabel", keylabel);
-  m.assign ("interpreter", interpreter);
-
-  return m;
-}
-
-octave_value
-patch::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = tag;
-  else if (name.compare ("type"))
-    retval = type;
-  else if (name.compare ("parent"))
-    retval = parent.as_octave_value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("__modified__"))
-    retval = __modified__;
-  else if (name.compare ("xdata"))
-    retval = xdata;
-  else if (name.compare ("ydata"))
-    retval = ydata;
-  else if (name.compare ("zdata"))
-    retval = zdata;
-  else if (name.compare ("cdata"))
-    retval = cdata;
-  else if (name.compare ("faces"))
-    retval = faces;
-  else if (name.compare ("vertices"))
-    retval = vertices;
-  else if (name.compare ("facecolor"))
-    retval = facecolor;
-  else if (name.compare ("facealpha"))
-    retval = facealpha;
-  else if (name.compare ("edgecolor"))
-    retval = edgecolor;
-  else if (name.compare ("linestyle"))
-    retval = linestyle;
-  else if (name.compare ("linewidth"))
-    retval = linewidth;
-  else if (name.compare ("marker"))
-    retval = marker;
-  else if (name.compare ("markeredgecolor"))
-    retval = markeredgecolor;
-  else if (name.compare ("markerfacecolor"))
-    retval = markerfacecolor;
-  else if (name.compare ("markersize"))
-    retval = markersize;
-  else if (name.compare ("keylabel"))
-    retval = keylabel;
-  else if (name.compare ("interpreter"))
-    retval = interpreter;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
-}
-
-property_list::pval_map_type
-patch::properties::factory_defaults (void)
-{
-  property_list::pval_map_type m;
-
-  m["xdata"] = Matrix ();
-  m["ydata"] = Matrix ();
-  m["zdata"] = Matrix ();
-  m["cdata"] = Matrix ();
-  m["faces"] = Matrix ();
-  m["vertices"] = Matrix ();
-  m["facecolor"] = color_property ();
-  m["facealpha"] = 1.0;
-  m["edgecolor"] = color_property ("black");
-  m["linestyle"] = "-";
-  m["linewidth"] = 0.5;
-  m["marker"] = "none";
-  m["markeredgecolor"] = "auto";
-  m["markerfacecolor"] = "none";
-  m["markersize"] = 1;
-  m["keylabel"] = "";
-  m["interpreter"] = radio_property (radio_values ("{tex}|none|latex"));
-
-  return m;
-}
-
-std::string patch::properties::go_name ("patch");
+// Note: "patch" code is entirely auto-generated
 
 // ---------------------------------------------------------------------
 
-surface::properties::properties (const graphics_handle& mh,
-				 const graphics_handle& p)
-  : base_properties (go_name, mh, p),
-    xdata (Matrix ()),
-    ydata (Matrix ()),
-    zdata (Matrix ()),
-    cdata (Matrix ()),
-    facecolor (radio_values ("{flat}|none|interp")),
-    facealpha (1.0),
-    edgecolor (color_values (0, 0, 0), radio_values ("flat|none|interp")),
-    linestyle ("-"),
-    linewidth (0.5),
-    marker ("none"),
-    markeredgecolor ("auto"),
-    markerfacecolor ("none"),
-    markersize (1),
-    keylabel (""),
-    interpreter (radio_values ("{tex}|none|latex"))
-{ }
-
-void
-surface::properties::set (const caseless_str& name,
-			  const octave_value& val)
-{
-  bool modified = true;
-
-  if (name.compare ("tag"))
-    set_tag (val);
-  else if (name.compare ("parent"))
-    set_parent (val);
-  else if (name.compare ("children"))
-    children = maybe_set_children (children, val);
-  else if (name.compare ("__modified__"))
-    {
-      __modified__ = val.bool_value ();
-      modified = false;
-    }
-  else if (name.compare ("xdata"))
-    set_xdata (val);
-  else if (name.compare ("ydata"))
-    set_ydata (val);
-  else if (name.compare ("zdata"))
-    set_zdata (val);
-  else if (name.compare ("cdata"))
-    set_cdata (val);
-  else if (name.compare ("facecolor"))
-    set_facecolor (val);
-  else if (name.compare ("facealpha"))
-    set_facealpha (val);
-  else if (name.compare ("edgecolor"))
-    set_edgecolor (val);
-  else if (name.compare ("linestyle"))
-    set_linestyle (val);
-  else if (name.compare ("linewidth"))
-    set_linewidth (val);
-  else if (name.compare ("marker"))
-    set_marker (val);
-  else if (name.compare ("markeredgecolor"))
-    set_markeredgecolor (val);
-  else if (name.compare ("markerfacecolor"))
-    set_markerfacecolor (val);
-  else if (name.compare ("markersize"))
-    set_markersize (val);
-  else if (name.compare ("keylabel"))
-    set_keylabel (val);
-  else if (name.compare ("interpreter"))
-    set_interpreter (val);
-  else
-    {
-      modified = false;
-      warning ("set: invalid property `%s'", name.c_str ());
-    }
-
-  if (modified)
-    mark_modified ();
-}
-
-octave_value
-surface::properties::get (void) const
-{
-  Octave_map m;
-
-  m.assign ("tag", tag);
-  m.assign ("type", type);
-  m.assign ("parent", parent.as_octave_value ());
-  m.assign ("children", children);
-  m.assign ("__modified__", __modified__);
-  m.assign ("xdata", xdata);
-  m.assign ("ydata", ydata);
-  m.assign ("zdata", zdata);
-  m.assign ("cdata", cdata);
-  m.assign ("facecolor", facecolor);
-  m.assign ("facealpha", facealpha);
-  m.assign ("edgecolor", edgecolor);
-  m.assign ("linestyle", linestyle);
-  m.assign ("linewidth", linewidth);
-  m.assign ("marker", marker);
-  m.assign ("markeredgecolor", markeredgecolor);
-  m.assign ("markerface", markerfacecolor);
-  m.assign ("markersize", markersize);
-  m.assign ("keylabel", keylabel);
-  m.assign ("interpreter", interpreter);
-
-  return m;
-}
-
-octave_value
-surface::properties::get (const caseless_str& name) const
-{
-  octave_value retval;
-
-  if (name.compare ("tag"))
-    retval = tag;
-  else if (name.compare ("type"))
-    retval = type;
-  else if (name.compare ("parent"))
-    retval = parent.as_octave_value ();
-  else if (name.compare ("children"))
-    retval = children;
-  else if (name.compare ("__modified__"))
-    retval = __modified__;
-  else if (name.compare ("xdata"))
-    retval = xdata;
-  else if (name.compare ("ydata"))
-    retval = ydata;
-  else if (name.compare ("zdata"))
-    retval = zdata;
-  else if (name.compare ("cdata"))
-    retval = cdata;
-  else if (name.compare ("facecolor"))
-    retval = facecolor;
-  else if (name.compare ("facealpha"))
-    retval = facealpha;
-  else if (name.compare ("edgecolor"))
-    retval = edgecolor;
-  else if (name.compare ("linestyle"))
-    retval = linestyle;
-  else if (name.compare ("linewidth"))
-    retval = linewidth;
-  else if (name.compare ("marker"))
-    retval = marker;
-  else if (name.compare ("markeredgecolor"))
-    retval = markeredgecolor;
-  else if (name.compare ("markerfacecolor"))
-    retval = markerfacecolor;
-  else if (name.compare ("markersize"))
-    retval = markersize;
-  else if (name.compare ("keylabel"))
-    retval = keylabel;
-  else if (name.compare ("interpreter"))
-    retval = interpreter;
-  else
-    warning ("get: invalid property `%s'", name.c_str ());
-
-  return retval;
-}
-
-property_list::pval_map_type
-surface::properties::factory_defaults (void)
-{
-  property_list::pval_map_type m;
-
-  m["xdata"] = Matrix ();
-  m["ydata"] = Matrix ();
-  m["zdata"] = Matrix ();
-  m["cdata"] = Matrix ();
-  m["facecolor"] = color_property ();
-  m["facealpha"] = 1.0;
-  m["edgecolor"] = color_property ("black");
-  m["linestyle"] = "-";
-  m["linewidth"] = 0.5;
-  m["marker"] = "none";
-  m["markeredgecolor"] = "auto";
-  m["markerfacecolor"] = "none";
-  m["markersize"] = 1;
-  m["keylabel"] = "";
-  m["interpreter"] = radio_property (radio_values ("{tex}|none|latex"));
-
-  return m;
-}
-
-std::string surface::properties::go_name ("surface");
+// Note: "surface" code is entirely auto-generated
 
 // ---------------------------------------------------------------------
 
--- a/src/graphics.h.in	Sat Jan 12 08:00:38 2008 +0000
+++ b/src/graphics.h.in	Sat Jan 12 08:21:57 2008 +0000
@@ -82,450 +82,6 @@
 
 // ---------------------------------------------------------------------
 
-class radio_values
-{
-public:
-  radio_values (const std::string& opt_string = std::string ());
-
-  radio_values (const radio_values& a)
-    : default_val (a.default_val), possible_vals (a.possible_vals) { }
-
-  radio_values& operator = (const radio_values& a)
-  {
-    if (&a != this)
-      {
-	default_val = a.default_val;
-	possible_vals = a.possible_vals;
-      }
-
-    return *this;
-  }
-
-  std::string default_value (void) const { return default_val; }
-
-  bool validate (const std::string& val)
-  {
-    bool retval = true;
-
-    if (! contains (val))
-      {
-	error ("invalid value = %s", val.c_str ());
-	retval = false;
-      }
-
-    return retval;
-  }
-  
-  bool contains (const std::string& val)
-  {
-    return (possible_vals.find (val) != possible_vals.end ());
-  }
-
-private:
-  // Might also want to cache
-  std::string default_val;
-  std::set<caseless_str> possible_vals;
-};
-
-class radio_property
-{
-public:
-  radio_property (const radio_values& v = radio_values ())
-    : vals (v), current_val (v.default_value ()) { }
-
-  radio_property (const radio_property& a)
-    : vals (a.vals), current_val (a.current_val) { }
-
-  radio_property& operator = (const radio_property& a)
-  {
-    if (&a != this)
-      {
-	vals = a.vals;
-	current_val = a.current_val;
-      }
-
-    return *this;
-  }
-
-  radio_property& operator = (const std::string& newval)
-  {
-    if (vals.validate (newval))
-      current_val = newval;
-    else
-      error ("invalid value");
-
-    return *this;
-  }
-
-  radio_property& operator = (const octave_value& newval) 
-  {
-    if (newval.is_string ())
-      {
-	std::string s = newval.string_value ();
-	if (vals.validate (s))
-	  current_val = s;
-	else
-	  error ("invalid value");
-      }
-    else	
-      error ("invalid value");
-
-    return *this;
-  }
-
-  operator octave_value (void) const { return current_val; }
-
-  const std::string& current_value (void) const { return current_val; }
-
-private:
-  radio_values vals;
-  std::string current_val;
-};
-
-class color_values
-{
-public:
-  color_values (double r = 0, double g = 0, double b = 1)
-  {
-    xrgb[0] = r;
-    xrgb[1] = g;
-    xrgb[2] = b;
-
-    validate ();
-  }
-
-  color_values (std::string str)
-  {
-    if (! str2rgb (str))
-      error ("invalid color specification");
-  }
-
-  color_values (const color_values& c)
-  {
-    xrgb[0] = c.xrgb[0];
-    xrgb[1] = c.xrgb[1];
-    xrgb[2] = c.xrgb[2];
-  }
-
-  color_values& operator = (const color_values& c)
-  {
-    if (&c != this)
-      {
-	xrgb[0] = c.xrgb[0];
-	xrgb[1] = c.xrgb[1];
-	xrgb[2] = c.xrgb[2];
-
-      }
-
-    return *this;
-  }
-
-  const double* rgb (void) const { return xrgb; }
-
-  void validate (void) const
-  {
-    for (int i = 0; i < 3; i++)
-      {
-	if (xrgb[i] < 0 ||  xrgb[i] > 1)
-	  {
-	    error ("invalid RGB color specification");
-	    break;
-	  }
-      }
-  }
-
-private:
-  double xrgb[3];
-
-  bool str2rgb (std::string str);
-};
-
-
-class color_property
-{
-public:
-  color_property (const color_values& c = color_values (),
-		  const radio_values& v = radio_values ())
-    : current_type (color_t), color_val (c), radio_val (v),
-      current_val (v.default_value ())
-  { }
-
-  color_property (const radio_values& v)
-    : current_type (radio_t), color_val (color_values ()), radio_val (v),
-      current_val (v.default_value ())
-  { }
-
-  color_property (const radio_values& v, const std::string& initial_value)
-    : current_type (radio_t), color_val (color_values ()), radio_val (v),
-      current_val (initial_value)
-  { }
-
-  color_property (const octave_value& val);
-
-  operator octave_value (void) const
-  {
-    if (current_type == color_t)
-      {
-	Matrix retval (1, 3);
-	const double *xrgb = color_val.rgb ();
-
-	for (int i = 0; i < 3 ; i++)
-	  retval(i) = xrgb[i];
-
-	return retval;
-      }
-
-    return current_val;
-  }
-
-  color_property& operator = (const color_property& a)
-  {
-    if (&a != this)
-      {
-	current_type = a.current_type;
-	color_val = a.color_val;
-	radio_val = a.radio_val;
-	current_val = a.current_val;
-      }
-
-    return *this;
-  }
-
-  color_property& operator = (const std::string& newval)
-  {
-    if (radio_val.validate (newval))
-      {
-	current_val = newval;
-	current_type = radio_t;
-      }
-
-    return *this;
-  }
-
-  color_property& operator = (const color_values& newval)
-  {
-    color_val = newval;
-    current_type = color_t;
-
-    return *this;
-  }
-
-  color_property& operator = (const octave_value& newval);
-
-  bool is_rgb (void) const { return (current_type == color_t); }
-
-  bool is_radio (void) const { return (current_type == radio_t); }
-
-  const double* rgb (void) const
-  {
-    if (current_type != color_t)
-      error ("color has no rgb value");
-
-    return color_val.rgb ();
-  }
-
-  const std::string& current_value (void) const
-  {
-    if (current_type != radio_t)
-      error ("color has no radio value");
-
-    return current_val;
-  }
-
-private:
-  enum current_enum { color_t, radio_t } current_type;
-  color_values color_val;
-  radio_values radio_val;
-  std::string current_val;
-};
-
-class colormap_property
-{
-public:
-  colormap_property (const Matrix& m = Matrix ())
-    : cmap (m)
-  {
-    if (cmap.is_empty ())
-      {
-	cmap = Matrix (64, 3, 0.0);
-
-	for (octave_idx_type i = 0; i < 64; i++)
-	  {
-	    // This is the jet colormap.  It would be nice to be able
-	    // to feval the jet function but since there is a static
-	    // property object that includes a colormap_property
-	    // object, we need to initialize this before main is even
-	    // called, so calling an interpreted function is not
-	    // possible.
-
-	    double x = i / 63.0;
-
-	    if (x >= 3.0/8.0 && x < 5.0/8.0)
-	      cmap(i,0) = 4.0 * x - 3.0/2.0;
-	    else if (x >= 5.0/8.0 && x < 7.0/8.0)
-	      cmap(i,0) = 1.0;
-	    else if (x >= 7.0/8.0)
-	      cmap(i,0) = -4.0 * x + 9.0/2.0;
-
-	    if (x >= 1.0/8.0 && x < 3.0/8.0)
-	      cmap(i,1) = 4.0 * x - 1.0/2.0;
-	    else if (x >= 3.0/8.0 && x < 5.0/8.0)
-	      cmap(i,1) = 1.0;
-	    else if (x >= 5.0/8.0 && x < 7.0/8.0)
-	      cmap(i,1) = -4.0 * x + 7.0/2.0;
-
-	    if (x < 1.0/8.0)
-	      cmap(i,2) = 4.0 * x + 1.0/2.0;
-	    else if (x >= 1.0/8.0 && x < 3.0/8.0)
-	      cmap(i,2) = 1.0;
-	    else if (x >= 3.0/8.0 && x < 5.0/8.0)
-	      cmap(i,2) = -4.0 * x + 5.0/2.0;
-	  }
-      }
-
-    validate ();
-  }
-
-  colormap_property (const octave_value& val)
-  {
-    cmap = val.matrix_value ();
-
-    validate ();
-  }
-
-  void validate (void) const
-  {
-    if (error_state || cmap.columns () != 3)
-      error ("invalid colormap specification");
-  }
-
-  operator octave_value (void) const { return cmap; }
-
-private:
-  Matrix cmap;
-};
-
-class data_property
-{
-public:
-  data_property (const NDArray& m = NDArray ())
-    : data (m), xmin (octave_Inf), xmax (-octave_Inf), xminp (octave_Inf)
-  {
-    get_data_limits ();
-  }
-
-  data_property (const Matrix& m)
-    : data (m), xmin (octave_Inf), xmax (-octave_Inf), xminp (octave_Inf)
-  {
-    get_data_limits ();
-  }
-
-  data_property (const octave_value& val)
-    : data (), xmin (octave_Inf), xmax (-octave_Inf), xminp (octave_Inf)
-  {
-    data = val.array_value ();
-
-    get_data_limits ();
-  }
-
-  data_property& operator = (const data_property& a)
-  {
-    if (&a != this)
-      {
-	data = a.data;
-	xmin = a.xmin;
-	xmax = a.xmax;
-	xminp = a.xminp;
-      }
-
-    return *this;
-  }
-
-  operator octave_value (void) const { return data; }
-
-  double min_val (void) const { return xmin; }
-  double max_val (void) const { return xmax; }
-  double min_pos (void) const { return xminp; }
-
-private:
-  NDArray data;
-  double xmin;
-  double xmax;
-  double xminp;
-
-  void get_data_limits (void)
-  {
-    octave_idx_type nel = data.numel ();
-
-    if (nel > 0)
-      {
-	const double *d = data.data ();
-
-	for (octave_idx_type i = 0; i < nel; i++)
-	  {
-	    double val = d[i];
-
-	    if (! (xisinf (val) || xisnan (val)))
-	      {
-		if (val < xmin)
-		  xmin = val;
-
-		if (val > xmax)
-		  xmax = val;
-
-		if (val > 0 && val < xminp)
-		  xminp = val;
-	      }
-	  }
-      }
-  }
-};
-
-class property_list
-{
-public:
-  typedef std::map<std::string, octave_value> pval_map_type;
-  typedef std::map<std::string, pval_map_type> plist_map_type;
-  
-  typedef pval_map_type::iterator pval_map_iterator;
-  typedef pval_map_type::const_iterator pval_map_const_iterator;
-
-  typedef plist_map_type::iterator plist_map_iterator;
-  typedef plist_map_type::const_iterator plist_map_const_iterator;
-
-  property_list (const plist_map_type& m = plist_map_type ())
-    : plist_map (m) { }
-
-  ~property_list (void) { }
-
-  void set (const caseless_str& name, const octave_value& val);
-
-  octave_value lookup (const caseless_str& name) const;
-
-  plist_map_iterator begin (void) { return plist_map.begin (); }
-  plist_map_const_iterator begin (void) const { return plist_map.begin (); }
-
-  plist_map_iterator end (void) { return plist_map.end (); }
-  plist_map_const_iterator end (void) const { return plist_map.end (); }
-
-  plist_map_iterator find (const std::string& go_name)
-  {
-    return plist_map.find (go_name);
-  }
-
-  plist_map_const_iterator find (const std::string& go_name) const
-  {
-    return plist_map.find (go_name);
-  }
-
-  Octave_map as_struct (const std::string& prefix_arg) const;
-
-private:
-  plist_map_type plist_map;
-};
-
-// ---------------------------------------------------------------------
-
 class graphics_handle
 {
 public:
@@ -626,16 +182,790 @@
 
 // ---------------------------------------------------------------------
 
+class property;
+
+class base_property
+{
+public:
+  friend class property;
+
+public:
+  base_property (void) : count (0) { }
+
+  base_property (const std::string& s, const graphics_handle& h)
+    : count (0), name (s), parent (h), hidden (false) { }
+
+  base_property (const base_property& p)
+    : count (0), name (p.name), parent (p.parent), hidden (p.hidden) { }
+
+  virtual ~base_property (void) { }
+
+  bool ok (void) const { return parent.ok (); }
+
+  std::string get_name (void) const { return name; }
+
+  void set_name (const std::string& s) { name = s; }
+
+  graphics_handle get_parent (void) const { return parent; }
+
+  void set_parent (const graphics_handle &h) { parent = h; }
+
+  bool is_hidden (void) const { return hidden; }
+
+  void set_hidden (bool flag) { hidden = flag; }
+
+  virtual void set (const octave_value& val)
+    { error ("set: invalid property \"%s\"", name.c_str ()); }
+
+  virtual octave_value get (void) const
+    {
+      error ("get: invalid property \"%s\"", name.c_str ());
+      return octave_value ();
+    }
+
+  base_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  int count;
+  std::string name;
+  graphics_handle parent;
+  bool hidden;
+};
+
+// ---------------------------------------------------------------------
+
+class string_property : public base_property
+{
+public:
+  string_property (const std::string& s, const graphics_handle& h,
+                   const std::string& val = "")
+    : base_property (s, h), str (val) { }
+
+  string_property (const string_property& p)
+    : base_property (p), str (p.str) { }
+
+  void set (const octave_value& val)
+    {
+      if (val.is_string ())
+        str = val.string_value ();
+      else
+        error ("set: invalid string property value for \"%s\"",
+               get_name ().c_str ());
+    }
+
+  octave_value get (void) const
+    { return octave_value (str); }
+
+  std::string string_value (void) const { return str; }
+
+  string_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  std::string str;
+};
+
+// ---------------------------------------------------------------------
+
+class radio_values
+{
+public:
+  OCTINTERP_API radio_values (const std::string& opt_string = std::string ());
+
+  radio_values (const radio_values& a)
+    : default_val (a.default_val), possible_vals (a.possible_vals) { }
+
+  radio_values& operator = (const radio_values& a)
+  {
+    if (&a != this)
+      {
+	default_val = a.default_val;
+	possible_vals = a.possible_vals;
+      }
+
+    return *this;
+  }
+
+  std::string default_value (void) const { return default_val; }
+
+  bool validate (const std::string& val)
+  {
+    bool retval = true;
+
+    if (! contains (val))
+      {
+	error ("invalid value = %s", val.c_str ());
+	retval = false;
+      }
+
+    return retval;
+  }
+  
+  bool contains (const std::string& val)
+  {
+    return (possible_vals.find (val) != possible_vals.end ());
+  }
+
+private:
+  // Might also want to cache
+  std::string default_val;
+  std::set<caseless_str> possible_vals;
+};
+
+class radio_property : public base_property
+{
+public:
+  radio_property (const std::string& name, const graphics_handle& h,
+                  const radio_values& v = radio_values ())
+    : base_property (name, h),
+      vals (v), current_val (v.default_value ()) { }
+
+  radio_property (const std::string& name, const graphics_handle& h,
+                  const std::string& v)
+    : base_property (name, h),
+      vals (v), current_val (vals.default_value ()) { }
+
+  radio_property (const std::string& name, const graphics_handle& h,
+                  const radio_values& v, const std::string& def)
+    : base_property (name, h),
+      vals (v), current_val (def) { }
+
+  radio_property (const radio_property& p)
+    : base_property (p), vals (p.vals), current_val (p.current_val) { }
+
+  void set (const octave_value& newval) 
+  {
+    if (newval.is_string ())
+      {
+        std::string s = newval.string_value ();
+        if (vals.validate (s))
+          current_val = s;
+        else
+          error ("set: invalid value for radio property \"%s\" (value = %s)",
+              get_name ().c_str (), s.c_str ());
+      }
+    else	
+      error ("set: invalid value for radio property \"%s\"",
+          get_name ().c_str ());
+  }
+
+  octave_value get (void) const { return octave_value (current_val); }
+
+  const std::string& current_value (void) const { return current_val; }
+
+  bool is (const caseless_str& v) const
+    { return v.compare (current_val); }
+
+  radio_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  radio_values vals;
+  std::string current_val;
+};
+
+// ---------------------------------------------------------------------
+
+class color_values
+{
+public:
+  color_values (double r = 0, double g = 0, double b = 1)
+    : xrgb (1, 3)
+  {
+    xrgb(0) = r;
+    xrgb(1) = g;
+    xrgb(2) = b;
+
+    validate ();
+  }
+
+  color_values (std::string str)
+    : xrgb (1, 3)
+  {
+    if (! str2rgb (str))
+      error ("invalid color specification: %s", str.c_str ());
+  }
+
+  color_values (const color_values& c)
+    : xrgb (c.xrgb)
+  { }
+
+  color_values& operator = (const color_values& c)
+  {
+    if (&c != this)
+      xrgb = c.xrgb;
+
+    return *this;
+  }
+
+  Matrix rgb (void) const { return xrgb; }
+
+  operator octave_value (void) const { return xrgb; }
+
+  void validate (void) const
+  {
+    for (int i = 0; i < 3; i++)
+      {
+	if (xrgb(i) < 0 ||  xrgb(i) > 1)
+	  {
+	    error ("invalid RGB color specification");
+	    break;
+	  }
+      }
+  }
+
+private:
+  Matrix xrgb;
+
+  OCTINTERP_API bool str2rgb (std::string str);
+};
+
+class color_property : public base_property
+{
+public:
+  color_property (const color_values& c, const radio_values& v)
+    : base_property ("", graphics_handle ()),
+      current_type (color_t), color_val (c), radio_val (v),
+      current_val (v.default_value ())
+  { }
+
+  color_property (const std::string& name, const graphics_handle& h,
+                  const color_values& c = color_values (),
+                  const radio_values& v = radio_values ())
+    : base_property (name, h),
+      current_type (color_t), color_val (c), radio_val (v),
+      current_val (v.default_value ())
+  { }
+
+  color_property (const std::string& name, const graphics_handle& h,
+                  const radio_values& v)
+    : base_property (name, h),
+      current_type (radio_t), color_val (color_values ()), radio_val (v),
+      current_val (v.default_value ())
+  { }
+
+  color_property (const std::string& name, const graphics_handle& h,
+                  const std::string& v)
+    : base_property (name, h),
+      current_type (radio_t), color_val (color_values ()), radio_val (v),
+      current_val (radio_val.default_value ())
+  { }
+  
+  color_property (const std::string& name, const graphics_handle& h,
+                  const color_property& v)
+    : base_property (name, h),
+      current_type (v.current_type), color_val (v.color_val),
+      radio_val (v.radio_val), current_val (v.current_val)
+  { }
+
+  color_property (const color_property& p)
+    : base_property (p), current_type (p.current_type),
+      color_val (p.color_val), radio_val (p.radio_val),
+      current_val (p.current_val) { }
+
+  octave_value get (void) const
+  {
+    if (current_type == color_t)
+      return color_val.rgb ();
+
+    return current_val;
+  }
+
+  OCTINTERP_API void set (const octave_value& newval);
+
+  bool is_rgb (void) const { return (current_type == color_t); }
+
+  bool is_radio (void) const { return (current_type == radio_t); }
+
+  bool is (const std::string& v) const
+    { return (is_radio () && current_val == v); }
+
+  Matrix rgb (void) const
+  {
+    if (current_type != color_t)
+      error ("color has no rgb value");
+
+    return color_val.rgb ();
+  }
+
+  const std::string& current_value (void) const
+  {
+    if (current_type != radio_t)
+      error ("color has no radio value");
+
+    return current_val;
+  }
+
+  color_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+  operator octave_value (void) const { return get (); }
+
+private:
+  enum current_enum { color_t, radio_t } current_type;
+  color_values color_val;
+  radio_values radio_val;
+  std::string current_val;
+};
+
+// ---------------------------------------------------------------------
+
+class double_property : public base_property
+{
+public:
+  double_property (const std::string& name, const graphics_handle& h,
+                   double d = 0)
+    : base_property (name, h),
+      current_val (d) { }
+
+  double_property (const double_property& p)
+    : base_property (p), current_val (p.current_val) { }
+
+  void set (const octave_value& v)
+    {
+      if (v.is_scalar_type () && v.is_real_type ())
+        current_val = v.double_value ();
+      else
+        error ("set: invalid value for double property \"%s\"",
+               get_name ().c_str ());
+    }
+
+  octave_value get (void) const { return octave_value (current_val); }
+
+  double double_value (void) const { return current_val; }
+
+  double_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  double current_val;
+};
+
+// ---------------------------------------------------------------------
+
+class array_property : public base_property
+{
+public:
+  array_property (const std::string& name, const graphics_handle& h,
+                  const octave_value& m)
+    : base_property (), data (m) { }
+
+  octave_value get (void) const { return data; }
+
+  void set (const octave_value& v)
+    {
+      if (validate (v))
+        data = v;
+      else
+        error ("invalid value for array property \"%s\"",
+               get_name ().c_str ());
+    }
+
+  void add_constraint (const std::string& type)
+    { type_constraints.push_back (type); }
+
+  void add_constraint (dim_vector dims)
+    { size_constraints.push_back (dims); }
+
+  array_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  OCTINTERP_API bool validate (const octave_value& v);
+
+private:
+  octave_value data;
+  std::list<std::string> type_constraints;
+  std::list<dim_vector> size_constraints;
+};
+
+// ---------------------------------------------------------------------
+
+class data_property : public base_property
+{
+public:
+  data_property (void)
+    : base_property ("", graphics_handle ()) { }
+
+  data_property (const std::string& name, const graphics_handle& h,
+                 const NDArray& m = NDArray ())
+    : base_property (name, h),
+      data (m), xmin (octave_Inf), xmax (-octave_Inf), xminp (octave_Inf)
+  {
+    get_data_limits ();
+  }
+
+  data_property (const std::string& name, const graphics_handle& h,
+                 const Matrix& m)
+    : base_property (name, h),
+      data (m), xmin (octave_Inf), xmax (-octave_Inf), xminp (octave_Inf)
+  {
+    get_data_limits ();
+  }
+
+  data_property (const data_property& p)
+    : base_property (p), data (p.data),
+      xmin (p.xmin), xmax (p.xmax), xminp (p.xminp) { }
+
+  void set (const octave_value& val)
+  {
+    data = val.array_value ();
+
+    get_data_limits ();
+  }
+
+  octave_value get (void) const { return data; }
+
+  NDArray array_value (void) const { return data; }
+
+  Matrix matrix_value (void) const { return data.matrix_value (); }
+
+  double min_val (void) const { return xmin; }
+  double max_val (void) const { return xmax; }
+  double min_pos (void) const { return xminp; }
+
+  data_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  NDArray data;
+  double xmin;
+  double xmax;
+  double xminp;
+
+  void get_data_limits (void)
+  {
+    octave_idx_type nel = data.numel ();
+
+    if (nel > 0)
+      {
+	const double *d = data.data ();
+
+	for (octave_idx_type i = 0; i < nel; i++)
+	  {
+	    double val = d[i];
+
+	    if (! (xisinf (val) || xisnan (val)))
+	      {
+		if (val < xmin)
+		  xmin = val;
+
+		if (val > xmax)
+		  xmax = val;
+
+		if (val > 0 && val < xminp)
+		  xminp = val;
+	      }
+	  }
+      }
+  }
+};
+
+// ---------------------------------------------------------------------
+
+class bool_property : public radio_property
+{
+public:
+  bool_property (const std::string& name, const graphics_handle& h,
+                 bool val)
+    : radio_property (name, h, radio_values (val ? "{on}|off" : "on|{off}"))
+    { }
+
+  bool_property (const std::string& name, const graphics_handle& h,
+                 const char* val)
+    : radio_property (name, h, radio_values ("on|off"), val)
+    { }
+
+  bool_property (const bool_property& p)
+    : radio_property (p) { }
+
+  void set (const octave_value& val)
+    {
+      if (val.is_bool_scalar ())
+        radio_property::set (val.bool_value () ? "on" : "off");
+      else
+        radio_property::set (val);
+    }
+
+  bool is_on (void) const { return is ("on"); }
+  
+  bool_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+};
+
+// ---------------------------------------------------------------------
+
+class handle_property : public base_property
+{
+public:
+  handle_property (const std::string& name, const graphics_handle& h,
+                   const graphics_handle& val = graphics_handle ())
+    : base_property (name, h),
+      current_val (val) { }
+
+  handle_property (const handle_property& p)
+    : base_property (p), current_val (p.current_val) { }
+
+  OCTINTERP_API void set (const octave_value& v);
+
+  octave_value get (void) const { return current_val.as_octave_value (); }
+
+  graphics_handle handle_value (void) const { return current_val; }
+
+  handle_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+  handle_property& operator = (const graphics_handle& h)
+    {
+      set (octave_value (h.value ()));
+      return *this;
+    }
+
+private:
+  graphics_handle current_val;
+};
+
+// ---------------------------------------------------------------------
+
+class any_property : public base_property
+{
+public:
+  any_property (const std::string& name, const graphics_handle& h,
+                  const octave_value& m = Matrix ())
+    : base_property (), data (m) { }
+
+  octave_value get (void) const { return data; }
+
+  void set (const octave_value& v) { data = v; }
+
+  any_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  octave_value data;
+};
+
+// ---------------------------------------------------------------------
+
+class callback_property : public base_property
+{
+public:
+  callback_property (const std::string& name, const graphics_handle& h,
+                     const octave_value& m)
+    : base_property (), callback (m) { }
+
+  octave_value get (void) const { return callback; }
+
+  void set (const octave_value& v)
+    {
+      if (validate (v))
+        callback = v;
+      else
+        error ("invalid value for callback property \"%s\"",
+               get_name ().c_str ());
+    }
+
+  OCTINTERP_API void execute (void);
+
+  callback_property& operator = (const octave_value& val)
+    {
+      set (val);
+      return *this;
+    }
+
+private:
+  OCTINTERP_API bool validate (const octave_value& v) const;
+
+private:
+  octave_value callback;
+};
+
+// ---------------------------------------------------------------------
+
+class property
+{
+public:
+  property (void) : rep (new base_property ("", graphics_handle ()))
+    { rep->count++; }
+
+  property (base_property *bp, bool persist = false) : rep (bp)
+    { rep->count++; if (persist) rep->count++; }
+
+  property (const property& p)
+    {
+      rep = p.rep;
+      rep->count++;
+    }
+
+  ~property (void)
+    {
+      if (--rep->count <= 0)
+        delete rep;
+    }
+
+  bool ok (void) const
+    { return rep->ok (); }
+
+  std::string get_name (void) const
+    { return rep->get_name (); }
+
+  void set_name (const std::string& name)
+    { rep->set_name (name); }
+
+  graphics_handle get_parent (void) const
+    { return rep->get_parent (); }
+
+  void set_parent (const graphics_handle& h)
+    { rep->set_parent (h); }
+
+  bool is_hidden (void) const
+    { return rep->is_hidden (); }
+
+  void set_hidden (bool flag)
+    { rep->set_hidden (flag); }
+
+  octave_value get (void) const
+    { return rep->get (); }
+
+  void set (const octave_value& val)
+    { rep->set (val); }
+
+  property& operator = (const octave_value& val)
+    {
+      *rep = val;
+      return *this;
+    }
+
+  property& operator = (const property& p)
+    {
+      if (rep && --rep->count <= 0)
+        delete rep;
+      
+      rep = p.rep;
+      rep->count++;
+
+      return *this;
+    }
+
+  /*
+  const string_property& as_string_property (void) const
+    { return *(dynamic_cast<string_property*> (rep)); }
+
+  const radio_property& as_radio_property (void) const
+    { return *(dynamic_cast<radio_property*> (rep)); }
+
+  const color_property& as_color_property (void) const
+    { return *(dynamic_cast<color_property*> (rep)); }
+
+  const double_property& as_double_property (void) const
+    { return *(dynamic_cast<double_property*> (rep)); }
+
+  const data_property& as_data_property (void) const
+    { return *(dynamic_cast<data_property*> (rep)); }
+  
+  const bool_property& as_bool_property (void) const
+    { return *(dynamic_cast<bool_property*> (rep)); }
+  
+  const handle_property& as_handle_property (void) const
+    { return *(dynamic_cast<handle_property*> (rep)); }
+    */
+
+private:
+  base_property *rep;
+};
+
+// ---------------------------------------------------------------------
+
+class property_list
+{
+public:
+  typedef std::map<std::string, octave_value> pval_map_type;
+  typedef std::map<std::string, pval_map_type> plist_map_type;
+  
+  typedef pval_map_type::iterator pval_map_iterator;
+  typedef pval_map_type::const_iterator pval_map_const_iterator;
+
+  typedef plist_map_type::iterator plist_map_iterator;
+  typedef plist_map_type::const_iterator plist_map_const_iterator;
+
+  property_list (const plist_map_type& m = plist_map_type ())
+    : plist_map (m) { }
+
+  ~property_list (void) { }
+
+  void set (const caseless_str& name, const octave_value& val);
+
+  octave_value lookup (const caseless_str& name) const;
+
+  plist_map_iterator begin (void) { return plist_map.begin (); }
+  plist_map_const_iterator begin (void) const { return plist_map.begin (); }
+
+  plist_map_iterator end (void) { return plist_map.end (); }
+  plist_map_const_iterator end (void) const { return plist_map.end (); }
+
+  plist_map_iterator find (const std::string& go_name)
+  {
+    return plist_map.find (go_name);
+  }
+
+  plist_map_const_iterator find (const std::string& go_name) const
+  {
+    return plist_map.find (go_name);
+  }
+
+  Octave_map as_struct (const std::string& prefix_arg) const;
+
+private:
+  plist_map_type plist_map;
+};
+
+// ---------------------------------------------------------------------
+
 class base_graphics_object;
 
 class base_properties
 {
 public:
   base_properties (const std::string& ty = "unknown",
-		   const graphics_handle& mh = graphics_handle (),
-		   const graphics_handle& p = graphics_handle ())
-    : tag (), type (ty), __modified__ (true), __myhandle__ (mh),
-      parent (p), children () { }
+                   const graphics_handle& mh = graphics_handle (),
+                   const graphics_handle& p = graphics_handle ())
+    : tag ("tag", mh),
+      type ("type", mh, ty),
+      __modified__ ("__modified__", mh, true),
+      __myhandle__ (mh),
+      parent ("parent", mh, p), children ()
+    { }
 
   virtual ~base_properties (void) { }
 
@@ -650,15 +980,28 @@
 
   void set_from_list (base_graphics_object& obj, property_list& defaults);
 
-  virtual void set (const caseless_str&, const octave_value&) { }
-
-  std::string get_tag (void) const { return tag; }
-
-  graphics_handle get_parent (void) const { return parent; }
-
-  std::string get_type (void) const { return type; }
-
-  bool is_modified (void) const { return __modified__; }
+  void insert_property (const std::string& name, property p)
+    {
+      p.set_name (name);
+      p.set_parent (__myhandle__);
+      all_props[name] = p;
+    }
+
+  virtual void set (const caseless_str&, const octave_value&);
+
+  virtual octave_value get (const caseless_str&) const;
+
+  virtual octave_value get (void) const;
+
+  property get_property (const caseless_str&) const;
+
+  std::string get_tag (void) const { return tag.string_value (); }
+
+  graphics_handle get_parent (void) const { return parent.handle_value (); }
+
+  std::string get_type (void) const { return type.string_value (); }
+
+  bool is_modified (void) const { return __modified__.is_on (); }
  
   graphics_handle get___myhandle__ (void) const { return __myhandle__; }
  
@@ -671,7 +1014,7 @@
     children(n) = h.value ();
   }
 
-  void set_tag (const octave_value& val);
+  void set_tag (const octave_value& val) { tag = val; }
 
   void set_parent (const octave_value& val);
 
@@ -690,61 +1033,71 @@
   // genprops.awk script.
   //
   // EMIT_BASE_PROPERTIES_GET_FUNCTIONS
-  virtual data_property get_xdata (void) const
+  virtual data_property get_xdata_property (void) const
   {
     error ("get: invalid property \"xdata\"");
     return data_property ();
   }
 
-  virtual data_property get_ydata (void) const
+  virtual data_property get_ydata_property (void) const
   {
     error ("get: invalid property \"ydata\"");
     return data_property ();
   }
 
-  virtual data_property get_zdata (void) const
+  virtual data_property get_zdata_property (void) const
   {
     error ("get: invalid property \"zdata\"");
     return data_property ();
   }
 
-  virtual data_property get_ldata (void) const
+  virtual data_property get_ldata_property (void) const
   {
     error ("get: invalid property \"ldata\"");
     return data_property ();
   }
 
-  virtual data_property get_udata (void) const
+  virtual data_property get_udata_property (void) const
   {
     error ("get: invalid property \"udata\"");
     return data_property ();
   }
 
-  virtual data_property get_xldata (void) const
+  virtual data_property get_xldata_property (void) const
   {
     error ("get: invalid property \"xldata\"");
     return data_property ();
   }
 
-  virtual data_property get_xudata (void) const
+  virtual data_property get_xudata_property (void) const
   {
     error ("get: invalid property \"xudata\"");
     return data_property ();
   }
 
-  virtual data_property get_cdata (void) const
+  virtual data_property get_cdata_property (void) const
   {
     error ("get: invalid property \"cdata\"");
     return data_property ();
   }
 
 protected:
-  std::string tag;
-  std::string type;
-  bool __modified__;
+  string_property tag;
+  string_property type;
+  bool_property __modified__;
   graphics_handle __myhandle__;
-  graphics_handle parent;
+  handle_property parent;
+  // FIXME: use a property class for children
   Matrix children;
+
+protected:
+  std::map<caseless_str, property> all_props;
+
+protected:
+  void insert_static_property (const std::string& name, base_property& p)
+    { insert_property (name, property (&p, true)); }
+  
+  virtual void init (void) { }
 };
 
 class base_graphics_object
@@ -981,52 +1334,52 @@
   // genprops.awk script.
   //
   // EMIT_GRAPHICS_OBJECT_GET_FUNCTIONS
-  data_property get_xdata (void) const
+  data_property get_xdata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_xdata ();
+    return props.get_xdata_property ();
   }
 
-  data_property get_ydata (void) const
+  data_property get_ydata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_ydata ();
+    return props.get_ydata_property ();
   }
 
-  data_property get_zdata (void) const
+  data_property get_zdata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_zdata ();
+    return props.get_zdata_property ();
   }
 
-  data_property get_ldata (void) const
+  data_property get_ldata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_ldata ();
+    return props.get_ldata_property ();
   }
 
-  data_property get_udata (void) const
+  data_property get_udata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_udata ();
+    return props.get_udata_property ();
   }
 
-  data_property get_xldata (void) const
+  data_property get_xldata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_xldata ();
+    return props.get_xldata_property ();
   }
 
-  data_property get_xudata (void) const
+  data_property get_xudata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_xudata ();
+    return props.get_xudata_property ();
   }
 
-  data_property get_cdata (void) const
+  data_property get_cdata_property (void) const
   {
     const base_properties& props = get_properties ();
-    return props.get_cdata ();
+    return props.get_cdata_property ();
   }
 
 private:
@@ -1041,31 +1394,13 @@
   class properties : public base_properties
   {
   public:
-    properties (void)
-      : base_properties ("root figure", 0, graphics_handle ()),
-	currentfigure (),
-	visible ("on")
-    { }
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
-    std::string graphics_object_name (void) const { return go_name; }
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      graphics_handle currentfigure S
-      octave_value visible
+    BEGIN_PROPERTIES(root_figure)
+      handle_property currentfigure S , graphics_handle ()
+      bool_property visible , "on"
     END_PROPERTIES
-
-    static std::string go_name;
   };
 
 private:
@@ -1073,7 +1408,7 @@
 
 public:
 
-  root_figure (void) : xproperties (), default_properties () { }
+  root_figure (void) : xproperties (0, graphics_handle ()), default_properties () { }
 
   ~root_figure (void) { xproperties.delete_children (); }
 
@@ -1191,38 +1526,29 @@
   class properties : public base_properties
   {
   public:
-    properties (const graphics_handle& mh, const graphics_handle& p);
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
     void close (void);
 
-    std::string graphics_object_name (void) const { return go_name; }
-
-    static property_list::pval_map_type factory_defaults (void);
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      octave_value __plot_stream__
-      octave_value __enhanced__
-      octave_value nextplot
-      octave_value closerequestfcn
-      graphics_handle currentaxes S
-      colormap_property colormap
-      octave_value visible S
-      octave_value paperorientation
-      color_property color
+    BEGIN_PROPERTIES(figure)
+      any_property __plot_stream__ , Matrix ()
+      bool_property __enhanced__ , "on"
+      radio_property nextplot , "add|replace_children|{replace}"
+      callback_property closerequestfcn , "closereq"
+      handle_property currentaxes S , graphics_handle ()
+      array_property colormap , jet_colormap ()
+      bool_property visible S , "on"
+      radio_property paperorientation , "{portrait}|landscape"
+      color_property color , color_values (1, 1, 1)
     END_PROPERTIES
-
-    static std::string go_name;
+    
+  protected:
+    void init (void)
+      {
+        colormap.add_constraint (dim_vector (-1, 3));
+      }
+
   };
 
 private:
@@ -1327,90 +1653,95 @@
   class properties : public base_properties
   {
   public:
-    properties (const graphics_handle& mh, const graphics_handle& p);
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
     void set_defaults (base_graphics_object& obj, const std::string& mode);
 
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
     void remove_child (const graphics_handle& h);
 
     void delete_children (void);
 
-    std::string graphics_object_name (void) const { return go_name; }
-
-    static property_list::pval_map_type factory_defaults (void);
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      octave_value position
-      mutable graphics_handle title GSO
-      octave_value box
-      octave_value key
-      octave_value keybox
-      octave_value keypos
-      octave_value colororder
-      octave_value dataaspectratio m
-      octave_value dataaspectratiomode
-      radio_property layer a
-      octave_value xlim m
-      octave_value ylim m
-      octave_value zlim m
-      octave_value clim m
-      radio_property xlimmode al
-      radio_property ylimmode al
-      radio_property zlimmode al
-      radio_property climmode al
-      mutable graphics_handle xlabel GSO
-      mutable graphics_handle ylabel GSO
-      mutable graphics_handle zlabel GSO
-      octave_value xgrid
-      octave_value ygrid
-      octave_value zgrid
-      octave_value xminorgrid
-      octave_value yminorgrid
-      octave_value zminorgrid
-      octave_value xtick m
-      octave_value ytick m
-      octave_value ztick m
-      octave_value xtickmode
-      octave_value ytickmode
-      octave_value ztickmode
-      octave_value xticklabel m
-      octave_value yticklabel m
-      octave_value zticklabel m
-      octave_value xticklabelmode
-      octave_value yticklabelmode
-      octave_value zticklabelmode
-      color_property color a
-      color_property xcolor
-      color_property ycolor
-      color_property zcolor
-      radio_property xscale al
-      radio_property yscale al
-      radio_property zscale al
-      octave_value xdir
-      octave_value ydir
-      octave_value zdir
-      octave_value xaxislocation
-      octave_value yaxislocation
-      octave_value view
-      octave_value visible
-      octave_value nextplot
-      octave_value outerposition
-      radio_property activepositionproperty a
-      radio_property __colorbar__ a
+    BEGIN_PROPERTIES(axes)
+      array_property position , Matrix ()
+      mutable handle_property title GSO , graphics_handle ()
+      bool_property box , "on"
+      bool_property key , "off"
+      bool_property keybox , "off"
+      double_property keypos , 1
+      array_property colororder , default_colororder ()
+      array_property dataaspectratio m , Matrix (1, 3, 1.0)
+      radio_property dataaspectratiomode , "{auto}|manual"
+      radio_property layer a , "{bottom}|top"
+      array_property xlim m , default_lim ()
+      array_property ylim m , default_lim ()
+      array_property zlim m , default_lim ()
+      array_property clim m , default_lim ()
+      radio_property xlimmode al , "{auto}|manual"
+      radio_property ylimmode al , "{auto}|manual"
+      radio_property zlimmode al , "{auto}|manual"
+      radio_property climmode al , "{auto}|manual"
+      mutable handle_property xlabel GSO , graphics_handle ()
+      mutable handle_property ylabel GSO , graphics_handle ()
+      mutable handle_property zlabel GSO , graphics_handle ()
+      bool_property xgrid , "off"
+      bool_property ygrid , "off"
+      bool_property zgrid , "off"
+      bool_property xminorgrid , "off"
+      bool_property yminorgrid , "off"
+      bool_property zminorgrid , "off"
+      array_property xtick m , Matrix ()
+      array_property ytick m , Matrix ()
+      array_property ztick m , Matrix ()
+      radio_property xtickmode , "{auto}|manual"
+      radio_property ytickmode , "{auto}|manual"
+      radio_property ztickmode , "{auto}|manual"
+      any_property xticklabel m , ""
+      any_property yticklabel m , ""
+      any_property zticklabel m , ""
+      radio_property xticklabelmode , "{auto}|manual"
+      radio_property yticklabelmode , "{auto}|manual"
+      radio_property zticklabelmode , "{auto}|manual"
+      color_property color a , color_property (color_values (1, 1, 1), radio_values ("none"))
+      color_property xcolor , color_values (0, 0, 0)
+      color_property ycolor , color_values (0, 0, 0)
+      color_property zcolor , color_values (0, 0, 0)
+      radio_property xscale al , "{linear}|log"
+      radio_property yscale al , "{linear}|log"
+      radio_property zscale al , "{linear}|log"
+      radio_property xdir , "{normal}|reverse"
+      radio_property ydir , "{normal}|reverse"
+      radio_property zdir , "{normal}|reverse"
+      radio_property yaxislocation , "{left}|right"
+      radio_property xaxislocation , "{bottom}|top"
+      array_property view , Matrix ()
+      bool_property visible , "on"
+      radio_property nextplot , "add|replace_children|{replace}"
+      array_property outerposition , Matrix ()
+      radio_property activepositionproperty a , "{outerposition}|position"
+      radio_property __colorbar__ a , "{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside"
    END_PROPERTIES
 
-    static std::string go_name;
+  protected:
+    void init (void)
+      {
+        position.add_constraint (dim_vector (1, 4));
+		position.add_constraint (dim_vector (0, 0));
+        outerposition.add_constraint (dim_vector (1, 4));
+        colororder.add_constraint (dim_vector (-1, 3));
+        dataaspectratio.add_constraint (dim_vector (1, 3));
+        xlim.add_constraint (dim_vector (1, 2));
+        ylim.add_constraint (dim_vector (1, 2));
+        zlim.add_constraint (dim_vector (1, 2));
+        clim.add_constraint (dim_vector (1, 2));
+        xtick.add_constraint (dim_vector (1, -1));
+        ytick.add_constraint (dim_vector (1, -1));
+        ztick.add_constraint (dim_vector (1, -1));
+        Matrix vw (1, 2, 0);
+        vw(1) = 90;
+        view = vw;
+        view.add_constraint (dim_vector (1, 2));
+      }
   };
 
 private:
@@ -1519,43 +1850,27 @@
   class properties : public base_properties
   {
   public:
-    properties (const graphics_handle& mh, const graphics_handle& p);
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
-    std::string graphics_object_name (void) const { return go_name; }
-
-    static property_list::pval_map_type factory_defaults (void);
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      data_property xdata l
-      data_property ydata l
-      data_property zdata l
-      data_property ldata l
-      data_property udata l
-      data_property xldata l
-      data_property xudata l
-      color_property color
-      octave_value linestyle
-      octave_value linewidth
-      octave_value marker
-      octave_value markeredgecolor
-      octave_value markerfacecolor
-      octave_value markersize
-      octave_value keylabel
-      radio_property interpreter a
+    BEGIN_PROPERTIES(line)
+      data_property xdata l , default_data ()
+      data_property ydata l , default_data ()
+      data_property zdata l , Matrix ()
+      data_property ldata l , Matrix ()
+      data_property udata l , Matrix ()
+      data_property xldata l , Matrix ()
+      data_property xudata l , Matrix ()
+      color_property color , color_values (0, 0, 0)
+      radio_property linestyle , "{-}|--|:|-.|none"
+      double_property linewidth , 0.5
+      radio_property marker , "{none}|s|o|x|+|.|*|<|>|v|^|d|p|h"
+      color_property markeredgecolor , "{auto}|none"
+      color_property markerfacecolor , "auto|{none}"
+      double_property markersize , 6
+      string_property keylabel , ""
+      radio_property interpreter a , "{tex}|none|latex"
     END_PROPERTIES
-
-    static std::string go_name;
   };
 
 private:
@@ -1626,38 +1941,28 @@
   class properties : public base_properties
   {
   public:
-    properties (const graphics_handle& mh, const graphics_handle& p);
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
-    std::string graphics_object_name (void) const { return go_name; }
-
-    static property_list::pval_map_type factory_defaults (void);
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      octave_value string
-      octave_value units
-      octave_value position
-      octave_value rotation
-      octave_value horizontalalignment
-      color_property color
-      octave_value fontname
-      octave_value fontsize
-      radio_property fontangle a
-      radio_property fontweight a
-      radio_property interpreter a
+    BEGIN_PROPERTIES(text)
+      string_property string , ""
+      radio_property units , "{data}|pixels|normalized|inches|centimeters|points"
+      array_property position , Matrix (1, 3, 0.0)
+      double_property rotation , 0
+      radio_property horizontalalignment , "{left}|center|right"
+      color_property color , color_values (0, 0, 0)
+      string_property fontname , "Helvetica"
+      double_property fontsize , 10
+      radio_property fontangle a , "{normal}|italic|oblique"
+      radio_property fontweight a , "light|{normal}|demi|bold"
+      radio_property interpreter a , "{tex}|none|latex"
     END_PROPERTIES
 
-    static std::string go_name;
+  protected:
+    void init (void)
+      {
+        position.add_constraint (dim_vector (1, 3));
+      }
   };
 
 private:
@@ -1728,30 +2033,19 @@
   class properties : public base_properties
   {
   public:
-    properties (const graphics_handle& mh, const graphics_handle& p);
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
-    std::string graphics_object_name (void) const { return go_name; }
-
-    static property_list::pval_map_type factory_defaults (void);
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      data_property xdata l
-      data_property ydata l
-      data_property cdata l
+    BEGIN_PROPERTIES(image)
+      data_property xdata l , Matrix ()
+      data_property ydata l , Matrix ()
+      data_property cdata l , Matrix ()
     END_PROPERTIES
 
-    static std::string go_name;
+  protected:
+    void init (void)
+      {
+      }
   };
 
 private:
@@ -1822,44 +2116,35 @@
   class properties : public base_properties
   {
   public:
-    properties (const graphics_handle& mh, const graphics_handle& p);
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
-    std::string graphics_object_name (void) const { return go_name; }
-
-    static property_list::pval_map_type factory_defaults (void);
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      data_property xdata l
-      data_property ydata l
-      data_property zdata l
-      data_property cdata l
-      octave_value faces
-      octave_value vertices
-      color_property facecolor a
-      octave_value facealpha
-      color_property edgecolor a
-      octave_value linestyle
-      octave_value linewidth
-      octave_value marker
-      octave_value markeredgecolor
-      octave_value markerfacecolor
-      octave_value markersize
-      octave_value keylabel
-      radio_property interpreter a
+    BEGIN_PROPERTIES(patch)
+      data_property xdata l , Matrix ()
+      data_property ydata l , Matrix ()
+      data_property zdata l , Matrix ()
+      data_property cdata l , Matrix ()
+      array_property faces , Matrix ()
+      array_property vertices , Matrix ()
+      color_property facecolor a , "{flat}|none|interp"
+      double_property facealpha , 1.0
+      color_property edgecolor a , color_property (color_values (0, 0, 0), radio_values ("flat|none|interp"))
+      radio_property linestyle , "{-}|--|:|-.|none"
+      double_property linewidth , 0.5
+      radio_property marker , "{none}|s|o|x|+|.|*|<|>|v|^|d|p|h"
+      color_property markeredgecolor , "{auto}|none"
+      color_property markerfacecolor , "auto|{none}"
+      double_property markersize , 6
+      string_property keylabel , ""
+      radio_property interpreter a , "{tex}|none|latex"
     END_PROPERTIES
 
-    static std::string go_name;
+  protected:
+    void init (void)
+      {
+        vertices.add_constraint (dim_vector (-1, 2));
+        vertices.add_constraint (dim_vector (-1, 3));
+      }
   };
 
 private:
@@ -1930,42 +2215,31 @@
   class properties : public base_properties
   {
   public:
-    properties (const graphics_handle& mh, const graphics_handle& p);
-
-    ~properties (void) { }
-
-    void set (const caseless_str& name, const octave_value& val);
-
-    octave_value get (void) const;
-
-    octave_value get (const caseless_str& name) const;
-
-    std::string graphics_object_name (void) const { return go_name; }
-
-    static property_list::pval_map_type factory_defaults (void);
-
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    BEGIN_PROPERTIES
-      data_property xdata l
-      data_property ydata l
-      data_property zdata l
-      data_property cdata l
-      color_property facecolor a
-      octave_value facealpha
-      color_property edgecolor a
-      octave_value linestyle
-      octave_value linewidth
-      octave_value marker
-      octave_value markeredgecolor
-      octave_value markerfacecolor
-      octave_value markersize
-      octave_value keylabel
-      radio_property interpreter a
+    BEGIN_PROPERTIES(surface)
+      data_property xdata l , Matrix ()
+      data_property ydata l , Matrix ()
+      data_property zdata l , Matrix ()
+      data_property cdata l , Matrix ()
+      color_property facecolor a , "{flat}|none|interp"
+      double_property facealpha , 1.0
+      color_property edgecolor a , color_property (color_values (0, 0, 0), radio_values ("flat|none|interp"))
+      radio_property linestyle , "{-}|--|:|-.|none"
+      double_property linewidth , 0.5
+      radio_property marker , "{none}|s|o|x|+|.|*|<|>|v|^|d|p|h"
+      color_property markeredgecolor , "{auto}|none"
+      color_property markerfacecolor , "auto|{none}"
+      double_property markersize , 6
+      string_property keylabel , ""
+      radio_property interpreter a , "{tex}|none|latex"
     END_PROPERTIES
 
-    static std::string go_name;
+  protected:
+    void init (void)
+      {
+      }
   };
 
 private:
@@ -2153,7 +2427,7 @@
 
   graphics_handle do_lookup (double val)
   {
-    iterator p = handle_map.find (val);
+    iterator p = (xisnan (val) ? handle_map.end () : handle_map.find (val));
 
     return (p != handle_map.end ()) ? p->first : graphics_handle ();
   }