]> code.delx.au - gnu-emacs/blobdiff - src/xfaces.c
(mark_byte_stack): Use XMARKBIT and XMARK.
[gnu-emacs] / src / xfaces.c
index c50a8463744327d01f4ad832906d8bf6f929b563..52b9f1b5841a0e15915e55144d8970b2d26ee30b 100644 (file)
@@ -177,9 +177,9 @@ Boston, MA 02111-1307, USA.  */
 
 #define SCALABLE_FONTS 1
 
+#include <config.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <config.h>
 #include "lisp.h"
 #include "charset.h"
 #include "frame.h"
@@ -187,6 +187,10 @@ Boston, MA 02111-1307, USA.  */
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #include "fontset.h"
+#ifdef USE_MOTIF
+#include <Xm/Xm.h>
+#include <Xm/XmStrDefs.h>
+#endif /* USE_MOTIF */
 #endif
 
 #ifdef MSDOS
@@ -219,7 +223,6 @@ Boston, MA 02111-1307, USA.  */
 #endif /* HAVE_X_WINDOWS */
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <ctype.h>
 #include "keyboard.h"
 
@@ -286,7 +289,7 @@ Lisp_Object Qframe_update_face_colors;
 /* Names of basic faces.  */
 
 Lisp_Object Qdefault, Qmode_line, Qtool_bar, Qregion, Qfringe;
-Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse;;
+Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu;
 
 /* The symbol `face-alias'.  A symbols having that property is an
    alias for another face.  Value of the property is the name of
@@ -346,7 +349,7 @@ extern Lisp_Object Qmouse_face;
 
 /* Error symbol for wrong_type_argument in load_pixmap.  */
 
