#include <sys/types.h>
#include <sys/stat.h>
#include <config.h>
#include "lisp.h"
#include "charset.h"
#include "frame.h"
static int next_face_id;
#ifdef HAVE_FACES
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#include "fontset.h"
#endif
#ifdef MSDOS
#include "dosfns.h"
#endif
#include "buffer.h"
#include "dispextern.h"
#include "blockinput.h"
#include "window.h"
#include "intervals.h"
#ifdef HAVE_X_WINDOWS
#ifdef XOS_NEEDS_TIME_H
#include <time.h>
#undef USG
#include <X11/Xos.h>
#define USG
#define __TIMEVAL__
#else
#include <X11/Xos.h>
#endif
#endif
static int region_face;
#define FACE_DEFAULT (~0)
Lisp_Object Qface;
Lisp_Object Qpixmap_spec_p;
int face_name_id_number ( );
struct face *intern_face ( );
static int new_computed_face ( );
static int intern_computed_face ( );
static void ensure_face_ready ( );
void recompute_basic_faces ( );
static void merge_face_list ( );
extern Lisp_Object Qforeground_color, Qbackground_color, Qmouse_face;
static struct face *
allocate_face ()
{
struct face *result = (struct face *) xmalloc (sizeof (struct face));
bzero (result, sizeof (struct face));
result->font = (XFontStruct *) FACE_DEFAULT;
result->fontset = -1;
result->foreground = FACE_DEFAULT;
result->background = FACE_DEFAULT;
result->stipple = FACE_DEFAULT;
return result;
}
static struct face *
copy_face (face)
struct face *face;
{
struct face *result = allocate_face ();
result->font = face->font;
result->fontset = face->fontset;
result->foreground = face->foreground;
result->background = face->background;
result->stipple = face->stipple;
result->underline = face->underline;
result->pixmap_h = face->pixmap_h;
result->pixmap_w = face->pixmap_w;
return result;
}
static int
face_eql (face1, face2)
struct face *face1, *face2;
{
return ( face1->font == face2->font
&& face1->fontset == face2->fontset
&& face1->foreground == face2->foreground
&& face1->background == face2->background
&& face1->stipple == face2->stipple
&& face1->underline == face2->underline);
}
#ifdef HAVE_X_WINDOWS
struct face *
intern_face (f, face)
struct frame *f;
struct face *face;
{
GC gc;
XGCValues xgcv;
unsigned long mask;
if (face->gc)
return face;
BLOCK_INPUT;
if (face->foreground != FACE_DEFAULT)
xgcv.foreground = face->foreground;
else
xgcv.foreground = f->output_data.x->foreground_pixel;
if (face->background != FACE_DEFAULT)
xgcv.background = face->background;
else
xgcv.background = f->output_data.x->background_pixel;
if (face->font && face->font != (XFontStruct *) FACE_DEFAULT)
xgcv.font = face->font->fid;
else
xgcv.font = f->output_data.x->font->fid;
xgcv.graphics_exposures = 0;
mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
if (face->stipple && face->stipple != FACE_DEFAULT)
{
xgcv.fill_style = FillStippled;
xgcv.stipple = x_bitmap_pixmap (f, face->stipple);
mask |= GCFillStyle | GCStipple;
}
gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
mask, &xgcv);
face->gc = gc;
face->non_ascii_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
mask, &xgcv);
UNBLOCK_INPUT;
return face;
}
void
clear_face_cache ()
{
Lisp_Object tail, frame;
BLOCK_INPUT;
FOR_EACH_FRAME (tail, frame)
{
FRAME_PTR f = XFRAME (frame);
if (FRAME_X_P (f))
{
int i;
Display *dpy = FRAME_X_DISPLAY (f);
for (i = 2; i < FRAME_N_COMPUTED_FACES (f); i++)
{
struct face *face = FRAME_COMPUTED_FACES (f) [i];
if (face->gc)
{
XFreeGC (dpy, face->gc);
XFreeGC (dpy, face->non_ascii_gc);
}
face->gc = 0;
}
}
}
UNBLOCK_INPUT;
}
static XFontStruct *
load_font (f, name)
struct frame *f;
Lisp_Object name;
{
XFontStruct *font;
if (NILP (name))
return (XFontStruct *) FACE_DEFAULT;
CHECK_STRING (name, 0);
BLOCK_INPUT;
font = XLoadQueryFont (FRAME_X_DISPLAY (f), (char *) XSTRING (name)->data);
UNBLOCK_INPUT;
if (! font)
Fsignal (Qerror, Fcons (build_string ("undefined font"),
Fcons (name, Qnil)));
return font;
}
static void
unload_font (f, font)
struct frame *f;
XFontStruct *font;
{
int len = FRAME_N_COMPUTED_FACES (f);
int i;
if (!font || font == ((XFontStruct *) FACE_DEFAULT))
return;
BLOCK_INPUT;
for (i = 2; i < len; i++)
{
struct face *face = FRAME_COMPUTED_FACES (f)[i];
if (face->font == font)
{
Display *dpy = FRAME_X_DISPLAY (f);
if (face->gc)
XFreeGC (dpy, face->gc);
face->gc = 0;
face->font = 0;
}
}
XFreeFont (FRAME_X_DISPLAY (f), font);
UNBLOCK_INPUT;
}
static unsigned long
load_color (f, name)
struct frame *f;
Lisp_Object name;
{
XColor color;
int result;
if (NILP (name))
return FACE_DEFAULT;
CHECK_STRING (name, 0);
result = defined_color (f, (char *) XSTRING (name)->data, &color, 1);
if (! result)
Fsignal (Qerror, Fcons (build_string ("undefined color"),
Fcons (name, Qnil)));
return (unsigned long) color.pixel;
}
void
unload_color (f, pixel)
struct frame *f;
unsigned long pixel;
{
Colormap cmap;
Display *dpy = FRAME_X_DISPLAY (f);
int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
if (pixel == FACE_DEFAULT
|| pixel == BLACK_PIX_DEFAULT (f)
|| pixel == WHITE_PIX_DEFAULT (f))
return;
cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy));
if (! (class == StaticColor || class == StaticGray || class == TrueColor))
{
int len = FRAME_N_COMPUTED_FACES (f);
int i;
BLOCK_INPUT;
for (i = 2; i < len; i++)
{
struct face *face = FRAME_COMPUTED_FACES (f)[i];
if (face->foreground == pixel
|| face->background == pixel)
{
Display *dpy = FRAME_X_DISPLAY (f);
if (face->gc)
XFreeGC (dpy, face->gc);
face->gc = 0;
face->font = 0;
}
}
XFreeColors (dpy, cmap, &pixel, 1, (unsigned long)0);
UNBLOCK_INPUT;
}
}
DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
"Return t if OBJECT is a valid pixmap specification.")
(object)
Lisp_Object object;
{
Lisp_Object height, width;
return ((STRINGP (object)
|| (CONSP (object)
&& CONSP (XCONS (object)->cdr)
&& CONSP (XCONS (XCONS (object)->cdr)->cdr)
&& NILP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->cdr)
&& (width = XCONS (object)->car, INTEGERP (width))
&& (height = XCONS (XCONS (object)->cdr)->car, INTEGERP (height))
&& STRINGP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)
&& XINT (width) > 0
&& XINT (height) > 0
&& ((XSTRING (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)->size
* (BITS_PER_INT / sizeof (int)))
>= XFASTINT (width) * XFASTINT (height))))
? Qt : Qnil);
}
static long
load_pixmap (f, name, w_ptr, h_ptr)
FRAME_PTR f;
Lisp_Object name;
unsigned int *w_ptr, *h_ptr;
{
int bitmap_id;
Lisp_Object tem;
if (NILP (name))
return FACE_DEFAULT;
tem = Fpixmap_spec_p (name);
if (NILP (tem))
wrong_type_argument (Qpixmap_spec_p, name);
BLOCK_INPUT;
if (CONSP (name))
{
int h, w;
Lisp_Object bits;
w = XINT (Fcar (name));
h = XINT (Fcar (Fcdr (name)));
bits = Fcar (Fcdr (Fcdr (name)));
bitmap_id = x_create_bitmap_from_data (f, XSTRING (bits)->data,
w, h);
}
else
{
bitmap_id = x_create_bitmap_from_file (f, name);
}
UNBLOCK_INPUT;
if (bitmap_id < 0)
Fsignal (Qerror, Fcons (build_string ("invalid or undefined bitmap"),
Fcons (name, Qnil)));
*w_ptr = x_bitmap_width (f, bitmap_id);
*h_ptr = x_bitmap_height (f, bitmap_id);
return bitmap_id;
}
#else
struct face *
intern_face (f, face)
struct frame *f;
struct face *face;
{
return face;
}
void
clear_face_cache ()
{
}
#ifdef MSDOS
unsigned long
load_color (f, name)
FRAME_PTR f;
Lisp_Object name;
{
Lisp_Object result;
if (NILP (name))
return FACE_DEFAULT;
CHECK_STRING (name, 0);
result = call1 (Qmsdos_color_translate, name);
if (INTEGERP (result))
return XINT (result);
else
Fsignal (Qerror, Fcons (build_string ("undefined color"),
Fcons (name, Qnil)));
}
#endif
#endif
void
init_frame_faces (f)
FRAME_PTR f;
{
ensure_face_ready (f, 0);
ensure_face_ready (f, 1);
FRAME_N_COMPUTED_FACES (f) = 0;
FRAME_SIZE_COMPUTED_FACES (f) = 0;
new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
recompute_basic_faces (f);
{
Lisp_Object tail, frame, result;
result = Qnil;
FOR_EACH_FRAME (tail, frame)
if ((FRAME_MSDOS_P (XFRAME (frame)) || FRAME_X_P (XFRAME (frame)))
&& XFRAME (frame) != f)
{
result = frame;
break;
}
if (FRAMEP (result))
{
int i;
int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
for (i = 2; i < n_faces; i++)
if (faces[i])
ensure_face_ready (f, i);
}
}
}
void
free_frame_faces (f)
struct frame *f;
{
Display *dpy = FRAME_X_DISPLAY (f);
int i;
BLOCK_INPUT;
for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
{
struct face *face = FRAME_PARAM_FACES (f) [i];
if (face)
{
if (face->fontset < 0)
unload_font (f, face->font);
unload_color (f, face->foreground);
unload_color (f, face->background);
x_destroy_bitmap (f, face->stipple);
xfree (face);
}
}
xfree (FRAME_PARAM_FACES (f));
FRAME_PARAM_FACES (f) = 0;
FRAME_N_PARAM_FACES (f) = 0;
for (i = 0; i < FRAME_N_COMPUTED_FACES (f); i++)
{
struct face *face = FRAME_COMPUTED_FACES (f) [i];
if (face)
{
if (face->gc)
{
XFreeGC (dpy, face->gc);
XFreeGC (dpy, face->non_ascii_gc);
}
xfree (face);
}
}
xfree (FRAME_COMPUTED_FACES (f));
FRAME_COMPUTED_FACES (f) = 0;
FRAME_N_COMPUTED_FACES (f) = 0;
UNBLOCK_INPUT;
}
static int
new_computed_face (f, new_face)
struct frame *f;
struct face *new_face;
{
int len = FRAME_N_COMPUTED_FACES (f);
int i;
for (i = 0; i < len; i++)
{
struct face *face = FRAME_COMPUTED_FACES (f)[i];
if (face->font == 0)
{
FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
return i;
}
}
if (i >= FRAME_SIZE_COMPUTED_FACES (f))
{
int new_size = i + 32;
FRAME_COMPUTED_FACES (f)
= (struct face **) (FRAME_SIZE_COMPUTED_FACES (f) == 0
? xmalloc (new_size * sizeof (struct face *))
: xrealloc (FRAME_COMPUTED_FACES (f),
new_size * sizeof (struct face *)));
FRAME_SIZE_COMPUTED_FACES (f) = new_size;
}
i = FRAME_N_COMPUTED_FACES (f)++;
FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
return i;
}
static int
intern_computed_face (f, new_face)
struct frame *f;
struct face *new_face;
{
int len = FRAME_N_COMPUTED_FACES (f);
int i;
for (i = 0; i < len; i++)
{
if (! FRAME_COMPUTED_FACES (f)[i])
abort ();
if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
return i;
}
return new_computed_face (f, new_face);
}
static void
ensure_face_ready (f, id)
struct frame *f;
int id;
{
if (FRAME_N_PARAM_FACES (f) <= id)
{
int n = id + 10;
int i;
if (!FRAME_N_PARAM_FACES (f))
FRAME_PARAM_FACES (f)
= (struct face **) xmalloc (sizeof (struct face *) * n);
else
FRAME_PARAM_FACES (f)
= (struct face **) xrealloc (FRAME_PARAM_FACES (f),
sizeof (struct face *) * n);
bzero (FRAME_PARAM_FACES (f) + FRAME_N_PARAM_FACES (f),
(n - FRAME_N_PARAM_FACES (f)) * sizeof (struct face *));
FRAME_N_PARAM_FACES (f) = n;
}
if (FRAME_PARAM_FACES (f) [id] == 0)
FRAME_PARAM_FACES (f) [id] = allocate_face ();
}
#ifdef HAVE_X_WINDOWS
int
same_size_fonts (font1, font2)
XFontStruct *font1, *font2;
{
XCharStruct *bounds1 = &font1->min_bounds;
XCharStruct *bounds2 = &font2->min_bounds;
return (bounds1->width == bounds2->width);
}
int
frame_update_line_height (f)
FRAME_PTR f;
{
int i;
int fontset = f->output_data.x->fontset;
int biggest = (fontset > 0
? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
: FONT_HEIGHT (f->output_data.x->font));
for (i = 0; i < f->output_data.x->n_param_faces; i++)
if (f->output_data.x->param_faces[i] != 0
&& f->output_data.x->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
{
int height = ((fontset = f->output_data.x->param_faces[i]->fontset) > 0
? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
: FONT_HEIGHT (f->output_data.x->param_faces[i]->font));
if (height > biggest)
biggest = height;
}
if (biggest == f->output_data.x->line_height)
return 0;
f->output_data.x->line_height = biggest;
return 1;
}
#endif
static void
merge_faces (from, to)
struct face *from, *to;
{
if (from->font != (XFontStruct *) FACE_DEFAULT
&& same_size_fonts (from->font, to->font))
to->font = from->font;
if (from->fontset != -1)
to->fontset = from->fontset;
if (from->foreground != FACE_DEFAULT)
to->foreground = from->foreground;
if (from->background != FACE_DEFAULT)
to->background = from->background;
if (from->stipple != FACE_DEFAULT)
{
to->stipple = from->stipple;
to->pixmap_h = from->pixmap_h;
to->pixmap_w = from->pixmap_w;
}
if (from->underline)
to->underline = from->underline;
}
static void
compute_base_face (f, face)
FRAME_PTR f;
struct face *face;
{
face->gc = 0;
face->foreground = FRAME_FOREGROUND_PIXEL (f);
face->background = FRAME_BACKGROUND_PIXEL (f);
face->font = FRAME_FONT (f);
face->fontset = -1;
face->stipple = 0;
face->underline = 0;
}
int
compute_glyph_face (f, face_code, current_face)
struct frame *f;
int face_code, current_face;
{
struct face face;
face = *FRAME_COMPUTED_FACES (f)[current_face];
if (face_code >= 0 && face_code < FRAME_N_PARAM_FACES (f)
&& FRAME_PARAM_FACES (f) [face_code] != 0)
merge_faces (FRAME_PARAM_FACES (f) [face_code], &face);
return intern_computed_face (f, &face);
}
int
compute_glyph_face_1 (f, face_name, current_face)
struct frame *f;
Lisp_Object face_name;
int current_face;
{
struct face face;
face = *FRAME_COMPUTED_FACES (f)[current_face];
if (!NILP (face_name))
{
int facecode = face_name_id_number (f, face_name);
if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
&& FRAME_PARAM_FACES (f) [facecode] != 0)
merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
}
return intern_computed_face (f, &face);
}
int
compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
struct frame *f;
struct window *w;
int pos;
int region_beg, region_end;
int *endptr;
int limit;
int mouse;
{
struct face face;
Lisp_Object prop, position;
int i, j, noverlays;
int facecode;
Lisp_Object *overlay_vec;
Lisp_Object frame;
int endpos;
Lisp_Object propname;
if (XBUFFER (w->buffer) != current_buffer)
abort ();
XSETFRAME (frame, f);
endpos = ZV;
if (pos < region_beg && region_beg < endpos)
endpos = region_beg;
XSETFASTINT (position, pos);
if (mouse)
propname = Qmouse_face;
else
propname = Qface;
prop = Fget_text_property (position, propname, w->buffer);
{
Lisp_Object limit1, end;
XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
end = Fnext_single_property_change (position, propname, w->buffer, limit1);
if (INTEGERP (end))
endpos = XINT (end);
}
{
int next_overlay;
int len;
len = 40;
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
noverlays = overlays_at (pos, 0, &overlay_vec, &len,
&next_overlay, (int *) 0);
if (noverlays > len)
{
len = noverlays;
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
noverlays = overlays_at (pos, 0, &overlay_vec, &len,
&next_overlay, (int *) 0);
}
if (next_overlay < endpos)
endpos = next_overlay;
}
*endptr = endpos;
if (noverlays == 0 && NILP (prop)
&& !(pos >= region_beg && pos < region_end))
return 0;
compute_base_face (f, &face);
merge_face_list (f, &face, prop);
noverlays = sort_overlays (overlay_vec, noverlays, w);
for (i = 0; i < noverlays; i++)
{
Lisp_Object oend;
int oendpos;
prop = Foverlay_get (overlay_vec[i], propname);
merge_face_list (f, &face, prop);
oend = OVERLAY_END (overlay_vec[i]);
oendpos = OVERLAY_POSITION (oend);
if (oendpos < endpos)
endpos = oendpos;
}
if (pos >= region_beg && pos < region_end)
{
if (region_end < endpos)
endpos = region_end;
if (region_face >= 0 && region_face < next_face_id)
merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
}
*endptr = endpos;
return intern_computed_face (f, &face);
}
static void
merge_face_list (f, face, prop)
FRAME_PTR f;
struct face *face;
Lisp_Object prop;
{
Lisp_Object length;
int len;
Lisp_Object *faces;
int j;
if (CONSP (prop)
&& ! STRINGP (XCONS (prop)->cdr))
{
length = Fsafe_length (prop);
len = XFASTINT (length);
faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
for (j = 0; j < len; j++)
{
faces[j] = Fcar (prop);
prop = Fcdr (prop);
}
}
else
{
faces = (Lisp_Object *) alloca (sizeof (Lisp_Object));
faces[0] = prop;
len = 1;
}
for (j = len - 1; j >= 0; j--)
{
if (CONSP (faces[j]))
{
if (EQ (XCONS (faces[j])->car, Qbackground_color))
face->background = load_color (f, XCONS (faces[j])->cdr);
if (EQ (XCONS (faces[j])->car, Qforeground_color))
face->foreground = load_color (f, XCONS (faces[j])->cdr);
}
else
{
int facecode = face_name_id_number (f, faces[j]);
if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
&& FRAME_PARAM_FACES (f) [facecode] != 0)
merge_faces (FRAME_PARAM_FACES (f) [facecode], face);
}
}
}
void
recompute_basic_faces (f)
FRAME_PTR f;
{
if (FRAME_N_PARAM_FACES (f) < 2)
return;
BLOCK_INPUT;
if (FRAME_DEFAULT_FACE (f)->gc)
{
XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->gc);
XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->non_ascii_gc);
}
if (FRAME_MODE_LINE_FACE (f)->gc)
{
XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->gc);
XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->non_ascii_gc);
}
compute_base_face (f, FRAME_DEFAULT_FACE (f));
compute_base_face (f, FRAME_MODE_LINE_FACE (f));
merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
intern_face (f, FRAME_DEFAULT_FACE (f));
intern_face (f, FRAME_MODE_LINE_FACE (f));
UNBLOCK_INPUT;
}
DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
"Create face number FACE-ID on all frames.")
(face_id)
Lisp_Object face_id;
{
Lisp_Object rest, frame;
int id = XINT (face_id);
CHECK_NUMBER (face_id, 0);
if (id < 0 || id >= next_face_id)
error ("Face id out of range");
FOR_EACH_FRAME (rest, frame)
{
if (FRAME_MSDOS_P (XFRAME (frame)) || FRAME_X_P (XFRAME (frame)))
ensure_face_ready (XFRAME (frame), id);
}
return Qnil;
}
DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
Sset_face_attribute_internal, 4, 4, 0, "")
(face_id, attr_name, attr_value, frame)
Lisp_Object face_id, attr_name, attr_value, frame;
{
struct face *face;
struct frame *f;
int magic_p;
int id;
int garbaged = 0;
CHECK_FRAME (frame, 0);
CHECK_NUMBER (face_id, 0);
CHECK_SYMBOL (attr_name, 0);
f = XFRAME (frame);
id = XINT (face_id);
if (id < 0 || id >= next_face_id)
error ("Face id out of range");
if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
return Qnil;
ensure_face_ready (f, id);
face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
if (EQ (attr_name, intern ("font")))
{
#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
face->font = (XFontStruct *)1 ;
#else
XFontStruct *font;
int fontset;
if (NILP (attr_value))
{
font = (XFontStruct *) FACE_DEFAULT;
fontset = -1;
}
else
{
CHECK_STRING (attr_value, 0);
fontset = fs_query_fontset (f, XSTRING (attr_value)->data);
if (fontset >= 0)
{
struct font_info *fontp;
if (!(fontp = FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
CHARSET_ASCII, NULL, fontset)))
Fsignal (Qerror,
Fcons (build_string ("ASCII font can't be loaded"),
Fcons (attr_value, Qnil)));
font = (XFontStruct *) (fontp->font);
}
else
font = load_font (f, attr_value);
}
if (face->fontset == -1 && face->font != f->output_data.x->font)
unload_font (f, face->font);
face->font = font;
face->fontset = fontset;
if (frame_update_line_height (f))
x_set_window_size (f, 0, f->width, f->height);
garbaged = 1;
#endif
}
else if (EQ (attr_name, intern ("foreground")))
{
unsigned long new_color = load_color (f, attr_value);
unload_color (f, face->foreground);
face->foreground = new_color;
garbaged = 1;
}
else if (EQ (attr_name, intern ("background")))
{
unsigned long new_color = load_color (f, attr_value);
unload_color (f, face->background);
face->background = new_color;
garbaged = 1;
}
else if (EQ (attr_name, intern ("background-pixmap")))
{
unsigned int w, h;
unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h);
x_destroy_bitmap (f, face->stipple);
face->stipple = new_pixmap;
face->pixmap_w = w;
face->pixmap_h = h;
garbaged = 1;
}
else if (EQ (attr_name, intern ("underline")))
{
int new = !NILP (attr_value);
face->underline = new;
}
else
error ("unknown face attribute");
if (id == 0 || id == 1)
recompute_basic_faces (f);
if (garbaged)
{
SET_FRAME_GARBAGED (f);
#ifdef HAVE_X_WINDOWS
FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
#endif
}
return Qnil;
}
int
face_name_id_number (f, name)
FRAME_PTR f;
Lisp_Object name;
{
Lisp_Object tem;
tem = Fcdr (assq_no_quit (name, f->face_alist));
if (NILP (tem))
return 0;
CHECK_VECTOR (tem, 0);
tem = XVECTOR (tem)->contents[2];
CHECK_NUMBER (tem, 0);
return XINT (tem);
}
#endif
DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
"")
(frame)
Lisp_Object frame;
{
CHECK_FRAME (frame, 0);
return XFRAME (frame)->face_alist;
}
DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
2, 2, 0, "")
(frame, value)
Lisp_Object frame, value;
{
CHECK_FRAME (frame, 0);
XFRAME (frame)->face_alist = value;
return value;
}
DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
0, 0, 0, "")
()
{
return make_number (next_face_id++);
}
void
syms_of_xfaces ()
{
#ifdef HAVE_FACES
Qface = intern ("face");
staticpro (&Qface);
Qpixmap_spec_p = intern ("pixmap-spec-p");
staticpro (&Qpixmap_spec_p);
DEFVAR_INT ("region-face", ®ion_face,
"Face number to use to highlight the region\n\
The region is highlighted with this face\n\
when Transient Mark mode is enabled and the mark is active.");
defsubr (&Smake_face_internal);
defsubr (&Sset_face_attribute_internal);
#endif
#ifdef HAVE_X_WINDOWS
defsubr (&Spixmap_spec_p);
#endif
defsubr (&Sframe_face_alist);
defsubr (&Sset_frame_face_alist);
defsubr (&Sinternal_next_face_id);
}