diff lwlib/xlwmenu.c @ 5118:e0db3c197671 ben-lisp-object

merge up to latest default branch, doesn't compile yet
author Ben Wing <ben@xemacs.org>
date Sat, 26 Dec 2009 21:18:49 -0600
parents 726060ee587c
children a6c778975d7d
line wrap: on
line diff
--- a/lwlib/xlwmenu.c	Sat Dec 26 00:20:27 2009 -0600
+++ b/lwlib/xlwmenu.c	Sat Dec 26 21:18:49 2009 -0600
@@ -45,6 +45,11 @@
 #define XmFONTLIST_DEFAULT_TAG XmSTRING_DEFAULT_CHARSET
 #endif /* XmVersion < 1.2 */
 #endif
+
+/* #### we may want to turn off USE_XFT here if !USE_XFT_MENUBARS
+   In fact, maybe that's the right interface overall? */
+#include "lwlib-fonts.h"
+#include "lwlib-colors.h"
 #include "xlwmenuP.h"
 
 #ifdef USE_DEBUG_MALLOC
@@ -65,91 +70,112 @@
 
 extern Widget lw_menubar_widget;
 
-#define offset(field) XtOffset(XlwMenuWidget, field)
 static XtResource
 xlwMenuResources[] =
 {
-#ifdef NEED_MOTIF
+/* The offset macro is a standard trick.  The remaining macros are an
+   experiment to compress redundancies in resource descriptions, and shut
+   up GCC 4.3 (the String casts, which keep G++ from complaining about
+   implicit conversions from const char *). */
+#define offset(field) XtOffset(XlwMenuWidget, menu.field)
+#define fontres(name,_class,repr,type,member,value) \
+  Xt_RESOURCE (name, _class, repr, type, offset(member), XtRString, value)
+#define mflres(name,cls,member,repr,value) \
+  Xt_RESOURCE (name, cls, XmRFontList, XmFontList, offset(member), repr, value)
+#define dimres(name,cls,repr,member,value) \
+  Xt_RESOURCE (name, cls, repr, Dimension, offset(member), XtRImmediate, value)
+#define boolres(nm,cls,member,val) \
+  Xt_RESOURCE (nm, cls, XtRBoolean, Boolean, offset(member), XtRImmediate, val)
+#define cbres(name,member,value)					  \
+  Xt_RESOURCE (name, XtCCallback, XtRCallback, XtPointer, offset(member), \
+	       XtRCallback, value)
+#define pixres(name,_class,member,repr,value) \
+  Xt_RESOURCE (name, _class, XtRPixel, Pixel, offset(member), repr, value)
+#define fgpixres(name,_class,member) \
+  pixres (name, _class, member, XtRString, "XtDefaultForeground")
+#define nullpixres(name,_class,member) \
+  pixres (name, _class, member, XtRImmediate, -1)
+#define pmres(name,cls,member) \
+  Xt_RESOURCE (name, cls, XtRPixmap, Pixmap, offset(member), XtRImmediate, None)
+
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   /* There are three font list resources, so that we can accept either of
      the resources *fontList: or *font:, and so that we can tell the
      difference between them being specified, and being defaulted to a
      font from the XtRString specified here. */
-  {XmNfontList,  XmCFontList, XmRFontList, sizeof(XmFontList),
-     offset(menu.font_list),  XtRImmediate, (XtPointer)0},
-  {XtNfont,      XtCFont,     XmRFontList, sizeof(XmFontList),
-     offset(menu.font_list_2),XtRImmediate, (XtPointer)0},
-  {XmNfontList,  XmCFontList, XmRFontList, sizeof(XmFontList),
-     offset(menu.fallback_font_list),
+  mflres (XmNfontList,  XmCFontList, font_list,	  XtRImmediate, 0),
+  mflres (XtNfont,      XtCFont,     font_list_2, XtRImmediate, 0),
+  mflres (XmNfontList,  XmCFontList, fallback_font_list,
      /* We must use an iso8859-1 font here, or people without $LANG set lose.
 	It's fair to assume that those who do have $LANG set also have the
 	*fontList resource set, or at least know how to deal with this. */
-     XtRString, (XtPointer) "-*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-1"},
+     XtRString, (XtPointer) "-*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-1"),
 #else
-  {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
-     offset(menu.font), XtRString, (XtPointer) "XtDefaultFont"},
+  fontres (XtNfont, XtCFont, XtRFontStruct, XFontStruct *, font,
+	   "XtDefaultFont"),
+#ifdef USE_XFT_MENUBARS
+  fontres (XtNfcFontName, XtCFcFontName, XtRString, String, fcFontName,
+	   "sans-serif-12:bold"),
+  /* #### This needs to be fixed to give a proper type and converter for
+     XftFonts.  See also xlwtabs.c. */
+  fontres (XtNxftFont, XtCXftFont, XtRString, XtPointer, xftFontName,
+	   "Helvetica-12:bold"),
+#endif
 # ifdef USE_XFONTSET
   /* #### Consider using the same method as for Motif; see the comment in
      XlwMenuInitialize(). */
-  {XtNfontSet,  XtCFontSet, XtRFontSet, sizeof(XFontSet),
-     offset(menu.font_set), XtRString, (XtPointer) "XtDefaultFontSet"},
+  fontres (XtNfontSet, XtCFontSet, XtRFontSet, XFontSet, font_set,
+	   "XtDefaultFontSet"),
 # endif
 #endif
-  {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
-     offset(menu.foreground), XtRString, (XtPointer) "XtDefaultForeground"},
-  {XtNbuttonForeground, XtCButtonForeground, XtRPixel, sizeof(Pixel),
-     offset(menu.button_foreground), XtRString, (XtPointer) "XtDefaultForeground"},
-  {XtNhighlightForeground, XtCHighlightForeground, XtRPixel, sizeof(Pixel),
-     offset(menu.highlight_foreground), XtRString, (XtPointer) "XtDefaultForeground"},
-  {XtNtitleForeground, XtCTitleForeground, XtRPixel, sizeof(Pixel),
-     offset(menu.title_foreground), XtRString, (XtPointer) "XtDefaultForeground"},
-  {XtNmargin, XtCMargin, XtRDimension,  sizeof(Dimension),
-     offset(menu.margin), XtRImmediate, (XtPointer)2},
-  {XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension, sizeof(Dimension),
-     offset(menu.horizontal_margin), XtRImmediate, (XtPointer)2},
-  {XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension, sizeof(Dimension),
-     offset(menu.vertical_margin), XtRImmediate, (XtPointer)1},
-  {XmNspacing, XmCSpacing, XmRHorizontalDimension,  sizeof(Dimension),
-     offset(menu.column_spacing), XtRImmediate, (XtPointer)4},
-  {XmNindicatorSize, XmCIndicatorSize, XtRDimension,  sizeof(Dimension),
-     offset(menu.indicator_size), XtRImmediate, (XtPointer)0},
+  fgpixres (XtNforeground, XtCForeground, foreground),
+  fgpixres (XtNbuttonForeground, XtCButtonForeground, button_foreground),
+  fgpixres (XtNhighlightForeground, XtCHighlightForeground,
+	    highlight_foreground),
+  fgpixres (XtNtitleForeground, XtCTitleForeground, title_foreground),
+  dimres (XtNmargin, XtCMargin, XtRDimension, margin, 2),
+  dimres (XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension,
+	  horizontal_margin, 2),
+  dimres (XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension,
+	  vertical_margin, 1),
+  dimres (XmNspacing, XmCSpacing, XmRHorizontalDimension, column_spacing, 4),
+  dimres (XmNindicatorSize, XmCIndicatorSize, XtRDimension, indicator_size, 0),
 #if 0
-  {XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
-     sizeof (Dimension), offset (menu.shadow_thickness),
-     XtRImmediate, (XtPointer) 2},
+  dimres (XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
+	  shadow_thickness, 2),
 #else
-  {XmNshadowThickness, XmCShadowThickness, XtRDimension,
-     sizeof (Dimension), offset (menu.shadow_thickness),
-     XtRImmediate, (XtPointer) 2},
+  dimres (XmNshadowThickness, XmCShadowThickness, XtRDimension,
+	  shadow_thickness, 2),
 #endif
-  {XmNselectColor, XmCSelectColor, XtRPixel, sizeof (Pixel),
-     offset (menu.select_color), XtRImmediate, (XtPointer)-1},
-  {XmNtopShadowColor, XmCTopShadowColor, XtRPixel, sizeof (Pixel),
-     offset (menu.top_shadow_color), XtRImmediate, (XtPointer)-1},
-  {XmNbottomShadowColor, XmCBottomShadowColor, XtRPixel, sizeof (Pixel),
-     offset (menu.bottom_shadow_color), XtRImmediate, (XtPointer)-1},
-  {XmNtopShadowPixmap, XmCTopShadowPixmap, XtRPixmap, sizeof (Pixmap),
-     offset (menu.top_shadow_pixmap), XtRImmediate, (XtPointer)None},
-  {XmNbottomShadowPixmap, XmCBottomShadowPixmap, XtRPixmap, sizeof (Pixmap),
-     offset (menu.bottom_shadow_pixmap), XtRImmediate, (XtPointer)None},
-
-  {XtNopen, XtCCallback, XtRCallback, sizeof(XtPointer),
-     offset(menu.open), XtRCallback, (XtPointer)NULL},
-  {XtNselect, XtCCallback, XtRCallback, sizeof(XtPointer),
-     offset(menu.select), XtRCallback, (XtPointer)NULL},
-  {XtNmenu, XtCMenu, XtRPointer, sizeof(XtPointer),
-     offset(menu.contents), XtRImmediate, (XtPointer)NULL},
-  {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
-     offset(menu.cursor_shape), XtRString, (XtPointer) "right_ptr"},
-  {XtNhorizontal, XtCHorizontal, XtRInt, sizeof(int),
-     offset(menu.horizontal), XtRImmediate, (XtPointer)True},
-  {XtNuseBackingStore, XtCUseBackingStore, XtRBoolean, sizeof (Boolean),
-     offset (menu.use_backing_store), XtRImmediate, (XtPointer)False},
-  {XtNbounceDown, XtCBounceDown, XtRBoolean, sizeof (Boolean),
-     offset (menu.bounce_down), XtRImmediate, (XtPointer)True},
-  {XtNresourceLabels, XtCResourceLabels, XtRBoolean, sizeof (Boolean),
-     offset (menu.lookup_labels), XtRImmediate, (XtPointer)False},
+  nullpixres (XmNselectColor, XmCSelectColor, select_color),
+  nullpixres (XmNtopShadowColor, XmCTopShadowColor, top_shadow_color),
+  nullpixres (XmNbottomShadowColor, XmCBottomShadowColor, bottom_shadow_color),
+  pmres (XmNtopShadowPixmap, XmCTopShadowPixmap, top_shadow_pixmap),
+  pmres (XmNbottomShadowPixmap, XmCBottomShadowPixmap, bottom_shadow_pixmap),
+
+  cbres (XtNopen, open, NULL),
+  cbres (XtNselect, select, NULL),
+  Xt_RESOURCE (XtNmenu, XtCMenu, XtRPointer, XtPointer, offset(contents),
+	       XtRImmediate, NULL),
+  Xt_RESOURCE (XtNcursor, XtCCursor, XtRCursor, Cursor, offset(cursor_shape),
+	       XtRString, "right_ptr"),
+  Xt_RESOURCE (XtNhorizontal, XtCHorizontal, XtRInt, int, offset(horizontal),
+	       XtRImmediate, True),
+  boolres (XtNuseBackingStore, XtCUseBackingStore, use_backing_store, False),
+  boolres (XtNbounceDown,      XtCBounceDown,      bounce_down,       True),
+  boolres (XtNresourceLabels,  XtCResourceLabels,  lookup_labels,     False),
+
+#undef offset
+#undef mflres
+#undef fontres
+#undef dimres
+#undef boolres
+#undef cbres
+#undef pixres
+#undef fgpixres
+#undef nullpixres
+#undef pmres
 };
