This is buttons only and Motif only at the moment. Athena should be trivial
depending on what Athena actually supports. Some properties are not
implemented. Try glyph-tests.el for examples.
I will apply this to cvs.
andy
1999-06-25  Andy Piper  <andy(a)xemacs.org>
	* menubar-x.c (menu_item_descriptor_to_widget_value_1): use new
 	gui functions.
	* menubar-msw.c: move MAX_MENUITEM_LENGTH to gui.h
	* gui.h (struct Lisp_Gui_Item): add accelerator.
	* gui.c (gui_item_add_keyval_pair): deal with accelerators.
	(gui_item_init): ditto.
	(gui_add_item_keywords_to_plist): ditto.
	(mark_gui_item): ditto.
	(gui_item_hash): ditto.
	(gui_item_accelerator): new function.
	(gui_name_accelerator): new function stolen from gui-x.c
	* gui-x.c (popup_selection_callback): always define. mark
 	subwindows changed after calling a callback.
	(menu_name_to_accelerator): deleted.
	(button_item_to_widget_value): forward gui_item things to gui_item
 	functions.
	* glyphs-x.h (struct x_subwindow_data): add data for widgets. add
 	appropriate accesors.
	* glyphs-x.c: declare new glyph formats.
	(x_finalize_image_instance): unmanage and destroy widgets if they
 	exist.
	(x_unmap_subwindow): handle widgets specially.
	(x_map_subwindow): ditto. offset display of widgets by offset of
 	text widget within container.
	(x_update_subwindow): new function. call lw_modify_all_widgets
 	when we are a widget.
	(x_widget_instantiate): new function for generically creating
 	widgets-glyphs. toolkit specifics forwarded to lwlib.
	(x_button_instantiate): new function for instantiating
 	widgets-glyph buttons.
	(console_type_create_glyphs_x): register update_subwindow.
	(image_instantiator_format_create_glyphs_x): register widget and
 	button types.
	* event-msw.c (mswindows_wnd_proc): remove redundant variable.
	* event-Xt.c (x_event_to_emacs_event): call handle_focus_event_1
 	when we get a button press in case we do not have the focus.
	(handle_focus_event_1): set the keyboard focus to the text widget
 	if we do not have it.
	* dialog-x.c (dbox_descriptor_to_widget_value): use new gui_item
 	functions.
	* lwlib.h (_widget_value): add arglist slots.
	declare new functions.
	* lwlib.c (free_widget_value_contents): handle arglists when
 	freeing.
	(lw_add_value_args_to_args): new function. add arglist entries
 	from a widget_value structure.
	* lwlib-Xm.c (make_button): new function, create a motif button
 	for display in a buffer as a glyph.
	(xm_creation_table): add make_button.
? munge.awk
? Root
? tmp
? tst
? wid.patch
? etc/ChangeLog
? lib-src/run.res
? lisp/.emacs_andyp
? lisp/msw-faces.el.fm
? lisp/mule
? lisp/prim
? lisp/x-font-menu.el.dist
? lisp/x-font-menu.el.fm
? man/internals/patch.exe.core
? modules/ChangeLog
? nt/Addtargetscheckandcheck-temacstoxemacsmakremovemule-c.txt
? nt/Installation
? nt/obj
? nt/puresize-adjust.h
? nt/xemacs.mak+
? nt/xemacs95.mak
? src/depend.tmp
? src/l
? src/mkdc
? src/t.c
? src/TDOC
? src/temacs.exe.core
? src/tstdoc
? src/weblogic.log
? src/winsup
? src/xstrace.gz
Index: CHANGES-beta
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/CHANGES-beta,v
retrieving revision 1.153.2.61
diff -u -r1.153.2.61 CHANGES-beta
--- CHANGES-beta 1999/06/23 12:25:28 1.153.2.61
+++ CHANGES-beta 1999/06/25 14:13:12
@@ -1,5 +1,6 @@
 							-*- indented-text -*-
 to 21.2.18 "Toshima"
+-- glyph widget support under X/Motif from Andy Piper
 -- Make docdir configurable, update package searching rules from Michael
    Sperber
 -- Fix for Japanese word/character movements from MORIOKA Tomohiko
Index: etc/NEWS
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/etc/NEWS,v
retrieving revision 1.58.2.16
diff -u -r1.58.2.16 NEWS
--- etc/NEWS 1999/06/23 12:25:51 1.58.2.16
+++ etc/NEWS 1999/06/25 14:13:17
@@ -108,6 +108,18 @@
 
 ** The font-menu is now available under MS-Windows
 
