changeset 3074:96b4623fdeb3

* xterm.h: New section for declarations for xfaces.c. (init_frame_faces, free_frame_faces, intern_face, face_name_id_number, same_size_fonts, recompute_basic_faces, compute_char_face, compute_glyph_face): Declare these here. * xfaces.c (same_size_fonts): We can now remove this extern declaration. * xfns.c (face_name_id_number): Likewise. * xterm.c (intern_face): Likewise. * xfaces.c (build_face, unload_font, free_frame_faces): Don't forget to block input while making X calls. Treat faces as structures specifying modifications to the frame's parameters, rather than things which need to specify a complete set of parameters by themselves. * xfaces.c (init_frame_faces): Don't set up the two frame display faces by querying the GC - just leave all their fields blank, and call recompute_basic_faces, letting build_face do the work of consulting the frame when necessary. (recompute_basic_faces): New function. (compute_base_faces): New function for obtaining the "identity" for compute_char_face and compute_glyph_face. (compute_char_face, compute_glyph_face): Call it, instead of copying FRAME_DEFAULT_FACE. * xfns.c (x_make_gc): No need to call init_frame_faces here. * xfaces.c (intern_frame_face): This can be static. * dispextern.h (struct face): New field - `copy', to help us with resource allocation. * xfaces.c (free_frame_faces): Do free the first two faces; don't free anything from a face that's a copy. (intern_frame_face): Mark every face we intern as a copy; its resources are actually a combination of the real faces. (Fset_face_attribute_internal): No need to check if we're trying to free one of the frame's GC's; they never enter into the picture. * xfns.c (Fx_list_fonts): New function. (face_name_id_number): Add extern declaration for this. * xfaces.c (face_name_id_number): Make this externally visible, and make the FRAME argument a FRAME_PTR, not a Lisp_Object. (compute_char_face): Call face_name_id_number properly.
author Jim Blandy <jimb@redhat.com>
date Tue, 25 May 1993 14:02:58 +0000
parents 905f9fda79b8
children 878381e48b0d
files src/xfaces.c
diffstat 1 files changed, 104 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/src/xfaces.c	Tue May 25 14:01:54 1993 +0000
+++ b/src/xfaces.c	Tue May 25 14:02:58 1993 +0000
@@ -61,6 +61,8 @@
        BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
            use right now, and
        UNDERLINE-P is non-nil if the face should be underlined.
+   If any of these elements are nil, that allows the frame's parameters to
+   show through.
    (lisp/faces.el maintains these association lists.)
 
    The frames' private alists hold the frame-local definitions for the
@@ -136,10 +138,6 @@
 /* The number of the face to use to indicate the region.  */
 int region_face;
 
-/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
-   We assume that they're both character-cell fonts.  */
-extern int same_size_fonts ();
-
 /* This is what appears in a slot in a face to signify that the face
    does not specify that display aspect.  */
 #define FACE_DEFAULT (~0)
@@ -318,27 +316,37 @@
   XGCValues xgcv;
   unsigned long mask;
 
+  BLOCK_INPUT;
+
   if (face->foreground != FACE_DEFAULT)
     xgcv.foreground = face->foreground;
   else
-    xgcv. foreground = f->display.x->foreground_pixel;
+    xgcv.foreground = f->display.x->foreground_pixel;
+
   if (face->background != FACE_DEFAULT)
     xgcv.background = face->background;
   else
-    xgcv. background = f->display.x->background_pixel;
+    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->stipple && face->stipple != FACE_DEFAULT)
     XSetStipple (x_current_display, gc, face->stipple);
 #endif
+
   face->gc = gc;
+
+  UNBLOCK_INPUT;
 }
 
 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps.  */
@@ -371,7 +379,10 @@
 {
   if (!font || font == ((XFontStruct *) FACE_DEFAULT))
     return;
+
+  BLOCK_INPUT;
   XFreeFont (x_current_display, font);
+  UNBLOCK_INPUT;
 }
 
 static unsigned long
@@ -432,46 +443,16 @@
 
 /* Initializing face arrays for frames. */
 
-/* Set up faces 0 and 1 based on the normal text and modeline GC's.
-   This gets called whenever the parameters stored in the frame itself
-   (i.e. font, background color, etcetera) change.
-
-   Note that the first two faces just contain references to the
-   frame's own resources.  We shouldn't free them.  */
 void
 init_frame_faces (f)
-     struct frame *f;
+     FRAME_PTR f;
 {
   ensure_face_ready (f, 0);
-  {
-    XGCValues gcv;
-    struct face *face = FRAME_FACES (f) [0];
-
-    XGetGCValues (x_current_display, f->display.x->normal_gc,
-		  GCForeground | GCBackground | GCFont, &gcv);
-    face->gc         = f->display.x->normal_gc;
-    face->foreground = gcv.foreground;
-    face->background = gcv.background;
-    face->font       = f->display.x->font;
-    face->stipple = 0;
-    face->underline = 0;
-  }
+  ensure_face_ready (f, 1);
 
-  ensure_face_ready (f, 1);
-  {
-    XGCValues gcv;
-    struct face *face = FRAME_FACES (f) [1];
+  recompute_basic_faces (f);
+}
 
-    XGetGCValues (x_current_display, f->display.x->reverse_gc,
-		  GCForeground | GCBackground | GCFont, &gcv);
-    face->gc         = f->display.x->reverse_gc;
-    face->foreground = gcv.foreground;
-    face->background = gcv.background;
-    face->font       = f->display.x->font;
-    face->stipple = 0;
-    face->underline = 0;
-  }
-}
 
 /* Called from Fdelete_frame.  */
 void