-#undef offset
 
 static Boolean XlwMenuSetValues (Widget current, Widget request, Widget new_,
 				 ArgList args, Cardinal *num_args);
@@ -165,16 +191,16 @@
 static void Drag  (Widget w, XEvent *ev, String *params, Cardinal *num_params);
 static void Select(Widget w, XEvent *ev, String *params, Cardinal *num_params);
 
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 static XFontStruct *default_font_of_font_list (XmFontList);
 #endif
 
 static XtActionsRec
 xlwMenuActionsList [] =
 {
-  {"start",	Start},
-  {"drag",	Drag},
-  {"select",	Select},
+  { (String) "start",	Start},
+  { (String) "drag",	Drag},
+  { (String) "select",	Select},
 };
 
 #define SuperClass ((CoreWidgetClass)&coreClassRec)
@@ -183,7 +209,7 @@
 {
   {  /* CoreClass fields initialization */
     (WidgetClass) SuperClass,		/* superclass		  */
-    "XlwMenu",				/* class_name		  */
+    (String) "XlwMenu",			/* class_name		  */
     sizeof(XlwMenuRec),			/* size			  */
     XlwMenuClassInitialize,		/* class_initialize	  */
     NULL,				/* class_part_initialize  */
@@ -241,57 +267,6 @@
 
 #endif /* 0 */
 
-/* Replacement for XAllocColor() that tries to return the nearest
-   available color if the colormap is full.  From FSF Emacs. */
-
-static int
-allocate_nearest_color (Display *display, Colormap screen_colormap,
-		        XColor *color_def)
-{
-  int status = XAllocColor (display, screen_colormap, color_def);
-  if (status)
-    return status;
-
-    {
-      /* If we got to this point, the colormap is full, so we're
-	 going to try to get the next closest color.
-	 The algorithm used is a least-squares matching, which is
-	 what X uses for closest color matching with StaticColor visuals.  */
-
-      int nearest, x;
-      unsigned long nearest_delta = ULONG_MAX;
-
-      int no_cells = XDisplayCells (display, XDefaultScreen (display));
-      /* Don't use alloca here because lwlib doesn't have the
-         necessary configuration information that src does. */
-      XColor *cells = (XColor *) malloc (sizeof (XColor) * no_cells);
-
-      for (x = 0; x < no_cells; x++)
-	cells[x].pixel = x;
-
-      XQueryColors (display, screen_colormap, cells, no_cells);
-
-      for (nearest = 0, x = 0; x < no_cells; x++)
-	{
-	  long dred   = (color_def->red   >> 8) - (cells[x].red   >> 8);
-	  long dgreen = (color_def->green >> 8) - (cells[x].green >> 8);
-	  long dblue  = (color_def->blue  >> 8) - (cells[x].blue  >> 8);
-	  unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
-
-	  if (delta < nearest_delta)
-	    {
-	      nearest = x;
-	      nearest_delta = delta;
-	    }
-	}
-      color_def->red   = cells[nearest].red;
-      color_def->green = cells[nearest].green;
-      color_def->blue  = cells[nearest].blue;
-      free (cells);
-      return XAllocColor (display, screen_colormap, color_def);
-    }
-}
-
 static void
 push_new_stack (XlwMenuWidget mw, widget_value *val)
 {
@@ -355,14 +330,14 @@
 /* Size code */
 static int
 string_width (XlwMenuWidget mw,
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 	      XmString s
 #else
 	      char *s
 #endif
 	      )
 {
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   Dimension width, height;
   XmStringExtent (mw->menu.font_list, s, &width, &height);
   return width;
@@ -372,10 +347,17 @@
   XmbTextExtents (mw->menu.font_set, s, strlen (s), &ri, &rl);
   return rl.width;
 # else
+#ifdef USE_XFT_MENUBARS
+  XGlyphInfo glyphinfo;
+  XftTextExtents8 (XtDisplay (mw), mw->menu.renderFont, (FcChar8 *) s,
+		   strlen (s), &glyphinfo);
+  return glyphinfo.xOff;
+#else
   XCharStruct xcs;
   int drop;
   XTextExtents (mw->menu.font, s, strlen (s), &drop, &drop, &drop, &xcs);
   return xcs.width;
+#endif
 # endif /* USE_XFONTSET */
 #endif
 }
@@ -402,22 +384,26 @@
 
 static int
 string_width_u (XlwMenuWidget mw,
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 	      XmString string
 #else
 	      char *string
 #endif
 	      )
 {
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   Dimension width, height;
   XmString newstring;
 #else
 # ifdef USE_XFONTSET
   XRectangle ri, rl;
 # else /* ! USE_XFONTSET */
+#ifdef USE_XFT_MENUBARS
+  XGlyphInfo glyphinfo;
+#else
   XCharStruct xcs;
   int drop;
+#endif
 # endif
 #endif
   char* newchars;
@@ -425,7 +411,7 @@
   char *chars;
   int i, j;
 
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   chars = "";
   if (!XmStringGetLtoR (string, XmFONTLIST_DEFAULT_TAG, &chars))
     chars = "";
@@ -442,7 +428,7 @@
 	    newchars[j++] = chars[i];
   newchars[j] = '\0';
 
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   newstring = XmStringLtoRCreate (newchars, XmFONTLIST_DEFAULT_TAG);
   XmStringExtent (mw->menu.font_list, newstring, &width, &height);
   XmStringFree (newstring);
@@ -453,8 +439,14 @@
   XmbTextExtents (mw->menu.font_set, newchars, j, &ri, &rl);
   return rl.width;
 # else /* ! USE_XFONTSET */
+#ifdef USE_XFT_MENUBARS
+  XftTextExtents8 (XtDisplay (mw), mw->menu.renderFont, (FcChar8 *) newchars,
+		   j, &glyphinfo);
+  return glyphinfo.xOff;
+#else
   XTextExtents (mw->menu.font, newchars, j, &drop, &drop, &drop, &xcs);
   return xcs.width;
+#endif
 # endif /* USE_XFONTSET */
 #endif
 }
@@ -515,7 +507,7 @@
 static XtResource
 nameResource[] =
 {
-  { "labelString", "LabelString", XtRString, sizeof(String),
+  { (String) "labelString", (String) "LabelString", XtRString, sizeof(String),
     0, XtRImmediate, 0 }
 };
 
@@ -621,7 +613,7 @@
   return result;
 }
 
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 
 static XmString
 resource_widget_value (XlwMenuWidget mw, widget_value *val)
@@ -769,20 +761,41 @@
 
 #endif /* !Motif */
 
+#define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
+		   ? ((unsigned long) (x)) : ((unsigned long) (y)))
+
+#ifdef USE_XFT_MENUBARS
+static int
+x_xft_text_width (Display *dpy, XftFont *xft_font, char *run, int len)
+{
+  static XGlyphInfo glyphinfo;
+
+  XftTextExtents8 (dpy,
+		   xft_font,
+		   (FcChar8 *) run, len, &glyphinfo);
+  return glyphinfo.xOff;
+}
+#endif
+
 /* Code for drawing strings. */
 static void
 string_draw (XlwMenuWidget mw,
 	     Window window,
 	     int x, int y,
+#ifdef USE_XFT_MENUBARS
+	     XftColor *color,
+	     XftColor *colorBg,
+#else
 	     GC gc,
-#ifdef NEED_MOTIF
+#endif
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 	     XmString string
 #else
 	     char *string
 #endif
 )
 {
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   XmStringDraw (XtDisplay (mw), window,
 		mw->menu.font_list,
 		string, gc,
@@ -792,15 +805,31 @@
 		0, /* ???? layout_direction */
 		0);
 #else
-# ifdef USE_XFONTSET
+# ifdef USE_XFT_MENUBARS
+  Display *display = XtDisplay (mw);
+  Visual *visual = DefaultVisualOfScreen (XtScreen (mw));
+  Colormap cmap = mw->core.colormap;
+  XftDraw *xftDraw = XftDrawCreate (display, window, visual, cmap);
+  XftFont *renderFont = mw->menu.renderFont;
+  /* draw background rect */
+  XftDrawRect (xftDraw, colorBg,
+	       x, y,
+	       x_xft_text_width (display, renderFont, string, strlen (string)),
+	       renderFont->ascent + renderFont->descent);  /* XXX */
+  /* draw text */
+  XftDrawString8 (xftDraw, color, renderFont, x, y + mw->menu.font_ascent,
+		  (FcChar8 *) string, strlen (string));
+  XftDrawDestroy (xftDraw);
+# else
+#  ifdef USE_XFONTSET
   XmbDrawString (XtDisplay (mw), window, mw->menu.font_set, gc,
 	       x, y + mw->menu.font_ascent, string, strlen (string));
-# else
+#  else
   XDrawString (XtDisplay (mw), window, gc,
 	       x, y + mw->menu.font_ascent, string, strlen (string));
-# endif /* USE_XFONTSET */
-
-#endif
+#  endif /* USE_XFONTSET */
+# endif /* USE_XFT_MENUBARS */
+#endif /* NEED_MOTIF */
 }
 
 static int
@@ -808,13 +837,18 @@
 	XlwMenuWidget mw,
 	Window window,
 	int x, int y,
+#ifdef USE_XFT_MENUBARS
+	XftColor *color,
+	XftColor *colorBg,
+#else
 	GC gc,
+#endif
 	char *string,
 	int start,
 	int end
 )
 {
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 	Dimension width, height;
 	XmString newstring;
 	int c;
@@ -851,18 +885,50 @@
 		mw->menu.font_set, &string[start], end - start, &ri, &rl);
 	return rl.width;
 # else
+#ifdef USE_XFT_MENUBARS
+	if (end <= start)
+		return 0;
+	else
+	  {
+	    XGlyphInfo glyphinfo;
+	    Display *display = XtDisplay (mw);
+	    Visual *visual = DefaultVisualOfScreen (XtScreen (mw));
+	    Colormap cmap = mw->core.colormap;
+	    XftFont *renderFont = mw->menu.renderFont;
+	    /* #### should use parent frame's .xftDraw? */
+	    XftDraw *xftDraw = XftDrawCreate (display, window, visual, cmap);
+	    /* draw background rect */
+	    XftDrawRect (xftDraw, colorBg,
+			 x, y,
+			 x_xft_text_width (display, 
+					   renderFont, &string[start], end - start),
+			 renderFont->ascent + renderFont->descent);  /* XXX */
+	    /* draw text */
+	    XftDrawString8 (xftDraw, color, renderFont,
+			    x, y + mw->menu.font_ascent,
+			    (FcChar8 *) &string[start], end - start);
+	    
+	    XftTextExtents8 (display, renderFont, (FcChar8 *) &string[start],
+			     end - start, &glyphinfo);
+
+	    /* #### should use parent frame's .xftDraw */
+	    XftDrawDestroy (xftDraw);
+	    return glyphinfo.xOff;
+	  }    
+#else
 	XCharStruct xcs;
 	int drop;
 
 	if (end <= start)
 		return 0;
-	XDrawString (
+	XDrawString (     /* XXX */
 		XtDisplay (mw), window, gc,
 		x, y + mw->menu.font_ascent, &string[start], end - start);
 	XTextExtents (
 		mw->menu.font, &string[start], end - start,
 		&drop, &drop, &drop, &xcs);
 	return xcs.width;
+#endif
 # endif
 #endif
 }
@@ -871,8 +937,12 @@
 string_draw_u (XlwMenuWidget mw,
 	       Window window,
 	       int x, int y,
+#ifdef USE_XFT_MENUBARS
+	       XftColor *color, XftColor *colorBg, GC gc,
+#else
 	       GC gc,
-#ifdef NEED_MOTIF
+#endif
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 	       XmString string
 #else
 	       char *string
@@ -882,7 +952,7 @@
   int i, s = 0;
   char *chars;
 
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   chars = "";
   if (!XmStringGetLtoR (string, XmFONTLIST_DEFAULT_TAG, &chars))
     chars = "";
@@ -893,8 +963,13 @@
       if (chars[i] == '%' && chars[i+1] == '_') {
 	  int w;
 
+#ifdef USE_XFT_MENUBARS
+	  x += string_draw_range (mw, window, x, y, color, colorBg, chars, s, i);
+	  w = string_draw_range (mw, window, x, y, color, colorBg, chars, i+2, i+3);
+#else
 	  x += string_draw_range (mw, window, x, y, gc, chars, s, i);
 	  w = string_draw_range (mw, window, x, y, gc, chars, i+2, i+3);
+#endif
 
 	  /* underline next character */
 	  XDrawLine (XtDisplay (mw), window, gc, x - 1,
@@ -905,22 +980,37 @@
 	  i += 2;
       }
   }
+#ifdef USE_XFT_MENUBARS
+  x += string_draw_range (mw, window, x, y, color, colorBg, chars, s, i);
+#else
   x += string_draw_range (mw, window, x, y, gc, chars, s, i);
-#ifdef NEED_MOTIF
+#endif
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   XtFree (chars);
 #endif
 }
 
-static void
-binding_draw (XlwMenuWidget mw, Window w, int x, int y, GC gc, char *value)
+static void /* XXX */
+binding_draw (XlwMenuWidget mw, Window w, int x, int y,
+#ifdef USE_XFT_MENUBARS
+	      XftColor *color,
+	      XftColor *colorBg,
+#else
+	      GC gc,
+#endif
+	      char *value)
 {
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   XmString xm_value = XmStringCreateLtoR(value, XmSTRING_DEFAULT_CHARSET);
   string_draw (mw, w, x, y, gc, xm_value);
   XmStringFree (xm_value);
 #else
+#ifdef USE_XFT_MENUBARS
+  string_draw (mw, w, x, y, color, colorBg, value);
+#else
   string_draw (mw, w, x, y, gc, value);
 #endif
+#endif
 }
 
 /* Low level code for drawing 3-D edges. */
@@ -1562,21 +1652,57 @@
   int y_offset = mw->menu.shadow_thickness + mw->menu.vertical_margin;
   GC gc;
 
+#ifdef USE_XFT_MENUBARS
+  XftColor color, colorBg;
+  Display *display = XtDisplay (mw);
+  Colormap cmap = mw->core.colormap;
+  Visual *visual;
+  int ignored, pixel, pixelBg;
+
+  visual_info_from_widget ((Widget) mw, &visual, &ignored);
+#endif
+
   if (!label_offset)
     label_offset = mw->menu.shadow_thickness + mw->menu.horizontal_margin;
 
-  if (highlighted && (in_menubar || val->contents))
-    gc = mw->menu.highlight_gc;
+  if (highlighted && (in_menubar || val->contents)) 
+    {
+#ifdef USE_XFT_MENUBARS
+      pixel = mw->menu.highlight_foreground;
+      pixelBg = mw->core.background_pixel;
+#endif
+      gc = mw->menu.highlight_gc;
+    }
   else if (in_menubar || val->contents)
-    gc = mw->menu.foreground_gc;
+    {
+#ifdef USE_XFT_MENUBARS
+      pixel = mw->menu.foreground;
+      pixelBg = mw->core.background_pixel;
+#endif
+      gc = mw->menu.foreground_gc;
+    }
   else
-    gc = mw->menu.title_gc;
+    {
+#ifdef USE_XFT_MENUBARS
+      pixel = mw->menu.title_foreground;
+      pixelBg = mw->core.background_pixel;
+#endif
+      gc = mw->menu.title_gc;
+    }
+#ifdef USE_XFT_MENUBARS
+  color = xft_convert_color (display, cmap, visual, pixel, 0);
+  colorBg = xft_convert_color (display, cmap, visual, pixelBg, 0);
+#endif
 
   /*  Draw the label string. */
-  string_draw_u (mw,
-	       window,
-	       x + label_offset, y + y_offset,
+  string_draw_u (mw,    /* XXX */
+		 window,
+		 x + label_offset, y + y_offset,
+#ifdef USE_XFT_MENUBARS
+		 &color, &colorBg, gc,
+#else
 	       gc,
+#endif
 	       resource_widget_value (mw, val));
 }
 
@@ -1598,7 +1724,7 @@
   if (!in_menubar && val->key)
     {
       int w;
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
       XmString key = XmStringCreateLtoR (val->key, XmSTRING_DEFAULT_CHARSET);
       w = string_width (mw, key);
       XmStringFree (key);
@@ -1627,6 +1753,16 @@
   shadow_type type;
   Boolean menu_pb = in_menubar && (menu_item_type (val) == BUTTON_TYPE);
 
+#ifdef USE_XFT_MENUBARS
+  XftColor color, colorBg;
+  Display *display = XtDisplay (mw);
+  Colormap cmap = mw->core.colormap;
+  Visual *visual;
+  int ignored, pixel, pixelBg, dim = 0;
+
+  visual_info_from_widget ((Widget) mw, &visual, &ignored);
+#endif
+
   /* Draw the label string. */
   if (!label_offset)
     label_offset = mw->menu.shadow_thickness + mw->menu.horizontal_margin;
@@ -1634,29 +1770,77 @@
   if (highlighted)
     {
       if (val->enabled)
-	gc = mw->menu.highlight_gc;
+    {
+#ifdef USE_XFT_MENUBARS
+      pixel = mw->menu.highlight_foreground;
+      pixelBg = mw->core.background_pixel;
+#endif
+      gc = mw->menu.highlight_gc;
+    }
       else
-	gc = mw->menu.inactive_gc;
+    {
+#ifdef USE_XFT_MENUBARS
+      dim = 1;
+      pixel = mw->menu.foreground;
+      pixelBg = mw->core.background_pixel;
+#endif
+      gc = mw->menu.inactive_gc;
+    }
     }
   else if (menu_pb)
     {
       if (val->enabled)
-	gc = mw->menu.button_gc;
+	{
+#ifdef USE_XFT_MENUBARS
+	  pixel = mw->menu.button_foreground;
+	  pixelBg = mw->core.background_pixel;
+#endif
+	  gc = mw->menu.button_gc;
+	}
       else
-	gc = mw->menu.inactive_button_gc;
+	{
+#ifdef USE_XFT_MENUBARS
+	  dim = 1;
+	  pixel = mw->menu.button_foreground;
+	  pixelBg = mw->core.background_pixel;
+#endif
+	  gc = mw->menu.inactive_button_gc;
+	}
     }
   else
     {
       if (val->enabled)
-	gc = mw->menu.foreground_gc;
+	{
+#ifdef USE_XFT_MENUBARS
+	  pixel = mw->menu.foreground;
+	  pixelBg = mw->core.background_pixel;
+#endif
+	  gc = mw->menu.foreground_gc;
+	}
       else
-	gc = mw->menu.inactive_gc;
+	{
+#ifdef USE_XFT_MENUBARS
+	  dim = 1;
+	  pixel = mw->menu.foreground;
+	  pixelBg = mw->core.background_pixel;
+#endif
+	  gc = mw->menu.inactive_gc;
+	}
     }
 
+#ifdef USE_XFT_MENUBARS
+  color = xft_convert_color (display, cmap, visual, pixel, dim);
+  colorBg = xft_convert_color (display, cmap, visual, pixelBg, 0);
+#endif
+
   string_draw_u (mw,
-	       window,
-	       x + label_offset, y + y_offset,
-	       gc,
+		 window,
+		 x + label_offset, y + y_offset,
+#ifdef USE_XFT_MENUBARS
+		 &color, &colorBg, gc,
+#else
+		 gc,
+#endif
 	       resource_widget_value (mw, val));
 
   /* Draw the keybindings */
@@ -1670,7 +1854,13 @@
 	}
       binding_draw (mw, window,
 		    x + binding_offset + mw->menu.column_spacing,
-		    y + y_offset, gc, val->key);
+		    y + y_offset, 
+#ifdef USE_XFT_MENUBARS
+		    &color, &colorBg,
+#else
+		    gc,
+#endif
+		    val->key);
     }
 
   /* Draw the shadow */
