So, I've found the problem.

After comparing code with the latest version of good old twm original,
I finally spotted where things were going wrong.

CTWM is handling fonts very incorrectly!

The first big problem is the broken hack of tacking ",*" onto the end of
every font specification in some lame attempt to try to turn broken XLFD
font specifications into "working" FontSets.  This is WRONG.  It is a
very unstable and problematic hack.  It is _NOT_ what modern twm does.
The result is entirely dependent on whatever fonts are installed and how
the X server's font path is configured.  NEVER EVER do this!  When CTWM
was first changed to create FontSets it should have been documented as
using FontSets, and this hack should never have been used at all, even
for the built-in fonts!  All you end up with is the first random font in
your font list -- I ended up with a fixed 75dpi bitmap font and I was
trying to display it on 218dpi and 331dpi monitors!  Users should be
free create their on full fontSets, and to add whatever wildcard fonts
to the end of the fontSet specs if desired, but in reality with
iso10646-1 fonts widely available these days it is rare to ever need
more than just one font in a fontSet.

The next big problem is that any attempt to use a font alias, e.g. the
"misc" font.alias entries like "fixed" or "variable" is probably not
ever going to work with FontSets.  While I don't think the code or any
built-in font or configuration was still using said aliases, the
documentation was.

The attached patches fix the first problem, and also should fix the
built-in fonts to use scalable fonts, in iso10646-1, so that they will
work correctly on high-resolution monitors, and to use generic enough
font families to work on a much wider variety of default X11 installs.
(I've tested with XQuartz (on macos), Debian, NetBSD, and FreeBSD.)

I also added some warning messages, taken from the current twm, that
might help people see what might be wrong with their hand-crafted
fontSet specifications, especially with the broken-in-modern-times
en_US-UTF-8/XLC_LOCALE database still shipped with libX11.  (That's
another story!)

There may be some artificial "height" adjustment that might still be
causing line spacing, e.g. especially in menus, to be a little too much,
but I haven't looked into that yet.

I left some other hacks in to keep the diff small and readable,
including some memory minor leaks (but I fixed one memory leak!).

The documentation also needs some serious fixing in related areas,
specifically to tell people these are indeed in fact fontSets, and that
they should consider setting "*international:true" in their resources
and switching everything to fontSets, and that when specifying scalable
fonts for a monitor that has a different apparent DPI than the original
font was designed for they must explicitly specify the actual/apparent
resolution in the XLFD spec, and NEVER EVER use pixel sized fonts --
that MUST be set to '0' for scaling to work.

The DefaultFont itself should also be configurable -- or maybe instead a
special new font variable should be created for about and identify
windows, though the whole concept of a "default font" when there are
built-in defaults for all fonts is kinda questionable.

A better set of fixes might be to ditch XLFD entirely and move to Xft.
(then users only need to set the DPI once globally in a resource)

--
                                        Greg A. Woods <[email protected]>

Kelowna, BC     +1 250 762-7675           RoboHack <[email protected]>
Planix, Inc. <[email protected]>     Avoncote Farms <[email protected]>

diff --git a/ctwm_main.c b/ctwm_main.c
index 0a0aefb4..90d42ef2 100644
--- a/ctwm_main.c
+++ b/ctwm_main.c
@@ -1328,10 +1328,31 @@ InitScreenInfo(int scrnum, Window croot, int crootx, 
int crooty,
        scr->workSpaceMgr.icon_name = "WorkSpaceManager Icon";


-       // Setup default fonts in case the config file doesn't
-#define DEFAULT_NICE_FONT "-*-helvetica-bold-r-normal-*-*-120-*"
-#define DEFAULT_FAST_FONT 
"-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-*"
-#define SETFONT(fld, var) (scr->fld##Font.basename = DEFAULT_##var##_FONT)
+       /* from xdpyinfo.c:
+        * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
+        *
+        *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
+        *         = N pixels / (M inch / 25.4)
+        *         = N * 25.4 pixels / M inch
+        */
+       scr->xres = (int) (((((double) DisplayWidth(dpy, scr->screen)) * 25.4) /
+                      ((double) DisplayWidthMM(dpy, scr->screen))) + 0.5);
+       scr->yres = (int) (((((double) DisplayHeight(dpy, scr->screen)) * 25.4) 
/
+                           ((double) DisplayHeightMM(dpy, scr->screen))) + 
0.5);
+
+       // Setup default fontSets in case the config file doesn't
+       //
+       // Use iso10646-1 because that's why we're here!
+       //
+       // "bitstream charter" is the only proportional, scalable, iso10646-1
+       // font common to most modern X11 platforms (especially GNU/Linux!)
+       //
+       // "courier*" must have the star(*) because it may need to match either
+       // "courier" or "courier 10 pitch", depending on which is available.
+       //
+#define DEFAULT_NICE_FONT "-*-bitstream 
charter-medium-r-normal--0-100-%d-%d-p-*-iso10646-1"
+#define DEFAULT_FAST_FONT 
"-*-courier*-medium-r-normal--0-100-%d-%d-m-*-iso10646-1"
+#define SETFONT(fld, var) asprintf(&scr->fld##Font.basename, 
DEFAULT_##var##_FONT, scr->xres, scr->yres)

        SETFONT(TitleBar,    NICE);
        SETFONT(Menu,        NICE);
@@ -1339,8 +1360,9 @@ InitScreenInfo(int scrnum, Window croot, int crootx, int 
crooty,
        SETFONT(Size,        FAST);
        SETFONT(IconManager, NICE);
        SETFONT(Default,     FAST);
-       scr->workSpaceMgr.windowFont.basename =
-               "-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1";
+       asprintf(&scr->workSpaceMgr.windowFont.basename,
+                "-*-courier*-medium-r-normal--0-75-%d-%d-m-*-iso10646-1", // 
FAST, but smaller
+                scr->xres, scr->yres);

 #undef SETFONT
 #undef DEFAULT_FAST_FONT
diff --git a/parse_be.c b/parse_be.c
index e84e865f..6ccaea3e 100644
--- a/parse_be.c
+++ b/parse_be.c
@@ -970,6 +970,10 @@ do_string_keyword(int keyword, char *s)
                }

                case kws_IconFont:
+                       // see the comment in ctwm_main.c just before the call
+                       // to CreateFonts() as to why are these all wrapped in
+                       // !HaveFonts XXX it still maybe doesn't make sense here
+                       // though....
                        if(!Scr->HaveFonts) {
                                Scr->IconFont.basename = s;
                        }
diff --git a/screen.h b/screen.h
index de281e48..81603eb8 100644
--- a/screen.h
+++ b/screen.h
@@ -142,6 +142,9 @@ struct ScreenInfo {
        /// @}
 #endif

+       int xres;       ///< horizontal DPI
+       int yres;       ///< vertical DPI
+
        int MaxWindowWidth;   ///< Largest window width to allow
        int MaxWindowHeight;  ///< Largest window height to allow

diff --git a/system.ctwmrc b/system.ctwmrc
index f23b68d5..cc5325cf 100644
--- a/system.ctwmrc
+++ b/system.ctwmrc
@@ -10,11 +10,8 @@
 # any windows and to use meta-keys.
 #

-TitleFont      "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*"
-ResizeFont     "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*"
-MenuFont       "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*"
-IconFont       "-adobe-helvetica-bold-r-normal--*-100-*-*-*-*-*-*"
-IconManagerFont        "-adobe-helvetica-bold-r-normal--*-100-*-*-*"
+# n.b. the default fonts are scalable fonts with the correct resolution
+
 ShowWorkSpaceManager                   # start with workspace manager up
 UseThreeDMenus
 UseThreeDTitles
diff --git a/util.c b/util.c
index 3cc91503..991c92dd 100644
--- a/util.c
+++ b/util.c
@@ -338,15 +338,19 @@ GetFont(MyFont *font)
                XFreeFontSet(dpy, font->font_set);
        }

-       asprintf(&basename2, "%s,*", font->basename);
+       /* xxx eliminate the VERY bad ",*" hack but keep the asprintf() for now 
*/
+       asprintf(&basename2, "%s", font->basename);
        if((font->font_set = XCreateFontSet(dpy, basename2,
                                            &missing_charset_list_return,
                                            &missing_charset_count_return,
                                            &def_string_return)) == NULL) {
-               fprintf(stderr, "Failed to get fontset %s\n", basename2);
+               fprintf(stderr, "Failed to get fontset \"%s\"\n", basename2);
                if(Scr->DefaultFont.basename) {
                        deffontname = Scr->DefaultFont.basename;
                }
+               free(basename2);
+               asprintf(&basename2, "%s", deffontname);
+               fprintf(stderr, "trying default fontset \"%s\"\n", basename2);
                if((font->font_set = XCreateFontSet(dpy, deffontname,
                                                    
&missing_charset_list_return,
                                                    
&missing_charset_count_return,
@@ -356,7 +360,16 @@ GetFont(MyFont *font)
                        exit(1);
                }
        }
-       free(basename2);
+        if (missing_charset_count_return) {
+               fprintf(stderr, "%d charsets are missing from fontset \"%s\"\n",
+                       missing_charset_count_return, basename2);
+               for (i = 0; i < missing_charset_count_return; i++) {
+                       fprintf(stderr, "font for charset %s is lacking.\n",
+                               missing_charset_list_return[i]);
+               }
+               XFreeStringList(missing_charset_list_return);
+        }
+
        font_extents = XExtentsOfFontSet(font->font_set);

        fnum = XFontsOfFontSet(font->font_set, &xfonts, &font_names);
@@ -373,6 +386,12 @@ GetFont(MyFont *font)
        font->avg_height = 0;
        font->avg_fheight = 0.0;
        font->avg_count = 0;
+       if(CLarg.PrintErrorMessages) {  /* xxx overload, but kinda like old twm 
*/
+               fprintf(stderr, "created fontset with %d fonts (%d missing) for 
\"%s\"\n",
+                       fnum, missing_charset_count_return,
+                       basename2);
+       }
+       free(basename2);
 }


Attachment: pgpuNB4pmuxNF.pgp
Description: OpenPGP Digital Signature

Reply via email to