@@ -481,34 +462,39 @@
   Display *dpy = x_current_display;
   int i;
 
-  /* The first two faces on the frame are just made of resources which 
-     we borrowed from the frame's GC's, so don't free them.  Let
-     them get freed by the x_destroy_window code.  */
-  for (i = 2; i < FRAME_N_FACES (f); i++)
+  BLOCK_INPUT;
+
+  for (i = 0; i < FRAME_N_FACES (f); i++)
     {
       struct face *face = FRAME_FACES (f) [i];
-      if (! face)
-        continue;
-      if (face->gc)
-	XFreeGC (dpy, face->gc);
-      unload_font (f, face->font);
-      unload_color (f, face->foreground);
-      unload_color (f, face->background);
+      if (face)
+	{
+	  if (face->gc)
+	    XFreeGC (dpy, face->gc);
+	  if (! face->copy)
+	    {
+	      unload_font (f, face->font);
+	      unload_color (f, face->foreground);
+	      unload_color (f, face->background);
 #if 0
-      unload_pixmap (f, face->stipple);
+	      unload_pixmap (f, face->stipple);
 #endif
-      xfree (face);
+	    }
+	  xfree (face);
+	}
     }
   xfree (FRAME_FACES (f));
   FRAME_FACES (f) = 0;
   FRAME_N_FACES (f) = 0;
+
+  UNBLOCK_INPUT;
 }
 
 /* Interning faces in a frame's face array.  */
 
 /* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
    find one.  */
-int
+static int
 intern_frame_face (frame, new_face)
      struct frame *frame;
      struct face *new_face;
@@ -530,6 +516,7 @@
 
   ensure_face_ready (frame, i);
   bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face));
+  FRAME_FACES (frame)[i]->copy = 1;
 
   return i;
 }
@@ -564,6 +551,20 @@
 
 /* Computing faces appropriate for a given piece of text in a buffer.  */
 
+/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
+   We assume that they're both character-cell fonts.  */
+int
+same_size_fonts (font1, font2)
+     XFontStruct *font1, *font2;
+{
+  XCharStruct *bounds1 = &font1->min_bounds;
+  XCharStruct *bounds2 = &font2->min_bounds;
+
+  return (bounds1->width == bounds2->width
+	  && bounds1->ascent == bounds2->ascent
+	  && bounds1->descent == bounds2->descent);
+}
+
 /* Modify face TO by copying from FROM all properties which have
    nondefault settings.  */
 static void 
@@ -584,6 +585,23 @@
     to->underline = from->underline;
 }
 
+/* Set up the basic set of facial parameters, based on the frame's
+   data; all faces are deltas applied to this.  */
+static void
+compute_base_face (f, face)
+     FRAME_PTR f;
+     struct face *face;
+{
+  struct x_display *d = f->display.x;
+  
+  face->gc = 0;
+  face->foreground = d->foreground_pixel;
+  face->background = d->background_pixel;
+  face->font = d->font;
+  face->underline = 0;
+}
+
+
 struct sortvec
 {
   Lisp_Object overlay;
@@ -680,8 +698,7 @@
       && !(pos >= region_beg && pos < region_end))
     return 0;
 
-  bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face));
-  face.gc = 0;
+  compute_base_face (f, &face);
 
   if (!NILP (prop))
     {
@@ -777,8 +794,7 @@
 {
   struct face face;
 
-  bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (face));
-  face.gc = 0;
+  compute_base_face (f, &face);
 
   if (face_code >= 0 && face_code < FRAME_N_FACES (f)
       && FRAME_FACES (f) [face_code] != 0)
@@ -786,6 +802,34 @@
 
   return intern_frame_face (f, &face);
 }
+
+
+/* Recompute the GC's for the default and modeline faces.
+   We call this after changing frame parameters on which those GC's
+   depend.  */
+void
+recompute_basic_faces (f)
+     FRAME_PTR f;
+{
+  /* If the frame's faces haven't been initialized yet, don't worry about
+     this stuff.  */
+  if (FRAME_N_FACES (f) < 2)
+    return;
+
+  BLOCK_INPUT;
+
+  if (FRAME_DEFAULT_FACE (f)->gc)
+    XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
+  build_face (f, FRAME_DEFAULT_FACE (f));
+
+  if (FRAME_MODE_LINE_FACE (f)->gc)
+    XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
+  build_face (f, FRAME_MODE_LINE_FACE (f));
+
+  UNBLOCK_INPUT;
+}
+
+
 
 /* Lisp interface. */
 
@@ -900,9 +944,7 @@
   if (id == 0)
     {
       BLOCK_INPUT;
-      if (FRAME_DEFAULT_FACE (f)->gc != 0
-	  && FRAME_DEFAULT_FACE (f)->gc != f->display.x->normal_gc
-	  && FRAME_DEFAULT_FACE (f)->gc != f->display.x->reverse_gc)
+      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;
@@ -911,9 +953,7 @@
   if (id == 1)
     {
       BLOCK_INPUT;
-      if (FRAME_MODE_LINE_FACE (f)->gc != 0
-	  && FRAME_MODE_LINE_FACE (f)->gc != f->display.x->normal_gc
-	  && FRAME_MODE_LINE_FACE (f)->gc != f->display.x->reverse_gc)
+      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;