@@ -2336,6 +2526,7 @@
     return;
 
   root = RootWindowOfScreen (XtScreen(mw));
+  /* use visual_info_from_widget() from lwlib-colors.c */
   /* grab the visual and depth from the nearest shell ancestor */
   visual = CopyFromParent;
   depth = CopyFromParent;
@@ -2615,13 +2806,19 @@
 make_drawing_gcs (XlwMenuWidget mw)
 {
   XGCValues xgcv;
+#ifdef USE_XFT_MENUBARS
+  unsigned long flags = (GCForeground | GCBackground);
+#else
   unsigned long flags = (GCFont | GCForeground | GCBackground);
-
-#ifdef NEED_MOTIF
+#endif
+
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   xgcv.font = default_font_of_font_list (mw->menu.font_list)->fid;
 #else
+#ifndef USE_XFT_MENUBARS
   xgcv.font = mw->menu.font->fid;
 #endif
+#endif
 
   xgcv.foreground = mw->core.background_pixel;
   xgcv.background = mw->menu.foreground;
@@ -2645,18 +2842,22 @@
       else
 	{ /* color */
 	  XColor xcolor;
-	  Colormap cmap = mw->core.colormap;
+	  Visual *visual;
+	  int ignore;
+	  Colormap cmap;
+	  visual_info_from_widget ((Widget) mw, &visual, &ignore);
+	  cmap = mw->core.colormap;
 	  xcolor.pixel = mw->core.background_pixel;
 	  XQueryColor (dpy, cmap, &xcolor);
 	  xcolor.red   = (xcolor.red   * 17) / 20;
 	  xcolor.green = (xcolor.green * 17) / 20;
 	  xcolor.blue  = (xcolor.blue  * 17) / 20;
-	  if (allocate_nearest_color (dpy, cmap, &xcolor))
+	  if (x_allocate_nearest_color (dpy, cmap, visual, &xcolor))
 	    xgcv.foreground = xcolor.pixel;
 	}
     }
   xgcv.background = mw->core.background_pixel;
