*** empty log message ***
[bpt/emacs.git] / src / xfaces.c
index 3ea260f..1f7c906 100644 (file)
@@ -1,5 +1,5 @@
 /* xfaces.c -- "Face" primitives.
-   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001
+   Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation.
 
 This file is part of GNU Emacs.
@@ -196,7 +196,7 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/stat.h>
 
 #include "lisp.h"
-#include "charset.h"
+#include "character.h"
 #include "keyboard.h"
 #include "frame.h"
 
@@ -364,6 +364,7 @@ Lisp_Object Qframe_update_face_colors;
 
 Lisp_Object Qdefault, Qtool_bar, Qregion, Qfringe;
 Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu;
+Lisp_Object Qmode_line_inactive;
 extern Lisp_Object Qmode_line;
 
 /* The symbol `face-alias'.  A symbols having that property is an
@@ -549,14 +550,14 @@ static unsigned hash_string_case_insensitive P_ ((Lisp_Object));
 static unsigned lface_hash P_ ((Lisp_Object *));
 static int lface_same_font_attributes_p P_ ((Lisp_Object *, Lisp_Object *));
 static struct face_cache *make_face_cache P_ ((struct frame *));
-static void free_realized_face P_ ((struct frame *, struct face *));
 static void clear_face_gcs P_ ((struct face_cache *));
 static void free_face_cache P_ ((struct face_cache *));
 static int face_numeric_weight P_ ((Lisp_Object));
 static int face_numeric_slant P_ ((Lisp_Object));
 static int face_numeric_swidth P_ ((Lisp_Object));
 static int face_fontset P_ ((Lisp_Object *));
-static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int));
+static char *choose_face_font P_ ((struct frame *, Lisp_Object *,
+                                  struct face *, int));
 static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*, Lisp_Object));
 static void merge_face_inheritance P_ ((struct frame *f, Lisp_Object,
                                        Lisp_Object *, Lisp_Object));
@@ -566,7 +567,6 @@ static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
                                         Lisp_Object, int, int));
 static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
 static struct face *make_realized_face P_ ((Lisp_Object *));
-static void free_realized_faces P_ ((struct face_cache *));
 static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
                                     struct font_name *, int, int));
 static void cache_face P_ ((struct face_cache *, struct face *, unsigned));
@@ -1267,12 +1267,13 @@ load_face_font (f, face, c)
   face->font_info_id = -1;
   face->font = NULL;
 
-  font_name = choose_face_font (f, face->lface, face->fontset, c);
+  font_name = choose_face_font (f, face->lface, face, c);
+
   if (!font_name)
     return;
 
   BLOCK_INPUT;
-  font_info = FS_LOAD_FACE_FONT (f, c, font_name, face);
+  font_info = FS_LOAD_FONT (f, font_name);
   UNBLOCK_INPUT;
 
   if (font_info)
@@ -2111,6 +2112,61 @@ face_numeric_swidth (width)
 }
 
 
+Lisp_Object
+generate_ascii_font (name, ascii_spec)
+     Lisp_Object name, ascii_spec;
+{
+  struct font_name font;
+  char *p;
+
+  font.name = LSTRDUPA (name);
+  if (! split_font_name (NULL, &font, 0))
+    return Qnil;
+
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_FAMILY_INDEX)))
+    {
+      p = LSTRDUPA (AREF (ascii_spec, FONT_SPEC_FAMILY_INDEX));
+      font.fields[XLFD_FOUNDRY] = p;
+      while (*p != '-') p++;
+      if (*p)
+       {
+         *p++ = 0;
+         font.fields[XLFD_FAMILY] = p;
+       }
+      else
+       {
+         font.fields[XLFD_FAMILY] = font.fields[XLFD_FOUNDRY];
+         font.fields[XLFD_FOUNDRY] = "*";
+       }
+    }
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_WEIGHT_INDEX)))
+    font.fields[XLFD_WEIGHT]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_WEIGHT_INDEX))->data;
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_SLANT_INDEX)))
+    font.fields[XLFD_SLANT]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_SLANT_INDEX))->data;
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_SWIDTH_INDEX)))
+    font.fields[XLFD_SWIDTH]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_SWIDTH_INDEX))->data;
+  if (STRINGP (AREF (ascii_spec, FONT_SPEC_ADSTYLE_INDEX)))
+    font.fields[XLFD_ADSTYLE]
+      = XSTRING (AREF (ascii_spec, FONT_SPEC_ADSTYLE_INDEX))->data;
+  p = LSTRDUPA (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
+  font.fields[XLFD_REGISTRY] = p;
+  while (*p != '-') p++;
+  if (*p)
+    *p++ = 0;
+  else
+    p = "*";
+  font.fields[XLFD_ENCODING] = p;
+
+  p = build_font_name (&font);
+  name = build_string (p);
+  xfree (p);
+  return name;
+}
+
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Return non-zero if FONT is the name of a fixed-pitch font.  */
@@ -3148,7 +3204,7 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p)
      caching it now is not futail because we anyway load the font
      later.  */
   BLOCK_INPUT;