+** MS-Windows support for selection is much more robust
+
+Generally selection should now do what you would expect under
+MS-Windows: the middle mouse button will paste your current selection
+or the clipboard; conversions from different types of selection to the
+clipboard can be made; the kill-ring and friends will be updated as
+per X.
+
+The only thing selection doesn't do is set the clipboard automatically
+as this would break the MS-Windows model. If you want this behaviour
+then set `selection-sets-clipboard' to t
+
 
 * Lisp and internal changes in XEmacs 21.2
 ==========================================
Index: lwlib/lwlib-Xm.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lwlib/lwlib-Xm.c,v
retrieving revision 1.11
diff -u -r1.11 lwlib-Xm.c
--- lwlib/lwlib-Xm.c 1998/01/19 01:57:48 1.11
+++ lwlib/lwlib-Xm.c 1999/06/25 14:13:25
@@ -63,12 +63,10 @@
 
 #ifdef LWLIB_MENUBARS_MOTIF
 static void xm_pull_down_callback (Widget, XtPointer, XtPointer);
-#if 0
-static void xm_pop_down_callback (Widget, XtPointer, XtPointer);
-#endif /* 0 */
 #endif
 static void xm_internal_update_other_instances (Widget, XtPointer,
 						XtPointer);
+static void xm_pop_down_callback (Widget, XtPointer, XtPointer);
 static void xm_generic_callback (Widget, XtPointer, XtPointer);
 #ifdef LWLIB_DIALOGS_MOTIF
 static void xm_nosel_callback (Widget, XtPointer, XtPointer);
@@ -946,7 +944,7 @@
 /* This function is for activating a button from a program.  It's wrong because
    we pass a NULL argument in the call_data which is not Motif compatible.
    This is used from the XmNdefaultAction callback of the List widgets to
-   have a dble-click put down a dialog box like the button woudl do. 
+   have a double-click put down a dialog box like the button would do. 
    I could not find a way to do that with accelerators.
  */
 static void
@@ -1571,6 +1569,54 @@
 
 #endif /* LWLIB_SCROLLBARS_MOTIF */
 
+/* glyph widgets */
+static Widget
+make_button (widget_instance *instance)
+{
+  Arg al[20];
+  int ac = 0;
+  Widget button = 0;
+  widget_value* val = instance->info->val;
+
+  XtSetArg (al [ac], XmNsensitive, val->enabled);		ac++;
+  XtSetArg (al [ac], XmNalignment, XmALIGNMENT_BEGINNING);	ac++;
+  XtSetArg (al [ac], XmNuserData, val->call_data);		ac++;
+  XtSetArg (al [ac], XmNmappedWhenManaged, FALSE);	ac++;
+  /* The highlight doesn't appear to be dynamically set which makes it
+     look ugly.  I think this may be a LessTif bug but for now we just
+     get rid of it. */
+  XtSetArg (al [ac], XmNhighlightThickness, (Dimension)0);ac++;
+
+  /* add any args the user supplied for creation time */
+  lw_add_value_args_to_args (val, al, &ac);
+
+  if (!val->call_data)
+    button = XmCreateLabel (instance->parent, val->name, al, ac);
+  
+  else if (val->type == TOGGLE_TYPE || val->type == RADIO_TYPE)
+    {
+      XtSetArg (al [ac], XmNset, val->selected);	ac++;
+      XtSetArg (al [ac], XmNindicatorType,
+		(val->type == TOGGLE_TYPE ?
+		 XmN_OF_MANY : XmONE_OF_MANY));    ac++;
+      XtSetArg (al [ac], XmNvisibleWhenOff, True); ac++;
+      button = XmCreateToggleButton (instance->parent, val->name, al, ac);
+      XtRemoveAllCallbacks (button, XmNvalueChangedCallback);
+      XtAddCallback (button, XmNvalueChangedCallback, xm_generic_callback,
+		     (XtPointer)instance);
+    }
+  else
+    {
+      button = XmCreatePushButton (instance->parent, val->name, al, ac);
+      XtAddCallback (button, XmNactivateCallback, xm_generic_callback,
+		     (XtPointer)instance);
+    }
+
+  XtManageChild (button);
+
+  return button;
+}
+
 /* Table of functions to create widgets */
 
 widget_creation_entry
@@ -1584,6 +1630,7 @@
   {"vertical-scrollbar",	make_vertical_scrollbar},
   {"horizontal-scrollbar",	make_horizontal_scrollbar},
 #endif
+  {"button",		make_button},
   {NULL, NULL}
 };
 
@@ -1795,6 +1842,12 @@
   do_call (widget, closure, selection);
 }
 
+static void
+xm_pop_down_callback (Widget widget, XtPointer closure, XtPointer call_data)
+{
+  do_call (widget, closure, post_activate);
+}
+
 #ifdef LWLIB_DIALOGS_MOTIF
 
 static void
@@ -1829,14 +1882,6 @@
 #endif 
     do_call (widget, closure, pre_activate);
 }
-
-#if 0
-static void
-xm_pop_down_callback (Widget widget, XtPointer closure, XtPointer call_data)
-{
-  do_call (widget, closure, post_activate);
-}
-#endif /* 0 */
 
 #endif /* LWLIB_MENUBARS_MOTIF */
 
Index: lwlib/lwlib.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lwlib/lwlib.c,v
retrieving revision 1.13
diff -u -r1.13 lwlib.c
--- lwlib/lwlib.c 1998/03/31 20:11:14 1.13
+++ lwlib/lwlib.c 1999/06/25 14:13:27
@@ -155,6 +155,12 @@
       free_widget_value_tree (wv->contents);
       wv->contents = (widget_value *) 0xDEADBEEF;
     }
+  if (wv->args && wv->free_args)
+    {
+      free (wv->args);
+      wv->args = (void *) 0xDEADBEEF;
+      wv->nargs = 0;
+    }
   if (wv->next)
     {
       free_widget_value_tree (wv->next);
@@ -263,6 +269,13 @@
       copy->next = copy_widget_value_tree (val->next, change);
       copy->toolkit_data = NULL;
       copy->free_toolkit_data = False;
+      if (val->nargs)
+	{
+	  copy->args = (ArgList)malloc (sizeof (Arg) * val->nargs);
+	  memcpy (copy->args, val->args, sizeof(Arg) * val->nargs);
+	  copy->nargs = val->nargs;
+	  copy->free_args = True;
+	}
 #ifdef NEED_SCROLLBARS
       copy_scrollbar_values (val, copy);
 #endif
@@ -1298,5 +1311,18 @@
 	      show_one_widget_busy (next->widget, busy);
 	  info->busy = busy;
 	}
+    }
+}
+
+void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset)
+{
+  int i;
+  if (wv->nargs && wv->args)
+    {
+      for (i = 0; i<wv->nargs; i++)
+	{
+	  addto[i + *offset] = wv->args[i];
+	}
+      *offset += wv->nargs;
     }
 }
Index: lwlib/lwlib.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lwlib/lwlib.h,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 lwlib.h
--- lwlib/lwlib.h 1999/02/16 14:27:49 1.4.2.1
+++ lwlib/lwlib.h 1999/06/25 14:13:27
@@ -148,9 +148,14 @@
   scrollbar_values *scrollbar_data;
 
   /* we resource the widget_value structures; this points to the next
-     one on the free list if this one has been deallocated.
-   */
+     one on the free list if this one has been deallocated.  */
   struct _widget_value *free_list;
+
+  /* some things are only possible at creation time. args are applied
+     to widgets at creation time.  */
+  ArgList args;
+  int	nargs;
+  Boolean	free_args;
 } widget_value;
 
 
@@ -201,6 +206,7 @@
 Boolean lw_get_some_values (LWLIB_ID id, widget_value* val);
 void lw_pop_up_all_widgets (LWLIB_ID id);
 void lw_pop_down_all_widgets (LWLIB_ID id);
+void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset);
 
 widget_value *malloc_widget_value (void);
 void free_widget_value (widget_value *);
Index: src/dialog-x.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/dialog-x.c,v
retrieving revision 1.6.2.1
diff -u -r1.6.2.1 dialog-x.c
--- src/dialog-x.c 1998/12/05 16:55:31 1.6.2.1
+++ src/dialog-x.c 1999/06/25 14:13:45
@@ -120,7 +120,7 @@
   widget_value *prev = 0, *kids = 0;
   int n = 0;
   int count = specpdl_depth ();
-  Lisp_Object wv_closure;
+  Lisp_Object wv_closure, gui_item;
 
   CHECK_CONS (desc);
   CHECK_STRING (XCAR (desc));
@@ -163,7 +163,8 @@
       CHECK_VECTOR (button);
       wv = xmalloc_widget_value ();
 
-      if (!button_item_to_widget_value (button, wv, allow_text_p, 1))
+      gui_item = gui_parse_item_keywords (button);
+      if (!button_item_to_widget_value (gui_item, wv, allow_text_p, 1))
 	{
 	  free_widget_value (wv);
 	  continue;
Index: src/event-Xt.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/event-Xt.c,v
retrieving revision 1.41.2.4
diff -u -r1.41.2.4 event-Xt.c
--- src/event-Xt.c 1998/12/14 13:54:29 1.41.2.4
+++ src/event-Xt.c 1999/06/25 14:13:52
@@ -78,6 +78,7 @@
 #include "events-mod.h"
 
 static void enqueue_Xt_dispatch_event (Lisp_Object event);
+static void handle_focus_event_1 (struct frame *f, int in_p);
 
 static struct event_stream *Xt_event_stream;
 
@@ -1046,6 +1047,7 @@
 	  {
 	    XButtonEvent *ev = &x_event->xbutton;
 	    struct frame *frame = x_window_to_frame (d, ev->window);
+
 	    if (! frame)
 	      return 0;	/* not for us */
 	    XSETFRAME (emacs_event->channel, frame);
@@ -1058,7 +1060,11 @@
 	    emacs_event->event.button.button	= ev->button;
 	    emacs_event->event.button.x		= ev->x;
 	    emacs_event->event.button.y		= ev->y;
-
+	    /* because we don't seem to get a FocusIn event for button clicks
+	       when a widget-glyph is selected we will assume that we want the
+	       focus if a button gets pressed. */
+	    if (x_event->type == ButtonPress)
+	      handle_focus_event_1 (frame, 1);
 	  }
       }
     break;
@@ -1304,6 +1310,7 @@
 static void
 handle_focus_event_1 (struct frame *f, int in_p)
 {
+  Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
 #ifdef HAVE_XIM
   XIM_focus_event (f, in_p);
 #endif /* HAVE_XIM */
@@ -1319,7 +1326,22 @@
      Actually, we half handle it: we handle it as far as changing the
      box cursor for redisplay, but we don't call any hooks or do any
      select-frame stuff until after the sit-for.
-   */
+
+     Unfortunately native widgets break the model because they grab
+     the keyboard focus and nothing sets it back again. I cannot find
+     any reasonable way to do this elsewhere so we assert here that
+     the keybpard focus is on the emacs text widget. Menus and dialogs
+     do this in their selection callback, but we don't want that since
+     a button having focus is legitimate. An edit field having focus
+     is mandatory. Weirdly you get a FocusOut event when you glick in
+     a widget-glyph but you don't get a correspondng FocusIn when you
+     click in the frame. Why is this?  */
+  if (in_p && FRAME_X_TEXT_WIDGET (f) != focus_widget)
+    {
+      lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
+			     FRAME_X_TEXT_WIDGET (f));
+    }
+  /* do the generic event-stream stuff. */
   {
     Lisp_Object frm;
     Lisp_Object conser;
@@ -1404,7 +1426,7 @@
 
       /* Bleagh!!!!!!  Apparently some window managers (e.g. MWM)
 	 send synthetic MapNotify events when a window is first
-	 created, EVENT IF IT'S CREATED ICONIFIED OR INVISIBLE.
+	 created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
 	 Or something like that.  We initially tried a different
 	 solution below, but that ran into a different window-
 	 manager bug.
@@ -1579,6 +1601,7 @@
 
     case FocusIn:
     case FocusOut:
+
 #ifdef EXTERNAL_WIDGET
       /* External widget lossage: Ben said:
 	 YUCK.  The only way to make focus changes work properly is to
Index: src/event-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/event-msw.c,v
retrieving revision 1.38.2.11
diff -u -r1.38.2.11 event-msw.c
--- src/event-msw.c 1999/06/13 21:45:13 1.38.2.11
+++ src/event-msw.c 1999/06/25 14:14:00
@@ -1929,7 +1929,6 @@
   case WM_NOTIFY:
     {
       LPNMHDR nmhdr = (LPNMHDR)lParam;
-      int idCtrl = (int)wParam;
 
       if (nmhdr->code ==  TTN_NEEDTEXT)
 	{
Index: src/glyphs-x.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.c,v
retrieving revision 1.49.2.8
diff -u -r1.49.2.8 glyphs-x.c
--- src/glyphs-x.c 1999/04/22 01:22:36 1.49.2.8
+++ src/glyphs-x.c 1999/06/25 14:14:05
@@ -51,6 +51,7 @@
 #include "console-x.h"
 #include "glyphs-x.h"
 #include "objects-x.h"
+#include "gui-x.h"
 #include "xmu.h"
 
 #include "buffer.h"
@@ -58,6 +59,8 @@
 #include "frame.h"
 #include "insdel.h"
 #include "opaque.h"
+#include "gui.h"
+#include "faces.h"
 
 #include "imgproc.h"
 
@@ -97,6 +100,9 @@
 
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
 
+DEFINE_DEVICE_IIFORMAT (x, widget);
+DEFINE_DEVICE_IIFORMAT (x, button);
+
 static void cursor_font_instantiate (Lisp_Object image_instance,
 				     Lisp_Object instantiator,
 				     Lisp_Object pointer_fg,
@@ -336,11 +342,18 @@
     {
       Display *dpy = DEVICE_X_DISPLAY (XDEVICE (p->device));
 
-      if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET
-	  || 
-	  IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
+      if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
 	{
 	  if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
+	    {
+	      XtUnmanageChild (IMAGE_INSTANCE_X_WIDGET_ID (p));
+	      XtDestroyWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
+	      IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
+	    }
+	}
+      else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
+	{
+	  if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
 	    XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
 	  IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
 	}
@@ -1967,8 +1980,16 @@
 static void
 x_unmap_subwindow (struct Lisp_Image_Instance *p)
 {
-  XUnmapWindow (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p)),
-		IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
+  if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
+    {
+      XUnmapWindow 
+	(DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p)), 
+	 IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
+    }
+  else				/* must be a widget */
+    {
+      XtUnmapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
+    }
 }
 
 /* map the subwindow. This is used by redisplay via
@@ -1976,10 +1997,35 @@
 static void
 x_map_subwindow (struct Lisp_Image_Instance *p, int x, int y)
 {
-  XMapWindow (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p)),
-	      IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
-  XMoveWindow (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p)),
-	       IMAGE_INSTANCE_X_SUBWINDOW_ID (p), x, y);
+  if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
+    {
+      Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
+      Screen* screen = IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p);
+      XMapWindow (DisplayOfScreen (screen), subwindow);
+      XMoveWindow (DisplayOfScreen (screen), subwindow, x, y);
+    }
+  else				/* must be a widget */
+    {
+      XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p), 
+		    x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
+		    y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
+      XtMapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
+    }
+}
+
+/* when you click on a widget you may activate another widget this
+   needs to be checked and all appropriate widgets updated */
+static void
+x_update_subwindow (struct Lisp_Image_Instance *p)
+{
+  if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
+    {
+      widget_value* wv = xmalloc_widget_value ();
+      button_item_to_widget_value (IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (p),
+				   wv, 1, 1);
+      lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p), 
+			     wv, 1);
+    }
 }
 
 /* instantiate and x type subwindow */
@@ -2007,11 +2053,7 @@
   dpy = DEVICE_X_DISPLAY (XDEVICE (device));
   xs = DefaultScreenOfDisplay (dpy);
 
-  if (dest_mask & IMAGE_SUBWINDOW_MASK)
-    IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
-  else
-    incompatible_image_types (instantiator, dest_mask,
-			      IMAGE_SUBWINDOW_MASK);
+  IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
 
   pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
 
@@ -2070,6 +2112,119 @@
 		 w, h);
 }
 
+/************************************************************************/
+/*                            widgets                            */
+/************************************************************************/
+
+static void
+x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+		      Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		      int dest_mask, Lisp_Object domain,
+		      CONST char* type, widget_value* wv)
+{
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
+  struct device* d = XDEVICE (device);
+  Lisp_Object frame = FW_FRAME (domain);
+  struct frame* f = XFRAME (frame);
+  XColor fcolor, bcolor;
+  Extbyte* nm=0;
+  Widget wid;
+  Arg al [32];
+  int ac = 0;
+  int id = new_lwlib_id ();
+
+  if (!DEVICE_X_P (d))
+    signal_simple_error ("Not an mswindows device", device);
+
+  /* have to set the type this late in case there is no device
+     instantiation for a widget. But we can go ahead and do it without
+     checking because there is always a generic instantiator. */
+  IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
+
+  if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+    GET_C_STRING_OS_DATA_ALLOCA (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm);
+
+  ii->data = xnew_and_zero (struct x_subwindow_data);
+
+  /* copy any args we were given */
+  if (wv->nargs)
+    lw_add_value_args_to_args (wv, al, &ac);
+
+  /* add our own arguments */
+  pixel = FACE_FOREGROUND 
+    (IMAGE_INSTANCE_WIDGET_FACE (ii),
+     IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+  fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
+  pixel = FACE_BACKGROUND
+    (IMAGE_INSTANCE_WIDGET_FACE (ii),
+     IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+  bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
+
+  XtSetArg (al [ac], XtNbackground, bcolor.pixel);		ac++;
+  XtSetArg (al [ac], XtNforeground, fcolor.pixel);		ac++;
+  XtSetArg (al [ac], XtNfont, (void*)FONT_INSTANCE_X_FONT 
+	    (XFONT_INSTANCE (widget_face_font_info 
+			     (domain, 
+			      IMAGE_INSTANCE_WIDGET_FACE (ii),
+			      0, 0))));			ac++;
+
+  wv->nargs = ac;
+  wv->args = al;
+  
+  wid = lw_create_widget (type, wv->name, id, wv, FRAME_X_CONTAINER_WIDGET (f),
+			  False, 0, popup_selection_callback, 0);
+
+  IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
+
+  /* because the EmacsManager is the widgets parent we have to
+     offset the redisplay of the widget by the amount the text
+     widget is inside the manager. */
+  ac = 0;
+  XtSetArg (al [ac], XtNwidth, 
+	    (Dimension)IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii)); ac++;
+  XtSetArg (al [ac], XtNheight, 
+	    (Dimension)IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); ac++;
+  XtSetValues (wid, al, ac);
+  /* finally get offsets in the frame */
+  ac = 0;
+  XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
+  XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
+  XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
+
+  IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid; 
+
+  free_widget_value (wv);
+}
+
+/* Instantiate a button widget. Unfortunately instantiated widgets are
+   particular to a frame since they need to have a parent. It's not
+   like images where you just select the image into the context you
+   want to display it in and BitBlt it. So images instances can have a
+   many-to-one relationship with things you see, whereas widgets can
+   only be one-to-one (i.e. per frame) */
+static void
+x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+		      Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		      int dest_mask, Lisp_Object domain)
+{
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+  Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
+  widget_value* wv = xmalloc_widget_value ();
+
+  button_item_to_widget_value (gui, wv, 1, 1);
+
+  if (!NILP (glyph))
+    {
+      if (!IMAGE_INSTANCEP (glyph))
+	glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
+    }
+
+  x_widget_instantiate (image_instance, instantiator, pointer_fg,
+			pointer_bg, dest_mask, domain, "button", wv);
+}
+
 
 /************************************************************************/
 /*                            initialization                            */
@@ -2098,6 +2253,7 @@
   CONSOLE_HAS_METHOD (x, unmap_subwindow);
   CONSOLE_HAS_METHOD (x, map_subwindow);
   CONSOLE_HAS_METHOD (x, resize_subwindow);
+  CONSOLE_HAS_METHOD (x, update_subwindow);
 }
 
 void
@@ -2113,6 +2269,15 @@
   INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
   IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
 
+  /* button widget */
+  INITIALIZE_DEVICE_IIFORMAT (x, button);
+  /*  IIFORMAT_HAS_DEVMETHOD (x, button, property);*/
+  IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
+
+  INITIALIZE_DEVICE_IIFORMAT (x, widget);
+  /*IIFORMAT_HAS_DEVMETHOD (x, widget, property);*/
+  /*IIFORMAT_HAS_DEVMETHOD (x, widget, set_property);*/
+
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
 
   IIFORMAT_HAS_METHOD (cursor_font, validate);
@@ -2159,6 +2324,8 @@
 the environment variable XBMLANGPATH is set, it is consulted first).
 */ );
   Vx_bitmap_file_path = Qnil;
+
+  Fprovide (Qbutton);
 }
 
 void
Index: src/glyphs-x.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.h,v
retrieving revision 1.4.2.2
diff -u -r1.4.2.2 glyphs-x.h
--- src/glyphs-x.h 1998/12/25 02:37:28 1.4.2.2
+++ src/glyphs-x.h 1999/06/25 14:14:07
@@ -80,22 +80,48 @@
 
 struct x_subwindow_data
 {
-  Screen *xscreen;
-  Window parent_window;
+  union
+  {
+    struct
+    {
+      Screen *xscreen;
+      Window parent_window;
+    } sub;
+    struct 
+    {
+      Position x_offset;
+      Position y_offset;
+      LWLIB_ID	id;
+    } wid;
+  } data;
 };
 
 #define X_SUBWINDOW_INSTANCE_DATA(i) ((struct x_subwindow_data *) (i)->data)
 
 #define IMAGE_INSTANCE_X_SUBWINDOW_SCREEN(i) \
-  (X_SUBWINDOW_INSTANCE_DATA (i)->xscreen)
+  (X_SUBWINDOW_INSTANCE_DATA (i)->data.sub.xscreen)
 #define IMAGE_INSTANCE_X_SUBWINDOW_PARENT(i) \
-  (X_SUBWINDOW_INSTANCE_DATA (i)->parent_window)
+  (X_SUBWINDOW_INSTANCE_DATA (i)->data.sub.parent_window)
+#define IMAGE_INSTANCE_X_WIDGET_XOFFSET(i) \
+  (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.x_offset)
+#define IMAGE_INSTANCE_X_WIDGET_YOFFSET(i) \
+  (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.y_offset)
+#define IMAGE_INSTANCE_X_WIDGET_LWID(i) \
+  (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.id)
 #define XIMAGE_INSTANCE_X_SUBWINDOW_PARENT(i) \
   IMAGE_INSTANCE_X_SUBWINDOW_PARENT (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_X_SUBWINDOW_SCREEN(i) \
   IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_X_WIDGET_XOFFSET(i) \
+  IMAGE_INSTANCE_X_WIDGET_XOFFSET (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_X_WIDGET_YOFFSET(i) \
+  IMAGE_INSTANCE_X_WIDGET_YOFFSET (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_X_WIDGET_LWID(i) \
+  IMAGE_INSTANCE_X_WIDGET_LWID (XIMAGE_INSTANCE (i))
 #define IMAGE_INSTANCE_X_SUBWINDOW_ID(i) \
   ((Window) IMAGE_INSTANCE_SUBWINDOW_ID (i))
+#define IMAGE_INSTANCE_X_WIDGET_ID(i) \
+  ((Widget) IMAGE_INSTANCE_SUBWINDOW_ID (i))
 
 #endif /* HAVE_X_WINDOWS */
 #endif /* _XEMACS_GLYPHS_X_H_ */
Index: src/gui-x.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui-x.c,v
retrieving revision 1.14.2.4
diff -u -r1.14.2.4 gui-x.c
--- src/gui-x.c 1999/06/22 18:02:57 1.14.2.4
+++ src/gui-x.c 1999/06/25 14:14:07
@@ -35,11 +35,10 @@
 #include "device.h"
 #include "frame.h"
 #include "gui.h"
+#include "redisplay.h"
 #include "opaque.h"
 
-#ifdef HAVE_POPUPS
 Lisp_Object Qmenu_no_selection_hook;
-#endif
 
 /* we need a unique id for each popup menu, dialog box, and scrollbar */
 static unsigned int lwlib_id_tick;
@@ -59,8 +58,6 @@
 }
 
 
-#ifdef HAVE_POPUPS
-
 struct mark_widget_value_closure
 {
   void (*markobj) (Lisp_Object);
@@ -259,7 +256,10 @@
       arg = Qmenu_no_selection_hook;
     }
   else
-    get_gui_callback (data, &fn, &arg);
+    {
+      MARK_SUBWINDOWS_CHANGED;
+      get_gui_callback (data, &fn, &arg);
+    }
 
   /* This is the timestamp used for asserting focus so we need to get an
      up-to-date value event if no events has been dispatched to emacs
@@ -315,139 +315,44 @@
   return NULL;
 }
 
-/* set menu accelerator key to first underlined character in menu name */
-
-Lisp_Object
-menu_name_to_accelerator (char *name)
-{
-  while (*name) {
-    if (*name=='%') {
-      ++name;
-      if (!(*name))
-	return Qnil;
-      if (*name=='_' && *(name+1))
-	{
-	  int accelerator = (int) (unsigned char) (*(name+1));
-	  return make_char (tolower (accelerator));
-	}
-    }
-    ++name;
-  }
-  return Qnil;
-}
 
 /* This does the dirty work.  gc_currently_forbidden is 1 when this is called.
  */
-
 int
-button_item_to_widget_value (Lisp_Object desc, widget_value *wv,
+button_item_to_widget_value (Lisp_Object gui_item, widget_value *wv,
 			     int allow_text_field_p, int no_keys_p)
 {
   /* !!#### This function has not been Mule-ized */
   /* This function cannot GC because gc_currently_forbidden is set when
      it's called */
-  Lisp_Object name       = Qnil;
-  Lisp_Object callback   = Qnil;
-  Lisp_Object suffix     = Qnil;
-  Lisp_Object active_p   = Qt;
-  Lisp_Object include_p  = Qt;
-  Lisp_Object selected_p = Qnil;
-  Lisp_Object keys       = Qnil;
-  Lisp_Object style      = Qnil;
-  Lisp_Object config_tag = Qnil;
-  Lisp_Object accel = Qnil;
-  int length = XVECTOR_LENGTH (desc);
-  Lisp_Object *contents = XVECTOR_DATA (desc);
-  int plist_p;
-  int selected_spec = 0, included_spec = 0;
-
-  if (length < 2)
-    signal_simple_error ("Button descriptors must be at least 2 long", desc);
-
-  /* length 2:		[ "name" callback ]
-     length 3:		[ "name" callback active-p ]
-     length 4:		[ "name" callback active-p suffix ]
-     		   or	[ "name" callback keyword  value  ]
-     length 5+:		[ "name" callback [ keyword value ]+ ]
-   */
-  plist_p = (length >= 5 || (length > 2 && KEYWORDP (contents [2])));
-
-  if (!plist_p && length > 2)
-    /* the old way */
-    {
-      name = contents [0];
-      callback = contents [1];
-      active_p = contents [2];
-      if (length == 4)
-	suffix = contents [3];
-    }
-  else
-    {
-      /* the new way */
-      int i;
-      if (length & 1)
-	signal_simple_error (
-		"Button descriptor has an odd number of keywords and values",
-			     desc);
-
-      name = contents [0];
-      callback = contents [1];
-      for (i = 2; i < length;)
-	{
-	  Lisp_Object key = contents [i++];
-	  Lisp_Object val = contents [i++];
-	  if (!KEYWORDP (key))
-	    signal_simple_error_2 ("Not a keyword", key, desc);
-
-	  if      (EQ (key, Q_active))   active_p   = val;
-	  else if (EQ (key, Q_suffix))   suffix     = val;
-	  else if (EQ (key, Q_keys))     keys       = val;
-	  else if (EQ (key, Q_style))    style      = val;
-	  else if (EQ (key, Q_selected)) selected_p = val, selected_spec = 1;
-	  else if (EQ (key, Q_included)) include_p  = val, included_spec = 1;
-	  else if (EQ (key, Q_config))	 config_tag = val;
-	  else if (EQ (key, Q_accelerator))
-	    {
-	      if ( SYMBOLP (val)
-		   || CHARP (val))
-		accel = val;
-	      else
-		signal_simple_error ("Bad keyboard accelerator", val);
-	    }
-	  else if (EQ (key, Q_filter))
-	    signal_simple_error(":filter keyword not permitted on leaf nodes", desc);
-	  else
-	    signal_simple_error_2 ("Unknown menu item keyword", key, desc);
-	}
-    }
+  struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui_item);
+
+  if (!NILP (pgui->filter))
+    signal_simple_error(":filter keyword not permitted on leaf nodes",
gui_item);
 
 #ifdef HAVE_MENUBARS
-  if ((!NILP (config_tag) && NILP (Fmemq (config_tag, Vmenubar_configuration)))
-      || (included_spec && NILP (Feval (include_p))))
+  if (!gui_item_included_p (gui_item, Vmenubar_configuration))
     {
       /* the include specification says to ignore this item. */
       return 0;
     }
 #endif /* HAVE_MENUBARS */
 
-  CHECK_STRING (name);
-  wv->name = (char *) XSTRING_DATA (name);
+  CHECK_STRING (pgui->name);
+  wv->name = (char *) XSTRING_DATA (pgui->name);
+  wv->accel = LISP_TO_VOID (gui_item_accelerator (gui_item));
 
-  if (NILP (accel))
-    accel = menu_name_to_accelerator (wv->name);
-  wv->accel = LISP_TO_VOID (accel);
-
-  if (!NILP (suffix))
+  if (!NILP (pgui->suffix))
     {
       CONST char *const_bogosity;
       Lisp_Object suffix2;
 
       /* Shortcut to avoid evaluating suffix each time */
-      if (STRINGP (suffix))
-	suffix2 = suffix;
+      if (STRINGP (pgui->suffix))
+	suffix2 = pgui->suffix;
       else
 	{
-	  suffix2 = Feval (suffix);
+	  suffix2 = Feval (pgui->suffix);
 	  CHECK_STRING (suffix2);
 	}
 
@@ -456,10 +361,10 @@
       wv->value = xstrdup (wv->value);
     }
 
-  wv_set_evalable_slot (wv->enabled, active_p);
-  wv_set_evalable_slot (wv->selected, selected_p);
+  wv_set_evalable_slot (wv->enabled, pgui->active);
+  wv_set_evalable_slot (wv->selected, pgui->selected);
 
-  wv->call_data = LISP_TO_VOID (callback);
+  wv->call_data = LISP_TO_VOID (pgui->callback);
 
   if (no_keys_p
 #ifdef HAVE_MENUBARS
@@ -467,28 +372,28 @@
 #endif
       )
     wv->key = 0;
-  else if (!NILP (keys))	/* Use this string to generate key bindings */
+  else if (!NILP (pgui->keys))	/* Use this string to generate key bindings */
     {
-      CHECK_STRING (keys);
-      keys = Fsubstitute_command_keys (keys);
-      if (XSTRING_LENGTH (keys) > 0)
-	wv->key = xstrdup ((char *) XSTRING_DATA (keys));
+      CHECK_STRING (pgui->keys);
+      pgui->keys = Fsubstitute_command_keys (pgui->keys);
+      if (XSTRING_LENGTH (pgui->keys) > 0)
+	wv->key = xstrdup ((char *) XSTRING_DATA (pgui->keys));
       else
 	wv->key = 0;
     }
-  else if (SYMBOLP (callback))	/* Show the binding of this command. */
+  else if (SYMBOLP (pgui->callback))	/* Show the binding of this command. */
     {
       char buf [1024];
       /* #### Warning, dependency here on current_buffer and point */
-      where_is_to_char (callback, buf);
+      where_is_to_char (pgui->callback, buf);
       if (buf [0])
 	wv->key = xstrdup (buf);
       else
 	wv->key = 0;
     }
 
-  CHECK_SYMBOL (style);
-  if (NILP (style))
+  CHECK_SYMBOL (pgui->style);
+  if (NILP (pgui->style))
     {
       /* If the callback is nil, treat this item like unselectable text.
 	 This way, dashes will show up as a separator. */
@@ -515,13 +420,13 @@
 	    wv->type = BUTTON_TYPE;
 	}
     }
-  else if (EQ (style, Qbutton))
+  else if (EQ (pgui->style, Qbutton))
     wv->type = BUTTON_TYPE;
-  else if (EQ (style, Qtoggle))
+  else if (EQ (pgui->style, Qtoggle))
     wv->type = TOGGLE_TYPE;
-  else if (EQ (style, Qradio))
+  else if (EQ (pgui->style, Qradio))
     wv->type = RADIO_TYPE;
-  else if (EQ (style, Qtext))
+  else if (EQ (pgui->style, Qtext))
     {
       wv->type = TEXT_TYPE;
 #if 0
@@ -530,19 +435,18 @@
 #endif
     }
   else
-    signal_simple_error_2 ("Unknown style", style, desc);
+    signal_simple_error_2 ("Unknown style", pgui->style, gui_item);
 
   if (!allow_text_field_p && (wv->type == TEXT_TYPE))
-    signal_simple_error ("Text field not allowed in this context", desc);
+    signal_simple_error ("Text field not allowed in this context", gui_item);
 
-  if (selected_spec && EQ (style, Qtext))
+  if (!NILP (pgui->selected) && EQ (pgui->style, Qtext))
     signal_simple_error (
-         ":selected only makes sense with :style toggle, radio or button",
-			 desc);
+			 ":selected only makes sense with :style toggle, radio or button",
+			 gui_item);
   return 1;
 }
 
-#endif /* HAVE_POPUPS */
 
 /* This is a kludge to make sure emacs can only link against a version of
    lwlib that was compiled in the right way.  Emacs references symbols which
@@ -600,9 +504,7 @@
 void
 syms_of_gui_x (void)
 {
-#ifdef HAVE_POPUPS
   defsymbol (&Qmenu_no_selection_hook, "menu-no-selection-hook");
-#endif
 }
 
 void
@@ -610,7 +512,6 @@
 {
   lwlib_id_tick = (1<<16);	/* start big, to not conflict with Energize */
 
-#ifdef HAVE_POPUPS
   popup_up_p = 0;
 
   Vpopup_callbacks = Qnil;
@@ -625,7 +526,6 @@
 */ );
 #endif
   Fset (Qmenu_no_selection_hook, Qnil);
-#endif /* HAVE_POPUPS */
 
   /* this makes only safe calls as in emacs.c */
   sanity_check_lwlib ();
Index: src/gui.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui.c,v
retrieving revision 1.10.2.7
diff -u -r1.10.2.7 gui.c
--- src/gui.c 1999/06/22 18:02:57 1.10.2.7
+++ src/gui.c 1999/06/25 14:14:09
@@ -122,6 +122,13 @@
   else if (EQ (key, Q_callback))	 pgui_item->callback     = val;
   else if (EQ (key, Q_key_sequence)) ;   /* ignored for FSF compatability */
   else if (EQ (key, Q_label)) ;   /* ignored for 21.0 implement in 21.2  */
+  else if (EQ (key, Q_accelerator))
+    {
+      if (SYMBOLP (val) || CHARP (val))
+	pgui_item->accelerator = val;
+      else if (ERRB_EQ (errb, ERROR_ME))
+	signal_simple_error ("Bad keyboard accelerator", val);
+    }
   else if (ERRB_EQ (errb, ERROR_ME))
     signal_simple_error_2 ("Unknown keyword in gui item", key,
pgui_item->name);
 }
@@ -141,6 +148,7 @@
   lp->style    = Qnil;
   lp->selected = Qnil;
   lp->keys     = Qnil;
+  lp->accelerator     = Qnil;
 }
 
 Lisp_Object
@@ -262,6 +270,8 @@
     Fplist_put (plist, Q_selected, pgui_item->selected);
   if (!NILP (pgui_item->keys))
     Fplist_put (plist, Q_keys, pgui_item->keys);
+  if (!NILP (pgui_item->accelerator))
+    Fplist_put (plist, Q_accelerator, pgui_item->accelerator);
 }
 
 /*
@@ -278,6 +288,41 @@
 	  || !NILP (Feval (XGUI_ITEM (gui_item)->active)));
 }
 
+/* set menu accelerator key to first underlined character in menu name */
+Lisp_Object
+gui_item_accelerator (Lisp_Object gui_item)
+{
+  struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui_item);
+  
+  if (!NILP (pgui->accelerator))
+    return pgui->accelerator;
+
+  else
+    return pgui->name;
+}
+
+Lisp_Object
+gui_name_accelerator (Lisp_Object nm)
+{
+  /* !!#### This function has not been Mule-ized */
+  char* name = (char*)XSTRING_DATA (nm);
+
+  while (*name) {
+    if (*name=='%') {
+      ++name;
+      if (!(*name))
+	return Qnil;
+      if (*name=='_' && *(name+1))
+	{
+	  int accelerator = (int) (unsigned char) (*(name+1));
+	  return make_char (tolower (accelerator));
+	}
+    }
+    ++name;
+  }
+  return Qnil;
+}
+
 /*
  * Decide whether a GUI item is selected by evaluating its :selected form
  * if any
@@ -427,6 +472,7 @@
 
   markobj (p->name);
   markobj (p->callback);
+  markobj (p->config);
   markobj (p->suffix);
   markobj (p->active);
   markobj (p->included);
@@ -435,6 +481,7 @@
   markobj (p->style);
   markobj (p->selected);
   markobj (p->keys);
+  markobj (p->accelerator);
 
   return Qnil;
 }
@@ -492,6 +539,8 @@
 	EQ (p1->style, p2->style)
 	&&
 	EQ (p1->selected, p2->selected)
+	&&
+	EQ (p1->accelerator, p2->accelerator)
 	&&
 	EQ (p1->keys, p2->keys)))
     return 0;
Index: src/gui.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui.h,v
retrieving revision 1.6.2.4
diff -u -r1.6.2.4 gui.h
--- src/gui.h 1999/06/13 21:45:15 1.6.2.4
+++ src/gui.h 1999/06/25 14:14:09
@@ -60,6 +60,7 @@
   Lisp_Object style;		/* Symbol */
   Lisp_Object selected;		/* Form */
   Lisp_Object keys;		/* String */
+  Lisp_Object accelerator;	/* Char or Symbol  */
 };
 
 extern Lisp_Object Q_accelerator, Q_active, Q_config, Q_filter, Q_included;
@@ -74,6 +75,8 @@
 int  gui_item_active_p (Lisp_Object);
 int  gui_item_selected_p (Lisp_Object);
 int  gui_item_included_p (Lisp_Object, Lisp_Object into);
+Lisp_Object gui_item_accelerator (Lisp_Object gui_item);
+Lisp_Object gui_name_accelerator (Lisp_Object name);
 int  gui_item_id_hash (Lisp_Object, Lisp_Object gui_item, int);
 unsigned int gui_item_display_flush_left  (Lisp_Object pgui_item,
 					   char* buf, Bytecount buf_len);
@@ -88,5 +91,7 @@
 #define GUI_ITEM_ID_MIN(s) (s * 0x2000)
 #define GUI_ITEM_ID_MAX(s) (0x1FFF + GUI_ITEM_ID_MIN (s))
 #define GUI_ITEM_ID_BITS(x,s) (((x) & 0x1FFF) + GUI_ITEM_ID_MIN (s))
+
+#define MAX_MENUITEM_LENGTH 128
 
 #endif /* _XEMACS_GUI_H_ */
Index: src/menubar-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/menubar-msw.c,v
retrieving revision 1.16.2.6
diff -u -r1.16.2.6 menubar-msw.c
--- src/menubar-msw.c 1999/06/13 21:45:15 1.16.2.6
+++ src/menubar-msw.c 1999/06/25 14:14:12
@@ -116,8 +116,6 @@
 #define MENU_ITEM_ID_BITS(x) (((x) & 0x7FFF) | 0x8000)
 static HMENU top_level_menu;
 
-#define MAX_MENUITEM_LENGTH 128
-
 /*
  * This returns Windows-style menu item string:
  * "Left Flush\tRight Flush"
Index: src/menubar-x.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/menubar-x.c,v
retrieving revision 1.18.2.6
diff -u -r1.18.2.6 menubar-x.c
--- src/menubar-x.c 1999/05/06 10:16:59 1.18.2.6
+++ src/menubar-x.c 1999/06/25 14:14:13
@@ -131,7 +131,8 @@
     }
   else if (VECTORP (desc))
     {
-      if (!button_item_to_widget_value (desc, wv, 1,
+      Lisp_Object gui_item = gui_parse_item_keywords (desc);
+      if (!button_item_to_widget_value (gui_item, wv, 1,
 					(menu_type == MENUBAR_TYPE
 					 && depth <= 1)))
 	{
@@ -157,7 +158,7 @@
 	  wv->enabled = 1;
 	  wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc)));
 
-	  accel = menu_name_to_accelerator (wv->name);
+	  accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc)));
 	  wv->accel = LISP_TO_VOID (accel);
 
 	  desc = Fcdr (desc);
Index: tests/glyph-test.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/tests/Attic/glyph-test.el,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 glyph-test.el
--- tests/glyph-test.el 1999/06/13 21:45:16 1.1.2.5
+++ tests/glyph-test.el 1999/06/25 14:14:13
@@ -17,15 +17,26 @@
  (make-extent (point) (point))
  (make-glyph [button :descriptor ["ok" (setq ok-select nil) :style radio 
 				  :selected (not ok-select)]]))
+;; toggle button
+(set-extent-begin-glyph 
+ (make-extent (point) (point))
+ (make-glyph [button :descriptor ["ok" (setq ok-select nil) :style toggle 
+				  :selected (not ok-select)]]))
+(set-extent-begin-glyph 
+ (make-extent (point) (point))
+ (make-glyph [button :descriptor ["ok" :style toggle 
+				  :callback 
+				  (setq ok-select (not ok-select))
+				  :selected ok-select]]))
+
 ;; normal pushbutton
 (set-extent-begin-glyph 
  (make-extent (point) (point))
  (setq pbutton (make-glyph 
-		[button :width 10 :height 2 
+		[button :width 10 :height 2
 			:face modeline-mousable
 			:descriptor "ok" :callback foo 
 			:selected t])))
-
 ;; tree view
 (set-extent-begin-glyph 
  (make-extent (point) (point))
@@ -111,6 +122,6 @@
 ; (make-glyph [scrollbar :width 50 :height 20 :descriptor ["Hello"]]))
 
 ;; generic subwindow
-(setq sw (make-glyph [subwindow :pixel-width 50 :pixel-height 50]))
+(setq sw (make-glyph [subwindow :pixel-width 50 :pixel-height 70]))
 (set-extent-begin-glyph (make-extent (point) (point)) sw)
 
--------------------------------------------------------------
Dr Andy Piper
Senior Consultant Architect, BEA Systems Ltd