emacs-devel
[Top][All Lists]
Advanced

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

Re: char-displayable-p issue


From: Michael Mauger
Subject: Re: char-displayable-p issue
Date: Mon, 27 Oct 2003 15:48:32 -0800 (PST)

--- Michael Mauger <address@hidden> 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  <address@hidden>

        * (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
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 @@
 }

 
+/* 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.  */

reply via email to

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