]> git.eshelyaron.com Git - emacs.git/commitdiff
(split_font_name): Compute numeric value of
authorGerd Moellmann <gerd@gnu.org>
Mon, 5 Feb 2001 20:01:01 +0000 (20:01 +0000)
committerGerd Moellmann <gerd@gnu.org>
Mon, 5 Feb 2001 20:01:01 +0000 (20:01 +0000)
XLFD_AVGWIDTH.
(LFACE_AVGWIDTH): New macro.
(LFACEP): Use AREF.
(check_lface_attrs): Check LFACE_AVGWIDTH.
(lface_fully_specified_p): Don't check LFACE_AVGWIDTH.
(set_lface_from_font_name): Set LFACE_AVGWIDTH.
(merge_face_vectors): Check LFACE_AVGWIDTH.
(Finternal_make_lisp_face): Use AREF.
(xm_set_menu_resources_from_menu_face)
(xl_set_menu_resources_from_menu_face): Check LFACE_AVGWIDTH.
(Finternal_lisp_face_empty_p): Use AREF.
(lface_same_font_attributes_p): Compare LFACE_AVGWIDTH.
(better_font_p, exact_face_match_p): Add parameter AVGWIDTH.
Compare average widths..
(best_matching_font): Arrange for comparing average widths.

src/ChangeLog
src/xfaces.c

index ac307862aa496c41c81e08e24dafaa0c206dbf64..df8e58ac4bcd0e65248c2c35a7545a8349e6788f 100644 (file)
@@ -1,3 +1,25 @@
+2001-02-05  Gerd Moellmann  <gerd@gnu.org>
+
+       * xfaces.c (split_font_name): Compute numeric value of
+       XLFD_AVGWIDTH.
+       (LFACE_AVGWIDTH): New macro.
+       (LFACEP): Use AREF.
+       (check_lface_attrs): Check LFACE_AVGWIDTH.
+       (lface_fully_specified_p): Don't check LFACE_AVGWIDTH.
+       (set_lface_from_font_name): Set LFACE_AVGWIDTH.
+       (merge_face_vectors): Check LFACE_AVGWIDTH.
+       (Finternal_make_lisp_face): Use AREF.
+       (xm_set_menu_resources_from_menu_face)
+       (xl_set_menu_resources_from_menu_face): Check LFACE_AVGWIDTH.
+       (Finternal_lisp_face_empty_p): Use AREF.
+       (lface_same_font_attributes_p): Compare LFACE_AVGWIDTH.
+       (better_font_p, exact_face_match_p): Add parameter AVGWIDTH.
+       Compare average widths..
+       (best_matching_font): Arrange for comparing average widths.
+
+       * dispextern.h (enum lface_attribute_index): Add
+       LFACE_AVGWIDTH_INDEX (invisible from Lisp).
+       
 2001-02-05  Dave Love  <fx@gnu.org>
 
        * puresize.h: Revert last change following loadup.el change.
index fc8a224b5bd82f72cd7c69f1668e4a788ebaedc9..64e53fc12d6ed64393cb377982d35504ae7786fd 100644 (file)
@@ -68,6 +68,10 @@ Boston, MA 02111-1307, USA.  */
 
    15. A face name or list of face names from which to inherit attributes.
 
+   16. A specified average font width, which is invisible from Lisp,
+   and is used to ensure that a font specified on the command line,
+   for example, can be matched exactly.
+
    Faces are frame-local by nature because Emacs allows to define the
    same named face (face names are symbols) differently for different
    frames.  Each frame has an alist of face definitions for all named
