(tty_supports_face_attributes_p): Use instead of LFACE_INVERSE_INDEX
[bpt/emacs.git] / src / xfaces.c
index 89fad41..26c98c4 100644 (file)
@@ -1,12 +1,12 @@
 /* xfaces.c -- "Face" primitives.
    Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005 Free Software Foundation, Inc.
+                 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -486,7 +486,6 @@ static int font_scalable_p P_ ((struct font_name *));
 static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int));
 static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *));
 static unsigned char *xstrlwr P_ ((unsigned char *));
-static void signal_error P_ ((char *, Lisp_Object));
 static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
 static void load_face_font P_ ((struct frame *, struct face *, int));
 static void load_face_colors P_ ((struct frame *, struct face *, Lisp_Object *));
@@ -855,17 +854,6 @@ xstrlwr (s)
 }
 
 
-/* Signal `error' with message S, and additional argument ARG.  */
-
-static void
-signal_error (s, arg)
-     char *s;
-     Lisp_Object arg;
-{
-  Fsignal (Qerror, Fcons (build_string (s), Fcons (arg, Qnil)));
-}
-
-
 /* If FRAME is nil, return a pointer to the selected frame.
    Otherwise, check that FRAME is a live frame, and return a pointer
    to it.  NPARAM is the parameter number of FRAME, for
@@ -1171,14 +1159,11 @@ load_pixmap (f, name, w_ptr, h_ptr)
      unsigned int *w_ptr, *h_ptr;
 {
   int bitmap_id;
-  Lisp_Object tem;
 
   if (NILP (name))
     return 0;
 
-  tem = Fbitmap_spec_p (name);
-  if (NILP (tem))
-    wrong_type_argument (Qbitmap_spec_p, name);
+  CHECK_TYPE (!NILP (Fbitmap_spec_p (name)), Qbitmap_spec_p, name);
 
   BLOCK_INPUT;
   if (CONSP (name))
@@ -1204,7 +1189,7 @@ load_pixmap (f, name, w_ptr, h_ptr)
 
   if (bitmap_id < 0)
     {
-      add_to_log ("Invalid or undefined bitmap %s", name, Qnil);
+      add_to_log ("Invalid or undefined bitmap `%s'", name, Qnil);
       bitmap_id = 0;
 
       if (w_ptr)
@@ -3276,7 +3261,7 @@ resolve_face_name (face_name, signal_p)
       if (EQ (hare, tortoise))
        {
          if (signal_p)
-           Fsignal (Qcircular_list, Fcons (orig_face, Qnil));
+           xsignal1 (Qcircular_list, orig_face);
          return Qdefault;
        }
     }
@@ -3576,8 +3561,6 @@ merge_face_vectors (f, from, to, named_merge_points)
       {
        if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
          to[i] = merge_face_heights (from[i], to[i], to[i]);
-       else if (IGNORE_DEFFACE_P (from[i]))
-         to[i] = Qunspecified;
        else
          to[i] = from[i];
       }
@@ -4054,7 +4037,18 @@ FRAME 0 means change the face on all frames, and change the default
 
   /* Set lface to the Lisp attribute vector of FACE.  */
   if (EQ (frame, Qt))
-    lface = lface_from_face_name (NULL, face, 1);
+    {
+      lface = lface_from_face_name (NULL, face, 1);
+
+      /* When updating face-new-frame-defaults, we put :ignore-defface
+        where the caller wants `unspecified'.  This forces the frame
+        defaults to ignore the defface value.  Otherwise, the defface
+        will take effect, which is generally not what is intended.
+        The value of that attribute will be inherited from some other
+        face during face merging.  See internal_merge_in_global_face. */
+      if (UNSPECIFIEDP (value))
+       value = Qignore_defface;
+    }
   else
     {
       if (NILP (frame))
@@ -4678,7 +4672,7 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
       if (SYMBOLP (boolean_value))
        value = boolean_value;
     }
-  else if (EQ (attr, QCbox))
+  else if (EQ (attr, QCbox) || EQ (attr, QCinherit))
     value = Fcar (Fread_from_string (value, Qnil, Qnil));
 
   return Finternal_set_lisp_face_attribute (face, attr, value, frame);
@@ -4790,7 +4784,14 @@ x_update_menu_appearance (f)
 DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p,
        Sface_attribute_relative_p,
        2, 2, 0,
-       doc: /* Return non-nil if face ATTRIBUTE VALUE is relative.  */)
+       doc: /* Check whether a face attribute value is relative.
+Specifically, this function returns t if the attribute ATTRIBUTE
+with the value VALUE is relative.
+
+A relative value is one that doesn't entirely override whatever is
+inherited from another face.  For most possible attributes,
+the only relative value that users see is `unspecified'.
+However, for :height, floating point values are also relative.  */)
      (attribute, value)
      Lisp_Object attribute, value;
 {
@@ -4880,6 +4881,9 @@ frames).  If FRAME is omitted or nil, use the selected frame.  */)
   else
     signal_error ("Invalid face attribute name", keyword);
 
