unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Today's buffer-local faces patch
@ 2004-05-04  2:10 Miles Bader
  0 siblings, 0 replies; only message in thread
From: Miles Bader @ 2004-05-04  2:10 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 650 bytes --]

This is a slight rework of my previous patch, incorporating some
suggestions.

Now the remapping is strictly only for display -- if lisp code wants to
know about it, it has to look at the variable (`face-remapping-alist').

[It would probably be good if such functions as describe-face and perhaps
customize-face would display a note when invoked on a remapped face.]

BTW one very nice use I've found is for reading mail in gnus:

   (defun use-variable-pitch-default-face ()
     (set (make-local-variable 'face-remappings)
          '((default variable-pitch))))

   (add-hook 'gnus-article-mode-hook 'use-variable-pitch-default-face)



Patch:



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: +face-remapping-20040504-0.patch --]
[-- Type: text/x-patch, Size: 23875 bytes --]

M  src/xfaces.c
M  src/dispextern.h
M  src/fontset.c
M  src/xdisp.c

* modified files

*** orig/src/dispextern.h
--- mod/src/dispextern.h
***************
*** 2838,2843 ****
--- 2838,2844 ----
  int xstricmp P_ ((const unsigned char *, const unsigned char *));
  int lookup_face P_ ((struct frame *, Lisp_Object *, int, struct face *));
  int lookup_named_face P_ ((struct frame *, Lisp_Object, int));
+ int lookup_basic_face P_ ((struct frame *, int));
  int smaller_face P_ ((struct frame *, int, int));
  int face_with_height P_ ((struct frame *, int, int));
  int lookup_derived_face P_ ((struct frame *, Lisp_Object, int, int));
***************
*** 2854,2859 ****
--- 2855,2862 ----
  extern char unspecified_fg[], unspecified_bg[];
  void free_realized_multibyte_face P_ ((struct frame *, int));
  
+ extern Lisp_Object Vface_remapping_alist;
+ 
  /* Defined in xfns.c  */
  
  #ifdef HAVE_X_WINDOWS


*** orig/src/fontset.c
--- mod/src/fontset.c
***************
*** 1252,1258 ****
        CHECK_NATNUM (ch);
        c = XINT (ch);
        f = XFRAME (selected_frame);
!       face_id = DEFAULT_FACE_ID;
      }
    else
      {
--- 1252,1258 ----
        CHECK_NATNUM (ch);
        c = XINT (ch);
        f = XFRAME (selected_frame);
!       face_id = lookup_basic_face (f, DEFAULT_FACE_ID);
      }
    else
      {


*** orig/src/xdisp.c
--- mod/src/xdisp.c
***************
*** 2028,2033 ****
--- 2028,2034 ----
       enum face_id base_face_id;
  {
    int highlight_region_p;
+   enum face_id remapped_base_face_id = base_face_id;
  
    /* Some precondition checks.  */
    xassert (w != NULL && it != NULL);
***************
*** 2044,2049 ****
--- 2045,2054 ----
        free_all_realized_faces (Qnil);
      }
  
+   /* Perhaps remap BASE_FACE_ID to a user-specified alternative.  */
+   if (! NILP (Vface_remapping_alist))
+     remapped_base_face_id = lookup_basic_face (XFRAME (w->frame), base_face_id);
+ 
    /* Use one of the mode line rows of W's desired matrix if
       appropriate.  */
    if (row == NULL)
***************
*** 2059,2065 ****
    bzero (it, sizeof *it);
    it->current.overlay_string_index = -1;
    it->current.dpvec_index = -1;
!   it->base_face_id = base_face_id;
    it->string = Qnil;
    IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
  
--- 2064,2070 ----
    bzero (it, sizeof *it);
    it->current.overlay_string_index = -1;
    it->current.dpvec_index = -1;
!   it->base_face_id = remapped_base_face_id;
    it->string = Qnil;
    IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
  
***************
*** 2243,2253 ****
      {
        struct face *face;
  
!       it->face_id = base_face_id;
  
        /* If we have a boxed mode line, make the first character appear
  	 with a left box line.  */
!       face = FACE_FROM_ID (it->f, base_face_id);
        if (face->box != FACE_NO_BOX)
  	it->start_of_box_run_p = 1;
  #ifdef HAVE_WINDOW_SYSTEM
--- 2248,2258 ----
      {
        struct face *face;
  
!       it->face_id = remapped_base_face_id;
  
        /* If we have a boxed mode line, make the first character appear
  	 with a left box line.  */
!       face = FACE_FROM_ID (it->f, remapped_base_face_id);
        if (face->box != FACE_NO_BOX)
  	it->start_of_box_run_p = 1;
  #ifdef HAVE_WINDOW_SYSTEM
***************
*** 3491,3497 ****
  	      /* Value is a multiple of the canonical char height.  */
  	      struct face *face;
  
! 	      face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
  	      new_height = (XFLOATINT (it->font_height)
  			    * XINT (face->lface[LFACE_HEIGHT_INDEX]));
  	    }
--- 3496,3503 ----
  	      /* Value is a multiple of the canonical char height.  */
  	      struct face *face;
  
! 	      face = FACE_FROM_ID (it->f,
! 				   lookup_basic_face (it->f, DEFAULT_FACE_ID));
  	      new_height = (XFLOATINT (it->font_height)
  			    * XINT (face->lface[LFACE_HEIGHT_INDEX]));
  	    }
***************
*** 3591,3597 ****
  	      || EQ (XCAR (prop), Qright_fringe))
  	  && CONSP (XCDR (prop)))
  	{
! 	  unsigned face_id = DEFAULT_FACE_ID;
  
  	  /* Save current settings of IT so that we can restore them
  	     when we are finished with the glyph property value.  */
--- 3597,3603 ----
  	      || EQ (XCAR (prop), Qright_fringe))
  	  && CONSP (XCDR (prop)))
  	{
! 	  unsigned face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
  
  	  /* Save current settings of IT so that we can restore them
  	     when we are finished with the glyph property value.  */


*** orig/src/xfaces.c
--- mod/src/xfaces.c
***************
*** 400,405 ****
--- 400,412 ----
  
  Lisp_Object Vface_new_frame_defaults;
  
+ /* Alist of face mappings.  Each element is either of the form
+    (FACE . NEW-FACE), or (FACE NEW-FACE MERGE-FACE...),
+    where FACE is the named used for lookups, and NEW-FACE is the name
+    that actually gets looked up.  If present, MERGE-FACE... are merged
+    during display of FACE, with NEW-FACE.  */
+ Lisp_Object Vface_remapping_alist;
+ 
  /* The next ID to assign to Lisp faces.  */
  
  static int next_lface_id;
***************
*** 475,481 ****
  static int x_face_list_fonts P_ ((struct frame *, char *,
  				  struct font_name **, int, int));
  static int font_scalable_p P_ ((struct font_name *));
! static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int));
  static int load_pixmap P_ ((struct frame *, Lisp_Object));
  static unsigned char *xstrlwr P_ ((unsigned char *));
  static void signal_error P_ ((char *, Lisp_Object));
--- 482,488 ----
  static int x_face_list_fonts P_ ((struct frame *, char *,
  				  struct font_name **, int, int));
  static int font_scalable_p P_ ((struct font_name *));
! static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int, Lisp_Object));
  static int load_pixmap P_ ((struct frame *, Lisp_Object));
  static unsigned char *xstrlwr P_ ((unsigned char *));
  static void signal_error P_ ((char *, Lisp_Object));
***************
*** 3190,3213 ****
  
  
  /* Return the face definition of FACE_NAME on frame F.  F null means
!    return the definition for new frames.  FACE_NAME may be a string or
!    a symbol (apparently Emacs 20.2 allowed strings as face names in
!    face text properties; Ediff uses that).  If FACE_NAME is an alias
!    for another face, return that face's definition.  If SIGNAL_P is
!    non-zero, signal an error if FACE_NAME is not a valid face name.
!    If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
!    name.  */
! 
  static INLINE Lisp_Object
! lface_from_face_name (f, face_name, signal_p)
       struct frame *f;
       Lisp_Object face_name;
       int signal_p;
  {
    Lisp_Object lface;
  
-   face_name = resolve_face_name (face_name);
- 
    if (f)
      lface = assq_no_quit (face_name, f->face_alist);
    else
--- 3197,3215 ----
  
  
  /* Return the face definition of FACE_NAME on frame F.  F null means
!    return the definition for new frames.  FACE_NAME may be a string or a
!    symbol (apparently Emacs 20.2 allowed strings as face names in face
!    text properties; Ediff uses that).  If SIGNAL_P is non-zero, signal
!    an error if FACE_NAME is not a valid face name.  If SIGNAL_P is zero,
!    value is nil if FACE_NAME is not a valid face name.  */
  static INLINE Lisp_Object
! lface_from_face_name_no_resolve (f, face_name, signal_p)
       struct frame *f;
       Lisp_Object face_name;
       int signal_p;
  {
    Lisp_Object lface;
  
    if (f)
      lface = assq_no_quit (face_name, f->face_alist);
    else
***************
*** 3219,3227 ****
--- 3221,3247 ----
      signal_error ("Invalid face", face_name);
  
    check_lface (lface);
+ 
    return lface;
  }
  
+ /* Return the face definition of FACE_NAME on frame F.  F null means
+    return the definition for new frames.  FACE_NAME may be a string or
+    a symbol (apparently Emacs 20.2 allowed strings as face names in
+    face text properties; Ediff uses that).  If FACE_NAME is an alias
+    for another face, return that face's definition.  If SIGNAL_P is
+    non-zero, signal an error if FACE_NAME is not a valid face name.
+    If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
+    name.  */
+ static INLINE Lisp_Object
+ lface_from_face_name (f, face_name, signal_p)
+      struct frame *f;
+      Lisp_Object face_name;
+      int signal_p;
+ {
+   return lface_from_face_name_no_resolve (f, face_name, signal_p);
+ }
+ 
  
  /* Get face attributes of face FACE_NAME from frame-local faces on
     frame F.  Store the resulting attributes in ATTRS which must point
***************
*** 3230,3255 ****
     Otherwise, value is zero if FACE_NAME is not a face.  */
  
  static INLINE int
! get_lface_attributes (f, face_name, attrs, signal_p)
       struct frame *f;
       Lisp_Object face_name;
       Lisp_Object *attrs;
       int signal_p;
  {
    Lisp_Object lface;
-   int success_p;
  
!   lface = lface_from_face_name (f, face_name, signal_p);
!   if (!NILP (lface))
!     {
!       bcopy (XVECTOR (lface)->contents, attrs,
! 	     LFACE_VECTOR_SIZE * sizeof *attrs);
!       success_p = 1;
      }
-   else
-     success_p = 0;
  
!   return success_p;
  }
  
  
--- 3250,3340 ----
     Otherwise, value is zero if FACE_NAME is not a face.  */
  
  static INLINE int
! get_lface_attributes_no_remap (f, face_name, attrs, signal_p)
       struct frame *f;
       Lisp_Object face_name;
       Lisp_Object *attrs;
       int signal_p;
  {
    Lisp_Object lface;
  
!   lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
! 
!   if (! NILP (lface))
!     bcopy (XVECTOR (lface)->contents, attrs,
! 	   LFACE_VECTOR_SIZE * sizeof *attrs);
! 
!   return !NILP (lface);
! }
! 
! /* Get face attributes of face FACE_NAME from frame-local faces on frame
!    F.  Store the resulting attributes in ATTRS which must point to a
!    vector of Lisp_Objects of size LFACE_VECTOR_SIZE.  If FACE_NAME is an
!    alias for another face, use that face's definition.  If SIGNAL_P is
!    non-zero, signal an error if FACE_NAME does not name a face.
!    Otherwise, value is zero if FACE_NAME is not a face.  */
! 
! static INLINE int
! get_lface_attributes (f, face_name, attrs, signal_p, cycle_check)
!      struct frame *f;
!      Lisp_Object face_name;
!      Lisp_Object *attrs;
!      int signal_p;
!      Lisp_Object cycle_check;
! {
!   Lisp_Object lface;
!   Lisp_Object face_remapping;
! 
!   face_name = resolve_face_name (face_name);
! 
!   /* See if SYMBOL has been remapped to some other face (usually this
!      is done buffer-locally).  */
!   face_remapping = assq_no_quit (face_name, Vface_remapping_alist);
!   if (CONSP (face_remapping))
!     {  
!       /* Make sure we're not in an mapping loop.  */
!       cycle_check = CYCLE_CHECK (cycle_check, face_name, 15);
! 
!       if (! NILP (cycle_check))
! 	{
! 	  /* No cycle detected, lookup FACE_NAME's mapping instead.  */
! 
! 	  face_remapping = XCDR (face_remapping);
! 
! 	  /* A mapping may also contain a list of `merge faces', which
! 	     we ignore in this function.  */
! 	  if (CONSP (face_remapping))
! 	    {
! 	      int first_ok;
! 	      Lisp_Object first_face;
! 
! 	      first_face = XCAR (face_remapping);
! 
! 	      /* See if this is a trivial recursion, and handle it
! 		 properly without incuring a cycle-check penalty.  */
! 	      if (EQ (first_face, face_name) || NILP (first_face))
! 		first_ok = get_lface_attributes_no_remap (f, face_name, attrs,
! 							  signal_p);
! 	      else
! 		first_ok = get_lface_attributes (f, first_face, attrs,
! 						 signal_p, cycle_check);
! 		
! 	      if (first_ok)
! 		{
! 		  /* Merge in any remaining faces.  */
! 
! 		  face_remapping = XCDR (face_remapping);
! 		  merge_face_inheritance (f, face_remapping, attrs,
! 					  cycle_check);
! 		}
! 
! 	      return first_ok;
! 	    }
! 	}
      }
  
