/[emacs]/emacs/src/macterm.c
ViewVC logotype

Diff of /emacs/src/macterm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.127 by mituharu, Thu Aug 25 08:20:33 2005 UTC revision 1.128 by mituharu, Tue Sep 6 08:07:32 2005 UTC
# Line 6084  x_wm_set_icon_position (f, icon_x, icon_ Line 6084  x_wm_set_icon_position (f, icon_x, icon_
6084    
6085    
6086  /***********************************************************************  /***********************************************************************
6087                              XLFD Pattern Match
6088     ***********************************************************************/
6089    
6090    /* An XLFD pattern is divided into blocks delimited by '*'.  This
6091       structure holds information for each block.  */
6092    struct xlfdpat_block
6093    {
6094      /* Length of the pattern string in this block.  Non-zero except for
6095         the first and the last blocks.  */
6096      int len;
6097    
6098      /* Pattern string except the last character in this block.  The last
6099         character is replaced with NUL in order to use it as a
6100         sentinel.  */
6101      unsigned char *pattern;
6102    
6103      /* Last character of the pattern string.  Must not be '?'.  */
6104      unsigned char last_char;
6105    
6106      /* One of the tables for the Boyer-Moore string search.  It
6107         specifies the number of positions to proceed for each character
6108         with which the match fails.  */
6109      int skip[256];
6110    
6111      /* The skip value for the last character in the above `skip' is
6112         assigned to `infinity' in order to simplify a loop condition.
6113         The original value is saved here.  */
6114      int last_char_skip;
6115    };
6116    
6117    struct xlfdpat
6118    {
6119      /* Normalized pattern string.  "Normalized" means that capital
6120         letters are lowered, blocks are not empty except the first and
6121         the last ones, and trailing '?'s in a block that is not the last
6122         one are moved to the next one.  The last character in each block
6123         is replaced with NUL.  */
6124      unsigned char *buf;
6125    
6126      /* Number of characters except '*'s and trailing '?'s in the
6127         normalized pattern string.  */
6128      int nchars;
6129    
6130      /* Number of trailing '?'s in the normalized pattern string.  */
6131      int trailing_anychars;
6132    
6133      /* Number of blocks and information for each block.  The latter is
6134         NULL if the pattern is exact (no '*' or '?' in it).  */
6135      int nblocks;
6136      struct xlfdpat_block *blocks;
6137    };
6138    
6139    static void
6140    xlfdpat_destroy (pat)
6141         struct xlfdpat *pat;
6142    {
6143      if (pat)
6144        {
6145          if (pat->buf)
6146            {
6147              if (pat->blocks)
6148                xfree (pat->blocks);
6149              xfree (pat->buf);
6150            }
6151          xfree (pat);
6152        }
6153    }
6154    
6155    static struct xlfdpat *
6156    xlfdpat_create (pattern)
6157         char *pattern;
6158    {
6159      struct xlfdpat *pat;
6160      int nblocks, i, skip;
6161      unsigned char last_char, *p, *q, *anychar_head;
6162      struct xlfdpat_block *blk;
6163    
6164      pat = xmalloc (sizeof (struct xlfdpat));
6165      if (pat == NULL)
6166        goto error;
6167    
6168      pat->buf = xmalloc (strlen (pattern) + 1);
6169      if (pat->buf == NULL)
6170        goto error;
6171    
6172      /* Normalize the pattern string and store it to `pat->buf'.  */
6173      nblocks = 0;
6174      anychar_head = NULL;
6175      q = pat->buf;
6176      last_char = '\0';
6177      for (p = pattern; *p; p++)
6178        {
6179          unsigned char c = *p;
6180    
6181          if (c == '*')
6182            if (last_char == '*')
6183              /*  ...a** -> ...a*  */
6184              continue;
6185            else
6186              {
6187                if (last_char == '?')
6188                  if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6189                    /*  ...*??* -> ...*??  */
6190                    continue;
6191                  else
6192                    /*  ...a??* -> ...a*??  */
6193                    {
6194                      *anychar_head++ = '*';
6195                      c = '?';
6196                    }
6197                nblocks++;
6198              }
6199          else if (c == '?')
6200            {
6201              if (last_char != '?')
6202                anychar_head = q;
6203            }
6204          else
6205            /* On Mac OS X 10.3, tolower also converts non-ASCII
6206               characters for some locales.  */
6207            if (isascii (c))
6208              c = tolower (c);
6209    
6210          *q++ = last_char = c;
6211        }
6212      *q = '\0';
6213      nblocks++;
6214      pat->nblocks = nblocks;
6215      if (last_char != '?')
6216        pat->trailing_anychars = 0;
6217      else
6218        {
6219          pat->trailing_anychars = q - anychar_head;
6220          q = anychar_head;
6221        }
6222      pat->nchars = q - pat->buf - (nblocks - 1);
6223    
6224      if (anychar_head == NULL && nblocks == 1)
6225        {
6226          /* The pattern is exact.  */
6227          pat->blocks = NULL;
6228          return pat;
6229        }
6230    
6231      pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6232      if (pat->blocks == NULL)
6233        goto error;
6234    
6235      /* Divide the normalized pattern into blocks.  */
6236      p = pat->buf;
6237      for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6238        {
6239          blk->pattern = p;
6240          while (*p != '*')
6241            p++;
6242          blk->len = p - blk->pattern;
6243          p++;
6244        }
6245      blk->pattern = p;
6246      blk->len = q - blk->pattern;
6247    
6248      /* Setup a table for the Boyer-Moore string search.  */
6249      for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6250        if (blk->len != 0)
6251          {
6252            blk->last_char = blk->pattern[blk->len - 1];
6253            blk->pattern[blk->len - 1] = '\0';
6254    
6255            for (skip = 1; skip < blk->len; skip++)
6256              if (blk->pattern[blk->len - skip - 1] == '?')
6257                break;
6258    
6259            for (i = 0; i < 256; i++)
6260              blk->skip[i] = skip;
6261    
6262            p = blk->pattern + (blk->len - skip);
6263            while (--skip > 0)
6264              blk->skip[*p++] = skip;
6265    
6266            blk->last_char_skip = blk->skip[blk->last_char];
6267          }
6268    
6269      return pat;
6270    
6271     error:
6272      xlfdpat_destroy (pat);
6273      return NULL;
6274    }
6275    
6276    static INLINE int
6277    xlfdpat_exact_p (pat)
6278         struct xlfdpat *pat;
6279    {
6280      return (pat)->blocks == NULL;
6281    }
6282    
6283    /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6284       that the pattern in *BLK matches with its prefix.  Return NULL
6285       there is no such strings.  STRING must be lowered in advance.  */
6286    
6287    static char *
6288    xlfdpat_block_match_1 (blk, string, start_max)
6289         struct xlfdpat_block *blk;
6290         unsigned char *string;
6291         int start_max;
6292    {
6293      int start, infinity;
6294      unsigned char *p, *s;
6295    
6296      xassert (blk->len > 0);
6297      xassert (start_max + blk->len <= strlen (string));
6298      xassert (blk->pattern[blk->len - 1] != '?');
6299    
6300      /* See the comments in the function `boyer_moore' (search.c) for the
6301         use of `infinity'.  */
6302      infinity = start_max + blk->len + 1;
6303      blk->skip[blk->last_char] = infinity;
6304    
6305      start = 0;
6306      do
6307        {
6308          /* Check the last character of the pattern. */
6309          s = string + blk->len - 1;
6310          do
6311            {
6312              start += blk->skip[*(s + start)];
6313            }
6314          while (start <= start_max);
6315    
6316          if (start < infinity)
6317            /* Couldn't find the last character.  */
6318            return NULL;
6319    
6320          /* No less than `infinity' means we could find the last
6321             character at `s[start - infinity]'.  */
6322          start -= infinity;
6323    
6324          /* Check the remaining characters.  We prefer making no-'?'
6325             cases faster because the use of '?' is really rare.  */
6326          p = blk->pattern;
6327          s = string + start;
6328          do
6329            {
6330              while (*p++ == *s++)
6331                ;
6332            }
6333          while (*(p - 1) == '?');
6334    
6335          if (*(p - 1) == '\0')
6336            /* Matched.  */
6337            return string + start;
6338    
6339          /* Didn't match.  */
6340          start += blk->last_char_skip;
6341        }
6342      while (start <= start_max);
6343    
6344      return NULL;
6345    }
6346    
6347    #define xlfdpat_block_match(b, s, m) \
6348      ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6349       : xlfdpat_block_match_1 (b, s, m))
6350    
6351    /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6352       matches with STRING.  STRING must be lowered in advance.  */
6353    
6354    static int
6355    xlfdpat_match (pat, string)
6356         struct xlfdpat *pat;
6357         unsigned char *string;
6358    {
6359      int str_len, nblocks, i, start_max;
6360      struct xlfdpat_block *blk;
6361      unsigned char *s;
6362    
6363      xassert (pat->nblocks > 0);
6364    
6365      if (xlfdpat_exact_p (pat))
6366        return strcmp (pat->buf, string) == 0;
6367    
6368      /* The number of the characters in the string must not be smaller
6369         than that in the pattern.  */
6370      str_len = strlen (string);
6371      if (str_len < pat->nchars + pat->trailing_anychars)
6372        return 0;
6373    
6374      /* Chop off the trailing '?'s.  */
6375      str_len -= pat->trailing_anychars;
6376    
6377      /* The last block.  When it is non-empty, it must match at the end
6378         of the string.  */
6379      nblocks = pat->nblocks;
6380      blk = pat->blocks + (nblocks - 1);
6381      if (nblocks == 1)
6382        /* The last block is also the first one.  */
6383        return (str_len == blk->len
6384                && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6385      else if (blk->len != 0)
6386        if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6387          return 0;
6388    
6389      /* The first block.  When it is non-empty, it must match at the
6390         beginning of the string.  */
6391      blk = pat->blocks;
6392      if (blk->len != 0)
6393        {
6394          s = xlfdpat_block_match (blk, string, 0);
6395          if (s == NULL)
6396            return 0;
6397          string = s + blk->len;
6398        }
6399    
6400      /* The rest of the blocks.  */
6401      start_max = str_len - pat->nchars;
6402      for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6403        {
6404          s = xlfdpat_block_match (blk, string, start_max);
6405          if (s == NULL)
6406            return 0;
6407          start_max -= s - string;
6408          string = s + blk->len;
6409        }
6410    
6411      return 1;
6412    }
6413    
6414    
6415    /***********************************************************************
6416                                  Fonts                                  Fonts
6417   ***********************************************************************/   ***********************************************************************/
6418    
# Line 6178  mac_to_x_fontname (name, size, style, ch Line 6507  mac_to_x_fontname (name, size, style, ch
6507  {  {
6508    Str31 foundry, cs;    Str31 foundry, cs;
6509    Str255 family;    Str255 family;
6510    char xf[256], *result, *p;    char xf[256], *result;
6511      unsigned char *p;
6512    
6513    if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)    if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6514      charset = cs;      charset = cs;
# Line 6195  mac_to_x_fontname (name, size, style, ch Line 6525  mac_to_x_fontname (name, size, style, ch
6525    result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);    result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6526    sprintf (result, "-%s-%s-%s", foundry, family, xf);    sprintf (result, "-%s-%s-%s", foundry, family, xf);
6527    for (p = result; *p; p++)    for (p = result; *p; p++)
6528      *p = tolower(*p);      /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6529           for some locales.  */
6530        if (isascii (*p))
6531          *p = tolower (*p);
6532    return result;    return result;
6533  }  }
6534    
# Line 6253  x_font_name_to_mac_font_name (xf, mf, mf Line 6586  x_font_name_to_mac_font_name (xf, mf, mf
6586      {      {
6587        setup_coding_system (coding_system, &coding);        setup_coding_system (coding_system, &coding);
6588        coding.src_multibyte = 1;        coding.src_multibyte = 1;
6589        coding.dst_multibyte = 1;        coding.dst_multibyte = 0;
6590        coding.mode |= CODING_MODE_LAST_BLOCK;        coding.mode |= CODING_MODE_LAST_BLOCK;
6591        encode_coding (&coding, mf_decoded, mf,        encode_coding (&coding, mf_decoded, mf,
6592                       strlen (mf_decoded), sizeof (Str255) - 1);                       strlen (mf_decoded), sizeof (Str255) - 1);
# Line 6267  add_font_name_table_entry (char *font_na Line 6600  add_font_name_table_entry (char *font_na
6600  {  {
6601    if (font_name_table_size == 0)    if (font_name_table_size == 0)
6602      {      {
6603        font_name_table_size = 16;        font_name_table_size = 256;
6604        font_name_table = (char **)        font_name_table = (char **)
6605          xmalloc (font_name_table_size * sizeof (char *));          xmalloc (font_name_table_size * sizeof (char *));
6606      }      }
6607    else if (font_name_count + 1 >= font_name_table_size)    else if (font_name_count + 1 >= font_name_table_size)
6608      {      {
6609        font_name_table_size += 16;        font_name_table_size *= 2;
6610        font_name_table = (char **)        font_name_table = (char **)
6611          xrealloc (font_name_table,          xrealloc (font_name_table,
6612                    font_name_table_size * sizeof (char *));                    font_name_table_size * sizeof (char *));
# Line 6498  static int xlfd_scalable_fields[] = Line 6831  static int xlfd_scalable_fields[] =
6831    };    };
6832    
6833  static Lisp_Object  static Lisp_Object
 mac_c_string_match (regexp, string, nonspecial, exact)  
      Lisp_Object regexp;  
      const char *string, *nonspecial;  
      int exact;  
 {  
   if (exact)  
     {  
       if (strcmp (string, nonspecial) == 0)  
         return build_string (string);  
     }  
   else if (strstr (string, nonspecial))  
     {  
       Lisp_Object str = build_string (string);  
   
       if (fast_string_match (regexp, str) >= 0)  
         return str;  
     }  
   
   return Qnil;  
 }  
   
 static Lisp_Object  
6834  mac_do_list_fonts (pattern, maxnames)  mac_do_list_fonts (pattern, maxnames)
6835       char *pattern;       char *pattern;
6836       int maxnames;       int maxnames;
6837  {  {
6838    int i, n_fonts = 0;    int i, n_fonts = 0;
6839    Lisp_Object font_list = Qnil, pattern_regex, fontname;    Lisp_Object font_list = Qnil;
6840    char *regex = (char *) alloca (strlen (pattern) * 2 + 3);    struct xlfdpat *pat;
6841    char *scaled, *ptr;    char *scaled, *ptr;
6842    int scl_val[XLFD_SCL_LAST], *field, *val;    int scl_val[XLFD_SCL_LAST], *field, *val;
6843    char *longest_start, *cur_start, *nonspecial;    int exact;
   int longest_len, exact;  
6844    
6845    if (font_name_table == NULL)  /* Initialize when first used.  */    if (font_name_table == NULL)  /* Initialize when first used.  */
6846      init_font_name_table ();      init_font_name_table ();
# Line 6588  mac_do_list_fonts (pattern, maxnames) Line 6898  mac_do_list_fonts (pattern, maxnames)
6898    else    else
6899      scl_val[XLFD_SCL_PIXEL_SIZE] = -1;      scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6900    
6901    ptr = regex;    pat = xlfdpat_create (pattern);
6902    *ptr++ = '^';    if (pat == NULL)
6903        return Qnil;
6904    
6905    longest_start = cur_start = ptr;    exact = xlfdpat_exact_p (pat);
   longest_len = 0;  
   exact = 1;  
   
   /* Turn pattern into a regexp and do a regexp match.  Also find the  
      longest substring containing no special characters.  */  
   for (; *pattern; pattern++)  
     {  
       if (*pattern == '?' || *pattern == '*')  
         {  
           if (ptr - cur_start > longest_len)  
             {  
               longest_start = cur_start;  
               longest_len = ptr - cur_start;  
             }  
           exact = 0;  
   
           if (*pattern == '?')  
             *ptr++ = '.';  
           else /* if (*pattern == '*') */  
             {  
               *ptr++ = '.';  
               *ptr++ = '*';  
             }  
           cur_start = ptr;  
         }  
       else  
         *ptr++ = tolower (*pattern);  
     }  
   
   if (ptr - cur_start > longest_len)  
     {  
       longest_start = cur_start;  
       longest_len = ptr - cur_start;  
     }  
   
   *ptr = '$';  
   *(ptr + 1) = '\0';  
   
   nonspecial = xmalloc (longest_len + 1);  
   strncpy (nonspecial, longest_start, longest_len);  
   nonspecial[longest_len] = '\0';  
   
   pattern_regex = build_string (regex);  
6906    
6907    for (i = 0; i < font_name_count; i++)    for (i = 0; i < font_name_count; i++)
6908      {      {
6909        fontname = mac_c_string_match (pattern_regex, font_name_table[i],        if (xlfdpat_match (pat, font_name_table[i]))
                                      nonspecial, exact);  
       if (!NILP (fontname))  
6910          {          {
6911            font_list = Fcons (fontname, font_list);            font_list = Fcons (build_string (font_name_table[i]), font_list);
6912            if (exact || maxnames > 0 && ++n_fonts >= maxnames)            if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6913              break;              break;
6914          }          }
# Line 6652  mac_do_list_fonts (pattern, maxnames) Line 6918  mac_do_list_fonts (pattern, maxnames)
6918            int former_len = ptr - font_name_table[i];            int former_len = ptr - font_name_table[i];
6919    
6920            scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);            scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
6921              if (scaled == NULL)
6922                continue;
6923            memcpy (scaled, font_name_table[i], former_len);            memcpy (scaled, font_name_table[i], former_len);
6924            sprintf (scaled + former_len,            sprintf (scaled + former_len,
6925                     "-%d-%d-75-75-m-%d-%s",                     "-%d-%d-75-75-m-%d-%s",
# Line 6659  mac_do_list_fonts (pattern, maxnames) Line 6927  mac_do_list_fonts (pattern, maxnames)
6927                     scl_val[XLFD_SCL_POINT_SIZE],                     scl_val[XLFD_SCL_POINT_SIZE],
6928                     scl_val[XLFD_SCL_AVGWIDTH],                     scl_val[XLFD_SCL_AVGWIDTH],
6929                     ptr + sizeof ("-0-0-0-0-m-0-") - 1);                     ptr + sizeof ("-0-0-0-0-m-0-") - 1);
6930            fontname = mac_c_string_match (pattern_regex, scaled,  
6931                                           nonspecial, exact);            if (xlfdpat_match (pat, scaled))
           xfree (scaled);  
           if (!NILP (fontname))  
6932              {              {
6933                font_list = Fcons (fontname, font_list);                font_list = Fcons (build_string (scaled), font_list);
6934                  xfree (scaled);
6935                if (exact || maxnames > 0 && ++n_fonts >= maxnames)                if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6936                  break;                    break;
6937              }              }
6938              else
6939                xfree (scaled);
6940          }          }
6941      }      }
6942    
6943    xfree (nonspecial);    xlfdpat_destroy (pat);
6944    
6945    return font_list;    return font_list;
6946  }  }

Legend:
Removed from v.1.127  
changed lines
  Added in v.1.128

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26