Faces
***********************************************************************/
-/* Set up iterator IT from face properties at its current position.
- Called from handle_stop. */
-
static enum prop_handled
-handle_face_prop (struct it *it)
+handle_face_prop_general (struct it *it,
+ enum lface_attribute_index attr_filter)
{
- int new_face_id;
+ int new_face_id, *face_id_ptr;
ptrdiff_t next_stop;
+ if (attr_filter == LFACE_EXTEND_INDEX)
+ face_id_ptr = &(it->extend_face_id);
+ else
+ face_id_ptr = &(it->face_id);
+
if (!STRINGP (it->string))
{
new_face_id
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
- false, it->base_face_id);
+ false, it->base_face_id, attr_filter);
/* Is this a start of a run of characters with box face?
Caveat: this can be called for a freshly initialized
face will not change until limit, i.e. if the new face has a
box, all characters up to limit will have one. But, as
usual, we don't know whether limit is really the end. */
- if (new_face_id != it->face_id)
+ if (new_face_id != *face_id_ptr)
{
struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
/* If it->face_id is -1, old_face below will be NULL, see
the definition of FACE_FROM_ID_OR_NULL. This will happen
if this is the initial call that gets the face. */
- struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
+ struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, *face_id_ptr);
/* If the value of face_id of the iterator is -1, we have to
look in front of IT's position and see whether there is a
box, all characters up to that position will have a
box. But, as usual, we don't know whether that position
is really the end. */
- if (new_face_id != it->face_id)
+ if (new_face_id != *face_id_ptr)
{
struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
- struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
+ struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, *face_id_ptr);
/* If new face has a box but old face hasn't, this is the
start of a run of characters with box, i.e. it has a
}
}
- it->face_id = new_face_id;
+ *face_id_ptr = new_face_id;
return HANDLED_NORMALLY;
}
+/* Set up iterator IT from face properties at its current position.
+ Called from handle_stop. */
+
+static enum prop_handled
+handle_face_prop (struct it *it)
+{
+ return handle_face_prop_general (it, 0);
+}
+
+
/* Return the ID of the face ``underlying'' IT's current position,
which is in a string. If the iterator is associated with a
buffer, return the face at IT's current buffer position.
face_id = face_at_buffer_position (it->w,
CHARPOS (pos),
&next_check_charpos,
- limit, false, -1);
+ limit, false, -1, 0);
/* Correct the face for charsets different from ASCII. Do it
for the multibyte case only. The face returned above is
else
{
next_face_id =
- face_at_buffer_position (it->w, CHARPOS (pos), &ignore,
+ face_at_buffer_position (it->w, CHARPOS (pos),
+ &ignore,
CHARPOS (pos)
+ TEXT_PROP_DISTANCE_LIMIT,
- false, -1);
+ false, -1, 0);
it->end_of_box_run_p
= (FACE_FROM_ID (it->f, next_face_id)->box
== FACE_NO_BOX);
hlinfo->mouse_face_face_id
= face_at_buffer_position (w, mouse_charpos, &ignore,
mouse_charpos + 1,
- !hlinfo->mouse_face_hidden, -1);
+ !hlinfo->mouse_face_hidden, -1, 0);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
}
static void free_face_cache (struct face_cache *);
static bool merge_face_ref (struct window *w,
struct frame *, Lisp_Object, Lisp_Object *,
- bool, struct named_merge_point *);
+ bool, struct named_merge_point *,
+ enum lface_attribute_index);
static int color_distance (Emacs_Color *x, Emacs_Color *y);
#ifdef HAVE_WINDOW_SYSTEM
attrs[i] = Qunspecified;
return merge_face_ref (w, f, XCDR (face_remapping), attrs,
- signal_p, named_merge_points);
+ signal_p, named_merge_points,
+ 0);
}
}
if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
&& !NILP (from[LFACE_INHERIT_INDEX]))
merge_face_ref (w, f, from[LFACE_INHERIT_INDEX],
- to, false, named_merge_points);
+ to, false, named_merge_points,
+ 0);
if (FONT_SPEC_P (from[LFACE_FONT_INDEX]))
{
static bool
merge_named_face (struct window *w,
struct frame *f, Lisp_Object face_name, Lisp_Object *to,
- struct named_merge_point *named_merge_points)
+ struct named_merge_point *named_merge_points,
+ enum lface_attribute_index attr_filter)
{
struct named_merge_point named_merge_point;
{
Lisp_Object from[LFACE_VECTOR_SIZE];
bool ok = get_lface_attributes (w, f, face_name, from, false,
- named_merge_points);
+ named_merge_points);
- if (ok)
+ eassert (attr_filter < LFACE_VECTOR_SIZE);
+
+ if (ok && (attr_filter == 0
+ || (!NILP (from[attr_filter])
+ && !UNSPECIFIEDP (from[attr_filter]))))
merge_face_vectors (w, f, from, to, named_merge_points);
return ok;
of ERR_MSGS). Use NAMED_MERGE_POINTS to detect loops in face
inheritance or list structure; it may be 0 for most callers.
+ attr_filter is the index of a parameter that conditions the merging
+ for named faces (case 1) to only the face_ref where
+ lface[merge_face_ref] is non-nil. To merge unconditionally set this
+ value to 0.
+
FACE_REF may be a single face specification or a list of such
specifications. Each face specification can be:
static bool
merge_face_ref (struct window *w,
struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
- bool err_msgs, struct named_merge_point *named_merge_points)
+ bool err_msgs, struct named_merge_point *named_merge_points,
+ enum lface_attribute_index attr_filter)
{
bool ok = true; /* Succeed without an error? */
Lisp_Object filtered_face_ref;
/* This is not really very useful; it's just like a
normal face reference. */
if (! merge_face_ref (w, f, value, to,
- err_msgs, named_merge_points))
+ err_msgs, named_merge_points,
+ 0))
err = true;
}
else if (EQ (keyword, QCextend))
Lisp_Object next = XCDR (face_ref);
if (! NILP (next))
- ok = merge_face_ref (w, f, next, to, err_msgs, named_merge_points);
+ ok = merge_face_ref (w, f, next, to, err_msgs,
+ named_merge_points, 0);
- if (! merge_face_ref (w, f, first, to, err_msgs, named_merge_points))
+ if (! merge_face_ref (w, f, first, to, err_msgs,
+ named_merge_points, 0))
ok = false;
}
}
else
{
/* FACE_REF ought to be a face name. */
- ok = merge_named_face (w, f, face_ref, to, named_merge_points);
+ ok = merge_named_face (w, f, face_ref, to, named_merge_points,
+ attr_filter);
if (!ok && err_msgs)
add_to_log ("Invalid face reference: %s", face_ref);
}
suitable face is found, realize a new one. */
int
-face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
+face_for_font (struct frame *f, Lisp_Object font_object,
+ struct face *base_face)
{
struct face_cache *cache = FRAME_FACE_CACHE (f);
unsigned hash;
Lisp_Object lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified);
merge_face_ref (NULL, XFRAME (selected_frame),
plist, XVECTOR (lface)->contents,
- true, 0);
+ true, NULL, 0);
return lface;
}
for (i = 0; i < LFACE_VECTOR_SIZE; i++)
attrs[i] = Qunspecified;
- merge_face_ref (NULL, f, attributes, attrs, true, 0);
+ merge_face_ref (NULL, f, attributes, attrs, true, NULL, 0);
def_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
if (def_face == NULL)
Lisp_Object attrs[LFACE_VECTOR_SIZE];
struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
memcpy (attrs, default_face->lface, sizeof attrs);
- merge_face_ref (NULL, f, prop, attrs, true, 0);
+ merge_face_ref (NULL, f, prop, attrs, true, NULL, 0);
face_id = lookup_face (f, attrs);
}
which a different face is needed, as far as text properties and
overlays are concerned. W is a window displaying current_buffer.
+ attr_filter is passed merge_face_ref.
+
REGION_BEG, REGION_END delimit the region, so it can be
highlighted.
int
face_at_buffer_position (struct window *w, ptrdiff_t pos,
ptrdiff_t *endptr, ptrdiff_t limit,
- bool mouse, int base_face_id)
+ bool mouse, int base_face_id,
+ enum lface_attribute_index attr_filter)
{
struct frame *f = XFRAME (w->frame);
Lisp_Object attrs[LFACE_VECTOR_SIZE];
}
/* Optimize common cases where we can use the default face. */
- if (noverlays == 0
- && NILP (prop))
+ if (noverlays == 0 && NILP (prop))
{
SAFE_FREE ();
return default_face->id;
/* Merge in attributes specified via text properties. */
if (!NILP (prop))
- merge_face_ref (w, f, prop, attrs, true, 0);
+ merge_face_ref (w, f, prop, attrs, true, NULL, 0);
/* Now merge the overlay data. */
noverlays = sort_overlays (overlay_vec, noverlays, w);
so discard the mouse-face text property, if any, and
use the overlay property instead. */
memcpy (attrs, default_face->lface, sizeof attrs);
- merge_face_ref (w, f, prop, attrs, true, 0);
+ merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
}
oend = OVERLAY_END (overlay_vec[i]);
ptrdiff_t oendpos;
prop = Foverlay_get (overlay_vec[i], propname);
+
if (!NILP (prop))
- merge_face_ref (w, f, prop, attrs, true, 0);
+ merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter);
oend = OVERLAY_END (overlay_vec[i]);
oendpos = OVERLAY_POSITION (oend);
/* Merge in attributes specified via text properties. */
if (!NILP (prop))
- merge_face_ref (w, f, prop, attrs, true, 0);
+ merge_face_ref (w, f, prop, attrs, true, NULL, 0);
*endptr = endpos;
face_at_string_position (struct window *w, Lisp_Object string,
ptrdiff_t pos, ptrdiff_t bufpos,
ptrdiff_t *endptr, enum face_id base_face_id,
- bool mouse_p)
+ bool mouse_p)
{
Lisp_Object prop, position, end, limit;
struct frame *f = XFRAME (WINDOW_FRAME (w));
/* Merge in attributes specified via text properties. */
if (!NILP (prop))
- merge_face_ref (w, f, prop, attrs, true, 0);
+ merge_face_ref (w, f, prop, attrs, true, NULL, 0);
/* Look up a realized face with the given face attributes,
or realize a new one for ASCII characters. */
if (!NILP (face_name))
{
- if (!merge_named_face (w, f, face_name, attrs, 0))
+ if (!merge_named_face (w, f, face_name, attrs, NULL, 0))
return base_face_id;
}
else