!   /* Default case, no remapping.  */
!   return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
  }
  
  
***************
*** 3491,3501 ****
    to[LFACE_INHERIT_INDEX] = Qnil;
  }
  
  /* Merge face attributes from the face on frame F whose name is
     INHERITS, into the vector of face attributes TO; INHERITS may also be
     a list of face names, in which case they are applied in order.
!    CYCLE_CHECK is used to detect loops in face inheritance.
!    Returns true if any of the inherited attributes are `font-related'.  */
  
  static void
  merge_face_inheritance (f, inherit, to, cycle_check)
--- 3576,3604 ----
    to[LFACE_INHERIT_INDEX] = Qnil;
  }
  
+ /* Merge the named face FACE_NAME on frame F, into the vector of face
+    attributes TO CYCLE_CHECK is used to detect loops in face
+    inheritance.  Returns true if FACE_NAME is a valid face name, and
+    false otherwise.  */
+ 
+ static int
+ merge_named_face (f, face_name, to, cycle_check)
+      struct frame *f;
+      Lisp_Object face_name;
+      Lisp_Object *to;
+      Lisp_Object cycle_check;
+ {
+   Lisp_Object from[LFACE_VECTOR_SIZE];
+   int ok = get_lface_attributes (f, face_name, from, 0, cycle_check);
+   if (ok)
+     merge_face_vectors (f, from, to, cycle_check);
+   return ok;
+ }
+ 
  /* Merge face attributes from the face on frame F whose name is
     INHERITS, into the vector of face attributes TO; INHERITS may also be
     a list of face names, in which case they are applied in order.
!    CYCLE_CHECK is used to detect loops in face inheritance.  */
  
  static void
  merge_face_inheritance (f, inherit, to, cycle_check)
