Function: internal-merge-in-global-face

internal-merge-in-global-face is a function defined in xfaces.c.

Signature

(internal-merge-in-global-face FACE FRAME)

Documentation

Add attributes from frame-default definition of FACE to FACE on FRAME.

Default face attributes override any local face attributes.

Source Code

// Defined in /usr/src/emacs/src/xfaces.c
{
  int i;
  Lisp_Object global_lface, local_lface, *gvec, *lvec;
  struct frame *f = XFRAME (frame);

  CHECK_LIVE_FRAME (frame);
  global_lface = lface_from_face_name (NULL, face, true);
  local_lface = lface_from_face_name (f, face, false);
  if (NILP (local_lface))
    local_lface = Finternal_make_lisp_face (face, frame);

  /* Make every specified global attribute override the local one.
     BEWARE!! This is only used from `face-set-after-frame-default' where
     the local frame is defined from default specs in `face-defface-spec'
     and those should be overridden by global settings.  Hence the strange
     "global before local" priority.  */
  lvec = XVECTOR (local_lface)->contents;
  gvec = XVECTOR (global_lface)->contents;
  for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
    if (IGNORE_DEFFACE_P (gvec[i]))
      ASET (local_lface, i, Qunspecified);
    else if (! UNSPECIFIEDP (gvec[i]))
      ASET (local_lface, i, AREF (global_lface, i));

  /* If the default face was changed, update the face cache and the
     `font' frame parameter.  */
  if (EQ (face, Qdefault))
    {
      struct face_cache *c = FRAME_FACE_CACHE (f);
      struct face *newface;
      struct face *oldface =
	c ? FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID) : NULL;
      Lisp_Object attrs[LFACE_VECTOR_SIZE];

      /* This can be NULL (e.g., in batch mode).  */
      if (oldface)
	{
	  /* In some cases, realize_face below can call Lisp, which could
             trigger redisplay.  But we are in the process of realizing
             the default face, and therefore are not ready to do display.  */
	  specpdl_ref count = SPECPDL_INDEX ();
	  specbind (Qinhibit_redisplay, Qt);

	  /* Ensure that the face vector is fully specified by merging
	     the previously-cached vector.  */
	  memcpy (attrs, oldface->lface, sizeof attrs);

	  merge_face_vectors (NULL, f, lvec, attrs, 0);
	  vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE);
	  newface = realize_face (c, lvec, DEFAULT_FACE_ID);

	  if ((! UNSPECIFIEDP (gvec[LFACE_FAMILY_INDEX])
	       || ! UNSPECIFIEDP (gvec[LFACE_FOUNDRY_INDEX])
	       || ! UNSPECIFIEDP (gvec[LFACE_HEIGHT_INDEX])
	       || ! UNSPECIFIEDP (gvec[LFACE_WEIGHT_INDEX])
	       || ! UNSPECIFIEDP (gvec[LFACE_SLANT_INDEX])
	       || ! UNSPECIFIEDP (gvec[LFACE_SWIDTH_INDEX])
	       || ! UNSPECIFIEDP (gvec[LFACE_FONT_INDEX]))
	      && newface->font)
	    {
	      Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
	      AUTO_FRAME_ARG (arg, Qfont, name);

#ifdef HAVE_WINDOW_SYSTEM
	      if (FRAME_WINDOW_P (f))
		/* This is a window-system frame.  Prevent changes of
		   the `font' parameter here from messing with the
		   `font-parameter' frame property, as the frame
		   parameter is not being changed by the user.  */
                gui_set_frame_parameters_1 (f, arg, true);
	      else
#endif
		Fmodify_frame_parameters (frame, arg);
	    }

	  if (STRINGP (gvec[LFACE_FOREGROUND_INDEX]))
	    {
	      AUTO_FRAME_ARG (arg, Qforeground_color,
			      gvec[LFACE_FOREGROUND_INDEX]);
	      Fmodify_frame_parameters (frame, arg);
	    }

	  if (STRINGP (gvec[LFACE_BACKGROUND_INDEX]))
	    {
	      AUTO_FRAME_ARG (arg, Qbackground_color,
			      gvec[LFACE_BACKGROUND_INDEX]);
	      Fmodify_frame_parameters (frame, arg);
	    }

	  unbind_to (count, Qnil);
	}
    }

  return Qnil;
}