emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Non-ASCII in Lucid menus


From: Stefan Monnier
Subject: Re: Non-ASCII in Lucid menus
Date: Wed, 16 Mar 2005 10:36:40 -0500
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)

>>> It is incompatible in the sense that settings in .Xresources that
>>> previously
>>> used
>>> ...*menu*font: ...
>> 
>>> now must use
>>> ...*menu*fontSet:
>> 
>>> for the lucid menus.  This should be mentioned in NEWS.
>> 
>> Hmm... good point.  Do you happen to know how I could get the expected
>> behavior that "if `font' is set but `fontSet' isn't, use `font'"?

> Basically you have to set the default to something else than the
> XtDdefaultFont(Set), and then check if either has been changed.

OK, I now understand how I could do that.

> But better would be to just have one, as Motif has FontList.

But I prefer this option as well.  In the patch below I simply changed the
semantics of the "font" Xresource so that it is now a fontset rather than
a font: you can still specify a font, but you can now also specify a list of
fonts.  So it should be 100% backward compatible with users's
Xresource customizations.

> It is just that the default for font and fontset in Xt differs.  It should
> perhaps be noted in NEWS, or we should perhaps just be prepared for "why
> have you changed the menu font" questions :-).  I don't think that this is
> a problem, it is just different.

Just to make sure I understand your judgment: you think it's not important
because the difference is minor, or because the "new" default (if
different") is also different for other apps and so it's still considered as
a legitimate default, or ...

In any case, here is the new improved patch.  This new patch should also
enable non-ASCII in Motif menus, although I haven't actually checked it.

I'll be happy to keep this patch for post-21.4, but if people feel like this
is important, I can install it as well.

W.r.t the fact that the menus only support chars in the user's locale rather
than always support unicode, that can be changed later with an additional
patch, but AFAICT the current patch would be a prerequisite anyway.


        Stefan


--- orig/lwlib/xlwmenu.c
+++ mod/lwlib/xlwmenu.c
@@ -135,8 +135,13 @@
 static XtResource
 xlwMenuResources[] =
 {
+#ifdef HAVE_X_I18N
+  {XtNfont,  XtCFont, XtRFontSet, sizeof(XFontSet),
+     offset(menu.font), XtRString, "XtDefaultFontSet"},
+#else
   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
-     offset(menu.font),XtRString, "XtDefaultFont"},
+     offset(menu.font), XtRString, "XtDefaultFont"},
+#endif
   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
      offset(menu.foreground), XtRString, "XtDefaultForeground"},
   {XtNdisabledForeground, XtCDisabledForeground, XtRPixel, sizeof(Pixel),
@@ -235,7 +240,7 @@
     XtNumber(xlwMenuResources),                /* resource_count         */
     NULLQUARK,                         /* xrm_class              */
     TRUE,                              /* compress_motion        */
-    TRUE,                              /* compress_exposure      */
+    XtExposeCompressMaximal,           /* compress_exposure      */
     TRUE,                              /* compress_enterleave    */
     FALSE,                             /* visible_interest       */
     XlwMenuDestroy,                    /* destroy                */
@@ -353,18 +358,30 @@
      XlwMenuWidget mw;
      char *s;
 {
+#ifdef HAVE_X_I18N
+  XRectangle ink, logical;
+  XmbTextExtents (mw->menu.font, s, strlen (s), &ink, &logical);
+  return logical.width;
+#else
   XCharStruct xcs;
   int drop;
 
   XTextExtents (mw->menu.font, s, strlen (s), &drop, &drop, &drop, &xcs);
   return xcs.width;
+#endif
 }
 
 static int
 arrow_width (mw)
      XlwMenuWidget mw;
 {
-  return (mw->menu.font->ascent * 3/4) | 1;
+  return (
+#ifdef HAVE_X_I18N
+         mw->menu.font_extents->max_logical_extent.height * 9 / 10
+#else
+         mw->menu.font->ascent
+#endif
+         * 3/4) | 1;
 }
 
 /* Return the width of toggle buttons of widget MW.  */
@@ -373,7 +390,13 @@
 toggle_button_width (mw)
      XlwMenuWidget mw;
 {
-  return ((mw->menu.font->ascent + mw->menu.font->descent) * 2 / 3) | 1;
+  return ((
+#ifdef HAVE_X_I18N
+          mw->menu.font_extents->max_logical_extent.height
+#else
+          mw->menu.font->ascent + mw->menu.font->descent
+#endif
+          ) * 2 / 3) | 1;
 }
 
 
@@ -455,7 +478,11 @@
   else
     {
       *height =
-       mw->menu.font->ascent + mw->menu.font->descent
+#ifdef HAVE_X_I18N
+          mw->menu.font_extents->max_logical_extent.height
+#else
+          mw->menu.font->ascent + mw->menu.font->descent
+#endif
          + 2 * mw->menu.vertical_spacing + 2 * mw->menu.shadow_thickness;
 
       *label_width =
@@ -571,7 +598,13 @@
   double factor = 1.62;
   int thickness2 = thickness * factor;
 
-  y += (mw->menu.font->ascent + mw->menu.font->descent - height) / 2;
+  y += (
+#ifdef HAVE_X_I18N
+       mw->menu.font_extents->max_logical_extent.height
+#else
+       mw->menu.font->ascent + mw->menu.font->descent
+#endif
+       - height) / 2;
 
   if (down_p)
     {
@@ -757,7 +790,13 @@
   width = toggle_button_width (mw);
   height = width;
   x += mw->menu.horizontal_spacing;
-  y += (mw->menu.font->ascent - height) / 2;
+  y += (
+#ifdef HAVE_X_I18N
+         mw->menu.font_extents->max_logical_extent.height * 9 / 10
+#else
+         mw->menu.font->ascent
+#endif
+       - height) / 2;
   draw_shadow_rectangle (mw, window, x, y, width, height, False, selected_p);
 }
 
@@ -777,7 +816,13 @@
   width = radio_button_width (mw);
   height = width;
   x += mw->menu.horizontal_spacing;
-  y += (mw->menu.font->ascent - height) / 2;
+  y += (
+#ifdef HAVE_X_I18N
+         mw->menu.font_extents->max_logical_extent.height * 9 / 10
+#else
+         mw->menu.font->ascent
+#endif
+       - height) / 2;
   draw_shadow_rhombus (mw, window, x, y, width, height, False, selected_p);
 }
 
@@ -954,8 +999,18 @@
 {
   GC deco_gc;
   GC text_gc;
-  int font_ascent = mw->menu.font->ascent;
-  int font_descent = mw->menu.font->descent;
+  int font_height =
+#ifdef HAVE_X_I18N
+    mw->menu.font_extents->max_logical_extent.height;
+#else
+    mw->menu.font->ascent + mw->menu.font->descent;
+#endif
+  int font_ascent =
+#ifdef HAVE_X_I18N
+         mw->menu.font_extents->max_logical_extent.height * 9 / 10;
+#else
+         mw->menu.font->ascent;
+#endif
   int shadow = mw->menu.shadow_thickness;
   int margin = mw->menu.margin;
   int h_spacing = mw->menu.horizontal_spacing;
@@ -1028,7 +1083,12 @@
            x_offset += ws->button_width;
 
 
-          XDrawString (XtDisplay (mw), ws->window, text_gc, x_offset,
+#ifdef HAVE_X_I18N
+          XmbDrawString (XtDisplay (mw), ws->window, mw->menu.font,
+#else
+          XDrawString (XtDisplay (mw), ws->window,
+#endif
+                      text_gc, x_offset,
                       y + v_spacing + shadow + font_ascent,
                       display_string, strlen (display_string));
 
@@ -1053,7 +1113,12 @@
                }
              else if (val->key)
                {
-                 XDrawString (XtDisplay (mw), ws->window, text_gc,
+#ifdef HAVE_X_I18N
+                 XmbDrawString (XtDisplay (mw), ws->window, mw->menu.font,
+#else
+                 XDrawString (XtDisplay (mw), ws->window,
+#endif
+                              text_gc,
                               x + label_width + mw->menu.arrow_spacing,
                               y + v_spacing + shadow + font_ascent,
                               val->key, strlen (val->key));
@@ -1065,7 +1130,7 @@
                              mw->menu.background_gc,
                              x + shadow, y + shadow,
                              label_width + h_spacing - 1,
-                             font_ascent + font_descent + 2 * v_spacing - 1);
+                             font_height + 2 * v_spacing - 1);
              draw_shadow_rectangle (mw, ws->window, x, y, width, height,
                                     True, False);
            }
@@ -1460,21 +1525,33 @@
   XGCValues xgcv;
   float scale;
 
+#ifndef HAVE_X_I18N
   xgcv.font = mw->menu.font->fid;
+#endif
   xgcv.foreground = mw->menu.foreground;
   xgcv.background = mw->core.background_pixel;
   mw->menu.foreground_gc = XtGetGC ((Widget)mw,
-                                   GCFont | GCForeground | GCBackground,
+#ifndef HAVE_X_I18N
+                                   GCFont |
+#endif
+                                   GCForeground | GCBackground,
                                    &xgcv);
 
+#ifndef HAVE_X_I18N
   xgcv.font = mw->menu.font->fid;
+#endif
   xgcv.foreground = mw->menu.button_foreground;
   xgcv.background = mw->core.background_pixel;
   mw->menu.button_gc = XtGetGC ((Widget)mw,
-                               GCFont | GCForeground | GCBackground,
+#ifndef HAVE_X_I18N
+                               GCFont |
+#endif
+                               GCForeground | GCBackground,
                                &xgcv);
 
+#ifndef HAVE_X_I18N
   xgcv.font = mw->menu.font->fid;
+#endif
   xgcv.background = mw->core.background_pixel;
 
 #define BRIGHTNESS(color) (((color) & 0xff) + (((color) >> 8) & 0xff) + 
(((color) >> 16) & 0xff))
@@ -1500,31 +1577,47 @@
       xgcv.fill_style = FillStippled;
       xgcv.stipple = mw->menu.gray_pixmap;
       mw->menu.disabled_gc = XtGetGC ((Widget)mw,
-                                     (GCFont | GCForeground | GCBackground
-                                      | GCFillStyle | GCStipple), &xgcv);
+#ifndef HAVE_X_I18N
+                                     GCFont |
+#endif
+                                     GCForeground | GCBackground
+                                     | GCFillStyle | GCStipple, &xgcv);
     }
   else
     {
       /* Many colors available, use disabled pixel.  */
       xgcv.foreground = mw->menu.disabled_foreground;
       mw->menu.disabled_gc = XtGetGC ((Widget)mw,
-                                     (GCFont | GCForeground | GCBackground), 
&xgcv);
+#ifndef HAVE_X_I18N
+                                     GCFont |
+#endif
+                                     GCForeground | GCBackground, &xgcv);
     }
 