+  if (IGNORE_DEFFACE_P (value))
+    return Qunspecified;
+
   return value;
 }
 
@@ -4962,7 +4966,12 @@ Default face attributes override any local face attributes.  */)
   gvec = XVECTOR (global_lface)->contents;
   for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
     if (! UNSPECIFIEDP (gvec[i]))
-      lvec[i] = gvec[i];
+      {
+       if (IGNORE_DEFFACE_P (gvec[i]))
+         lvec[i] = Qunspecified;
+       else
+         lvec[i] = gvec[i];
+      }
 
   return Qnil;
 }
@@ -5339,13 +5348,11 @@ If FRAME is unspecified or nil, the current frame is used.  */)
   CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
 
-  if ((CONSP (color1) && !parse_rgb_list (color1, &cdef1))
-      || !STRINGP (color1)
-      || !defined_color (f, SDATA (color1), &cdef1, 0))
+  if (!(CONSP (color1) && parse_rgb_list (color1, &cdef1))
+      && !(STRINGP (color1) && defined_color (f, SDATA (color1), &cdef1, 0)))
     signal_error ("Invalid color", color1);
-  if ((CONSP (color2) && !parse_rgb_list (color2, &cdef2))
-      || !STRINGP (color2)
-      || !defined_color (f, SDATA (color2), &cdef2, 0))
+  if (!(CONSP (color2) && parse_rgb_list (color2, &cdef2))
+      && !(STRINGP (color2) && defined_color (f, SDATA (color2), &cdef2, 0)))
     signal_error ("Invalid color", color2);
 
   return make_number (color_distance (&cdef1, &cdef2));
@@ -5708,6 +5715,8 @@ lookup_named_face (f, symbol, c, signal_p)
       if (!realize_basic_faces (f))
        return -1;
       default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+      if (default_face == NULL)
+       abort ();  /* realize_basic_faces must have set it up  */
     }
 
   if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p))
@@ -6055,7 +6064,7 @@ tty_supports_face_attributes_p (f, attrs, def_face)
   val = attrs[LFACE_INVERSE_INDEX];
   if (!UNSPECIFIEDP (val))
     {
-      if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
+      if (face_attr_equal_p (val, def_attrs[LFACE_INVERSE_INDEX]))
        return 0;               /* same as default */
       else
        test_caps |= TTY_CAP_INVERSE;
@@ -6098,7 +6107,7 @@ tty_supports_face_attributes_p (f, attrs, def_face)
   bg = attrs[LFACE_BACKGROUND_INDEX];
   if (STRINGP (bg))
     {
-      Lisp_Object def_bg = def_attrs[LFACE_FOREGROUND_INDEX];
+      Lisp_Object def_bg = def_attrs[LFACE_BACKGROUND_INDEX];
 
       if (face_attr_equal_p (bg, def_bg))
        return 0;               /* same as default */
@@ -6167,7 +6176,7 @@ face for italic.  */)
   (attributes, display)
      Lisp_Object attributes, display;
 {
-  int supports, i;
+  int supports = 0, i;
   Lisp_Object frame;
   struct frame *f;
   struct face *def_face;
@@ -6212,6 +6221,8 @@ face for italic.  */)
       if (! realize_basic_faces (f))
        error ("Cannot realize default face");
       def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+      if (def_face == NULL)
+       abort ();  /* realize_basic_faces must have set it up  */
     }
 
   /* Dispatch to the appropriate handler.  */
