unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: char-displayable-p issue
@ 2003-10-27 23:48 Michael Mauger
  2003-10-28  8:21 ` Jason Rumney
  0 siblings, 1 reply; 12+ messages in thread
From: Michael Mauger @ 2003-10-27 23:48 UTC (permalink / raw)
  Cc: emacs-devel, Kenichi Handa

[-- Attachment #1: Type: text/plain, Size: 2442 bytes --]

--- Michael Mauger <mmaug@yahoo.com> wrote:
> I ended up having to rewrite the parser.  (See diff attached).  The 
> XLFD
> string is broken into segments and the last wildcard prior to the last
> segment is expanded into multiple wildcards to fill out the full spec. 
> This is not perfect but seems to address the most common usages.  It
> does
> correct the bug that raised this thread.  However, it does expose some
> bugs deeper in the font selection process that I have not been able to
> isolate yet.  
> 
> I don't want to attempt this until I understand the font emun process
> better.
> 

I've spent some time looking into the font enum code.  There were
several interrelated bugs involved in the matching of font
specifications.  I've attached a patch that addresses these
problems.  Here's the ChangeLog for these changes. 

2003-10-27  Michael Mauger  <mmaug@yahoo.com>

	* (w32_normalize_xlfd): Added function.  Expands a partial XLFD
	specification into a fully qualified specification by filling in
	wildcards. Translates Windows-specific font format to a fully
	qualified XLFD specification.
	* (w32_get_xlfd_field): Added function.  Returns a portion of a
	XLFD specification.
	* (w32_to_x_font): Use "*" rather than "unknown" for unknown XLFD
	FOUNDRY.  Use "*" when FAMILY is empty.
	* (x_to_w32_font): Rewritten.  Use `w32_normalize_xlfd' and
	`w32_get_xlfd_field' to parse XLFD string properly.
	* (xlfd_strip_height): Rewrote to simplify and correct.  
	* (w32_font_match): Normalize XLFD pattern before stripping
	height or converting to a regex.  Because the pattern is fully
	qualified, wildcards now match "[^-]*" rather than ".*" as it
	did before. 
	* (w32_list_fonts): If face name has no wildcards then use it in
	Windows FontEnum to reduce the number of fonts enumerated.

This version runs in reasonable time (I'm running on a 200Mhz w/ 12Mb
and nearly 600 fonts -- font lookup is running in less than .5
secs -- much better than the 12+ secs before).  There are definitely
opportunities for improving performance (caching pattern regexs in long
font enums processes is a likely target).

As before, Jason, this probably still applies:
> Jason, you're probably the best one to evaluate these changes and their
> impact on the future unicode changes.
> 

-- Michael


__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com

[-- Attachment #2: w32fncs.diff --]
[-- Type: text/plain, Size: 21511 bytes --]

Index: emacs/src/w32fns.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/w32fns.c,v
retrieving revision 1.222
diff -u -r1.222 w32fns.c
--- emacs/src/w32fns.c	2 Oct 2003 23:07:28 -0000	1.222
+++ emacs/src/w32fns.c	27 Oct 2003 18:34:57 -0000
@@ -4601,6 +4601,23 @@
 }

 \f
+/* XLFD fields */
+#define XLFD_FOUNDRY	(0)
+#define XLFD_FAMILY	(1)
+#define XLFD_WEIGHT	(2)
+#define XLFD_SLANT 	(3)
+#define XLFD_SWIDTH 	(4)
+#define XLFD_ADSTYLE 	(5)
+#define XLFD_PIXELSIZE	(6)
+#define XLFD_POINTSIZE	(7)
+#define XLFD_RESX  	(8)
+#define XLFD_RESY  	(9)
+#define XLFD_SPACING	(10)
+#define XLFD_AVGWIDTH	(11)
+#define XLFD_REGISTRY	(12)
+#define XLFD_ENCODING	(13)
+#define XLFD_NUM_FIELDS	(14)
+
 /* Return the charset portion of a font name.  */
 char * xlfd_charset_of_font (char * fontname)
 {
@@ -4623,6 +4640,8 @@
 struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
                                      int size, char* filename);
 static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names);
+static BOOL w32_normalize_xlfd (char * normal, char * orig);
+static char * w32_get_xlfd_field (char * buf, char * normal, int field);
 static BOOL w32_to_x_font (LOGFONT * lplf, char * lpxstr, int len,
 			   char * charset);
 static BOOL x_to_w32_font (char *lpxstr, LOGFONT *lplogfont);
@@ -4918,6 +4937,218 @@
  *      )
  */

+static BOOL
+w32_normalize_xlfd (normal, orig)
+     char * normal;
+     char * orig;
+{
+  int nfields;
+  char * field[XLFD_NUM_FIELDS];
+  char * buf;
+  int i;
+  char * this;
+  char * next;
+  char widthbuf[10];
+
+  /* Make a copy of the XLFD string that we can modify. */
+  buf = alloca (strlen (orig) + 1);
+  strcpy (buf, orig);
+
+  /* Parse the string as an XLFD spec if it starts with a hyphen. */
+  if (*buf == '-')
+    {
+      int lastwild;
+
+      /* break XLFD string on hyphens */
+      next = buf;
+      lastwild = -1;
+      for (nfields = 0; nfields < XLFD_NUM_FIELDS; ++nfields)
+	{
+	  this = next + 1;
+
+	  /* Locate the next hyphen */
+	  next = strchr (this, '-');
+
+	  /* Terminate this segment */
+	  if (next != NULL)
+	    *next = '\0';
+
+	  /* Save this segment. */
+	  field[nfields] = this;
+
+	  /* Break out if there are no more segments. */
+	  if (next == NULL)
+	    {
+	      ++nfields;
+	      break;
+	    }
+
+	  /* Is this segment a wildcrd?
+
+	  This is done after we have bailed out on the last
+	  segment.  Thus `lastwild' is always < `fields'. */
+	  if (strcmp (field[nfields], "*") == 0)
+	    lastwild = nfields;
+	}
+
+      /* If there's still more to parse, return an error. */
+      if (next) return (FALSE);
+
+      /* If there are not enough fields, then expand the last
+	 wildcard to fill out the specification. */
+      if (nfields < XLFD_NUM_FIELDS)
+	{
+	  /* If there was a wildcard, expand it out. */
+	  if (lastwild > -1)
+	    {
+	      /* Copy what's after the wildcard to the end. */
+	      for (i = 1; i <= nfields - lastwild; ++i)
+		field[XLFD_NUM_FIELDS - i] = field[nfields - i];
+
+	      /* Fill in the middle with wildcards. */
+	      for (i = 1; i < XLFD_NUM_FIELDS - nfields; ++i)
+		field[lastwild + i] = "*";
+	    }
+
+	  /* There were no wildcards, pad it with wildcards. */
+	  else
+	    {
+	      for (i = nfields; i < XLFD_NUM_FIELDS; ++i)
+		field[i] = "*";
+	    }
+
+	  /* The font spec is now complete. */
+	  nfields = XLFD_NUM_FIELDS;
+	}
+    }
+  /* Provide a simple escape mechanism for specifying Windows font names
+     directly in this format:
+     "<font name>[:height in pixels[:width in pixels[:weight]]]"
+  */
+  else
+    {
+      /* Pre-fill the fields with wildcards. */
+      for (i = 0; i < XLFD_NUM_FIELDS; ++i)
+	field[i] = "*";
+
+      /* Parse off the font name. */
+      this = buf;
+      next = strchr (this, ':');
+      if (next != NULL)
+	*next = '\0';
+
+      if (this[1] != '\0')
+	field[XLFD_FAMILY] = this;
+
+      if (next == NULL)
+	this = NULL;
+      else
+	this = next + 1;
+
+      /* Parse off the height */
+      if (this != NULL)
+	{
+	  next = strchr (this, ':');
+	  if (next != NULL)
+	    *next = '\0';
+
+	  if (this[1] != '\0')
+	    field[XLFD_PIXELSIZE] = this;
+
+	  if (next == NULL)
+	    this = NULL;
+	  else
+	    this = next + 1;
+	}
+
+      /* Parse off the width */
+      if (this != NULL)
+	{
+	  next = strchr (this, ':');
+	  if (next != NULL)
+	    *next = '\0';
+
+	  if (this[1] != '\0')
+	    {
+	      strcpy (widthbuf, this);
+	      strcat (widthbuf, "0");
+	      field[XLFD_AVGWIDTH] = widthbuf;
+	    }
+
+	  if (next == NULL)
+	    this = NULL;
+	  else
+	    this = next + 1;
+	}
+
+      /* Parse off the weight */
+      if (this != NULL)
+	{
+	  next = strchr (this, ':');
+	  if (next != NULL)
+	    *next = '\0';
+
+	  if (this[1] != '\0')
+	    field[XLFD_WEIGHT] = this;
+
+	  if (next == NULL)
+	    this = NULL;
+	  else
+	    this = next + 1;
+	}
+
+      /* If there is more the format is bad */
+      if (this != NULL)
+	return (FALSE);
+
+      nfields = XLFD_NUM_FIELDS;
+    }
+
+  /* Format a complete XLFD string */
+  normal[0] = '\0';
+  for (i = 0; i < nfields; ++i)
+    {
+      strcat (normal, "-");
+      strcat (normal, field[i]);
+    }
+
+  return (TRUE);
+}
+
+static char *
+w32_get_xlfd_field (buf, normal, field)
+     char * buf;
+     char * normal;
+     int field;
+{
+  char * this;
+  char * next;
+
+  /* Skip to the desired field */
+  next = normal;
+  do
+    {
+      this = next + 1;
+      next = strchr (this, '-');
+    }
+  while (--field >= 0);
+
+  /* Copy the text of the field to the buf. */
+  if (next == NULL)
+    {
+      strcpy (buf, this);
+    }
+  else
+    {
+      int len = next - this;
+
+      strncpy (buf, this, len);
+      buf[len] = '\0';
+    }
+
+  return (buf);
+}
+
 static LONG
 x_to_w32_weight (lpw)
      char * lpw;