+#ifndef HAVE_X_I18N
   xgcv.font = mw->menu.font->fid;
+#endif
   xgcv.foreground = mw->menu.button_foreground;
   xgcv.background = mw->core.background_pixel;
   xgcv.fill_style = FillStippled;
   xgcv.stipple = mw->menu.gray_pixmap;
   mw->menu.inactive_button_gc = XtGetGC ((Widget)mw,
-                                 (GCFont | GCForeground | GCBackground
-                                  | GCFillStyle | GCStipple), &xgcv);
+#ifndef HAVE_X_I18N
+                                        GCFont |
+#endif
+                                        GCForeground | GCBackground
+                                        | GCFillStyle | GCStipple, &xgcv);
 
+#ifndef HAVE_X_I18N
   xgcv.font = mw->menu.font->fid;
+#endif
   xgcv.foreground = mw->core.background_pixel;
   xgcv.background = mw->menu.foreground;
   mw->menu.background_gc = XtGetGC ((Widget)mw,
-                                   GCFont | GCForeground | GCBackground,
+#ifndef HAVE_X_I18N
+                                   GCFont |
+#endif
+                                   GCForeground | GCBackground,
                                    &xgcv);
 }
 
@@ -1731,12 +1824,16 @@
                                   gray_bitmap_width, gray_bitmap_height,
                                   (unsigned long)1, (unsigned long)0, 1);
 