***************
*** 3507,3523 ****
    if (SYMBOLP (inherit) && !EQ (inherit, Qunspecified))
      /* Inherit from the named face INHERIT.  */
      {
-       Lisp_Object lface;
- 
        /* Make sure we're not in an inheritance loop.  */
        cycle_check = CYCLE_CHECK (cycle_check, inherit, 15);
        if (NILP (cycle_check))
  	/* Cycle detected, ignore any further inheritance.  */
  	return;
  
!       lface = lface_from_face_name (f, inherit, 0);
!       if (!NILP (lface))
! 	merge_face_vectors (f, XVECTOR (lface)->contents, to, cycle_check);
      }
    else if (CONSP (inherit))
      /* Handle a list of inherited faces by calling ourselves recursively
--- 3610,3622 ----
    if (SYMBOLP (inherit) && !EQ (inherit, Qunspecified))
      /* Inherit from the named face INHERIT.  */
      {
        /* Make sure we're not in an inheritance loop.  */
        cycle_check = CYCLE_CHECK (cycle_check, inherit, 15);
        if (NILP (cycle_check))
  	/* Cycle detected, ignore any further inheritance.  */
  	return;
  
!       merge_named_face (f, inherit, to, cycle_check);
      }
    else if (CONSP (inherit))
      /* Handle a list of inherited faces by calling ourselves recursively
***************
*** 3748,3758 ****
    else
      {
        /* PROP ought to be a face name.  */
