Mercurial > emacs
changeset 2391:226dcdb8ab67
*** empty log message ***
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Sat, 27 Mar 1993 18:32:23 +0000 |
parents | e611237d4420 |
children | 319c8db6eb51 |
files | src/xfaces.c |
diffstat | 1 files changed, 205 insertions(+), 131 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xfaces.c Sat Mar 27 18:04:02 1993 +0000 +++ b/src/xfaces.c Sat Mar 27 18:32:23 1993 +0000 @@ -1,6 +1,3 @@ -/* Must define frame->faces, frame->n_faces, - FRAME_NORMAL_FACE, FRAME_MODELINE_FACE. */ - /* "Face" primitives Copyright (C) 1992, 1993 Free Software Foundation. @@ -20,18 +17,7 @@ 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> @@ -41,9 +27,9 @@ #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> @@ -52,8 +38,8 @@ #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". @@ -81,8 +67,15 @@ #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 (); /* Make a new face that's a copy of an existing one. */ @@ -95,7 +88,7 @@ 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; @@ -108,7 +101,7 @@ 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); } @@ -123,6 +116,7 @@ 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. */ @@ -167,14 +161,15 @@ { 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; @@ -182,7 +177,8 @@ UNBLOCK_INPUT; } -/* 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) @@ -193,18 +189,27 @@ 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; } /* Modify face TO by copying from FROM all properties which have @@ -222,20 +227,28 @@ 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; { @@ -247,6 +260,10 @@ 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); @@ -257,18 +274,21 @@ /* 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]; @@ -276,11 +296,35 @@ 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. */ @@ -292,10 +336,10 @@ 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); @@ -311,6 +355,19 @@ 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. @@ -326,8 +383,9 @@ 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); } @@ -343,31 +401,31 @@ 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. */ @@ -384,7 +442,7 @@ result->font = (XFontStruct *) FACE_DEFAULT; result->foreground = FACE_DEFAULT; result->background = FACE_DEFAULT; - result->back_pixmap = FACE_DEFAULT; + result->stipple = FACE_DEFAULT; return result; } @@ -395,20 +453,25 @@ 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 (); } /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */ @@ -459,7 +522,7 @@ if (NILP (name)) return FACE_DEFAULT; - cmap = DefaultColormapOfScreen (x_screen); + cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display)); CHECK_STRING (name, 0); BLOCK_INPUT; @@ -486,7 +549,7 @@ 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; @@ -499,7 +562,7 @@ void init_frame_faces (f) - struct frame f; + struct frame *f; { struct frame *other_frame = 0; Lisp_Object rest; @@ -507,7 +570,7 @@ 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; @@ -517,14 +580,15 @@ 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)); } } @@ -538,22 +602,24 @@ 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; } @@ -587,9 +653,9 @@ 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) { @@ -611,67 +677,47 @@ 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"))) @@ -685,16 +731,18 @@ 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; } @@ -707,10 +755,36 @@ { 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); +} 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);