@@ -504,7 +508,7 @@ static Lisp_Object resolve_face_name P_ ((Lisp_Object));
 static int may_use_scalable_font_p P_ ((struct font_name *, char *));
 static void set_font_frame_param P_ ((Lisp_Object, Lisp_Object));
 static int better_font_p P_ ((int *, struct font_name *, struct font_name *,
-                             int));
+                             int, int));
 static int first_font_matching P_ ((struct frame *f, char *,
                                    struct font_name *));
 static int x_face_list_fonts P_ ((struct frame *, char *,
@@ -1859,7 +1863,9 @@ static struct frame *font_frame;
    set via set-face-font-sort-order.  */
 
 #ifdef macintosh
-static int font_sort_order[4] = { XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT };
+static int font_sort_order[4] = {
+  XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT
+};
 #else
 static int font_sort_order[4];
 #endif
@@ -2193,6 +2199,7 @@ split_font_name (f, font, numeric_p)
       font->numeric[XLFD_SLANT] = xlfd_numeric_slant (font);
       font->numeric[XLFD_WEIGHT] = xlfd_numeric_weight (font);
       font->numeric[XLFD_SWIDTH] = xlfd_numeric_swidth (font);
+      font->numeric[XLFD_AVGWIDTH] = atoi (font->fields[XLFD_AVGWIDTH]);
     }
 
   /* Initialize it to zero.  It will be overridden by font_list while
@@ -2835,38 +2842,24 @@ the WIDTH times as wide as FACE on FRAME.")
                              Lisp Faces
  ***********************************************************************/
 
-/* Access face attributes of face FACE, a Lisp vector.  */
-
-#define LFACE_FAMILY(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FAMILY_INDEX]
-#define LFACE_HEIGHT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_HEIGHT_INDEX]
-#define LFACE_WEIGHT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_WEIGHT_INDEX]
-#define LFACE_SLANT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_SLANT_INDEX]
-#define LFACE_UNDERLINE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_UNDERLINE_INDEX]
-#define LFACE_INVERSE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_INVERSE_INDEX]
-#define LFACE_FOREGROUND(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FOREGROUND_INDEX]
-#define LFACE_BACKGROUND(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_BACKGROUND_INDEX]
-#define LFACE_STIPPLE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_STIPPLE_INDEX]
-#define LFACE_SWIDTH(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_SWIDTH_INDEX]
-#define LFACE_OVERLINE(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_OVERLINE_INDEX]
-#define LFACE_STRIKE_THROUGH(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_STRIKE_THROUGH_INDEX]
-#define LFACE_BOX(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_BOX_INDEX]
-#define LFACE_FONT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_FONT_INDEX]
-#define LFACE_INHERIT(LFACE) \
-     XVECTOR (LFACE)->contents[LFACE_INHERIT_INDEX]
+/* Access face attributes of face LFACE, a Lisp vector.  */
+
+#define LFACE_FAMILY(LFACE)        AREF ((LFACE), LFACE_FAMILY_INDEX)
+#define LFACE_HEIGHT(LFACE)        AREF ((LFACE), LFACE_HEIGHT_INDEX)
+#define LFACE_WEIGHT(LFACE)        AREF ((LFACE), LFACE_WEIGHT_INDEX)
+#define LFACE_SLANT(LFACE)         AREF ((LFACE), LFACE_SLANT_INDEX)
+#define LFACE_UNDERLINE(LFACE)      AREF ((LFACE), LFACE_UNDERLINE_INDEX)
+#define LFACE_INVERSE(LFACE)       AREF ((LFACE), LFACE_INVERSE_INDEX)
+#define LFACE_FOREGROUND(LFACE)     AREF ((LFACE), LFACE_FOREGROUND_INDEX)
+#define LFACE_BACKGROUND(LFACE)     AREF ((LFACE), LFACE_BACKGROUND_INDEX)
+#define LFACE_STIPPLE(LFACE)       AREF ((LFACE), LFACE_STIPPLE_INDEX)
+#define LFACE_SWIDTH(LFACE)        AREF ((LFACE), LFACE_SWIDTH_INDEX)
+#define LFACE_OVERLINE(LFACE)      AREF ((LFACE), LFACE_OVERLINE_INDEX)
+#define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
+#define LFACE_BOX(LFACE)           AREF ((LFACE), LFACE_BOX_INDEX)
+#define LFACE_FONT(LFACE)          AREF ((LFACE), LFACE_FONT_INDEX)
+#define LFACE_INHERIT(LFACE)       AREF ((LFACE), LFACE_INHERIT_INDEX)
+#define LFACE_AVGWIDTH(LFACE)      AREF ((LFACE), LFACE_AVGWIDTH_INDEX)
 
 /* Non-zero if LFACE is a Lisp face.  A Lisp face is a vector of size
    LFACE_VECTOR_SIZE which has the symbol `face' in slot 0.  */
@@ -2874,7 +2867,7 @@ the WIDTH times as wide as FACE on FRAME.")
 #define LFACEP(LFACE)                                  \
      (VECTORP (LFACE)                                  \
       && XVECTOR (LFACE)->size == LFACE_VECTOR_SIZE    \
-      && EQ (XVECTOR (LFACE)->contents[0], Qface))
+      && EQ (AREF (LFACE, 0), Qface))
 
 
 #if GLYPH_DEBUG