!       Lisp_Object lface = lface_from_face_name (f, prop, 0);
!       if (NILP (lface))
  	add_to_log ("Invalid face text property value: %s", prop, Qnil);
-       else
- 	merge_face_vectors (f, XVECTOR (lface)->contents, to, Qnil);
      }
  }
  
--- 3847,3854 ----
    else
      {
        /* PROP ought to be a face name.  */
!       if (! merge_named_face (f, prop, to, Qnil))
  	add_to_log ("Invalid face text property value: %s", prop, Qnil);
      }
  }
  
***************
*** 5779,5789 ****
     face couldn't be determined, which might happen if the default face
     isn't realized and cannot be realized.  */
  
! int
! lookup_named_face (f, symbol, c)
       struct frame *f;
       Lisp_Object symbol;
       int c;
  {
    Lisp_Object attrs[LFACE_VECTOR_SIZE];
    Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
--- 5875,5886 ----
     face couldn't be determined, which might happen if the default face
     isn't realized and cannot be realized.  */
  
! static int
! lookup_named_face_1 (f, symbol, c, signal_p)
       struct frame *f;
       Lisp_Object symbol;
       int c;
+      int signal_p;
  {
    Lisp_Object attrs[LFACE_VECTOR_SIZE];
    Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
***************
*** 5796,5807 ****
        default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
      }
  
!   get_lface_attributes (f, symbol, symbol_attrs, 1);
    bcopy (default_face->lface, attrs, sizeof attrs);
    merge_face_vectors (f, symbol_attrs, attrs, Qnil);
    return lookup_face (f, attrs, c, NULL);
  }
  
  
  /* Return the ID of the realized ASCII face of Lisp face with ID
     LFACE_ID on frame F.  Value is -1 if LFACE_ID isn't valid.  */
