/* 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.
#include <sys/stat.h>
#include "lisp.h"
-#include "charset.h"
+#include "character.h"
#include "keyboard.h"
#include "frame.h"
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
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));
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));
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)
}
+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. */
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)
{
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));
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
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;
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;
}
/* 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);
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);
/* 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;
}
-/* 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;
{
{
face = cache->faces_by_id[i];
if (face
- && face != face->ascii_face
&& face->fontset == fontset)
{
uncache_face (cache, face);
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)
{
/* 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));
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;
}
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);
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;
}
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;
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;
}
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");