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);