--- 5893,5961 ----
        default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
      }
  
!   if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, Qnil))
!     return -1;
! 
    bcopy (default_face->lface, attrs, sizeof attrs);
    merge_face_vectors (f, symbol_attrs, attrs, Qnil);
+ 
    return lookup_face (f, attrs, c, NULL);
  }
  
+ /* Return the face id of the realized face for named face SYMBOL on
+    frame F suitable for displaying character C.  Value is -1 if the
+    face couldn't be determined, which might happen if the default face
+    isn't realized and cannot be realized.  */
+ 
+ int
+ lookup_named_face (f, symbol, c)
+      struct frame *f;
+      Lisp_Object symbol;
+      int c;
+ {
+   return lookup_named_face_1 (f, symbol, c);
+ }
+ 
+ 
+ /* Return the display face-id of the basic face who's canonical face-id
+    is FACE_ID.  The return value will usually simply be FACE_ID, unless that
+    basic face has bee remapped via Vface_remapping_alist.  This function is
+    conservative: if something goes wrong, it will simply return FACE_ID
+    rather than signal an error.   */
+ 
+ int
+ lookup_basic_face (f, face_id)
+      struct frame *f;
+      int face_id;
+ {
+   Lisp_Object name, mapping;
+   int remapped_face_id;
+ 
+   if (NILP (Vface_remapping_alist))
+     return face_id;		/* Nothing to do.  */
+ 
+   switch (face_id)
+     {
+     case DEFAULT_FACE_ID:		name = Qdefault;		break;
+     case MODE_LINE_FACE_ID:		name = Qmode_line;		break;
+     case MODE_LINE_INACTIVE_FACE_ID:	name = Qmode_line_inactive;	break;
+     case HEADER_LINE_FACE_ID:		name = Qheader_line;		break;
+ 
+     default:
+       return face_id;		/* Give up.  */
+     }
+ 
+   mapping = assq_no_quit (name, Vface_remapping_alist);
+   if (NILP (mapping))
+     return face_id;		/* Give up.  */
+ 
+   remapped_face_id = lookup_named_face_1 (f, name, 0, 0);
+   if (remapped_face_id < 0)
+     return face_id;		/* Give up. */
+ 
+   return remapped_face_id;
+ }
+ 
  
  /* Return the ID of the realized ASCII face of Lisp face with ID
     LFACE_ID on frame F.  Value is -1 if LFACE_ID isn't valid.  */