@@ -2889,6 +2882,8 @@ check_lface_attrs (attrs)
           || STRINGP (attrs[LFACE_FAMILY_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
           || SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
+  xassert (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
+          || INTEGERP (attrs[LFACE_AVGWIDTH_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
           || INTEGERP (attrs[LFACE_HEIGHT_INDEX])
           || FLOATP (attrs[LFACE_HEIGHT_INDEX])
@@ -3053,7 +3048,8 @@ lface_fully_specified_p (attrs)
   int i;
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX)
+    if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
+       && i != LFACE_AVGWIDTH_INDEX)
       if (UNSPECIFIEDP (attrs[i])) 
         break;
 
@@ -3148,6 +3144,12 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
     LFACE_SWIDTH (lface)
       = have_xlfd_p ? xlfd_symbolic_swidth (&font) : Qnormal;
 
+  if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
+    LFACE_AVGWIDTH (lface)
+      = (have_xlfd_p
+        ? make_number (font.numeric[XLFD_AVGWIDTH])
+        : Qunspecified);
+
   if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
     LFACE_WEIGHT (lface)
       = have_xlfd_p ? xlfd_symbolic_weight (&font) : Qnormal;
@@ -3263,7 +3265,8 @@ merge_face_vectors (f, from, to, cycle_check)
          || !UNSPECIFIEDP (from[LFACE_HEIGHT_INDEX])
          || !UNSPECIFIEDP (from[LFACE_WEIGHT_INDEX])
          || !UNSPECIFIEDP (from[LFACE_SLANT_INDEX])
-         || !UNSPECIFIEDP (from[LFACE_SWIDTH_INDEX])))
+         || !UNSPECIFIEDP (from[LFACE_SWIDTH_INDEX])
+         || !UNSPECIFIEDP (from[LFACE_AVGWIDTH_INDEX])))
     to[LFACE_FONT_INDEX] = Qnil;
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
@@ -3601,7 +3604,7 @@ Value is a vector of face attributes.")
     {
       global_lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
                                   Qunspecified);
-      XVECTOR (global_lface)->contents[0] = Qface;
+      AREF (global_lface, 0) = Qface;
       Vface_new_frame_defaults = Fcons (Fcons (face, global_lface),
                                        Vface_new_frame_defaults);
 
@@ -3623,7 +3626,7 @@ Value is a vector of face attributes.")
     }
   else if (f == NULL)
     for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-      XVECTOR (global_lface)->contents[i] = Qunspecified;
+      AREF (global_lface, i) = Qunspecified;
 
   /* Add a frame-local definition.  */
   if (f)
@@ -3632,12 +3635,12 @@ Value is a vector of face attributes.")
        {
          lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
                                Qunspecified);
