Merge from emacs--devo--0
[bpt/emacs.git] / src / xfont.c
index 0d5d2f7..59cc31d 100644 (file)
@@ -92,7 +92,7 @@ xfont_query_font (display, name, spec)
        {
          char *n = (char *) XGetAtomName (display, (Atom) value);
 
-         if (font_parse_xlfd (n, spec, 0) >= 0)
+         if (font_parse_xlfd (n, spec) >= 0)
            name = n;
          else
            XFree (n);
@@ -238,8 +238,8 @@ xfont_registry_charsets (registry, encoding, repertory)
 }
 
 static Lisp_Object xfont_get_cache P_ ((Lisp_Object));
-static int xfont_parse_name P_ ((FRAME_PTR, char *, Lisp_Object));
 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
+static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
 static Lisp_Object xfont_list_family P_ ((Lisp_Object));
 static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
 static void xfont_close P_ ((FRAME_PTR, struct font *));
@@ -255,10 +255,10 @@ static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
 
 struct font_driver xfont_driver =
   {
-    (Lisp_Object) NULL,                /* Qx */
+    0,                         /* Qx */
     xfont_get_cache,
-    xfont_parse_name,
     xfont_list,
+    xfont_match,
     xfont_list_family,
     NULL,
     xfont_open,
@@ -282,175 +282,206 @@ xfont_get_cache (frame)
   return (dpyinfo->name_list_element);
 }
 
-static int
-xfont_parse_name (f, name, spec)
-     FRAME_PTR f;
-     char *name;
-     Lisp_Object spec;
-{
-  if (font_parse_xlfd (name, spec, 0) >= 0)
-    return 0;
-  name = xfont_query_font (FRAME_X_DISPLAY (f), name, spec);
-  if (name)
-    {
-      XFree (name);
-      return 0;
-    }
-  return -1;
-}
-
 extern Lisp_Object Vface_alternative_font_registry_alist;
 
 static Lisp_Object
-xfont_list (frame, spec)
-     Lisp_Object frame, spec;
+xfont_list_pattern (frame, display, pattern)
+     Lisp_Object frame;
+     Display *display;
+     char *pattern;
 {
-  FRAME_PTR f = XFRAME (frame);
-  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  Lisp_Object *vec, val, extra, font_name, entity;
-  char name[256], **names;
-  int i, idx, limit, num_fonts;
-  int error_occurred = 0;
-  USE_SAFE_ALLOCA;
-  
-  extra = AREF (spec, FONT_EXTRA_INDEX);
-  font_name = Qnil;
-  if (CONSP (extra))
-    {
-      val = Fassq (QCotf, extra);
-      if (! NILP (val))
-       return null_vector;
-      val = Fassq (QCname, extra);
-      if (CONSP (val))
-       font_name = XCDR (val);
-    }
-
-  if (! STRINGP (font_name)
-      && font_unparse_xlfd (spec, 0, name, 256) < 0)
-    return null_vector;
+  Lisp_Object list = Qnil;
+  int i, limit, num_fonts;
+  char **names;
 
   BLOCK_INPUT;
-  x_catch_errors (dpyinfo->display);
+  x_catch_errors (display);
 
-  if (STRINGP (font_name))
+  for (limit = 512; ; limit *= 2)
     {
-      XFontStruct *font = XLoadQueryFont (dpyinfo->display,
-                                         (char *) SDATA (font_name));
-      unsigned long value;
-
-      num_fonts = 0;
-      if (x_had_errors_p (dpyinfo->display))
+      names = XListFonts (display, pattern, limit, &num_fonts);
+      if (x_had_errors_p (display))
        {
          /* This error is perhaps due to insufficient memory on X
             server.  Let's just ignore it.  */
-         font = NULL;
-         error_occurred = 1;
-         x_clear_errors (dpyinfo->display);
+         x_clear_errors (display);
+         num_fonts = 0;
+         break;
        }
-      if (font)
+      if (num_fonts < limit)
+       break;
+      XFreeFontNames (names);
+    }
+
+  for (i = 0; i < num_fonts; i++)
+    {
+      Lisp_Object entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
+      int result;
+
+      ASET (entity, FONT_TYPE_INDEX, Qx);
+      ASET (entity, FONT_FRAME_INDEX, frame);
+
+      result = font_parse_xlfd (names[i], entity);
+      if (result < 0)
        {
+         /* This may be an alias name.  Try to get the full XLFD name
+            from XA_FONT property of the font.  */
+         XFontStruct *font = XLoadQueryFont (display, names[i]);
+         unsigned long value;
+
+         if (! font)
+           continue;
          if (XGetFontProperty (font, XA_FONT, &value))
            {
-             char *n = (char *) XGetAtomName (dpyinfo->display, (Atom) value);
-             int len = strlen (n);
-             char *tmp;
+             char *name = (char *) XGetAtomName (display, (Atom) value);
+             int len = strlen (name);
 
              /* If DXPC (a Differential X Protocol Compressor)
                  Ver.3.7 is running, XGetAtomName will return null
                  string.  We must avoid such a name.  */
              if (len > 0)
-               {
-                 num_fonts = 1;
-                 names = (char **) alloca (sizeof (char *));
-                 /* Some systems only allow alloca assigned to a
-                     simple var.  */
-                 tmp = (char *) alloca (len + 1);  names[0] = tmp;
-                 bcopy (n, names[0], len + 1);
-               }
-             XFree (n);
+               result = font_parse_xlfd (name, entity);
+             XFree (name);
            }
-         XFreeFont (dpyinfo->display, font);
+         XFreeFont (display, font);
        }
-    }
-  else
-    {
-      Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
-      Lisp_Object alter = Qnil;
-      char *r = NULL;
-
-      if (! NILP (registry))
-       alter = Fassoc_string (SYMBOL_NAME (registry),
-                              Vface_alternative_font_registry_alist);
-      while (1)
+
+      if (result == 0)
        {
-         for (limit = 512, num_fonts = 0; ; limit *= 2)
-           {
-             names = XListFonts (dpyinfo->display, name, limit, &num_fonts);
-             if (x_had_errors_p (dpyinfo->display))
-               {
-                 /* This error is perhaps due to insufficient memory
-                    on X server.  Let's just ignore it.  */
-                 x_clear_errors (dpyinfo->display);
-                 error_occurred = 1;
-                 num_fonts = 0;
-                 break;
-               }
-             if (num_fonts < limit)
-               break;
-             XFreeFontNames (names);
-           }
-         if (num_fonts > 0
-             || NILP (alter))
-           break;
-
-         /* Setup for trying alternatives.  */
-         if (! r
-             && ! (r = strstr (name, (char *) SDATA (SYMBOL_NAME (registry)))))
-           abort ();
-         while (1)
+         Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX);
+         char *p = (char *) SDATA (SYMBOL_NAME (val));
+
+         /* P == "RESX-RESY-SPACING-AVGWIDTH.  We rejust this font if
+            it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0).  */
+         if (atoi (p) > 0)
            {
-             registry = Qnil;
-             alter = XCDR (alter);
-             if (NILP (alter))
-               break;
-             registry = XCAR (alter);
-             if ((r - name) + SBYTES (registry) < 255)
-               break;
+             p += SBYTES (SYMBOL_NAME (val));
+             while (p[-1] != '-') p--;
+             if (atoi (p) == 0)
+               continue;
            }
-         if (NILP (registry))
-           break;
-         bcopy (SDATA (registry), r, SBYTES (registry));
+         list = Fcons (entity, list);
        }
     }
 
   x_uncatch_errors ();
   UNBLOCK_INPUT;
 