***************
*** 5935,5941 ****
    if (!default_face)
      abort ();
  
!   get_lface_attributes (f, symbol, symbol_attrs, 1);
    bcopy (default_face->lface, attrs, sizeof attrs);
    merge_face_vectors (f, symbol_attrs, attrs, Qnil);
    return lookup_face (f, attrs, c, default_face);
--- 6089,6095 ----
    if (!default_face)
      abort ();
  
!   get_lface_attributes (f, symbol, symbol_attrs, 1, Qnil);
    bcopy (default_face->lface, attrs, sizeof attrs);
    merge_face_vectors (f, symbol_attrs, attrs, Qnil);
    return lookup_face (f, attrs, c, default_face);
***************
*** 6801,6807 ****
    struct face *new_face;
  
    /* The default face must exist and be fully specified.  */
!   get_lface_attributes (f, Qdefault, attrs, 1);
    check_lface_attrs (attrs);
    xassert (lface_fully_specified_p (attrs));
  
--- 6955,6961 ----
    struct face *new_face;
  
    /* The default face must exist and be fully specified.  */
!   get_lface_attributes (f, Qdefault, attrs, 1, Qnil);
    check_lface_attrs (attrs);
    xassert (lface_fully_specified_p (attrs));
  
***************
*** 6814,6820 ****
      }
  
    /* Merge SYMBOL's face with the default face.  */
!   get_lface_attributes (f, symbol, symbol_attrs, 1);
    merge_face_vectors (f, symbol_attrs, attrs, Qnil);
  
    /* Realize the face.  */
--- 6968,6974 ----
      }
  
    /* Merge SYMBOL's face with the default face.  */
!   get_lface_attributes (f, symbol, symbol_attrs, 1, Qnil);
    merge_face_vectors (f, symbol_attrs, attrs, Qnil);
  
    /* Realize the face.  */
***************
*** 7372,7384 ****
  
    *endptr = endpos;
  
!   default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
  
    /* Optimize common cases where we can use the default face.  */
    if (noverlays == 0
        && NILP (prop)
        && !(pos >= region_beg && pos < region_end))