-  font_info = FS_LOAD_FONT (f, 0, font_name, -1);
+  font_info = FS_LOAD_FONT (f, font_name);
   UNBLOCK_INPUT;
 
   if (!font_info)
@@ -3240,7 +3296,7 @@ merge_face_heights (from, to, invalid, gcpro)
     {
       if (INTEGERP (to))
        /* relative X absolute => absolute */
-       result = make_number (XFLOAT_DATA (from) * XINT (to));
+       result = make_number ((EMACS_INT)(XFLOAT_DATA (from) * XINT (to)));
       else if (FLOATP (to))
        /* relative X relative => relative */
        result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
@@ -3330,7 +3386,7 @@ merge_face_vectors (f, from, to, cycle_check)
    elements, this macro begins consing in order to keep more precise
    track of elements.
 
-   Returns NIL if a cycle was detected, otherwise a new value for CHECK
+   Returns nil if a cycle was detected, otherwise a new value for CHECK
    that includes EL.
 
    CHECK is evaluated multiple times, EL and SUSPICIOUS 0 or 1 times, so
@@ -3686,6 +3742,14 @@ Value is a vector of face attributes.  */)
   else
     lface = global_lface;
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   xassert (LFACEP (lface));
   check_lface (lface);
   return lface;
@@ -3753,6 +3817,14 @@ Value is TO.  */)
   bcopy (XVECTOR (lface)->contents, XVECTOR (copy)->contents,
         LFACE_VECTOR_SIZE * sizeof (Lisp_Object));
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   return to;
 }
 
@@ -4235,7 +4307,7 @@ set_font_frame_param (frame, lface)
          /* Choose a font name that reflects LFACE's attributes and has
             the registry and encoding pattern specified in the default
             fontset (3rd arg: -1) for ASCII characters (4th arg: 0).  */
-         font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0);
+         font = choose_face_font (f, XVECTOR (lface)->contents, NULL, 0);
          if (!font)
            error ("No font matches the specified attribute");
          font_name = build_string (font);
@@ -4263,6 +4335,14 @@ update_face_from_frame_parameter (f, param, new_value)
   if (NILP (f->face_alist))
     return;
 
+  /* Changing a named face means that all realized faces depending on
+     that face are invalid.  Since we cannot tell which realized faces
+     depend on the face, make sure they are all removed.  This is done
+     by incrementing face_change_count.  The next call to
+     init_iterator will then free realized faces.  */
+  ++face_change_count;
+  ++windows_or_buffers_changed;
+
   if (EQ (param, Qforeground_color))
     {
       lface = lface_from_face_name (f, Qdefault, 1);
@@ -4913,7 +4993,7 @@ make_realized_face (attr)
 /* Free realized face FACE, including its X resources.  FACE may
    be null.  */
 
-static void
+void
 free_realized_face (f, face)
      struct frame *f;
      struct face *face;
@@ -5091,11 +5171,10 @@ free_realized_faces (c)
 }
 
 
