-/* Must define frame->faces, frame->n_faces,
- FRAME_NORMAL_FACE, FRAME_MODELINE_FACE. */
-
/* "Face" primitives
Copyright (C) 1992, 1993 Free Software Foundation.
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-struct face
-{
- unsigned char underline;
- unsigned char hilited;
- unsigned char modif;
- GC facegc;
- XFontStruct * font;
- unsigned long foreground;
- unsigned long background;
- Pixmap back_pixmap;
- unsigned int pixmap_w, pixmap_h /* , pixmap_depth */;
-};
+/* This derived from work by Lucid (some parts very loosely so). */
#include <sys/types.h>
#include <sys/stat.h>
#include "xterm.h"
#include "buffer.h"
+#include "dispextern.h"
#include "frame.h"
-#include "window.h"
-#include "indent.h"
+/* #include "window.h" */
/* Display Context for the icons */
#include <X11/Intrinsic.h>
#include <X11/Xos.h>
/* We use face structures in two ways:
- At the frame level, each frame has a vector of faces. (f->faces).
- Face number 0 is the normal face (for normal text).
+ At the frame level, each frame has a vector of faces (FRAME_FACES).
+ Face number 0 is the default face (for normal text).
Face number 1 is the mode line face.
Higher face numbers have no built-in meaning.
The faces in these vectors are called "frame faces".
#define FACE_DEFAULT (~0)
+#define xfree free
+
+Lisp_Object Qface, Qwindow, Qpriority;
+
static struct face *allocate_face ();
static void build_face ();
+static int sort_overlays ();
+static struct face *get_display_face ();
+static Lisp_Object face_name_id_number ();
\f
/* Make a new face that's a copy of an existing one. */
result->font = face->font;
result->foreground = face->foreground;
result->background = face->background;
- result->back_pixmap = face->back_pixmap;
+ result->stipple = face->stipple;
result->underline = face->underline;
return result;
return (face1->font == face2->font
&& face1->foreground == face2->foreground
&& face1->background == face2->background
- && face1->back_pixmap == face2->back_pixmap
+ && face1->stipple == face2->stipple
&& face1->underline == face2->underline);
}
struct face *face;
{
int i, empty = -1;
+ struct face *result;
/* Look for an existing display face that does the job.
Also find an empty slot if any. */
{
Lisp_Object rest;
Display *dpy = x_current_display;
+ int i;
BLOCK_INPUT;
/* Free the display faces in the face_vector. */
for (i = 0; i < nfaces; i++)
{
struct face *face = face_vector[i];
- if (face->facegc)
- XFreeGC (dpy, face->facegc);
+ if (face->gc)
+ XFreeGC (dpy, face->gc);
xfree (face);
}
nfaces = 0;
UNBLOCK_INPUT;
}
\f
-/* Make a graphics context for face FACE, which is on frame F. */
+/* Make a graphics context for face FACE, which is on frame F,
+ if that can be done. */
static void
build_face (f, face)
XGCValues xgcv;
unsigned long mask;
- xgcv.foreground = face->foreground;
- xgcv.background = face->background;
- xgcv.font = face->font->fid;
+ if (face->foreground != FACE_DEFAULT)
+ xgcv.foreground = face->foreground;
+ else
+ xgcv. foreground = f->display.x->foreground_pixel;
+ if (face->background != FACE_DEFAULT)
+ xgcv.background = face->background;
+ else
+ xgcv. background = f->display.x->background_pixel;
+ if (face->font && (int) face->font != FACE_DEFAULT)
+ xgcv.font = face->font->fid;
+ else
+ xgcv.font = f->display.x->font->fid;
xgcv.graphics_exposures = 0;
mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
mask, &xgcv);
#if 0
- if (face->back_pixmap && face->back_pixmap != FACE_DEFAULT)
- XSetStipple (XtDisplay (f->display.x->widget), gc, face->back_pixmap);
+ if (face->stipple && face->stipple != FACE_DEFAULT)
+ XSetStipple (x_current_display, gc, face->stipple);
#endif
- face->facegc = gc;
+ face->gc = gc;
}
\f
/* Modify face TO by copying from FROM all properties which have
to->foreground = from->foreground;
if (from->background != FACE_DEFAULT)
to->background = from->background;
- if (from->back_pixmap != FACE_DEFAULT)
- to->back_pixmap = from->back_pixmap;
+ if (from->stipple != FACE_DEFAULT)
+ to->stipple = from->stipple;
if (from->underline)
to->underline = from->underline;
}
+struct sortvec
+{
+ Lisp_Object overlay;
+ int beg, end;
+ int priority;
+};
+
/* Return the display face associated with a buffer position POS.
Store into *ENDPTR the position at which a different face is needed.
This does not take account of glyphs that specify their own face codes.
- F is the frame in use for display. */
+ F is the frame in use for display, and W is the window. */
struct face *
-compute_char_face (f, pos, endptr)
+compute_char_face (f, w, pos, endptr)
struct frame *f;
+ struct window *w;
int pos;
int *endptr;
{
int endpos;
Lisp_Object *overlay_vec;
int len;
+ struct sortvec *sortvec;
+ Lisp_Object frame;
+
+ XSET (frame, Lisp_Frame, f);
XFASTINT (position) = pos;
prop = Fget_text_property (position, Qface);
/* Optimize the default case. */
if (noverlays == 0 && NILP (prop))
- return FRAME_NORMAL_FACE (f);
+ return FRAME_DEFAULT_FACE (f);
- bcopy (FRAME_NORMAL_FACE (f), &face, sizeof (struct face));
+ bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face));
if (!NILP (prop))
{
- facecode = Fface_name_id_number (prop);
- if (facecode >= 0 && facecode < f->n_faces && f->faces[facecode] != 0)
- merge_faces (f->faces[facecode], &face);
+ facecode = face_name_id_number (frame, prop);
+ if (facecode >= 0 && facecode < FRAME_N_FACES (f)
+ && FRAME_FACES (f) [facecode] != 0)
+ merge_faces (FRAME_FACES (f) [facecode], &face);
}
- /* Discard invalid overlays from the vector. */
+ /* Put the valid and relevant overlays into sortvec. */
+ sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
+
for (i = 0, j = 0; i < noverlays; i++)
{
overlay = overlay_vec[i];
if (OVERLAY_VALID (overlay)
&& OVERLAY_POSITION (OVERLAY_START (overlay)) > 0
&& OVERLAY_POSITION (OVERLAY_END (overlay)) > 0)
- overlay_vec[j++] = overlay;
+ {
+ Lisp_Object window;
+ window = Foverlay_get (overlay, Qwindow);
+
+ /* Also ignore overlays limited to one window
+ if it's not the window we are using. */
+ if (NILP (window) || XWINDOW (window) == w)
+ {
+ Lisp_Object tem;
+
+ /* This overlay is good and counts:
+ put it in sortvec. */
+ sortvec[j].overlay = overlay;
+ sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
+ sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
+ tem = Foverlay_get (overlay, Qpriority);
+ if (INTEGERP (tem))
+ sortvec[j].priority = XINT (tem);
+ else
+ sortvec[j].priority = 0;
+ j++;
+ }
+ }
}
noverlays = j;
- /* Sort the overlays into the proper order. */
+ /* Sort the overlays into the proper order: increasing priority. */
+
+ qsort (sortvec, noverlays, sizeof (struct sortvec), sort_overlays);
/* Now merge the overlay data in that order. */
Lisp_Object oend;
int oendpos;
- facecode = Fface_name_id_number (prop);
- if (facecode >= 0 && facecode < f->n_faces
- && f->faces[facecode] != 0)
- merge_faces (f->faces[facecode], &face);
+ facecode = face_name_id_number (frame, prop);
+ if (facecode >= 0 && facecode < FRAME_N_FACES (f)
+ && FRAME_FACES (f) [facecode] != 0)
+ merge_faces (FRAME_FACES (f) [facecode], &face);
oend = OVERLAY_END (overlay_vec[i]);
oendpos = OVERLAY_POSITION (oend);
return get_display_face (f, &face);
}
+int
+sort_overlays (s1, s2)
+ struct sortvec *s1, *s2;
+{
+ if (s1->priority != s2->priority)
+ return s1->priority - s2->priority;
+ if (s1->beg != s2->beg)
+ return s1->beg - s2->beg;
+ if (s1->end != s2->end)
+ return s2->end - s1->end;
+ return 0;
+}
+
/* Return the display face to use to display a special glyph
which selects FACE_CODE as the face ID,
assuming that ordinarily the face would be BASIC_FACE.
bcopy (basic_face, &face, sizeof (struct face));
- if (face_code >= 0 && face_code < f->n_faces && f->faces[face_code] != 0)
- merge_faces (f->faces[face_code], &face);
+ if (face_code >= 0 && face_code < FRAME_N_FACES (f)
+ && FRAME_FACES (f) [face_code] != 0)
+ merge_faces (FRAME_FACES (f) [face_code], &face);
return get_display_face (f, &face);
}
struct face *result;
/* Does the face have a GC already? */
- if (face->facegc)
+ if (face->gc)
return face;
- /* If it's equivalent to the normal face, use that. */
- if (face->font == FRAME_NORMAL_FACE (f)->font
- && face->foreground == FRAME_NORMAL_FACE (f)->foreground
- && face->background == FRAME_NORMAL_FACE (f)->background
- && face->back_pixmap == FRAME_NORMAL_FACE (f)->back_pixmap
- && face->underline == FRAME_NORMAL_FACE (f)->underline)
+ /* If it's equivalent to the default face, use that. */
+ if (face->font == FRAME_DEFAULT_FACE (f)->font
+ && face->foreground == FRAME_DEFAULT_FACE (f)->foreground
+ && face->background == FRAME_DEFAULT_FACE (f)->background
+ && face->stipple == FRAME_DEFAULT_FACE (f)->stipple
+ && face->underline == FRAME_DEFAULT_FACE (f)->underline)
{
- if (!FRAME_NORMAL_FACE (f)->framegc)
- build_frame (f, FRAME_NORMAL_FACE (f));
- return FRAME_NORMAL_FACE (f);
+ if (!FRAME_DEFAULT_FACE (f)->gc)
+ build_face (f, FRAME_DEFAULT_FACE (f));
+ return FRAME_DEFAULT_FACE (f);
}
/* If it's equivalent to the mode line face, use that. */
- if (face->font == FRAME_MODELINE_FACE (f)->font
- && face->foreground == FRAME_MODELINE_FACE (f)->foreground
- && face->background == FRAME_MODELINE_FACE (f)->background
- && face->back_pixmap == FRAME_MODELINE_FACE (f)->back_pixmap
- && face->underline == FRAME_MODELINE_FACE (f)->underline)
+ if (face->font == FRAME_MODE_LINE_FACE (f)->font
+ && face->foreground == FRAME_MODE_LINE_FACE (f)->foreground
+ && face->background == FRAME_MODE_LINE_FACE (f)->background
+ && face->stipple == FRAME_MODE_LINE_FACE (f)->stipple
+ && face->underline == FRAME_MODE_LINE_FACE (f)->underline)
{
- if (!FRAME_MODELINE_FACE (f)->framegc)
- build_frame (f, FRAME_MODELINE_FACE (f));
- return FRAME_MODELINE_FACE (f);
+ if (!FRAME_MODE_LINE_FACE (f)->gc)
+ build_face (f, FRAME_MODE_LINE_FACE (f));
+ return FRAME_MODE_LINE_FACE (f);
}
/* Get a specialized display face. */
result->font = (XFontStruct *) FACE_DEFAULT;
result->foreground = FACE_DEFAULT;
result->background = FACE_DEFAULT;
- result->back_pixmap = FACE_DEFAULT;
+ result->stipple = FACE_DEFAULT;
return result;
}
struct frame *f;
int id;
{
- if (f->n_faces <= id)
+ if (FRAME_N_FACES (f) <= id)
{
int n = id + 10;
int i;
- if (!f->n_faces)
- f->faces = (struct face **) xmalloc (sizeof (struct face *) * n);
+ if (!FRAME_N_FACES (f))
+ FRAME_FACES (f)
+ = (struct face **) xmalloc (sizeof (struct face *) * n);
else
- f->faces
- = (struct face **) xrealloc (f->faces, sizeof (struct face *) * n);
+ FRAME_FACES (f)
+ = (struct face **) xrealloc (FRAME_FACES (f),
+ sizeof (struct face *) * n);
- f->n_faces = n;
+ bzero (FRAME_FACES (f) + FRAME_N_FACES (f),
+ (n - FRAME_N_FACES (f)) * sizeof (struct face *));
+ FRAME_N_FACES (f) = n;
}
- f->faces[id] = allocate_face ();
+ if (FRAME_FACES (f) [id] == 0)
+ FRAME_FACES (f) [id] = allocate_face ();
}
\f
/* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
if (NILP (name))
return FACE_DEFAULT;
- cmap = DefaultColormapOfScreen (x_screen);
+ cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
CHECK_STRING (name, 0);
BLOCK_INPUT;
Display *dpy = x_current_display;
if (pixel == FACE_DEFAULT)
return;
- cmap = DefaultColormapOfScreen (x_screen);
+ cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
BLOCK_INPUT;
XFreeColors (dpy, cmap, &pixel, 1, 0);
UNBLOCK_INPUT;
void
init_frame_faces (f)
- struct frame f;
+ struct frame *f;
{
struct frame *other_frame = 0;
Lisp_Object rest;
for (rest = Vframe_list; !NILP (rest); rest = Fcdr (rest))
{
struct frame *f2 = XFRAME (Fcar (rest));
- if (f2 != f && FRAME_IS_X (f2))
+ if (f2 != f && FRAME_X_P (f2))
{
other_frame = f2;
break;
if (other_frame)
{
/* Make sure this frame's face vector is as big as the others. */
- f->n_faces = other_frame->n_faces;
- f->faces = (struct face **) xmalloc (f->n_faces * sizeof (struct face *));
+ FRAME_N_FACES (f) = FRAME_N_FACES (other_frame);
+ FRAME_FACES (f)
+ = (struct face **) xmalloc (FRAME_N_FACES (f) * sizeof (struct face *));
/* Make sure the frame has the two basic faces. */
- FRAME_NORMAL_FACE (f)
- = copy_face (FRAME_NORMAL_FACE (other_frame));
- FRAME_MODELINE_FACE (f)
- = copy_face (FRAME_MODELINE_FACE (other_frame));
+ FRAME_DEFAULT_FACE (f)
+ = copy_face (FRAME_DEFAULT_FACE (other_frame));
+ FRAME_MODE_LINE_FACE (f)
+ = copy_face (FRAME_MODE_LINE_FACE (other_frame));
}
}
Display *dpy = x_current_display;
int i;
- for (i = 0; i < f->n_faces; i++)
+ for (i = 0; i < FRAME_N_FACES (f); i++)
{
- struct face *face = f->faces [i];
+ struct face *face = FRAME_FACES (f) [i];
if (! face)
continue;
- if (face->facegc)
- XFreeGC (dpy, face->facegc);
+ if (face->gc)
+ XFreeGC (dpy, face->gc);
unload_font (f, face->font);
unload_color (f, face->foreground);
unload_color (f, face->background);
- unload_pixmap (f, face->back_pixmap);
+#if 0
+ unload_pixmap (f, face->stipple);
+#endif
xfree (face);
}
- xfree (f->faces);
- f->faces = 0;
- f->n_faces = 0;
+ xfree (FRAME_FACES (f));
+ FRAME_FACES (f) = 0;
+ FRAME_N_FACES (f) = 0;
}
\f
Lisp_Object rest;
int id = XINT (face_id);
- CHECK_FIXNUM (face_id, 0);
- if (id < 0)
- error ("Face id must be nonnegative");
+ CHECK_NUMBER (face_id, 0);
+ if (id < 0 || id >= next_face_id)
+ error ("Face id out of range");
for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
{
int id;
CHECK_FRAME (frame, 0);
- CHECK_FIXNUM (face_id, 0);
+ CHECK_NUMBER (face_id, 0);
CHECK_SYMBOL (attr_name, 0);
f = XFRAME (frame);
id = XINT (face_id);
- if (id < 0)
- Fsignal (Qerror, Fcons (build_string ("invalid face id"),
- Fcons (face_id, Fcons (frame, Qnil))));
+ if (id < 0 || id >= next_face_id)
+ error ("Face id out of range");
ensure_face_ready (f, id);
- face = f->faces [XFASTINT (face_id)];
- if (! face) abort ();
-
- magic_p = (NILP (attr_value) && XFASTINT (face_id) <= 1);
+ face = FRAME_FACES (f) [XFASTINT (face_id)];
if (EQ (attr_name, intern ("font")))
{
-#ifdef HAVE_X_WINDOWS
- XFontStruct *font;
- if (magic_p)
- error ("font of the `normal' or `modeline' face may not be nil");
- font = load_font (f, attr_value);
+ XFontStruct *font = load_font (f, attr_value);
unload_font (f, face->font);
face->font = font;
-#endif /* HAVE_X_WINDOWS */
}
else if (EQ (attr_name, intern ("foreground")))
{
-#ifdef HAVE_X_WINDOWS
- unsigned long new_color;
- if (magic_p)
- error ("forground color of the `normal' or `modeline' face may not be nil");
- new_color = load_color (f, attr_value);
+ unsigned long new_color = load_color (f, attr_value);
unload_color (f, face->foreground);
face->foreground = new_color;
-#endif /* HAVE_X_WINDOWS */
}
else if (EQ (attr_name, intern ("background")))
{
-#ifdef HAVE_X_WINDOWS
- unsigned long new_color;
- if (magic_p)
- error ("background color of the `normal' or `modeline' face may not be nil");
- new_color = load_color (f, attr_value);
+ unsigned long new_color = load_color (f, attr_value);
unload_color (f, face->background);
face->background = new_color;
-#endif /* HAVE_X_WINDOWS */
}
#if 0
else if (EQ (attr_name, intern ("background-pixmap")))
{
-#ifdef HAVE_X_WINDOWS
unsigned int w, h, d;
unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0);
- unload_pixmap (f, face->back_pixmap);
- if (magic_p) new_pixmap = 0;
- face->back_pixmap = new_pixmap;
+ unload_pixmap (f, face->stipple);
+ if (NILP (attr_value))
+ new_pixmap = 0;
+ face->stipple = new_pixmap;
face->pixmap_w = w;
face->pixmap_h = h;
/* face->pixmap_depth = d; */
-#endif /* HAVE_X_WINDOWS */
}
#endif /* 0 */
else if (EQ (attr_name, intern ("underline")))
if (id == 0)
{
BLOCK_INPUT;
- XFreeGC (dpy, FRAME_NORMAL_FACE (f)->facegc);
- build_face (f, FRAME_NORMAL_FACE (f));
+ if (FRAME_DEFAULT_FACE (f)->gc != 0)
+ XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
+ build_face (f, FRAME_DEFAULT_FACE (f));
UNBLOCK_INPUT;
}
if (id == 1)
{
BLOCK_INPUT;
- XFreeGC (dpy, FRAME_NORMAL_FACE (f)->facegc);
- build_face (f, FRAME_NORMAL_FACE (f));
+ if (FRAME_MODE_LINE_FACE (f)->gc != 0)
+ XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
+ build_face (f, FRAME_MODE_LINE_FACE (f));
UNBLOCK_INPUT;
}
{
return make_number (next_face_id++);
}
+
+/* Return the face id for name NAME on frame FRAME.
+ (It should be the same for all frames,
+ but it's as easy to use the "right" frame to look it up
+ as to use any other one.) */
+
+static Lisp_Object
+face_name_id_number (frame, name)
+ Lisp_Object frame, name;
+{
+ Lisp_Object tem;
+
+ CHECK_FRAME (frame, 0);
+ tem = Fcdr (Fassq (name, XFRAME (frame)->face_alist));
+ CHECK_VECTOR (tem, 0);
+ tem = XVECTOR (tem)->contents[2];
+ CHECK_NUMBER (tem, 0);
+ return XINT (tem);
+}
\f
void
-syms_of_faces ()
+syms_of_xfaces ()
{
+ Qwindow = intern ("window");
+ staticpro (&Qwindow);
+ Qface = intern ("face");
+ staticpro (&Qface);
+ Qpriority = intern ("priority");
+ staticpro (&Qpriority);
+
defsubr (&Sframe_face_alist);
defsubr (&Sset_frame_face_alist);
defsubr (&Smake_face_internal);