@@ -5417,7 +5648,7 @@
   else if (lplogfont->lfOutPrecision == OUT_STROKE_PRECIS)
     fonttype = "outline";
   else
-    fonttype = "unknown";
+    fonttype = "*";

   setup_coding_system (Fcheck_coding_system (Vlocale_coding_system),
                        &coding);
@@ -5433,6 +5664,8 @@
   decode_coding (&coding, lplogfont->lfFaceName, fontname,
                  strlen(lplogfont->lfFaceName), bufsz - 1);
   *(fontname + coding.produced) = '\0';
+  if (coding.produced == 0)
+    strcpy (fontname, "*");

   /* Replace dashes with underscores so the dashes are not
      misinterpreted.  */
@@ -5485,7 +5718,8 @@
      char * lpxstr;
      LOGFONT * lplogfont;
 {
-  struct coding_system coding;
+  char * field;
+  char * xstrbuf;

   if (!lplogfont) return (FALSE);

@@ -5508,156 +5742,112 @@
   lplogfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;

   if (!lpxstr)
-    return FALSE;
+    return (FALSE);

-  /* Provide a simple escape mechanism for specifying Windows font names
-   * directly -- if font spec does not beginning with '-', assume this
-   * format:
-   *   "<font name>[:height in pixels[:width in pixels[:weight]]]"
-   */
-
-  if (*lpxstr == '-')
-    {
-      int fields, tem;
-      char name[50], weight[20], slant, pitch, pixels[10], height[10],
-        width[10], resy[10], remainder[50];
-      char * encoding;
-      int dpi = (int) one_w32_display_info.resy;
-
-      fields = sscanf (lpxstr,
-		       "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
-		       name, weight, &slant, pixels, height, resy, &pitch, width, remainder);
-      if (fields == EOF)
-	return (FALSE);
+  /* Convert font pattern to a normalized XLFD string */
+  xstrbuf = alloca (strlen (lpxstr)
+		    + XLFD_NUM_FIELDS*2 + 1); /* enough extra space for 14 "-*" */
+  if (!w32_normalize_xlfd (xstrbuf, lpxstr))
+    return (FALSE);

-      /* In the general case when wildcards cover more than one field,
-	 we don't know which field is which, so don't fill any in.
-	 However, we need to cope with this particular form, which is
-	 generated by font_list_1 (invoked by try_font_list):
-	     "-raster-6x10-*-gb2312*-*"
-	 and make sure to correctly parse the charset field.  */
-      if (fields == 3)
-	{
-	  fields = sscanf (lpxstr,
-			   "-%*[^-]-%49[^-]-*-%49s",
-			   name, remainder);
-	}
-      else if (fields < 9)
-	{
-	  fields = 0;
-	  remainder[0] = 0;
-	}
+  field = alloca (strlen (xstrbuf) + 1);

-      if (fields > 0 && name[0] != '*')
-        {
-	  int bufsize;
-	  unsigned char *buf;
+  /* Copy the name portion to the facename. */
+  w32_get_xlfd_field (field, xstrbuf, XLFD_FAMILY);
+  if (strcmp (field, "*") != 0)
+    {
+      struct coding_system coding;
+      int bufsize;
+      unsigned char *buf;

-          setup_coding_system
-            (Fcheck_coding_system (Vlocale_coding_system), &coding);
-	  coding.src_multibyte = 1;
-	  coding.dst_multibyte = 1;
-	  bufsize = encoding_buffer_size (&coding, strlen (name));
-	  buf = (unsigned char *) alloca (bufsize);
-          coding.mode |= CODING_MODE_LAST_BLOCK;
-          encode_coding (&coding, name, buf, strlen (name), bufsize);
-	  if (coding.produced >= LF_FACESIZE)
-	    coding.produced = LF_FACESIZE - 1;
-	  buf[coding.produced] = 0;
-	  strcpy (lplogfont->lfFaceName, buf);
-	}
-      else
-        {
-	  lplogfont->lfFaceName[0] = '\0';
-	}
+      setup_coding_system
+	(Fcheck_coding_system (Vlocale_coding_system), &coding);
+      coding.src_multibyte = 1;
+      coding.dst_multibyte = 1;
+      bufsize = encoding_buffer_size (&coding, strlen (field));
+      buf = (unsigned char *) alloca (bufsize);
+      coding.mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (&coding, field, buf,
+		     strlen (field), bufsize);
+      if (coding.produced >= LF_FACESIZE)
+	coding.produced = LF_FACESIZE - 1;
+      buf[coding.produced] = 0;
+      strcpy (lplogfont->lfFaceName, buf);
+    }
+  else
+    {
+      lplogfont->lfFaceName[0] = '\0';
+    }

-      fields--;
+  /* Copy over the weight. */
+  w32_get_xlfd_field (field, xstrbuf, XLFD_WEIGHT);
+  lplogfont->lfWeight = x_to_w32_weight (field);

-      lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
+  /* Copy over the italic flag */
+  w32_get_xlfd_field (field, xstrbuf, XLFD_SLANT);
+  lplogfont->lfItalic = (field[0] == 'i');

-      fields--;
+  /* Copy over the pixel height. */
+  w32_get_xlfd_field (field, xstrbuf, XLFD_PIXELSIZE);
+  {
+    int pixelsize = atoi (field);

-      lplogfont->lfItalic = (fields > 0 && slant == 'i');
+    if (pixelsize > 0)
+      lplogfont->lfHeight = pixelsize;
+  }

-      fields--;
+  /* Copy over the X- and Y-resolution as height. */
+  if (lplogfont->lfHeight == 0)
+    {
+      int resy = 0;
+      int pointsize = 0;

-      if (fields > 0 && pixels[0] != '*')
-	lplogfont->lfHeight = atoi (pixels);
+      w32_get_xlfd_field (field, xstrbuf, XLFD_RESY);
+      if (strcmp (field, "*") != 0)
+	resy = atoi (field);
+      if (resy <= 0)
+	resy = (int) one_w32_display_info.resy;
+
+      w32_get_xlfd_field (field, xstrbuf, XLFD_POINTSIZE);
+      if (strcmp (field, "*") != 0)
+	pointsize = atoi (field);
+      if (pointsize > 0)
+	lplogfont->lfHeight = (pointsize * resy) / 720;
+    }

-      fields--;
-      fields--;
-      if (fields > 0 && resy[0] != '*')
-        {
-          tem = atoi (resy);
-          if (tem > 0) dpi = tem;
-        }
+  /* This makes TrueType fonts work better. */
+  lplogfont->lfHeight = - abs (lplogfont->lfHeight);

-      if (fields > -1 && lplogfont->lfHeight == 0 && height[0] != '*')
-	lplogfont->lfHeight = atoi (height) * dpi / 720;
+  /* Copy over the pitch. */
+  w32_get_xlfd_field (field, xstrbuf, XLFD_SPACING);
+  lplogfont->lfPitchAndFamily =
+    (field[0] == 'p') ? VARIABLE_PITCH : FIXED_PITCH;

-      if (fields > 0)
-      lplogfont->lfPitchAndFamily =
-	(fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
+  /* Copy over the point size. */
+  w32_get_xlfd_field (field, xstrbuf, XLFD_AVGWIDTH);
+  {
+    int avgwidth = atoi (field);

-      fields--;
+    if (avgwidth > 0)
+      lplogfont->lfWidth = avgwidth / 10;
+  }

-      if (fields > 0 && width[0] != '*')
-	lplogfont->lfWidth = atoi (width) / 10;
+  /* Copy over the character set encoding. */
+  {
+    char encoding[50];

-      fields--;
+    w32_get_xlfd_field (field, xstrbuf, XLFD_REGISTRY);
+    strcpy (encoding, field);

-      /* Strip the trailing '-' if present. (it shouldn't be, as it
-         fails the test against xlfd-tight-regexp in fontset.el).  */
+    w32_get_xlfd_field (field, xstrbuf, XLFD_ENCODING);
+    if (strcmp (field, "*") != 0)
       {
-	int len = strlen (remainder);
-	if (len > 0 && remainder[len-1] == '-')
-	  remainder[len-1] = 0;
+	strcat (encoding, "-");
+	strcat (encoding, field);
       }
-      encoding = remainder;
-#if 0
-      if (strncmp (encoding, "*-", 2) == 0)
-	encoding += 2;
-#endif
-      lplogfont->lfCharSet = x_to_w32_charset (encoding);
-    }
-  else
-    {
-      int fields;
-      char name[100], height[10], width[10], weight[20];
-
-      fields = sscanf (lpxstr,
-		       "%99[^:]:%9[^:]:%9[^:]:%19s",
-		       name, height, width, weight);

-      if (fields == EOF) return (FALSE);
-
-      if (fields > 0)
-        {
-	  strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
-	  lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
-	}
-      else
-        {
-	  lplogfont->lfFaceName[0] = 0;
-	}
-
-      fields--;
-
-      if (fields > 0)
-	lplogfont->lfHeight = atoi (height);
-
-      fields--;
-
-      if (fields > 0)
-	lplogfont->lfWidth = atoi (width);
-
-      fields--;
-
-      lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
-    }
-
-  /* This makes TrueType fonts work better. */
-  lplogfont->lfHeight = - abs (lplogfont->lfHeight);
+    lplogfont->lfCharSet = x_to_w32_charset (encoding);
+  }

   return (TRUE);
 }
@@ -5666,118 +5856,81 @@
    return the pixel height. If no pixel height is specified, calculate
    one from the point height, or if that isn't defined either, return
    0 (which usually signifies a scalable font).
+
+   `fontname' *must* be a fully qualified XLFD spec.
 */
 static int
 xlfd_strip_height (char *fontname)
 {
-  int pixel_height, field_number;
-  char *read_from, *write_to;
+  int pixel_height, point_size;
+  int field_number;
+  char * read_from;
+  char * write_to;
+  char * start;
+  char c;

   xassert (fontname);

-  pixel_height = field_number = 0;
-  write_to = NULL;
+  pixel_height = point_size = 0;

   /* Look for height fields.  */
-  for (read_from = fontname; *read_from; read_from++)
+  field_number = -1;
+  for (read_from = write_to = fontname; *read_from; read_from++)
     {
+      /* If we need to copy this character, copy it. */
+      if (read_from > write_to)
+	*write_to = *read_from;
+      ++write_to;
+
+      /* Is this the start of a field? */
       if (*read_from == '-')
         {
           field_number++;
-          if (field_number == 7) /* Pixel height.  */
+
+          if (field_number == XLFD_PIXELSIZE)
             {
-              read_from++;
-              write_to = read_from;
+	      start = ++read_from;

               /* Find end of field.  */
               for (;*read_from && *read_from != '-'; read_from++)
                 ;

-              /* Split the fontname at end of field.  */
-              if (*read_from)
-                {
-                  *read_from = '\0';
-                  read_from++;
-                }
-              pixel_height = atoi (write_to);
-              /* Blank out field. */
-              if (read_from > write_to)
-                {
-                  *write_to = '-';
-                  write_to++;
-                }
-              /* If the pixel height field is at the end (partial xlfd),
-                 return now.  */
-              else
-                return pixel_height;
-
-              /* If we got a pixel height, the point height can be
-                 ignored. Just blank it out and break now.  */
-              if (pixel_height)
-                {
-                  /* Find end of point size field.  */
-                  for (; *read_from && *read_from != '-'; read_from++)
-                    ;
-
-                  if (*read_from)
-                    read_from++;
-
-                  /* Blank out the point size field.  */
-                  if (read_from > write_to)
-                    {
-                      *write_to = '-';
-                      write_to++;
-                    }
-                  else
-                    return pixel_height;
-
-                  break;
-                }
-              /* If the point height is already blank, break now.  */
-              if (*read_from == '-')
-                {
-                  read_from++;
-                  break;
-                }
+              /* Terminate the field and evaluate.  */
+	      c = *read_from;
+	      *read_from = '\0';
+
+              pixel_height = atoi (start);
+
+	      /* Put the original terminator back,
+		 and prepare to re-read it. */
+	      *read_from-- = c;
             }
-          else if (field_number == 8)
+          else if (field_number == XLFD_POINTSIZE)
             {
-              /* If we didn't get a pixel height, try to get the point
-                 height and convert that.  */
-              int point_size;
-              char *point_size_start = read_from++;
+              start = ++read_from;

               /* Find end of field.  */
               for (; *read_from && *read_from != '-'; read_from++)
                 ;

-              if (*read_from)
-                {
-                  *read_from = '\0';
-                  read_from++;
-                }
-
-              point_size = atoi (point_size_start);
-
-              /* Convert to pixel height. */
-              pixel_height = point_size
-                           * one_w32_display_info.height_in / 720;
-
-              /* Blank out this field and break.  */
-              *write_to = '-';
-              write_to++;
-              break;
+	      /* Terminate the field and evaluate. */
+	      c = *read_from;
+	      *read_from = '\0';
+
+              point_size = atoi (start);
+
+	      /* Put the original terminator back,
+		 and prepare to re-read it. */
+	      *read_from-- = c;
             }
         }
     }

-  /* Shift the rest of the font spec into place.  */
-  if (write_to && read_from > write_to)
-    {
-      for (; *read_from; read_from++, write_to++)
-        *write_to = *read_from;
-      *write_to = '\0';
-    }
+  *write_to = '\0';
+
+  /* If pixel_size hasn't been set, but point_size has, use it. */
+  if (pixel_height == 0 && point_size > 0)
+    pixel_height = point_size * one_w32_display_info.height_in / 720;

   return pixel_height;
 }
@@ -5788,31 +5941,18 @@
     char * fontname;
     char * pattern;
 {
-  char *regex = alloca (strlen (pattern) * 2 + 3);
+  int pattern_len = strlen (pattern) + XLFD_NUM_FIELDS*2 + 1;
+  char *full_pattern = alloca (pattern_len);
+  char *regex;
   char *font_name_copy = alloca (strlen (fontname) + 1);
   char *ptr;

   /* Copy fontname so we can modify it during comparison.  */
   strcpy (font_name_copy, fontname);

-  ptr = regex;
-  *ptr++ = '^';
-
-  /* Turn pattern into a regexp and do a regexp match.  */
-  for (; *pattern; pattern++)
-    {
-      if (*pattern == '?')
-        *ptr++ = '.';
-      else if (*pattern == '*')
-        {
-          *ptr++ = '.';
-          *ptr++ = '*';
-        }
-      else
-        *ptr++ = *pattern;
-    }
-  *ptr = '$';
-  *(ptr + 1) = '\0';
+  /* Expand pattern into a full XFLD pattern */
+  if (!w32_normalize_xlfd (full_pattern, pattern))
+    return (FALSE);

   /* Strip out font heights and compare them seperately, since
      rounding error can cause mismatches. This also allows a
@@ -5823,7 +5963,7 @@
     int font_height, pattern_height;

     font_height = xlfd_strip_height (font_name_copy);
-    pattern_height = xlfd_strip_height (regex);
+    pattern_height = xlfd_strip_height (full_pattern);

     /* Compare now, and don't bother doing expensive regexp matching
        if the heights differ.  */
@@ -5831,6 +5971,31 @@
       return FALSE;
   }

+  /* Reformat pattern ito a regexp */
+  regex = alloca (strlen (full_pattern) * 3 + 3);
+
+  ptr = regex;
+  *ptr++ = '^';
+
+  /* Turn pattern into a regexp and do a regexp match.  */
+  for (; *full_pattern; full_pattern++)
+    {
+      if (*full_pattern == '?')
+        *ptr++ = '.';
+      else if (*full_pattern == '*')
+        {
+          *ptr++ = '[';
+          *ptr++ = '^';
+          *ptr++ = '-';
+          *ptr++ = ']';
+          *ptr++ = '*';
+        }
+      else
+        *ptr++ = *full_pattern;
+    }
+  *ptr = '$';
+  *(ptr + 1) = '\0';
+
   return (fast_c_string_match_ignore_case (build_string (regex),
                                            font_name_copy) >= 0);
 }
@@ -6170,7 +6335,15 @@
           = GetProcAddress ( gdi32, "EnumFontFamiliesExA");

         /* We do our own pattern matching so we can handle wildcards.  */
-        font_match_pattern.lfFaceName[0] = 0;
+	if (strchr (ef.logfont.lfFaceName, '*') == NULL
+	    && strchr (ef.logfont.lfFaceName, '_') == NULL)
+	  {
+	    strcpy (font_match_pattern.lfFaceName,
+		    ef.logfont.lfFaceName);
+	  }
+	else
+	  font_match_pattern.lfFaceName[0] = 0;
+
         font_match_pattern.lfPitchAndFamily = 0;
         /* We can use the charset, because if it is a wildcard it will
            be DEFAULT_CHARSET anyway.  */

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread
* Re: char-displayable-p issue
@ 2003-10-22 19:09 Michael Mauger
  2003-10-22 19:53 ` Jason Rumney
  0 siblings, 1 reply; 12+ messages in thread
From: Michael Mauger @ 2003-10-22 19:09 UTC (permalink / raw)
  Cc: emacs-devel

--- Michael Mauger <mmaug@yahoo.com> wrote:
> --- Kenichi Handa <handa@m17n.org> wrote:
> > --- Michael Mauger <mmaug@yahoo.com> wrote:
> > 
> > > I can't reproduce that bug. When I turned on ruler-mode, I
> > > see both characters in the ruler head. Isn't it a bug
> > > specific to Windows?
> > 
> > > Yes, it seems the problem is specific to Windows. Work
> > > well on my GNU/Linux box.
> > 
> > > The problem seems
> > > to be that the wildcard pattern generated in
> > > `char-displayable-p' is not matching multiple hyphen
> > > separated portions of the font name.  That is,
> > > '-*-*-iso8859-1' doesn't match any fonts while
> > > '-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1' does.
> > 
> > How about
> > '-*-iso8859-1'?  Doest it match all iso8859-1 fonts?  If so,
> > instead of just changing "-*-" to "-*-*-*-*-*-*-*-*-*-*-*-",
> > generating the most compact font-pattern (i.e. no succeeding
> > wildcards) will solve the problem without making Windows
> > version slow.
> > 
> > Even if that doesn't work, your patch is not enough.  I
> > think we must change the length of "-*-..-*-" according to
> > the form of car of font-pattern ("FOUNDRY-FAMILY",
> > "*FAMILY", or "FOUNDRY*")
> 
> I tried '-*-iso8859-1' and it also failed.  The problem appears to be
> in the Windows implementation of x-list-fonts (w32_list_fonts in
> src/w32fns.c).  The wildcarding is obviously not working as intended.
> 

Okay, I think I've isolated the font matching problem down to its
source.  The issue arises in the routine `x_to_w32_font' in
src/w32fns.c.  This routine translates a XLFD string into a Windows
LOGFONT structure.  The problem is that this routine only handles the
following formats:

[fully qualified]
-FOUNDRY-FAMILY-WEIGHT-SLANT-WIDTH-STYLE-PIXELSIZE-POINTSIZE-RESX-RESY
    -SPACING-AVGWIDTH-REGISTRY-ENCODING

[special case generated by font_list_1 invoked by try_font_list]
-FOUNDRY-FAMILY-*-REGISTRY-ENCODING

[Windows-specific formats]
FAMILY:PIXELHEIGHT:PIXELWIDTH:WEIGHT
FAMILY:PIXELHEIGHT:PIXELWIDTH
FAMILY:PIXELHEIGHT
FAMILY

Thus, the strings '-*-iso8859-1' and '-*-*-iso8859-1' are not being
parsed properly.

I see several possible solutions to this specific (char-displayable-p
failing) problem (somewhat in the order of complexity):

1. Alter `char-displayable-p' to generate a string of the form
   '-FOUNDRY-FAMILY-*-REGISTRY-ENCODING' in all cases.  Requires
   parsing the car of the result from fontset-font to ensure
   sufficient hyphens/wildcards have been inserted for it to be
   properly parsed on Windows.

2. Same as above but conditional on (eq window-system 'w32).

3. Modify `x_to_w32_font' to handle the forms:
   -FOUNDRY-*-REGISTRY-ENCODING
   -*-REGISTRY-ENCODING

   The code in this routine is a little fragile.  There are many
   special cases handled implicitly without explicit acknowledgement
   that they are there.  

4. Rewrite the parser in `x_to_w32_font' to more properly handle
   wildcards.  I'm not sure that this can even be done and it is
   probably unnecessary given the limited number of font patterns
   likely to be encountered.

I see option 3 as the ideal, and I will start to work on it. 

One other issue: Kenichi Handa said that the car of font-pattern
could be one of "FOUNDRY-FAMILY", "*FAMILY", or "FOUNDRY*", in
addition to nil.  My solution would not handle the "*FAMILY" form
unless it is really sent as "*-FAMILY".  The Windows code does
not handle partial wildcards in the font pattern.  Will these forms
ever be generated by the Windows code?

If the car of the font-pattern does not have the hyphens with the
wildcard then we need to handle these cases specially.  I would
propose handling them in `char-displayable-p' because their meaning
is clear at that point.  Trying to accommodate the partial wildcards
in `x_to_w32_font' may break other usages.

The internals of Emacs and Windows are by no means my strength, so
if you have comments please send them along.  Thanks.

-- Michael

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com

^ permalink raw reply	[flat|nested] 12+ messages in thread
* Re: char-displayable-p issue
@ 2003-10-21 23:22 Michael Mauger
  2003-10-22  5:51 ` Kenichi Handa
  0 siblings, 1 reply; 12+ messages in thread
From: Michael Mauger @ 2003-10-21 23:22 UTC (permalink / raw)



[-- Attachment #1.1: Type: text/plain, Size: 1699 bytes --]

I can't reproduce that bug. When I turned on ruler-mode, I see both characters in the ruler head. Isn't it a bug specific to Windows?

Yes, it seems the problem is specific to Windows. Work well on my GNU/Linux box. 


I'm not sure that this is just a Windows issue -- it may affect some X implementations as well.  The problem seems to be that the wildcard pattern generated in `char-displayable-p' is not matching multiple hyphen separated portions of the font name.  That is, '-*-*-iso8859-1' doesn't match any fonts while '-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1' does.

Here's a patch that corrects the problem (and should work reliably on all X implementations) but which runs very slowly on Windows.  

Please review...

Index: emacs/lisp/international/mule-util.el===================================================================RCS file: /cvsroot/emacs/emacs/lisp/international/mule-util.el,vretrieving revision 1.53diff -b -u -r1.53 mule-util.el--- emacs/lisp/international/mule-util.el       1 Sep 2003 18:45:35 -00001.53+++ emacs/lisp/international/mule-util.el       21 Oct 2003 22:47:42 -0000@@ -386,7 +386,7 @@                 (or (stringp font-pattern)                     (setq font-pattern (concat "-"                                                (or (car font-pattern) "*")-                                               "-*-"+                                               "-*-*-*-*-*-*-*-*-*-*-*-"                                                (cdr font-pattern))))                 (x-list-fonts font-pattern 'default (selected-frame) 1)))))        (t

-- Michael


---------------------------------
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software

[-- Attachment #1.2: Type: text/html, Size: 2110 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread
* char-displayable-p issue
@ 2003-10-08  7:04 David PONCE
  2003-10-13 23:40 ` Kenichi Handa
  0 siblings, 1 reply; 12+ messages in thread
From: David PONCE @ 2003-10-08  7:04 UTC (permalink / raw)


Hi,

I got a little problem in ruler-mode that no more chose the right
default characters to display in the ruler.

If fact, `char-displayable-p' wrongly says that characters ?¶ (2230)
and ?\¦ (2214) are not displayable although I clearly see them
displayed.

Here is some information about my running environment:

runemacs.exe -q -no-site-file

(frame-parameter (selected-frame) 'font)
"-outline-Courier New-normal-r-normal-normal-13-97-96-96-c-80-iso8859-1"

In GNU Emacs 21.3.50.1 (i386-mingw-nt4.0.1381)
 of 2003-10-08 on MYHOST
configured using `configure --with-gcc (3.2)'

Important settings:
  value of $LC_ALL: nil
  value of $LC_COLLATE: nil
  value of $LC_CTYPE: nil
  value of $LC_MESSAGES: nil
  value of $LC_MONETARY: nil
  value of $LC_NUMERIC: nil
  value of $LC_TIME: nil
  value of $LANG: ENU
  locale-coding-system: iso-latin-1
  default-enable-multibyte-characters: t

Hope it will help.

David

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2003-10-28 15:12 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-27 23:48 char-displayable-p issue Michael Mauger
2003-10-28  8:21 ` Jason Rumney
2003-10-28 15:12   ` Michael Mauger
  -- strict thread matches above, loose matches on Subject: below --
2003-10-22 19:09 Michael Mauger
2003-10-22 19:53 ` Jason Rumney
2003-10-23 20:21   ` Michael Mauger
2003-10-21 23:22 Michael Mauger
2003-10-22  5:51 ` Kenichi Handa
2003-10-22 16:00   ` Michael Mauger
2003-10-08  7:04 David PONCE
2003-10-13 23:40 ` Kenichi Handa
2003-10-14  5:56   ` David Ponce

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).