@@ -6366,6 +6377,12 @@ better_font_p (values, font1, font2, compare_pt_p, avgwidth)
 {
   int i;
 
+  /* Any font is better than no font.  */
+  if (! font1)
+    return 0;
+  if (! font2)
+    return 1;
+
   for (i = 0; i < DIM (font_sort_order); ++i)
     {
       int xlfd_idx = font_sort_order[i];
@@ -6610,29 +6627,19 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
   if (needs_overstrike)
     *needs_overstrike = 0;
 
-  /* Start with the first non-scalable font in the list.  */
-  for (i = 0; i < nfonts; ++i)
-    if (!font_scalable_p (fonts + i))
-      break;
+  best = NULL;
 
   /* Find the best match among the non-scalable fonts.  */
-  if (i < nfonts)
-    {
-      best = fonts + i;
-
-      for (i = 1; i < nfonts; ++i)
-       if (!font_scalable_p (fonts + i)
-           && better_font_p (specified, fonts + i, best, 1, avgwidth))
-         {
-           best = fonts + i;
+  for (i = 0; i < nfonts; ++i)
+    if (!font_scalable_p (fonts + i)
+       && better_font_p (specified, fonts + i, best, 1, avgwidth))
+      {
+       best = fonts + i;
 
-           exact_p = exact_face_match_p (specified, best, avgwidth);
-           if (exact_p)
-             break;
-         }
-    }
-  else
-    best = NULL;
+       exact_p = exact_face_match_p (specified, best, avgwidth);
+       if (exact_p)
+         break;
+      }
 
   /* Unless we found an exact match among non-scalable fonts, see if
      we can find a better match among scalable fonts.  */
@@ -6656,8 +6663,7 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
       for (i = 0; i < nfonts; ++i)
        if (font_scalable_p (fonts + i))
          {
-           if (best == NULL
-               || better_font_p (specified, fonts + i, best, 0, 0)
+           if (better_font_p (specified, fonts + i, best, 0, 0)
                || (!non_scalable_has_exact_height_p
                    && !better_font_p (specified, best, fonts + i, 0, 0)))
              {
@@ -6665,23 +6671,27 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike)
                best = fonts + i;
              }
          }
+    }
 
-      if (needs_overstrike)
-       {
-         enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
-         enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
+  /* We should have found SOME font.  */
+  if (best == NULL)
+    abort ();
 
-         if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
-           {
-             /* We want a bold font, but didn't get one; try to use
-                overstriking instead to simulate bold-face.  However,
-                don't overstrike an already-bold fontn unless the
-                desired weight grossly exceeds the available weight.  */
-             if (got_weight > XLFD_WEIGHT_MEDIUM)
-               *needs_overstrike = (got_weight - want_weight) > 2;
-             else
-               *needs_overstrike = 1;
-           }
+  if (! exact_p && needs_overstrike)
+    {
+      enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
+      enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
+
+      if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
+       {
+         /* We want a bold font, but didn't get one; try to use
+            overstriking instead to simulate bold-face.  However,
+            don't overstrike an already-bold font unless the
+            desired weight grossly exceeds the available weight.  */
+         if (got_weight > XLFD_WEIGHT_MEDIUM)
+           *needs_overstrike = (want_weight - got_weight) > 2;
+         else
+           *needs_overstrike = 1;
        }
     }
 
@@ -6782,20 +6792,22 @@ try_font_list (f, attrs, family, registry, fonts, prefer_face_family)
 
 #ifdef MAC_OS
   if (nfonts == 0 && STRINGP (try_family) && STRINGP (registry))
-    if (xstricmp (SDATA (registry), "mac-roman") == 0)
-      /* When realizing the default face and a font spec does not
-        matched exactly, Emacs looks for ones with the same registry
-        as the default font.  On the Mac, this is mac-roman, which
-        does not work if the family is -etl-fixed, e.g.  The
-        following widens the choices and fixes that problem.  */
-      nfonts = try_alternative_families (f, try_family, Qnil, fonts);
-    else if (SBYTES (try_family) > 0
-            && SREF (try_family, SBYTES (try_family) - 1) != '*')
-      /* Some Central European/Cyrillic font family names have the
-        Roman counterpart name as their prefix.  */
-      nfonts = try_alternative_families (f, concat2 (try_family,
-                                                    build_string ("*")),
-                                        registry, fonts);
+    {
+      if (xstricmp (SDATA (registry), "mac-roman") == 0)
+       /* When realizing the default face and a font spec does not
+          matched exactly, Emacs looks for ones with the same registry
+          as the default font.  On the Mac, this is mac-roman, which
+          does not work if the family is -etl-fixed, e.g.  The
+          following widens the choices and fixes that problem.  */
+       nfonts = try_alternative_families (f, try_family, Qnil, fonts);
+      else if (SBYTES (try_family) > 0
+              && SREF (try_family, SBYTES (try_family) - 1) != '*')
+       /* Some Central European/Cyrillic font family names have the
+          Roman counterpart name as their prefix.  */
+       nfonts = try_alternative_families (f, concat2 (try_family,
+                                                      build_string ("*")),
+                                          registry, fonts);
+    }
 #endif
 
   if (EQ (try_family, family))
@@ -7053,6 +7065,24 @@ realize_default_face (f)
   check_lface (lface);
   bcopy (XVECTOR (lface)->contents, attrs, sizeof attrs);
   face = realize_face (c, attrs, 0, NULL, DEFAULT_FACE_ID);
+
+#ifdef HAVE_WINDOW_SYSTEM
+#ifdef HAVE_X_WINDOWS
+  if (face->font != FRAME_FONT (f))
+    {
+      /* This can happen when making a frame on a display that does
+        not support the default font.  */
+      if (!face->font)
+       return 0;
+
+      /* Otherwise, the font specified for the frame was not
+        acceptable as a font for the default face (perhaps because
+        auto-scaled fonts are rejected), so we must adjust the frame
+        font.  */
+      x_set_font (f, build_string (face->font_name), Qnil);
+    }
+#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
   return 1;
 }
 
@@ -7957,7 +7987,7 @@ syms_of_xfaces ()
   staticpro (&QCforeground);
   QCbackground = intern (":background");
   staticpro (&QCbackground);
-  QCstipple = intern (":stipple");;
+  QCstipple = intern (":stipple");
   staticpro (&QCstipple);
   QCwidth = intern (":width");
   staticpro (&QCwidth);