-Lisp_Object Qpixmap_spec_p;
+Lisp_Object Qbitmap_spec_p;
 
 /* Alist of global face definitions.  Each element is of the form
    (FACE . LFACE) where FACE is a symbol naming a face and LFACE
@@ -397,6 +400,7 @@ static int ngcs;
 struct font_name;
 struct table_entry;
 
+static Lisp_Object resolve_face_name P_ ((Lisp_Object));
 static int may_use_scalable_font_p P_ ((struct font_name *, char *));
 static void set_font_frame_param P_ ((Lisp_Object, Lisp_Object));
 static int better_font_p P_ ((int *, struct font_name *, struct font_name *,
@@ -412,7 +416,6 @@ static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *)
 static char *xstrdup P_ ((char *));
 static unsigned char *xstrlwr P_ ((unsigned char *));
 static void signal_error P_ ((char *, Lisp_Object));
-static void add_to_log P_ ((struct frame *, char *, Lisp_Object, Lisp_Object));
 static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
 static void load_face_font_or_fontset P_ ((struct frame *, struct face *, char *, int));
 static void load_face_colors P_ ((struct frame *, struct face *, Lisp_Object *));
@@ -593,50 +596,6 @@ signal_error (s, arg)
 }
 
 
-/* Display a message with format string FORMAT and arguments ARG1 and
-   ARG2 on frame F.  Used to display errors if fonts, bitmaps, colors 
-   etc. for a realized face on frame F cannot be loaded.  (If we would
-   signal an error in these cases, we would end up in an infinite
-   recursion because this would stop realization, and the redisplay
-   triggered by the signal would try to realize that same face again.)
-
-   If basic faces of F are not realized, just add the message to the
-   messages buffer "*Messages*".  Because Fmessage calls
-   echo_area_display which tries to realize basic faces again, we would
-   otherwise also end in an infinite recursion.  */
-
-static void
-add_to_log (f, format, arg1, arg2)
-     struct frame *f;
-     char *format;
-     Lisp_Object arg1, arg2;
-{
-  Lisp_Object args[3];
-  Lisp_Object nargs;
-  Lisp_Object msg;
-  char *buffer;
-  extern int waiting_for_input;
-
-  /* Function note_mouse_highlight calls face_at_buffer_position which
-     may realize a face.  If some attribute of that face is invalid,
-     say an invalid color, don't display an error to avoid calling
-     Lisp from XTread_socket.  */
-  if (waiting_for_input)
-    return;
-
-  nargs = make_number (DIM (args));
-  args[0] = build_string (format);
-  args[1] = arg1;
-  args[2] = arg2;
-  msg = Fformat (nargs, args);
-
-  /* Log the error, but don't display it in the echo area.  This
-     proves to be annoying in many cases.  */
-  buffer = LSTRDUPA (msg);
-  message_dolog (buffer, strlen (buffer), 1, 0);
-}
-
-
 /* If FRAME is nil, return a pointer to the selected frame.
    Otherwise, check that FRAME is a live frame, and return a pointer
    to it.  NPARAM is the parameter number of FRAME, for
@@ -878,32 +837,53 @@ clear_font_table (f)
 
 #ifdef HAVE_X_WINDOWS
 
-DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
-  "Non-nil if OBJECT is a valid pixmap specification.\n\
-A pixmap specification is either a string, or a list (WIDTH HEIGHT DATA)\n\
-where WIDTH is the pixel width of the pixmap, HEIGHT is its height,\n\
-and DATA contains the bits of the pixmap.")
+DEFUN ("bitmap-spec-p", Fbitmap_spec_p, Sbitmap_spec_p, 1, 1, 0,
+  "Value is non-nil if OBJECT is a valid bitmap specification.\n\
+A bitmap specification is either a string, a file name, or a list\n\
+(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,\n\
+HEIGHT is its height, and DATA is a string containing the bits of\n\
+the pixmap.  Bits are stored row by row, each row occupies\n\
+(WIDTH + 7)/8 bytes.")
   (object)
      Lisp_Object object;
 {
-  Lisp_Object height, width;
+  int pixmap_p = 0;
+  
+  if (STRINGP (object))
+    /* If OBJECT is a string, it's a file name.  */
+    pixmap_p = 1;
+  else if (CONSP (object))
+    {
+      /* Otherwise OBJECT must be (WIDTH HEIGHT DATA), WIDTH and
+        HEIGHT must be integers > 0, and DATA must be string large
+        enough to hold a bitmap of the specified size.  */
+      Lisp_Object width, height, data;
 
-  return ((STRINGP (object)
-          || (CONSP (object)
-              && CONSP (XCONS (object)->cdr)
-              && CONSP (XCONS (XCONS (object)->cdr)->cdr)
-              && NILP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->cdr)
-              && (width = XCONS (object)->car, INTEGERP (width))
-              && (height = XCONS (XCONS (object)->cdr)->car,
-                  INTEGERP (height))
-              && STRINGP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)
-              && XINT (width) > 0
-              && XINT (height) > 0
-              /* The string must have enough bits for width * height.  */
-              && ((XSTRING (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)->size
-                   * (BITS_PER_INT / sizeof (int)))
-                  >= XFASTINT (width) * XFASTINT (height))))
-         ? Qt : Qnil);
+      height = width = data = Qnil;
+      
+      if (CONSP (object))
+       {
+         width = XCAR (object);
+         object = XCDR (object);
+         if (CONSP (object))
+           {
+             height = XCAR (object);
+             object = XCDR (object);
+             if (CONSP (object))
+               data = XCAR (object);
+           }
+       }
+
+      if (NATNUMP (width) && NATNUMP (height) && STRINGP (data))
+       {
+         int bytes_per_row = ((XFASTINT (width) + BITS_PER_CHAR - 1)
+                              / BITS_PER_CHAR);
+         if (STRING_BYTES (XSTRING (data)) >= bytes_per_row * height)
+           pixmap_p = 1;
+       }
+    }
+
+  return pixmap_p ? Qt : Qnil;
 }
 
 
@@ -926,9 +906,9 @@ load_pixmap (f, name, w_ptr, h_ptr)
   if (NILP (name))
     return 0;
 
-  tem = Fpixmap_spec_p (name);
+  tem = Fbitmap_spec_p (name);
   if (NILP (tem))
-    wrong_type_argument (Qpixmap_spec_p, name);
+    wrong_type_argument (Qbitmap_spec_p, name);
 
   BLOCK_INPUT;
   if (CONSP (name))
@@ -954,7 +934,7 @@ load_pixmap (f, name, w_ptr, h_ptr)
 
   if (bitmap_id < 0)
     {
-      add_to_log (f, "Invalid or undefined bitmap %s", name, Qnil);
+      add_to_log ("Invalid or undefined bitmap %s", name, Qnil);
       bitmap_id = 0;
 
       if (w_ptr)
@@ -1072,10 +1052,10 @@ load_face_font_or_fontset (f, face, font_name, fontset)
        }
     }
   else if (fontset >= 0)