-  if (error_occurred)
-    return Qnil;
-  if (num_fonts == 0)
-    return null_vector;
+  return list;
+}
 
-  entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
-  ASET (entity, FONT_TYPE_INDEX, Qx);
-  ASET (entity, FONT_FRAME_INDEX, frame);
+static Lisp_Object
+xfont_list (frame, spec)
+     Lisp_Object frame, spec;
+{
+  FRAME_PTR f = XFRAME (frame);
+  Display *display = FRAME_X_DISPLAY_INFO (f)->display;
+  Lisp_Object list, val, extra, font_name;
+  int len;
+  char name[256];
+  
+  extra = AREF (spec, FONT_EXTRA_INDEX);
+  font_name = Qnil;
+  if (CONSP (extra))
+    {
+      val = assq_no_quit (QCotf, extra);
+      if (! NILP (val))
+       return null_vector;
+      val = assq_no_quit (QCscript, extra);
+      if (! NILP (val))
+       return null_vector;
+      val = assq_no_quit (QClanguage, extra);
+      if (! NILP (val))
+       return null_vector;
+      val = assq_no_quit (QCname, extra);
+      if (CONSP (val))
+       font_name = XCDR (val);
+    }
 
-  SAFE_ALLOCA_LISP (vec, num_fonts);
-  for (i = idx = 0; i < num_fonts; i++)
+  if (STRINGP (font_name)
+      && ! strchr ((char *) SDATA (font_name), ':'))
+    list = xfont_list_pattern (frame, display, (char *) SDATA (font_name));
+  else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0)
+    return null_vector;
+  else
     {
-      if (font_parse_xlfd (names[i], entity, 0) > 0)
-       vec[idx++] = Fcopy_sequence (entity);
+      list = xfont_list_pattern (frame, display, name);
+      if (NILP (list))
+       {
+         Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
+         Lisp_Object alter;
+
+         if (! NILP (registry)
+             && (alter = Fassoc (SYMBOL_NAME (registry),
+                                 Vface_alternative_font_registry_alist),
+                 CONSP (alter)))
+           {
+             /* Pointer to REGISTRY-ENCODING field.  */
+             char *r = name + len - SBYTES (SYMBOL_NAME (registry));
+
+             for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
+               if (STRINGP (XCAR (alter))
+                   && ((r - name) + SBYTES (XCAR (alter))) < 255)
+                 {
+                   strcpy (r, (char *) SDATA (XCAR (alter)));
+                   list = xfont_list_pattern (frame, display, name);
+                   if (! NILP (list))
+                     break;
+                 }
+           }
+       }
     }