+#ifndef HAVE_X_I18N
   /* I don't understand why this ends up 0 sometimes,
      but it does.  This kludge works around it.
      Can anyone find a real fix?   -- rms.  */
   if (mw->menu.font == 0)
     mw->menu.font = xlwmenu_default_font;
-
+#else
+  mw->menu.font_extents = XExtentsOfFontSet (mw->menu.font);
+#endif
+      
   make_drawing_gcs (mw);
   make_shadow_gcs (mw);
 
@@ -1903,7 +2000,10 @@
 
   if (newmw->core.background_pixel != oldmw->core.background_pixel
       || newmw->menu.foreground != oldmw->menu.foreground
-      || newmw->menu.font != oldmw->menu.font)
+#ifndef HAVE_X_I18N
+      || newmw->menu.font != oldmw->menu.font
+#endif
+      )
     {
       release_drawing_gcs (newmw);
       make_drawing_gcs (newmw);
@@ -1929,6 +2029,14 @@
          }
     }
 
+#ifdef HAVE_X_I18N
+  if (newmw->menu.font != oldmw->menu.font)
+    {
+      redisplay = True;
+      newmw->menu.font_extents = XExtentsOfFontSet (newmw->menu.font);
+    }
+#endif
+
   return redisplay;
 }
 

--- orig/lwlib/xlwmenuP.h
+++ mod/lwlib/xlwmenuP.h
@@ -43,7 +43,12 @@
 typedef struct _XlwMenu_part
 {
   /* slots set by the resources */
+#ifdef HAVE_X_I18N
+  XFontSet     font;
+  XFontSetExtents *font_extents;
+#else
   XFontStruct* font;
+#endif
   Pixel                foreground;
   Pixel                disabled_foreground;
   Pixel                button_foreground;

--- orig/src/xmenu.c
+++ mod/src/xmenu.c
@@ -137,6 +137,8 @@
 #ifdef USE_GTK
 /* gtk just uses utf-8.  */
 # define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
+#elif defined HAVE_X_I18N
+# define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str)
 #else
 # define ENCODE_MENU_STRING(str) string_make_unibyte (str)
 #endif

--- orig/src/xfaces.c
+++ mod/src/xfaces.c
@@ -4695,13 +4695,25 @@
 #else
          const char *suffix = "";
 #endif
+#ifdef HAVE_X_I18N
+         /* Let's build an Xt fontset corresponding to a face.
+            Maybe we should try and use Mule fontsets more directly, but
+            for now, we'll stick to this simple solution.  --Stef  */
+         extern char * xic_create_fontsetname P_ ((char *base_fontname));
+         char *fontname = xic_create_fontsetname (face->font_name);
+#else
+         char *fontname = face->font_name;
+#endif
+         fprintf (stderr, "Setting menu's font : %s\n", fontname);
          sprintf (line, "%s.pane.menubar*font%s: %s",
-                  myname, suffix, face->font_name);
+                  myname, suffix, fontname);
          XrmPutLineResource (&rdb, line);
          sprintf (line, "%s.%s*font%s: %s",
-                  myname, popup_path, suffix, face->font_name);
+                  myname, popup_path, suffix, fontname);
          XrmPutLineResource (&rdb, line);
          changed_p = 1;
+         if (fontname != face->font_name)
+           xfree (fontname);
        }
 
       if (changed_p && f->output_data.x->menubar_widget)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]