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: Thu, 23 Oct 2003 13:21:27 -0700 (PDT)

--- Jason Rumney <address@hidden> wrote:
> Michael Mauger <address@hidden> writes:
> 
> > 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.  
> 
> > I see option 3 as the ideal, and I will start to work on it. 
> 
> Thank you. I have tweaked that bit of code many times now to fix
> bugs like this, it could do with a fresh set of eyes. Please document
> any implicit special cases that you find.
> 

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.  

For example, '-*-*-iso8859-1' returns all the Latin-1 fonts as does
'-*-*-*-*-*-*-iso8859-1' (6 segments prior to the charset), but
'-*-*-*-*-*-iso8859-1' (5 segments prior to the charset) returns none. 
The function `x_to_w32_font' returns the same LOGFONT structure in each
case.  The issues appear to be in interpreting portions of the XLFD
string later during the font enumeration process.  I haven't been able to
decypher that code as of yet.

I've been using the following elisp code to test `x-list-fonts':

(let ((i 0) (p "") l)
  (while (< i 14)
    (setq i (+ i 1)
          p (concat p "-*")
          l (length (x-list-fonts (concat p "-iso8859-1"))))
    (princ (concat (number-to-string i) "=>" (number-to-string l) " 
"))))

For values of `i' of 5, 8, and 9, no matches are made (also for values of
12 and 13, but that is because the the pattern is too long).

> > 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.
> 
> I recently changed the font selection code in the emacs-unicode-2
> branch to fix the same problem in charset and encoding fields. The
> approach I took is to treat partial wildcards as full wildcards in
> x_to_w32_charset, and to do more thorough comparisons in
> enum_font_cb2.
> 

I don't want to attempt this until I understand the font emun process
better.

> > Trying to accommodate the partial wildcards in `x_to_w32_font' may
> > break other usages.
> 
> That is my experience with trying to do anything in x_to_w32_font. It
> is not an easy piece of code to get "right". That is why I have not
> rushed into merging the changes I made to get emacs-unicode-2 to work
> back into HEAD.
> 

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 -b -c -r1.222 w32fns.c
*** emacs/src/w32fns.c  2 Oct 2003 23:07:28 -0000       1.222
--- emacs/src/w32fns.c  23 Oct 2003 18:47:29 -0000
***************
*** 5485,5492 ****
       char * lpxstr;
       LOGFONT * lplogfont;
  {
-   struct coding_system coding;
- 
    if (!lplogfont) return (FALSE);
  
    memset (lplogfont, 0, sizeof (*lplogfont));
--- 5485,5490 ----
***************
*** 5510,5555 ****
    if (!lpxstr)
      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);
! 
!       /* 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;
        }
  
!       if (fields > 0 && name[0] != '*')
          {
          int bufsize;
          unsigned char *buf;
  
--- 5508,5614 ----
    if (!lpxstr)
      return FALSE;
  
!   /* Parse the string as an XLFD spec if it starts with a hyphen. */
    if (*lpxstr == '-')
      {
!       int nfields;
! #define F_FOUNDRY     (0)
! #define F_FAMILY      (1)
! #define F_WEIGHT      (2)
! #define F_SLANT       (3)
! #define F_SWIDTH      (4)
! #define F_ADSTYLE     (5)
! #define F_PIXELSIZE   (6)
! #define F_POINTSIZE   (7)
! #define F_RESX        (8)
! #define F_RESY        (9)
! #define F_SPACING     (10)
! #define F_AVGWIDTH    (11)
! #define F_REGISTRY    (12)
! #define F_ENCODING    (13)
! 
! #define FCNT   14
! #define FSIZ 50
!       char field[FCNT][FSIZ];
!       char * next;
!       int lastwild;
! 
!       /* break XLFD string on hyphens */
!       next = lpxstr;
!       lastwild = -1;
!       for (nfields = 0; nfields < FCNT; ++nfields)
!       {
!         char * this = next + 1;
!         int len;
! 
!         /* Locate the next hyphen */
!         next = strchr (this, '-');
! 
!         /* Calculate the length of this segment. */
!         if (next == NULL)
!           len = strlen (this);
!         else
!           len = next - this;
! 
!         /* Make sure the segment is not too long. */
!         if (len >= FSIZ)
!           len = FSIZ - 1;
! 
!         /* Copy this segment and terminate it. */
!         strncpy (field[nfields], this, len);
!         field[nfields][len] = '\0';
! 
!         /* 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 < `nfields'. */
!         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 < FCNT)
!       {
!         int f0;
! 
!         /* If there was a wildcard, expand it out. */
!         if (lastwild > -1)
!           {
!             /* Copy what's after the wildcard to the end. */
!             for (f0 = 1; f0 <= nfields - lastwild; ++f0)
!               strcpy (field[FCNT - f0], field[nfields - f0]);
! 
!             /* Fill in the middle with wildcards. */
!             for (f0 = 1; f0 < FCNT - nfields; ++f0)
!               strcpy (field[lastwild + f0], "*");
            }
! 
!         /* There were no wildcards, pad it with wildcards. */
!         else
            {
!             for (f0 = nfields; f0 < FCNT; ++f0)
!               strcpy (field[f0], "*");
            }
  
!         /* The font spec is now complete. */
!         nfields = FCNT;
!       }
! 
!       /* Copy the name portion to the facename. */
!       if (strcmp (field[F_FAMILY], "*") != 0)
          {
+         struct coding_system coding;
          int bufsize;
          unsigned char *buf;
  
***************
*** 5557,5566 ****
              (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;
--- 5616,5626 ----
              (Fcheck_coding_system (Vlocale_coding_system), &coding);
          coding.src_multibyte = 1;
          coding.dst_multibyte = 1;
!         bufsize = encoding_buffer_size (&coding, strlen (field[F_FAMILY]));
          buf = (unsigned char *) alloca (bufsize);
            coding.mode |= CODING_MODE_LAST_BLOCK;
!           encode_coding (&coding, field[F_FAMILY], buf,
!                        strlen (field[F_FAMILY]), bufsize);
          if (coding.produced >= LF_FACESIZE)
            coding.produced = LF_FACESIZE - 1;
          buf[coding.produced] = 0;
***************
*** 5571,5637 ****
          lplogfont->lfFaceName[0] = '\0';
        }
  
!       fields--;
  
!       lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
  
!       fields--;
  
!       lplogfont->lfItalic = (fields > 0 && slant == 'i');
  
!       fields--;
  
!       if (fields > 0 && pixels[0] != '*')
!       lplogfont->lfHeight = atoi (pixels);
  
!       fields--;
!       fields--;
!       if (fields > 0 && resy[0] != '*')
!         {
!           tem = atoi (resy);
!           if (tem > 0) dpi = tem;
          }
  
!       if (fields > -1 && lplogfont->lfHeight == 0 && height[0] != '*')
!       lplogfont->lfHeight = atoi (height) * dpi / 720;
! 
!       if (fields > 0)
        lplogfont->lfPitchAndFamily =
!       (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
  
!       fields--;
  
!       if (fields > 0 && width[0] != '*')
!       lplogfont->lfWidth = atoi (width) / 10;
  
!       fields--;
  
!       /* Strip the trailing '-' if present. (it shouldn't be, as it
!          fails the test against xlfd-tight-regexp in fontset.el).  */
        {
!       int len = strlen (remainder);
!       if (len > 0 && remainder[len-1] == '-')
!         remainder[len-1] = 0;
        }
!       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;
--- 5631,5709 ----
          lplogfont->lfFaceName[0] = '\0';
        }
  
!       /* Copy over the weight. */
!       lplogfont->lfWeight = x_to_w32_weight (field[F_WEIGHT]);
  
!       /* Copy over the italic flag */
!       lplogfont->lfItalic = (field[F_SLANT][0] == 'i');
  
!       /* Copy over the pixel height. */
!       {
!       int pixelsize = atoi (field[F_PIXELSIZE]);
  
!       if (pixelsize > 0)
!         lplogfont->lfHeight = pixelsize;
!       }
  
!       /* Copy over the X- and Y-resolution as height. */
!       if (lplogfont->lfHeight == 0)
!       {
!         int resy = 0;
!         int pointsize = 0;
  
!         if (strcmp (field[F_RESY], "*") != 0)
!           resy = atoi (field[F_RESY]);
!         if (resy <= 0)
!           resy = (int) one_w32_display_info.resy;
  
!         if (strcmp (field[F_POINTSIZE], "*") != 0)
!           pointsize = atoi (field[F_POINTSIZE]);
!         if (pointsize > 0)
!           lplogfont->lfHeight = (pointsize * resy) / 720;
          }
  
!       /* Copy over the pitch. */
        lplogfont->lfPitchAndFamily =
!       (field[F_SPACING][0] == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
  
!       /* Copy over the point size. */
!       {
!       int avgwidth = atoi (field[F_AVGWIDTH]);
  
!       if (avgwidth > 0)
!         lplogfont->lfWidth = avgwidth / 10;
!       }
  
!       /* Copy over the character set encoding. */
!       {
!       char encoding[2 * FSIZ];
  
!       strcpy (encoding, field[F_REGISTRY]);
!       if (strcmp (field[F_ENCODING], "*") != 0)
          {
!           strcat (encoding, "-");
!           strcat (encoding, field[F_ENCODING]);
          }
! 
        lplogfont->lfCharSet = x_to_w32_charset (encoding);
        }
+     }
+   /* Provide a simple escape mechanism for specifying Windows font names
+      directly in this format:
+      "<font name>[:height in pixels[:width in pixels[:weight]]]"
+   */
    else
      {
!       int nfields;
        char name[100], height[10], width[10], weight[20];
  
!       nfields = sscanf (lpxstr,
                        "%99[^:]:%9[^:]:%9[^:]:%19s",
                        name, height, width, weight);
  
!       if (nfields == EOF) return (FALSE);
  
!       if (nfields > 0)
          {
          strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
          lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
***************
*** 5641,5659 ****
          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. */
--- 5713,5731 ----
          lplogfont->lfFaceName[0] = 0;
        }
  
!       nfields--;
  
!       if (nfields > 0)
        lplogfont->lfHeight = atoi (height);
  
!       nfields--;
  
!       if (nfields > 0)
        lplogfont->lfWidth = atoi (width);
  
!       nfields--;
  
!       lplogfont->lfWeight = x_to_w32_weight ((nfields > 0 ? weight : ""));
      }
  
    /* This makes TrueType fonts work better. */

reply via email to

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