-  mw->menu.select_gc = XtGetGC ((Widget)mw, flags, &xgcv);
+  mw->menu.select_gc = XtGetGC ((Widget) mw, flags, &xgcv);
 
   xgcv.foreground = mw->menu.foreground;
   xgcv.background = mw->core.background_pixel;
@@ -2688,6 +2889,7 @@
 static void
 release_drawing_gcs (XlwMenuWidget mw)
 {
+  
   XtReleaseGC ((Widget) mw, mw->menu.foreground_gc);
   XtReleaseGC ((Widget) mw, mw->menu.button_gc);
   XtReleaseGC ((Widget) mw, mw->menu.highlight_gc);
@@ -2707,9 +2909,6 @@
   mw->menu.select_gc          = (GC) -1;
 }
 
-#define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
-		   ? ((unsigned long) (x)) : ((unsigned long) (y)))
-
 static void
 make_shadow_gcs (XlwMenuWidget mw)
 {
@@ -2717,9 +2916,20 @@
   unsigned long pm = 0;
   Display *dpy = XtDisplay ((Widget) mw);
   Colormap cmap = mw->core.colormap;
+  Visual *visual;
+  int ignored;
   XColor topc, botc;
   int top_frobbed = 0, bottom_frobbed = 0;
 
+  visual_info_from_widget ((Widget) mw, &visual, &ignored);
+  /* #### Apparently this is called before any shell has a visual?
+     or maybe the widget doesn't have a parent yet? */
+  if (visual == CopyFromParent)
+    {
+      Screen *screen = DefaultScreenOfDisplay (dpy);
+      visual = DefaultVisualOfScreen (screen);
+    }
+
   if (mw->menu.top_shadow_color == (Pixel) (-1))
       mw->menu.top_shadow_color = mw->core.background_pixel;
   if (mw->menu.bottom_shadow_color == (Pixel) (-1))
@@ -2734,7 +2944,7 @@
       topc.red   = MINL (65535, topc.red   * 1.2);
       topc.green = MINL (65535, topc.green * 1.2);
       topc.blue  = MINL (65535, topc.blue  * 1.2);
-      if (allocate_nearest_color (dpy, cmap, &topc))
+      if (x_allocate_nearest_color (dpy, cmap, visual, &topc))
 	{
           if (topc.pixel == mw->core.background_pixel)
 	    {
@@ -2742,7 +2952,7 @@
 	      topc.red   = MINL (65535, topc.red   + 0x8000);
 	      topc.green = MINL (65535, topc.green + 0x8000);
 	      topc.blue  = MINL (65535, topc.blue  + 0x8000);
-	      if (allocate_nearest_color (dpy, cmap, &topc))
+	      if (x_allocate_nearest_color (dpy, cmap, visual, &topc))
 		{
 		  mw->menu.top_shadow_color = topc.pixel;
 		}
@@ -2763,7 +2973,7 @@
       botc.red   = (botc.red   * 3) / 5;
       botc.green = (botc.green * 3) / 5;
       botc.blue  = (botc.blue  * 3) / 5;
-      if (allocate_nearest_color (dpy, cmap, &botc))
+      if (x_allocate_nearest_color (dpy, cmap, visual, &botc))
 	{
 	  if (botc.pixel == mw->core.background_pixel)
 	    {
@@ -2771,7 +2981,7 @@
 	      botc.red   = MINL (65535, botc.red   + 0x4000);
 	      botc.green = MINL (65535, botc.green + 0x4000);
 	      botc.blue  = MINL (65535, botc.blue  + 0x4000);
-	      if (allocate_nearest_color (dpy, cmap, &botc))
+	      if (x_allocate_nearest_color (dpy, cmap, visual, &botc))
 		{
 		  mw->menu.bottom_shadow_color = botc.pixel;
 		}
@@ -2854,7 +3064,7 @@
 static void
 extract_font_extents (XlwMenuWidget mw)
 {
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   /* Find the maximal ascent/descent of the fonts in the font list
      so that all menu items can be the same height... */
   mw->menu.font_ascent  = 0;
@@ -2939,13 +3149,18 @@
           mw->menu.font_descent = font->descent;
   }
 # else /* ! USE_XFONTSET */
+#ifdef USE_XFT_MENUBARS
+  mw->menu.font_ascent  = mw->menu.renderFont->ascent;
+  mw->menu.font_descent = mw->menu.renderFont->descent;
+#else
   mw->menu.font_ascent  = mw->menu.font->ascent;
   mw->menu.font_descent = mw->menu.font->descent;
+#endif
 # endif
 #endif /* NEED_MOTIF */
 }
 
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
 static XFontStruct *
 default_font_of_font_list (XmFontList font_list)
 {
@@ -3015,7 +3230,7 @@
     XCreatePixmapFromBitmapData (display, window, (char *) gray_bits,
 				 gray_width, gray_height, 1, 0, 1);
 
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
   /* #### Even if it's a kludge!!!, we should consider doing the same for
      X Font Sets. */
   /* The menu.font_list slot came from the *fontList resource (Motif standard.)
@@ -3037,6 +3252,17 @@
     mw->menu.font_list = mw->menu.fallback_font_list;
 #endif
 
+#ifdef USE_XFT_MENUBARS
+  /* #### kludge for name change */
+  if (!mw->menu.fcFontName)
+    mw->menu.fcFontName = mw->menu.xftFontName;
+  /* to do this right, we should add a new Xt Resource type +
+     conversion function
+  */
+  mw->menu.renderFont =
+    xft_open_font_by_name (XtDisplay (mw), mw->menu.fcFontName);
+#endif
+
   make_drawing_gcs     (mw);
   make_shadow_gcs      (mw);
   extract_font_extents (mw);
@@ -3137,6 +3363,10 @@
   XFreePixmap (XtDisplay (mw), mw->menu.gray_pixmap);
   mw->menu.gray_pixmap = (Pixmap) -1;
 
+#ifdef USE_XFT_MENUBARS
+  XftFontClose (XtDisplay (mw), mw->menu.renderFont);
+#endif
+
   /* Don't free mw->menu.contents because that comes from our creator.
      The `*_stack' elements are just pointers into `contents' so leave
      that alone too.  But free the stacks themselves. */
@@ -3179,13 +3409,17 @@
   if (newmw->core.background_pixel != oldmw->core.background_pixel
       || newmw->menu.foreground != oldmw->menu.foreground
       /* For the XEditResource protocol, which may want to change the font. */
-#ifdef NEED_MOTIF
+#if defined(NEED_MOTIF) && !defined(USE_XFT_MENUBARS)
       || newmw->menu.font_list          != oldmw->menu.font_list
       || newmw->menu.font_list_2        != oldmw->menu.font_list_2
       || newmw->menu.fallback_font_list != oldmw->menu.fallback_font_list
 #else
+#ifdef USE_XFT_MENUBARS
+      || newmw->menu.renderFont != oldmw->menu.renderFont
+#else
       || newmw->menu.font != oldmw->menu.font
 #endif
+#endif
       )
     {
       release_drawing_gcs (newmw);
@@ -3415,8 +3649,8 @@
   if (!mw->menu.pointer_grabbed)
     {
       XWindowAttributes ret;
-      Window parent,root;
-      Window *waste;
+      Window parent,root = 0UL;
+      Window *waste = NULL;
       unsigned int num_waste;
 
       lw_menu_active = True;