-    add_to_log (f, "Unable to load ASCII font of fontset %d",
+    add_to_log ("Unable to load ASCII font of fontset %d",
                make_number (fontset), Qnil);
   else if (font_name)
-    add_to_log (f, "Unable to load font %s",
+    add_to_log ("Unable to load font %s",
                build_string (font_name), Qnil);
 }
 
@@ -1197,7 +1177,7 @@ load_color (f, face, name, target_index)
      to the values in an existing cell. */
   if (!defined_color (f, XSTRING (name)->data, &color, 1))
     {
-      add_to_log (f, "Unable to load color %s", name, Qnil);
+      add_to_log ("Unable to load color %s", name, Qnil);
       
       switch (target_index)
        {
@@ -1274,7 +1254,7 @@ load_face_colors (f, face, attrs)
      "supported" as background because we are supposed to use stipple
      for them.  */
   if (!face_color_supported_p (f, XSTRING (bg)->data, 0)
-      && !NILP (Fpixmap_spec_p (Vface_default_stipple)))
+      && !NILP (Fbitmap_spec_p (Vface_default_stipple)))
     {
       x_destroy_bitmap (f, face->stipple);
       face->stipple = load_pixmap (f, Vface_default_stipple,
@@ -1418,7 +1398,7 @@ load_color (f, face, name, target_index)
       if (INTEGERP (color))
        return (unsigned long)XINT (color);
 
-      add_to_log (f, "Unable to load color %s", name, Qnil);
+      add_to_log ("Unable to load color %s", name, Qnil);
       
       switch (target_index)
        {
@@ -2587,7 +2567,7 @@ check_lface_attrs (attrs)
 #ifdef HAVE_WINDOW_SYSTEM
   xassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
           || SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
-          || !NILP (Fpixmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
+          || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
 #endif
 }
 
@@ -2613,6 +2593,32 @@ check_lface (lface)
 #endif /* GLYPH_DEBUG == 0 */
 
 
+/* Resolve face name FACE_NAME.  If FACE_NAME Is a string, intern it
+   to make it a symvol.  If FACE_NAME is an alias for another face,
+   return that face's name.  */
+
+static Lisp_Object
+resolve_face_name (face_name)
+     Lisp_Object face_name;
+{
+  Lisp_Object aliased;
+  
+  if (STRINGP (face_name))
+    face_name = intern (XSTRING (face_name)->data);
+
+  for (;;)
+    {
+      aliased = Fget (face_name, Qface_alias);
+      if (NILP (aliased))
+       break;
+      else
+       face_name = aliased;
+    }
+
+  return face_name;
+}
+
+
 /* Return the face definition of FACE_NAME on frame F.  F null means
    return the global definition.  FACE_NAME may be a string or a
    symbol (apparently Emacs 20.2 allows strings as face names in face
@@ -2628,16 +2634,9 @@ lface_from_face_name (f, face_name, signal_p)
      Lisp_Object face_name;
      int signal_p;
 {
-  Lisp_Object lface, alias;
-
-  if (STRINGP (face_name))
-    face_name = intern (XSTRING (face_name)->data);
+  Lisp_Object lface;
 
-  /* If FACE_NAME is an alias for another face, return the definition
-     of the aliased face.  */
-  alias = Fget (face_name, Qface_alias);
-  if (!NILP (alias))
-    face_name = alias;
+  face_name = resolve_face_name (face_name);
 
   if (f)
     lface = assq_no_quit (face_name, f->face_alist);
@@ -2852,7 +2851,7 @@ merge_face_vector_with_property (f, to, prop)
                to[LFACE_BACKGROUND_INDEX] = color_name;
            }
          else
-           add_to_log (f, "Invalid face color", color_name, Qnil);
+           add_to_log ("Invalid face color", color_name, Qnil);
        }
       else if (SYMBOLP (first)
               && *XSYMBOL (first)->name->data == ':')
@@ -2868,14 +2867,14 @@ merge_face_vector_with_property (f, to, prop)
                  if (STRINGP (value))
                    to[LFACE_FAMILY_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face font family", value, Qnil);
+                   add_to_log ("Illegal face font family", value, Qnil);
                }
              else if (EQ (keyword, QCheight))
                {
                  if (INTEGERP (value))
                    to[LFACE_HEIGHT_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face font height", value, Qnil);
+                   add_to_log ("Illegal face font height", value, Qnil);
                }
              else if (EQ (keyword, QCweight))
                {
@@ -2883,7 +2882,7 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_weight (value) >= 0)
                    to[LFACE_WEIGHT_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face weight", value, Qnil);
+                   add_to_log ("Illegal face weight", value, Qnil);
                }
              else if (EQ (keyword, QCslant))
                {
@@ -2891,7 +2890,7 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_slant (value) >= 0)
                    to[LFACE_SLANT_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face slant", value, Qnil);
+                   add_to_log ("Illegal face slant", value, Qnil);
                }
              else if (EQ (keyword, QCunderline))
                {
@@ -2900,7 +2899,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_UNDERLINE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face underline", value, Qnil);
+                   add_to_log ("Illegal face underline", value, Qnil);
                }
              else if (EQ (keyword, QCoverline))
                {
@@ -2909,7 +2908,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_OVERLINE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face overline", value, Qnil);
+                   add_to_log ("Illegal face overline", value, Qnil);
                }
              else if (EQ (keyword, QCstrike_through))
                {
@@ -2918,7 +2917,7 @@ merge_face_vector_with_property (f, to, prop)
                      || STRINGP (value))
                    to[LFACE_STRIKE_THROUGH_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face strike-through", value, Qnil);
+                   add_to_log ("Illegal face strike-through", value, Qnil);
                }
              else if (EQ (keyword, QCbox))
                {
@@ -2930,7 +2929,7 @@ merge_face_vector_with_property (f, to, prop)
                      || NILP (value))
                    to[LFACE_BOX_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face box", value, Qnil);
+                   add_to_log ("Illegal face box", value, Qnil);
                }
              else if (EQ (keyword, QCinverse_video)
                       || EQ (keyword, QCreverse_video))
@@ -2938,30 +2937,30 @@ merge_face_vector_with_property (f, to, prop)
                  if (EQ (value, Qt) || NILP (value))
                    to[LFACE_INVERSE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face inverse-video", value, Qnil);
+                   add_to_log ("Illegal face inverse-video", value, Qnil);
                }
              else if (EQ (keyword, QCforeground))
                {
                  if (STRINGP (value))
                    to[LFACE_FOREGROUND_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face foreground", value, Qnil);
+                   add_to_log ("Illegal face foreground", value, Qnil);
                }
              else if (EQ (keyword, QCbackground))
                {
                  if (STRINGP (value))
                    to[LFACE_BACKGROUND_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face background", value, Qnil);
+                   add_to_log ("Illegal face background", value, Qnil);
                }
              else if (EQ (keyword, QCstipple))
                {
 #ifdef HAVE_X_WINDOWS
-                 Lisp_Object pixmap_p = Fpixmap_spec_p (value);
+                 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
                  if (!NILP (pixmap_p))
                    to[LFACE_STIPPLE_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face stipple", value, Qnil);
+                   add_to_log ("Illegal face stipple", value, Qnil);
 #endif
                }
              else if (EQ (keyword, QCwidth))
@@ -2970,10 +2969,10 @@ merge_face_vector_with_property (f, to, prop)
                      && face_numeric_swidth (value) >= 0)
                    to[LFACE_SWIDTH_INDEX] = value;
                  else
-                   add_to_log (f, "Illegal face width", value, Qnil);
+                   add_to_log ("Illegal face width", value, Qnil);
                }
              else
-               add_to_log (f, "Invalid attribute %s in face property",
+               add_to_log ("Invalid attribute %s in face property",
                            keyword, Qnil);
 
              prop = XCDR (XCDR (prop));
@@ -2996,7 +2995,7 @@ merge_face_vector_with_property (f, to, prop)
       /* PROP ought to be a face name.  */
       Lisp_Object lface = lface_from_face_name (f, prop, 0);
       if (NILP (lface))
-       add_to_log (f, "Invalid face text property value: %s", prop, Qnil);
+       add_to_log ("Invalid face text property value: %s", prop, Qnil);
       else
        merge_face_vectors (XVECTOR (lface)->contents, to);
     }
@@ -3163,6 +3162,8 @@ frame.")
   CHECK_SYMBOL (face, 0);
   CHECK_SYMBOL (attr, 1);
 
+  face = resolve_face_name (face);
+
   /* Set lface to the Lisp attribute vector of FACE.  */
   if (EQ (frame, Qt))
     lface = lface_from_face_name (NULL, face, 1);
@@ -3377,7 +3378,7 @@ frame.")
 #ifdef HAVE_X_WINDOWS
       if (!UNSPECIFIEDP (value)
          && !NILP (value)
-         && NILP (Fpixmap_spec_p (value)))
+         && NILP (Fbitmap_spec_p (value)))
        signal_error ("Invalid stipple attribute", value);
       old_value = LFACE_STIPPLE (lface);
       LFACE_STIPPLE (lface) = value;
@@ -3711,6 +3712,211 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
 }
 
 
+\f
+/***********************************************************************
+                             Menu face
+ ***********************************************************************/
+
+#ifdef USE_X_TOOLKIT
+
+/* Structure used to pass X resources to functions called via
+   XtApplyToWidgets.  */
+
+struct x_resources
+{
+  Arg *av;
+  int ac;
+};
+
+
+#ifdef USE_MOTIF
+
+static void xm_apply_resources P_ ((Widget, XtPointer));
+static void xm_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
+
+
+/* Set widget W's X resources from P which points to an x_resources
+   structure.  If W is a cascade button, apply resources to W's
+   submenu.  */
+
+static void
+xm_apply_resources (w, p)
+     Widget w;
+     XtPointer p;
+{
+  Widget submenu = 0;
+  struct x_resources *res = (struct x_resources *) p;
+  
+  XtSetValues (w, res->av, res->ac);
+  XtVaGetValues (w, XmNsubMenuId, &submenu, NULL);
+  if (submenu)
+    {
+      XtSetValues (submenu, res->av, res->ac);
+      XtApplyToWidgets (submenu, xm_apply_resources, p);
+    }
+}
+
+
+/* Set X resources of menu-widget WIDGET on frame F from face `menu'.
+   This is the LessTif/Motif version.  As of LessTif 0.88 it has the
+   following problems:
+
+   1. Setting the XmNfontList resource leads to an infinite loop
+   somewhere in LessTif.  */
+
+static void
+xm_set_menu_resources_from_menu_face (f, widget)
+     struct frame *f;
+     Widget widget;
+{
+  struct face *face;
+  Lisp_Object lface;
+  Arg av[3];
+  int ac = 0;
+  XmFontList fl = 0;
+
+  lface = lface_from_face_name (f, Qmenu, 1);
+  face = FACE_FROM_ID (f, MENU_FACE_ID);
+
+  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
+    {
+      XtSetArg (av[ac], XmNforeground, face->foreground);
+      ++ac;
+    }
+
+  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
+    {
+      XtSetArg (av[ac], XmNbackground, face->background);
+      ++ac;
+    }
+
+  /* If any font-related attribute of `menu' is set, set the font.  */
+  if (face->font
+      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+         || !UNSPECIFIEDP (LFACE_SLANT (lface))
+         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+    {
+#if 0 /* Setting the font leads to an infinite loop somewhere
+        in LessTif during geometry computation.  */
+      XmFontListEntry fe;
+      fe = XmFontListEntryCreate ("menu_font", XmFONT_IS_FONT, face->font);
+      fl = XmFontListAppendEntry (NULL, fe);
+      XtSetArg (av[ac], XmNfontList, fl);
+      ++ac;
+#endif
+    }
+
+  xassert (ac <= sizeof av / sizeof *av);
+  
+  if (ac)
+    {
+      struct x_resources res;
+      
+      XtSetValues (widget, av, ac);
+      res.av = av, res.ac = ac;
+      XtApplyToWidgets (widget, xm_apply_resources, &res);
+      if (fl)
+       XmFontListFree (fl);
+    }
+}
+
+
+#endif /* USE_MOTIF */
+
+#ifdef USE_LUCID
+
+static void xl_apply_resources P_ ((Widget, XtPointer));
+static void xl_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
+
+
+/* Set widget W's resources from P which points to an x_resources
+   structure.  */
+
+static void
+xl_apply_resources (widget, p)
+     Widget widget;
+     XtPointer p;
+{
+  struct x_resources *res = (struct x_resources *) p;
+  XtSetValues (widget, res->av, res->ac);
+}
+
+
+/* On frame F, set X resources of menu-widget WIDGET from face `menu'.
+   This is the Lucid version.  */
+
+static void
+xl_set_menu_resources_from_menu_face (f, widget)
+     struct frame *f;
+     Widget widget;
+{
+  struct face *face;
+  Lisp_Object lface;
+  Arg av[3];
+  int ac = 0;
+
+  lface = lface_from_face_name (f, Qmenu, 1);
+  face = FACE_FROM_ID (f, MENU_FACE_ID);
+
+  if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
+    {
+      XtSetArg (av[ac], XtNforeground, face->foreground);
+      ++ac;
+    }
+
+  if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
+    {
+      XtSetArg (av[ac], XtNbackground, face->background);
+      ++ac;
+    }
+
+  if (face->font
+      && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+         || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+         || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+         || !UNSPECIFIEDP (LFACE_SLANT (lface))
+         || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+    {
+      XtSetArg (av[ac], XtNfont, face->font);
+      ++ac;
+    }
+
+  if (ac)
+    {
+      struct x_resources res;
+      
+      XtSetValues (widget, av, ac);
+
+      /* We must do children here in case we're handling a pop-up menu
+        in which case WIDGET is a popup shell.  XtApplyToWidgets
+        is a function from lwlib.  */
+      res.av = av, res.ac = ac;
+      XtApplyToWidgets (widget, xl_apply_resources, &res);
+    }
+}
+
+#endif /* USE_LUCID */
+
+
+/* On frame F, set X resources of menu-widget WIDGET from face `menu'.  */
+
+void
+x_set_menu_resources_from_menu_face (f, widget)
+     struct frame *f;
+     Widget widget;
+{
+#ifdef USE_LUCID
+  xl_set_menu_resources_from_menu_face (f, widget);
+#endif
+#ifdef USE_MOTIF
+  xm_set_menu_resources_from_menu_face (f, widget);
+#endif
+}
+
+#endif /* USE_X_TOOLKIT */
+
 #endif /* HAVE_X_WINDOWS */
 
 
@@ -5262,6 +5468,7 @@ realize_basic_faces (f)
       realize_named_face (f, Qborder, BORDER_FACE_ID);
       realize_named_face (f, Qcursor, CURSOR_FACE_ID);
       realize_named_face (f, Qmouse, MOUSE_FACE_ID);
+      realize_named_face (f, Qmenu, MENU_FACE_ID);
       success_p = 1;
     }
 
@@ -6266,8 +6473,8 @@ syms_of_xfaces ()
 {
   Qface = intern ("face");
   staticpro (&Qface);
-  Qpixmap_spec_p = intern ("pixmap-spec-p");
-  staticpro (&Qpixmap_spec_p);
+  Qbitmap_spec_p = intern ("bitmap-spec-p");
+  staticpro (&Qbitmap_spec_p);
   Qframe_update_face_colors = intern ("frame-update-face-colors");
   staticpro (&Qframe_update_face_colors);
   
@@ -6385,6 +6592,8 @@ syms_of_xfaces ()
   staticpro (&Qheader_line);
   Qscroll_bar = intern ("scroll-bar");
   staticpro (&Qscroll_bar);
+  Qmenu = intern ("menu");
+  staticpro (&Qmenu);
   Qcursor = intern ("cursor");
   staticpro (&Qcursor);
   Qborder = intern ("border");
@@ -6456,7 +6665,7 @@ scaled if its name matches a regular expression in the list.");
 #endif /* SCALABLE_FONTS */
 
 #ifdef HAVE_X_WINDOWS
-  defsubr (&Spixmap_spec_p);
+  defsubr (&Sbitmap_spec_p);
   defsubr (&Sx_list_fonts);
   defsubr (&Sinternal_face_x_get_resource);
   defsubr (&Sx_family_fonts);