From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: Non-ASCII in Lucid menus Date: Wed, 16 Mar 2005 10:36:40 -0500 Message-ID: <87ll8nk49o.fsf-monnier+emacs@gnu.org> References: <877jkce8lv.fsf-monnier+emacs@gnu.org> <42341EC4.3060405@swipnet.se> <87r7ijbray.fsf-monnier+emacs@gnu.org> <7b2c4ca190cea7657e31ed04f07d3377@swipnet.se> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1110987973 31663 80.91.229.2 (16 Mar 2005 15:46:13 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 16 Mar 2005 15:46:13 +0000 (UTC) Cc: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Mar 16 16:46:12 2005 Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1DBaZh-00070n-MT for ged-emacs-devel@m.gmane.org; Wed, 16 Mar 2005 16:36:47 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DBapn-0001xE-Qn for ged-emacs-devel@m.gmane.org; Wed, 16 Mar 2005 10:53:23 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1DBap8-0001rl-HF for emacs-devel@gnu.org; Wed, 16 Mar 2005 10:52:45 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DBap0-0001pb-72 for emacs-devel@gnu.org; Wed, 16 Mar 2005 10:52:35 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DBap0-0001pR-4q for emacs-devel@gnu.org; Wed, 16 Mar 2005 10:52:34 -0500 Original-Received: from [209.226.175.188] (helo=tomts25-srv.bellnexxia.net) by monty-python.gnu.org with esmtp (Exim 4.34) id 1DBaZf-0008E0-Oa for emacs-devel@gnu.org; Wed, 16 Mar 2005 10:36:44 -0500 Original-Received: from alfajor ([67.68.217.141]) by tomts25-srv.bellnexxia.net (InterMail vM.5.01.06.10 201-253-122-130-110-20040306) with ESMTP id <20050316153642.URYM1567.tomts25-srv.bellnexxia.net@alfajor>; Wed, 16 Mar 2005 10:36:42 -0500 Original-Received: by alfajor (Postfix, from userid 1000) id 71339D74A6; Wed, 16 Mar 2005 10:36:40 -0500 (EST) Original-To: "Jan D." In-Reply-To: <7b2c4ca190cea7657e31ed04f07d3377@swipnet.se> (Jan D.'s message of "Sun, 13 Mar 2005 18:45:18 +0100") User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org X-MailScanner-To: ged-emacs-devel@m.gmane.org Xref: news.gmane.org gmane.emacs.devel:34632 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:34632 >>> 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)