-  if (! STRINGP (font_name))
+
+  return (NILP (list) ? null_vector : Fvconcat (1, &list));
+}
+
+static Lisp_Object
+xfont_match (frame, spec)
+     Lisp_Object frame, spec;
+{
+  FRAME_PTR f = XFRAME (frame);
+  Display *display = FRAME_X_DISPLAY_INFO (f)->display;
+  Lisp_Object extra, val, entity;
+  char *name;
+  XFontStruct *xfont;
+  unsigned long value;
+
+  extra = AREF (spec, FONT_EXTRA_INDEX);
+  val = assq_no_quit (QCname, extra);
+  if (! CONSP (val) || ! STRINGP (XCDR (val)))
+    return Qnil;
+
+  BLOCK_INPUT;
+  entity = Qnil;
+  name = (char *) SDATA (XCDR (val));
+  xfont = XLoadQueryFont (display, name);
+  if (xfont)
     {
-      BLOCK_INPUT;
-      XFreeFontNames (names);
-      UNBLOCK_INPUT;
+      if (XGetFontProperty (xfont, XA_FONT, &value))
+       {
+         int len;
+
+         name = (char *) XGetAtomName (display, (Atom) value);
+         len = strlen (name);
+
+         /* If DXPC (a Differential X Protocol Compressor)
+            Ver.3.7 is running, XGetAtomName will return null
+            string.  We must avoid such a name.  */
+         if (len > 0)
+           {
+             entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
+             ASET (entity, FONT_TYPE_INDEX, Qx);
+             ASET (entity, FONT_FRAME_INDEX, frame);
+             if (font_parse_xlfd (name, entity) < 0)
+               entity = Qnil;
+           }
+         XFree (name);
+       }
+      XFreeFont (display, xfont);
     }
-  val = Fvector (idx, vec);
-  SAFE_FREE ();
+  UNBLOCK_INPUT;
 
-  return val;
+  return entity;
 }
 
 static int
@@ -464,6 +495,7 @@ memq_no_quit (elt, list)
 
 static Lisp_Object
 xfont_list_family (frame)
+     Lisp_Object frame;
 {
   FRAME_PTR f = XFRAME (frame);
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
@@ -560,6 +592,7 @@ xfont_open (f, entity, pixel_size)
   if (! xfont)
     return NULL;
   font = malloc (sizeof (struct font));
+  font->format = Qx;
   font->font.font = xfont;
   font->entity = entity;
   font->pixel_size = pixel_size;
@@ -574,7 +607,7 @@ xfont_open (f, entity, pixel_size)
   bcopy (name, font->font.name, len + 1);
   font->font.charset = encoding->id;
   font->encoding_charset = encoding->id;
-  font->repertory_charet = repertory ? repertory->id : -1;
+  font->repertory_charset = repertory ? repertory->id : -1;
   font->ascent = xfont->ascent;
   font->descent = xfont->descent;
 
@@ -768,14 +801,14 @@ xfont_encode_char (font, c)
   code = ENCODE_CHAR (charset, c);
   if (code == CHARSET_INVALID_CODE (charset))
     return 0xFFFFFFFF;
-  if (font->repertory_charet >= 0)
+  if (font->repertory_charset >= 0)
     {
-      charset = CHARSET_FROM_ID (font->repertory_charet);
+      charset = CHARSET_FROM_ID (font->repertory_charset);
       return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
              ? code : 0xFFFFFFFF);
     }
-  char2b.byte1 = code >> 16;
-  char2b.byte2 = code & 0xFFFF;
+  char2b.byte1 = code >> 8;
+  char2b.byte2 = code & 0xFF;
   return (xfont_get_pcm (font->font.font, &char2b) ? code : 0xFFFFFFFF);
 }
 
@@ -824,6 +857,17 @@ xfont_draw (s, from, to, x, y, with_background)
 {
   XFontStruct *xfont = s->face->font;
   int len = to - from;
+  GC gc = s->gc;
+
+  if (gc != s->face->gc)
+    {
+      XGCValues xgcv;
+      Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (s->f);
+
+      XGetGCValues (s->display, gc, GCFont, &xgcv);
+      if (xgcv.font != xfont->fid)
+       XSetFont (s->display, gc, xfont->fid);
+    }
 
   if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
     {
@@ -836,20 +880,20 @@ xfont_draw (s, from, to, x, y, with_background)
        str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
       if (with_background > 0)
        XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
-                         s->gc, x, y, str, len);
+                         gc, x, y, str, len);
       else
        XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
-                    s->gc, x, y, str, len);
+                    gc, x, y, str, len);
       SAFE_FREE ();
       return s->nchars;
     }
 
   if (with_background > 0)
     XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
-                       s->gc, x, y, s->char2b + from, len);
+                       gc, x, y, s->char2b + from, len);
   else
     XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
-                  s->gc, x, y, s->char2b + from, len);
+                  gc, x, y, s->char2b + from, len);
 
   return len;
 }
@@ -866,3 +910,6 @@ syms_of_xfont ()
   xfont_driver.type = Qx;
   register_font_driver (&xfont_driver, NULL);
 }
+
+/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
+   (do not change this comment) */