-/* Free all faces realized for multibyte characters on frame F that
-   has FONTSET.  */
+/* Free all realized faces that are using FONTSET on frame F.  */
 
 void
-free_realized_multibyte_face (f, fontset)
+free_realized_faces_for_fontset (f, fontset)
      struct frame *f;
      int fontset;
 {
@@ -5112,7 +5191,6 @@ free_realized_multibyte_face (f, fontset)
     {
       face = cache->faces_by_id[i];
       if (face
-         && face != face->ascii_face
          && face->fontset == fontset)
        {
          uncache_face (cache, face);
@@ -5994,12 +6072,12 @@ try_font_list (f, attrs, family, registry, fonts)
   int nfonts = 0;
   Lisp_Object face_family = attrs[LFACE_FAMILY_INDEX];
 
-  if (STRINGP (face_family))
-    nfonts = try_alternative_families (f, face_family, registry, fonts);
-
-  if (nfonts == 0 && !NILP (family))
+  if (!NILP (family))
     nfonts = try_alternative_families (f, family, registry, fonts);
 
+  if (nfonts == 0 && STRINGP (face_family))
+    nfonts = try_alternative_families (f, face_family, registry, fonts);
+
   /* Try font family of the default face or "fixed".  */
   if (nfonts == 0)
     {
@@ -6039,26 +6117,28 @@ face_fontset (attrs)
 /* Choose a name of font to use on frame F to display character C with
    Lisp face attributes specified by ATTRS.  The font name is
    determined by the font-related attributes in ATTRS and the name
-   pattern for C in FONTSET.  Value is the font name which is
-   allocated from the heap and must be freed by the caller, or NULL if
-   we can get no information about the font name of C.  It is assured
-   that we always get some information for a single byte
-   character.  */
+   pattern for C in FACE->fontset (or Vdefault_fontset if FACE is
+   null).  Value is the font name which is allocated from the heap and
+   must be freed by the caller, or NULL if we can get no information
+   about the font name of C.  It is assured that we always get some
+   information for a single byte character.  */
 
 static char *
-choose_face_font (f, attrs, fontset, c)
+choose_face_font (f, attrs, face, c)
      struct frame *f;
      Lisp_Object *attrs;
-     int fontset, c;
+     struct face *face;
+     int c;
 {
-  Lisp_Object pattern;
+  Lisp_Object val;
+  Lisp_Object pattern, family, registry;
+  Lisp_Object new_attrs[LFACE_VECTOR_SIZE];
   char *font_name = NULL;
   struct font_name *fonts;
   int nfonts, width_ratio;
 
-  /* Get (foundry and) family name and registry (and encoding) name of
-     a font for C.  */
-  pattern = fontset_font_pattern (f, fontset, c);
+  /* Get font spec of a font for C.  */
+  pattern = fontset_font_pattern (f, face, c);
   if (NILP (pattern))
     {
       xassert (!SINGLE_BYTE_CHAR_P (c));
@@ -6069,13 +6149,34 @@ choose_face_font (f, attrs, fontset, c)
   if (STRINGP (pattern))
     return xstrdup (XSTRING (pattern)->data);
 
+  family = AREF (pattern, FONT_SPEC_FAMILY_INDEX);
+  registry = AREF (pattern, FONT_SPEC_REGISTRY_INDEX);
+
+  bcopy (attrs, new_attrs, sizeof (Lisp_Object) * LFACE_VECTOR_SIZE);
+
+#if 0
+  /* This doesn't work well for the moment.  */
+  if (! NILP (AREF (pattern, FONT_SPEC_WEIGHT_INDEX)))
+    new_attrs[LFACE_WEIGHT_INDEX] = AREF (pattern, FONT_SPEC_WEIGHT_INDEX);
+  if (! NILP (AREF (pattern, FONT_SPEC_SLANT_INDEX)))
+    new_attrs[LFACE_SLANT_INDEX] = AREF (pattern, FONT_SPEC_SLANT_INDEX);
+  if (! NILP (AREF (pattern, FONT_SPEC_SWIDTH_INDEX)))
+    new_attrs[LFACE_SWIDTH_INDEX] = AREF (pattern, FONT_SPEC_SWIDTH_INDEX);
+#endif
+
+  /* If C is an ASCII character, family name in ATTRS has higher
+     priority than what specified in the fontset.  */
+  if (STRINGP (attrs[LFACE_FAMILY_INDEX])
+      && ASCII_CHAR_P (c))
+    family = Qnil;
+
   /* Get a list of fonts matching that pattern and choose the
      best match for the specified face attributes from it.  */
-  nfonts = try_font_list (f, attrs, XCAR (pattern), XCDR (pattern), &fonts);
-  width_ratio = (SINGLE_BYTE_CHAR_P (c)
+  nfonts = try_font_list (f, new_attrs, family, registry, &fonts);
+  width_ratio = (ASCII_CHAR_P (c)
                 ? 1
-                : CHARSET_WIDTH (CHAR_CHARSET (c)));
-  font_name = best_matching_font (f, attrs, fonts, nfonts, width_ratio);
+                : CHAR_WIDTH (c));
+  font_name = best_matching_font (f, new_attrs, fonts, nfonts, width_ratio);
   return font_name;
 }
 
@@ -6106,8 +6207,9 @@ realize_basic_faces (f)
   if (realize_default_face (f))
     {
       realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
+      realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
       realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
-      realize_named_face (f, Qfringe, BITMAP_AREA_FACE_ID);
+      realize_named_face (f, Qfringe, FRINGE_FACE_ID);
       realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
       realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
       realize_named_face (f, Qborder, BORDER_FACE_ID);
@@ -6172,8 +6274,10 @@ realize_default_face (f)
       LFACE_FAMILY (lface) = build_string ("default");
       LFACE_SWIDTH (lface) = Qnormal;
       LFACE_HEIGHT (lface) = make_number (1);
-      LFACE_WEIGHT (lface) = Qnormal;
-      LFACE_SLANT (lface) = Qnormal;
+      if (UNSPECIFIEDP (LFACE_WEIGHT (lface)))
+       LFACE_WEIGHT (lface) = Qnormal;
+      if (UNSPECIFIEDP (LFACE_SLANT (lface)))
+       LFACE_SLANT (lface) = Qnormal;
       LFACE_AVGWIDTH (lface) = Qunspecified;
     }
 
@@ -6349,10 +6453,10 @@ realize_x_face (cache, attrs, c, base_face)
 
   f = cache->f;
 
-  /* If C is a multibyte character, we share all face attirbutes with
+  /* If C is a non-ASCII character, we share all face attirbutes with
      BASE_FACE including the realized fontset.  But, we must load a
      different font.  */
-  if (!SINGLE_BYTE_CHAR_P (c))
+  if (! ASCII_CHAR_P (c))
     {
       bcopy (base_face, face, sizeof *face);
       face->gc = 0;
@@ -6407,7 +6511,7 @@ realize_x_face (cache, attrs, c, base_face)
       if (STRINGP (attrs[LFACE_FONT_INDEX]))
         {
           struct font_info *font_info =
-            FS_LOAD_FONT (f, 0, XSTRING (attrs[LFACE_FONT_INDEX])->data, -1);
+            FS_LOAD_FONT (f, XSTRING (attrs[LFACE_FONT_INDEX])->data);
           if (font_info)
             face->font = font_info->font;
         }
@@ -7202,6 +7306,8 @@ syms_of_xfaces ()
   staticpro (&Qborder);
   Qmouse = intern ("mouse");
   staticpro (&Qmouse);
+  Qmode_line_inactive = intern ("mode-line-inactive");
+  staticpro (&Qmode_line_inactive);
   Qtty_color_desc = intern ("tty-color-desc");
   staticpro (&Qtty_color_desc);
   Qtty_color_by_index = intern ("tty-color-by-index");