!     return DEFAULT_FACE_ID;
  
    /* Begin with attributes from the default face.  */
    bcopy (default_face->lface, attrs, sizeof attrs);
--- 7526,7543 ----
  
    *endptr = endpos;
  
! 
!   /* Perhaps remap BASE_FACE_ID to a user-specified alternative.  */
!   if (NILP (Vface_remapping_alist))
!     default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
!   else
!     default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
  
    /* Optimize common cases where we can use the default face.  */
    if (noverlays == 0
        && NILP (prop)
        && !(pos >= region_beg && pos < region_end))
!     return default_face->id;
  
    /* Begin with attributes from the default face.  */
    bcopy (default_face->lface, attrs, sizeof attrs);
***************
*** 7407,7414 ****
    /* If in the region, merge in the region face.  */
    if (pos >= region_beg && pos < region_end)
      {
!       Lisp_Object region_face = lface_from_face_name (f, Qregion, 0);
!       merge_face_vectors (f, XVECTOR (region_face)->contents, attrs, Qnil);
  
        if (region_end < endpos)
  	endpos = region_end;
--- 7566,7572 ----
    /* If in the region, merge in the region face.  */
    if (pos >= region_beg && pos < region_end)
      {
!       merge_named_face (f, Qregion, attrs);
  
        if (region_end < endpos)
  	endpos = region_end;
***************
*** 7510,7519 ****
    if (bufpos
        && bufpos >= region_beg
        && bufpos < region_end)
!     {
!       Lisp_Object region_face = lface_from_face_name (f, Qregion, 0);
!       merge_face_vectors (f, XVECTOR (region_face)->contents, attrs, Qnil);
!     }
  
    /* Look up a realized face with the given face attributes,
       or realize a new one for ASCII characters.  */
--- 7668,7674 ----
    if (bufpos
        && bufpos >= region_beg
        && bufpos < region_end)
!     merge_named_face (f, Qregion, attrs, Qnil);
  
    /* Look up a realized face with the given face attributes,
       or realize a new one for ASCII characters.  */
***************
*** 7839,7844 ****
--- 7994,8021 ----
  ignore.  */);
    Vface_ignored_fonts = Qnil;
  
+   DEFVAR_LISP ("face-remapping-alist", &Vface_remapping_alist,
+ 	       doc: /* Alist of face remappings.
+ Each element is of the form:
+    (OLD-FACE REPLACEMENT-FACE...),
+ which causes uses of the face OLD-FACE to use
+ REPLACEMENT-FACE... instead.  If more than one replacement face is
+ specified, they are merged together.
+ 
+ Face-name remapping cycles are suppressed, causing the underlying face
+ to be used instead, so a remapping of the form:
+    (OLD-FACE OLD-FACE EXTRA-FACE...)
+ will cause EXTRA-FACE... to be _merged_ with the existing definition of
+ OLD-FACE.  For conciseness, the form (OLD-FACE nil EXTRA-FACE....) is
+ treated the same way.  Note that for the default face, this isn't
+ necessary, as every face inherits from the default face.
+ 
+ Making this variable buffer-local is a good way to allow buffer-specific
+ face definitions, for instance, the mode my-mode could define a face
+ `my-mode-default', and then in the mode setup function, do
+ (set (make-local-variable 'face-remapping-alist) '((default my-mode-default)))).  */);
+   Vface_remapping_alist = Qnil;
+ 
    DEFVAR_LISP ("face-font-rescale-alist", &Vface_font_rescale_alist,
  	       doc: /* Alist of fonts vs the rescaling factors.
  Each element is a cons (FONT-NAME-PATTERN . RESCALE-RATIO), where




[-- Attachment #3: Type: text/plain, Size: 35 bytes --]




-Miles
-- 
Run away!  Run away!

[-- Attachment #4: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-05-04  2:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-05-04  2:10 Today's buffer-local faces patch Miles Bader

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).