-         XVECTOR (lface)->contents[0] = Qface;
+         AREF (lface, 0) = Qface;
          f->face_alist = Fcons (Fcons (face, lface), f->face_alist);
        }
       else
        for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-         XVECTOR (lface)->contents[i] = Qunspecified;
+         AREF (lface, i) = Qunspecified;
     }
   else
     lface = global_lface;
@@ -4420,6 +4423,7 @@ xm_set_menu_resources_from_menu_face (f, widget)
   if (face->font
       && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
          || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+         || !UNSPECIFIEDP (LFACE_AVGWIDTH (lface))
          || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
          || !UNSPECIFIEDP (LFACE_SLANT (lface))
          || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
@@ -4500,6 +4504,7 @@ xl_set_menu_resources_from_menu_face (f, widget)
   if (face->font
       && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
          || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+         || !UNSPECIFIEDP (LFACE_AVGWIDTH (lface))
          || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
          || !UNSPECIFIEDP (LFACE_SLANT (lface))
          || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
@@ -4845,7 +4850,7 @@ If FRAME is omitted or nil, use the selected frame.")
     lface = lface_from_face_name (f, face, 1);
 
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
-    if (!UNSPECIFIEDP (XVECTOR (lface)->contents[i]))
+    if (!UNSPECIFIEDP (AREF (lface, i)))
       break;
 
   return i == LFACE_VECTOR_SIZE ? Qt : Qnil;
@@ -4911,6 +4916,7 @@ lface_same_font_attributes_p (lface1, lface2)
                    XSTRING (lface2[LFACE_FAMILY_INDEX])->data) == 0
          && EQ (lface1[LFACE_HEIGHT_INDEX], lface2[LFACE_HEIGHT_INDEX])
          && EQ (lface1[LFACE_SWIDTH_INDEX], lface2[LFACE_SWIDTH_INDEX])
+         && EQ (lface1[LFACE_AVGWIDTH_INDEX], lface2[LFACE_AVGWIDTH_INDEX])
          && EQ (lface1[LFACE_WEIGHT_INDEX], lface2[LFACE_WEIGHT_INDEX])
          && EQ (lface1[LFACE_SLANT_INDEX], lface2[LFACE_SLANT_INDEX])
          && (EQ (lface1[LFACE_FONT_INDEX], lface2[LFACE_FONT_INDEX])
@@ -5543,7 +5549,7 @@ Value is ORDER.")
 {
   Lisp_Object list;
   int i;
-  int indices[4];
+  int indices[DIM (font_sort_order)];
 
   CHECK_LIST (order, 0);
   bzero (indices, sizeof indices);
@@ -5572,13 +5578,11 @@ Value is ORDER.")
       indices[i] = xlfd;
     }
 
-  if (!NILP (list)
-      || i != DIM (indices)
-      || indices[0] == 0
-      || indices[1] == 0
-      || indices[2] == 0
-      || indices[3] == 0)
+  if (!NILP (list) || i != DIM (indices))
     signal_error ("Invalid font sort order", order);
+  for (i = 0; i < DIM (font_sort_order); ++i)
+    if (indices[i] == 0)
+      signal_error ("Invalid font sort order", order);
 
   if (bcmp (indices, font_sort_order, sizeof indices) != 0)
     {
@@ -5655,17 +5659,18 @@ font_scalable_p (font)
 /* Value is non-zero if FONT1 is a better match for font attributes
    VALUES than FONT2.  VALUES is an array of face attribute values in
    font sort order.  COMPARE_PT_P zero means don't compare point
-   sizes.  */
+   sizes.  AVGWIDTH, if not zero, is a specified font average width
+   to compare with.  */
 
 static int
-better_font_p (values, font1, font2, compare_pt_p)
+better_font_p (values, font1, font2, compare_pt_p, avgwidth)
      int *values;
      struct font_name *font1, *font2;
-     int compare_pt_p;
+     int compare_pt_p, avgwidth;
 {
   int i;
 
-  for (i = 0; i < 4; ++i)
+  for (i = 0; i < DIM (font_sort_order); ++i)
     {
       int xlfd_idx = font_sort_order[i];
 
@@ -5694,26 +5699,40 @@ better_font_p (values, font1, font2, compare_pt_p)
        }
     }
 
-  return (font1->registry_priority < font2->registry_priority);
+  if (avgwidth)
+    {
+      int delta1 = abs (avgwidth - font1->numeric[XLFD_AVGWIDTH]);
+      int delta2 = abs (avgwidth - font2->numeric[XLFD_AVGWIDTH]);
+      if (delta1 > delta2)
+       return 0;
+      else if (delta1 < delta2)
+       return 1;
+    }
+
+  return font1->registry_priority < font2->registry_priority;
 }
 
 
 /* Value is non-zero if FONT is an exact match for face attributes in
    SPECIFIED.  SPECIFIED is an array of face attribute values in font
-   sort order.  */
+   sort order.  AVGWIDTH, if non-zero, is an average width to compare
+   with.  */
 
 static int
-exact_face_match_p (specified, font)
+exact_face_match_p (specified, font, avgwidth)
      int *specified;
      struct font_name *font;
+     int avgwidth;
 {
   int i;
 
-  for (i = 0; i < 4; ++i)
+  for (i = 0; i < DIM (font_sort_order); ++i)
     if (specified[i] != font->numeric[font_sort_order[i]])
       break;
 
-  return i == 4;
+  return (i == DIM (font_sort_order)
+         && (avgwidth <= 0
+             || avgwidth == font->numeric[XLFD_AVGWIDTH]));
 }
 
 
@@ -5823,8 +5842,8 @@ best_matching_font (f, attrs, fonts, nfonts)
   char *font_name;
   struct font_name *best;
   int i, pt = 0;
-  int specified[4];
-  int exact_p;
+  int specified[5];
+  int exact_p, avgwidth;
 
   if (nfonts == 0)
     return NULL;
@@ -5847,6 +5866,10 @@ best_matching_font (f, attrs, fonts, nfonts)
        abort ();
     }
 
+  avgwidth = (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
+             ? 0
+             : XFASTINT (attrs[LFACE_AVGWIDTH_INDEX]));
+
   exact_p = 0;
 
   /* Start with the first non-scalable font in the list.  */
@@ -5861,11 +5884,11 @@ best_matching_font (f, attrs, fonts, nfonts)
 
       for (i = 1; i < nfonts; ++i)
        if (!font_scalable_p (fonts + i)
-           && better_font_p (specified, fonts + i, best, 1))
+           && better_font_p (specified, fonts + i, best, 1, avgwidth))
          {
            best = fonts + i;
 
-           exact_p = exact_face_match_p (specified, best);
+           exact_p = exact_face_match_p (specified, best, avgwidth);
            if (exact_p)
              break;
          }
@@ -5897,9 +5920,9 @@ best_matching_font (f, attrs, fonts, nfonts)
        if (font_scalable_p (fonts + i))
          {
            if (best == NULL
-               || better_font_p (specified, fonts + i, best, 0)
+               || better_font_p (specified, fonts + i, best, 0, 0)
                || (!non_scalable_has_exact_height_p
-                   && !better_font_p (specified, best, fonts + i, 0)))
+                   && !better_font_p (specified, best, fonts + i, 0, 0)))
              best = fonts + i;
          }
     }
@@ -6131,6 +6154,7 @@ realize_default_face (f)
       LFACE_HEIGHT (lface) = make_number (1);
       LFACE_WEIGHT (lface) = Qnormal;
       LFACE_SLANT (lface) = Qnormal;
+      LFACE_AVGWIDTH (lface) = Qunspecified;
     }
 
   if (UNSPECIFIEDP (LFACE_UNDERLINE (lface)))