Lisp_Object Qslice;
Lisp_Object Qcenter;
Lisp_Object Qmargin, Qpointer;
-Lisp_Object Qline_height, Qtotal;
+Lisp_Object Qline_height;
extern Lisp_Object Qheight;
extern Lisp_Object QCwidth, QCheight, QCascent;
extern Lisp_Object Qscroll_bar;
Lisp_Object Qtrailing_whitespace;
+/* Name and number of the face used to highlight escape glyphs. */
+
+Lisp_Object Qescape_glyph;
+int escape_glyph_face;
+
/* The symbol `image' which is the car of the lists used to represent
images in Lisp. */
\f
/* Function prototypes. */
-static void setup_for_ellipsis P_ ((struct it *));
+static void setup_for_ellipsis P_ ((struct it *, int));
static void mark_window_display_accurate_1 P_ ((struct window *, int));
-static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
+static int single_display_spec_string_p P_ ((Lisp_Object, Lisp_Object));
static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
static int cursor_row_p P_ ((struct window *, struct glyph_row *));
static int redisplay_mode_lines P_ ((Lisp_Object, int));
static void x_consider_frame_title P_ ((Lisp_Object));
static void handle_stop P_ ((struct it *));
static int tool_bar_lines_needed P_ ((struct frame *));
-static int single_display_prop_intangible_p P_ ((Lisp_Object));
+static int single_display_spec_intangible_p P_ ((Lisp_Object));
static void ensure_echo_area_buffers P_ ((void));
static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
Lisp_Object));
static int face_before_or_after_it_pos P_ ((struct it *, int));
static int next_overlay_change P_ ((int));
-static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
+static int handle_single_display_spec P_ ((struct it *, Lisp_Object,
Lisp_Object, struct text_pos *,
int));
static int underlying_face_id P_ ((struct it *));
/* If drawing a tool-bar window, draw it over the internal border
at the top of the window. */
- if (s->w == XWINDOW (s->f->tool_bar_window))
+ if (WINDOWP (s->f->tool_bar_window)
+ && s->w == XWINDOW (s->f->tool_bar_window))
r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
}
it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
}
else if (display_ellipsis_p)
- setup_for_ellipsis (it);
+ setup_for_ellipsis (it, 0);
}
}
}
-/* Make iterator IT return `...' next. */
+/* Make iterator IT return `...' next.
+ Replaces LEN characters from buffer. */
static void
-setup_for_ellipsis (it)
+setup_for_ellipsis (it, len)
struct it *it;
+ int len;
{
- if (it->dp
- && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+ /* Use the display table definition for `...'. Invalid glyphs
+ will be handled by the method returning elements from dpvec. */
+ if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
{
struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
it->dpvec = v->contents;
it->dpend = default_invis_vector + 3;
}
- /* The ellipsis display does not replace the display of the
- character at the new position. Indicate this by setting
- IT->dpvec_char_len to zero. */
- it->dpvec_char_len = 0;
-
+ it->dpvec_char_len = len;
it->current.dpvec_index = 0;
+
+ /* Remember the current face id in case glyphs specify faces.
+ IT's face is restored in set_iterator_to_next. */
+ it->saved_face_id = it->face_id;
it->method = next_element_from_display_vector;
+ it->ellipsis_p = 1;
}
***********************************************************************/
/* Set up iterator IT from `display' property at its current position.
- Called from handle_stop. */
+ Called from handle_stop.
+ We return HANDLED_RETURN if some part of the display property
+ overrides the display of the buffer text itself.
+ Otherwise we return HANDLED_NORMALLY. */
static enum prop_handled
handle_display_prop (it)
{
Lisp_Object prop, object;
struct text_pos *position;
+ /* Nonzero if some property replaces the display of the text itself. */
int display_replaced_p = 0;
if (STRINGP (it->string))
{
for (; CONSP (prop); prop = XCDR (prop))
{
- if (handle_single_display_prop (it, XCAR (prop), object,
+ if (handle_single_display_spec (it, XCAR (prop), object,
position, display_replaced_p))
display_replaced_p = 1;
}
{
int i;
for (i = 0; i < ASIZE (prop); ++i)
- if (handle_single_display_prop (it, AREF (prop, i), object,
+ if (handle_single_display_spec (it, AREF (prop, i), object,
position, display_replaced_p))
display_replaced_p = 1;
}
else
{
- if (handle_single_display_prop (it, prop, object, position, 0))
+ if (handle_single_display_spec (it, prop, object, position, 0))
display_replaced_p = 1;
}
}
-/* Set up IT from a single `display' sub-property value PROP. OBJECT
+/* Set up IT from a single `display' specification PROP. OBJECT
is the object in which the `display' property was found. *POSITION
is the position at which it was found. DISPLAY_REPLACED_P non-zero
- means that we previously saw a display sub-property which already
+ means that we previously saw a display specification which already
replaced text display with something else, for example an image;
- ignore such properties after the first one has been processed.
+ we ignore such properties after the first one has been processed.
- If PROP is a `space' or `image' sub-property, set *POSITION to the
- end position of the `display' property.
+ If PROP is a `space' or `image' specification, and in some other
+ cases too, set *POSITION to the position where the `display'
+ property ends.
Value is non-zero if something was found which replaces the display
of buffer or string text. */
static int
-handle_single_display_prop (it, prop, object, position,
+handle_single_display_spec (it, spec, object, position,
display_replaced_before_p)
struct it *it;
- Lisp_Object prop;
+ Lisp_Object spec;
Lisp_Object object;
struct text_pos *position;
int display_replaced_before_p;
{
- Lisp_Object value;
- int replaces_text_display_p = 0;
Lisp_Object form;
+ Lisp_Object location, value;
+ struct text_pos start_pos;
+ int valid_p;
- /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
- evaluated. If the result is nil, VALUE is ignored. */
+ /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
+ If the result is non-nil, use VALUE instead of SPEC. */
form = Qt;
- if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
+ if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
{
- prop = XCDR (prop);
- if (!CONSP (prop))
+ spec = XCDR (spec);
+ if (!CONSP (spec))
return 0;
- form = XCAR (prop);
- prop = XCDR (prop);
+ form = XCAR (spec);
+ spec = XCDR (spec);
}
if (!NILP (form) && !EQ (form, Qt))
if (NILP (form))
return 0;
- if (CONSP (prop)
- && EQ (XCAR (prop), Qheight)
- && CONSP (XCDR (prop)))
+ /* Handle `(height HEIGHT)' specifications. */
+ if (CONSP (spec)
+ && EQ (XCAR (spec), Qheight)
+ && CONSP (XCDR (spec)))
{
if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
return 0;
- /* `(height HEIGHT)'. */
- it->font_height = XCAR (XCDR (prop));
+ it->font_height = XCAR (XCDR (spec));
if (!NILP (it->font_height))
{
struct face *face = FACE_FROM_ID (it->f, it->face_id);
{
/* Evaluate IT->font_height with `height' bound to the
current specified height to get the new height. */
- Lisp_Object value;
int count = SPECPDL_INDEX ();
specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
if (new_height > 0)
it->face_id = face_with_height (it->f, it->face_id, new_height);
}
+
+ return 0;
}
- else if (CONSP (prop)
- && EQ (XCAR (prop), Qspace_width)
- && CONSP (XCDR (prop)))
+
+ /* Handle `(space_width WIDTH)'. */
+ if (CONSP (spec)
+ && EQ (XCAR (spec), Qspace_width)
+ && CONSP (XCDR (spec)))
{
- /* `(space_width WIDTH)'. */
if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
return 0;
- value = XCAR (XCDR (prop));
+ value = XCAR (XCDR (spec));
if (NUMBERP (value) && XFLOATINT (value) > 0)
it->space_width = value;
+
+ return 0;
}
- else if (CONSP (prop)
- && EQ (XCAR (prop), Qslice))
+
+ /* Handle `(slice X Y WIDTH HEIGHT)'. */
+ if (CONSP (spec)
+ && EQ (XCAR (spec), Qslice))
{
- /* `(slice X Y WIDTH HEIGHT)'. */
Lisp_Object tem;
if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
return 0;
- if (tem = XCDR (prop), CONSP (tem))
+ if (tem = XCDR (spec), CONSP (tem))
{
it->slice.x = XCAR (tem);
if (tem = XCDR (tem), CONSP (tem))
}
}
}
+
+ return 0;
}
- else if (CONSP (prop)
- && EQ (XCAR (prop), Qraise)
- && CONSP (XCDR (prop)))
+
+ /* Handle `(raise FACTOR)'. */
+ if (CONSP (spec)
+ && EQ (XCAR (spec), Qraise)
+ && CONSP (XCDR (spec)))
{
- /* `(raise FACTOR)'. */
if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
return 0;
#ifdef HAVE_WINDOW_SYSTEM
- value = XCAR (XCDR (prop));
+ value = XCAR (XCDR (spec));
if (NUMBERP (value))
{
struct face *face = FACE_FROM_ID (it->f, it->face_id);
* (FONT_HEIGHT (face->font)));
}
#endif /* HAVE_WINDOW_SYSTEM */
+
+ return 0;
}
- else if (!it->string_from_display_prop_p)
- {
- /* `((margin left-margin) VALUE)' or `((margin right-margin)
- VALUE) or `((margin nil) VALUE)' or VALUE. */
- Lisp_Object location, value;
- struct text_pos start_pos;
- int valid_p;
- /* Characters having this form of property are not displayed, so
- we have to find the end of the property. */
- start_pos = *position;
- *position = display_prop_end (it, object, start_pos);
- value = Qnil;
+ /* Don't handle the other kinds of display specifications
+ inside a string that we got from a `display' property. */
+ if (it->string_from_display_prop_p)
+ return 0;
- /* Let's stop at the new position and assume that all
- text properties change there. */
- it->stop_charpos = position->charpos;
+ /* Characters having this form of property are not displayed, so
+ we have to find the end of the property. */
+ start_pos = *position;
+ *position = display_prop_end (it, object, start_pos);
+ value = Qnil;
- if (CONSP (prop)
- && (EQ (XCAR (prop), Qleft_fringe)
- || EQ (XCAR (prop), Qright_fringe))
- && CONSP (XCDR (prop)))
- {
- unsigned face_id = DEFAULT_FACE_ID;
- int fringe_bitmap;
+ /* Stop the scan at that end position--we assume that all
+ text properties change there. */
+ it->stop_charpos = position->charpos;
- /* Save current settings of IT so that we can restore them
- when we are finished with the glyph property value. */
+ /* Handle `(left-fringe BITMAP [FACE])'
+ and `(right-fringe BITMAP [FACE])'. */
+ if (CONSP (spec)
+ && (EQ (XCAR (spec), Qleft_fringe)
+ || EQ (XCAR (spec), Qright_fringe))
+ && CONSP (XCDR (spec)))
+ {
+ int face_id = DEFAULT_FACE_ID;
+ int fringe_bitmap;
- /* `(left-fringe BITMAP FACE)'. */
- if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
- return 0;
+ if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+ /* If we return here, POSITION has been advanced
+ across the text with this property. */
+ return 0;
#ifdef HAVE_WINDOW_SYSTEM
- value = XCAR (XCDR (prop));
- if (!SYMBOLP (value)
- || !(fringe_bitmap = lookup_fringe_bitmap (value)))
- return 0;
+ value = XCAR (XCDR (spec));
+ if (!SYMBOLP (value)
+ || !(fringe_bitmap = lookup_fringe_bitmap (value)))
+ /* If we return here, POSITION has been advanced
+ across the text with this property. */
+ return 0;
- if (CONSP (XCDR (XCDR (prop))))
- {
- Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
+ if (CONSP (XCDR (XCDR (spec))))
+ {
+ Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
+ int face_id2 = lookup_named_face (it->f, face_name, 'A', 0);
+ if (face_id2 >= 0)
+ face_id = face_id2;
+ }
- face_id = lookup_named_face (it->f, face_name, 'A');
- if (face_id < 0)
- return 0;
- }
+ /* Save current settings of IT so that we can restore them
+ when we are finished with the glyph property value. */
- push_it (it);
+ push_it (it);
- it->area = TEXT_AREA;
- it->what = IT_IMAGE;
- it->image_id = -1; /* no image */
- it->position = start_pos;
- it->object = NILP (object) ? it->w->buffer : object;
- it->method = next_element_from_image;
- it->face_id = face_id;
+ it->area = TEXT_AREA;
+ it->what = IT_IMAGE;
+ it->image_id = -1; /* no image */
+ it->position = start_pos;
+ it->object = NILP (object) ? it->w->buffer : object;
+ it->method = next_element_from_image;
+ it->face_id = face_id;
- /* Say that we haven't consumed the characters with
- `display' property yet. The call to pop_it in
- set_iterator_to_next will clean this up. */
- *position = start_pos;
+ /* Say that we haven't consumed the characters with
+ `display' property yet. The call to pop_it in
+ set_iterator_to_next will clean this up. */
+ *position = start_pos;
- if (EQ (XCAR (prop), Qleft_fringe))
- {
- it->left_user_fringe_bitmap = fringe_bitmap;
- it->left_user_fringe_face_id = face_id;
- }
- else
- {
- it->right_user_fringe_bitmap = fringe_bitmap;
- it->right_user_fringe_face_id = face_id;
- }
-#endif /* HAVE_WINDOW_SYSTEM */
- return 1;
+ if (EQ (XCAR (spec), Qleft_fringe))
+ {
+ it->left_user_fringe_bitmap = fringe_bitmap;
+ it->left_user_fringe_face_id = face_id;
}
-
- location = Qunbound;
- if (CONSP (prop) && CONSP (XCAR (prop)))
+ else
{
- Lisp_Object tem;
+ it->right_user_fringe_bitmap = fringe_bitmap;
+ it->right_user_fringe_face_id = face_id;
+ }
+#endif /* HAVE_WINDOW_SYSTEM */
+ return 1;
+ }
- value = XCDR (prop);
- if (CONSP (value))
- value = XCAR (value);
+ /* Prepare to handle `((margin left-margin) ...)',
+ `((margin right-margin) ...)' and `((margin nil) ...)'
+ prefixes for display specifications. */
+ location = Qunbound;
+ if (CONSP (spec) && CONSP (XCAR (spec)))
+ {
+ Lisp_Object tem;
- tem = XCAR (prop);
- if (EQ (XCAR (tem), Qmargin)
- && (tem = XCDR (tem),
- tem = CONSP (tem) ? XCAR (tem) : Qnil,
- (NILP (tem)
- || EQ (tem, Qleft_margin)
- || EQ (tem, Qright_margin))))
- location = tem;
- }
+ value = XCDR (spec);
+ if (CONSP (value))
+ value = XCAR (value);
- if (EQ (location, Qunbound))
- {
- location = Qnil;
- value = prop;
- }
+ tem = XCAR (spec);
+ if (EQ (XCAR (tem), Qmargin)
+ && (tem = XCDR (tem),
+ tem = CONSP (tem) ? XCAR (tem) : Qnil,
+ (NILP (tem)
+ || EQ (tem, Qleft_margin)
+ || EQ (tem, Qright_margin))))
+ location = tem;
+ }
+
+ if (EQ (location, Qunbound))
+ {
+ location = Qnil;
+ value = spec;
+ }
+
+ /* After this point, VALUE is the property after any
+ margin prefix has been stripped. It must be a string,
+ an image specification, or `(space ...)'.
+
+ LOCATION specifies where to display: `left-margin',
+ `right-margin' or nil. */
- valid_p = (STRINGP (value)
+ valid_p = (STRINGP (value)
#ifdef HAVE_WINDOW_SYSTEM
- || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
+ || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
#endif /* not HAVE_WINDOW_SYSTEM */
- || (CONSP (value) && EQ (XCAR (value), Qspace)));
+ || (CONSP (value) && EQ (XCAR (value), Qspace)));
- if ((EQ (location, Qleft_margin)
- || EQ (location, Qright_margin)
- || NILP (location))
- && valid_p
- && !display_replaced_before_p)
- {
- replaces_text_display_p = 1;
-
- /* Save current settings of IT so that we can restore them
- when we are finished with the glyph property value. */
- push_it (it);
+ if (valid_p && !display_replaced_before_p)
+ {
+ /* Save current settings of IT so that we can restore them
+ when we are finished with the glyph property value. */
+ push_it (it);
- if (NILP (location))
- it->area = TEXT_AREA;
- else if (EQ (location, Qleft_margin))
- it->area = LEFT_MARGIN_AREA;
- else
- it->area = RIGHT_MARGIN_AREA;
+ if (NILP (location))
+ it->area = TEXT_AREA;
+ else if (EQ (location, Qleft_margin))
+ it->area = LEFT_MARGIN_AREA;
+ else
+ it->area = RIGHT_MARGIN_AREA;
- if (STRINGP (value))
- {
- it->string = value;
- it->multibyte_p = STRING_MULTIBYTE (it->string);
- it->current.overlay_string_index = -1;
- IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
- it->end_charpos = it->string_nchars = SCHARS (it->string);
- it->method = next_element_from_string;
- it->stop_charpos = 0;
- it->string_from_display_prop_p = 1;
- /* Say that we haven't consumed the characters with
- `display' property yet. The call to pop_it in
- set_iterator_to_next will clean this up. */
- *position = start_pos;
- }
- else if (CONSP (value) && EQ (XCAR (value), Qspace))
- {
- it->method = next_element_from_stretch;
- it->object = value;
- it->current.pos = it->position = start_pos;
- }
-#ifdef HAVE_WINDOW_SYSTEM
- else
- {
- it->what = IT_IMAGE;
- it->image_id = lookup_image (it->f, value);
- it->position = start_pos;
- it->object = NILP (object) ? it->w->buffer : object;
- it->method = next_element_from_image;
-
- /* Say that we haven't consumed the characters with
- `display' property yet. The call to pop_it in
- set_iterator_to_next will clean this up. */
- *position = start_pos;
- }
-#endif /* HAVE_WINDOW_SYSTEM */
+ if (STRINGP (value))
+ {
+ it->string = value;
+ it->multibyte_p = STRING_MULTIBYTE (it->string);
+ it->current.overlay_string_index = -1;
+ IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+ it->end_charpos = it->string_nchars = SCHARS (it->string);
+ it->method = next_element_from_string;
+ it->stop_charpos = 0;
+ it->string_from_display_prop_p = 1;
+ /* Say that we haven't consumed the characters with
+ `display' property yet. The call to pop_it in
+ set_iterator_to_next will clean this up. */
+ *position = start_pos;
+ }
+ else if (CONSP (value) && EQ (XCAR (value), Qspace))
+ {
+ it->method = next_element_from_stretch;
+ it->object = value;
+ it->current.pos = it->position = start_pos;
}
+#ifdef HAVE_WINDOW_SYSTEM
else
- /* Invalid property or property not supported. Restore
- the position to what it was before. */
- *position = start_pos;
+ {
+ it->what = IT_IMAGE;
+ it->image_id = lookup_image (it->f, value);
+ it->position = start_pos;
+ it->object = NILP (object) ? it->w->buffer : object;
+ it->method = next_element_from_image;
+
+ /* Say that we haven't consumed the characters with
+ `display' property yet. The call to pop_it in
+ set_iterator_to_next will clean this up. */
+ *position = start_pos;
+ }
+#endif /* HAVE_WINDOW_SYSTEM */
+
+ return 1;
}
- return replaces_text_display_p;
+ /* Invalid property or property not supported. Restore
+ POSITION to what it was before. */
+ *position = start_pos;
+ return 0;
}
-/* Check if PROP is a display sub-property value whose text should be
+/* Check if SPEC is a display specification value whose text should be
treated as intangible. */
static int
-single_display_prop_intangible_p (prop)
+single_display_spec_intangible_p (prop)
Lisp_Object prop;
{
/* Skip over `when FORM'. */
/* A list of sub-properties. */
while (CONSP (prop))
{
- if (single_display_prop_intangible_p (XCAR (prop)))
+ if (single_display_spec_intangible_p (XCAR (prop)))
return 1;
prop = XCDR (prop);
}
/* A vector of sub-properties. */
int i;
for (i = 0; i < ASIZE (prop); ++i)
- if (single_display_prop_intangible_p (AREF (prop, i)))
+ if (single_display_spec_intangible_p (AREF (prop, i)))
return 1;
}
else
- return single_display_prop_intangible_p (prop);
+ return single_display_spec_intangible_p (prop);
return 0;
}
/* Return 1 if PROP is a display sub-property value containing STRING. */
static int
-single_display_prop_string_p (prop, string)
+single_display_spec_string_p (prop, string)
Lisp_Object prop, string;
{
if (EQ (string, prop))
/* A list of sub-properties. */
while (CONSP (prop))
{
- if (single_display_prop_string_p (XCAR (prop), string))
+ if (single_display_spec_string_p (XCAR (prop), string))
return 1;
prop = XCDR (prop);
}
/* A vector of sub-properties. */
int i;
for (i = 0; i < ASIZE (prop); ++i)
- if (single_display_prop_string_p (AREF (prop, i), string))
+ if (single_display_spec_string_p (AREF (prop, i), string))
return 1;
}
else
- return single_display_prop_string_p (prop, string);
+ return single_display_spec_string_p (prop, string);
return 0;
}
/* If we have to display `...' for invisible text, set
the iterator up for that. */
if (display_ellipsis_p)
- setup_for_ellipsis (it);
+ setup_for_ellipsis (it, 0);
}
else
{
visible_p = 0;
}
+#if 0
+ /* Commenting this out fixes the bug described in
+ http://www.math.ku.dk/~larsh/emacs/emacs-loops-on-large-images/test-case.txt. */
if (visible_p)
{
struct it it2 = *it;
if (handle_display_prop (&it2) == HANDLED_RETURN)
visible_p = 0;
}
+#endif
/* Back one more newline if the current one is invisible. */
if (!visible_p)
we hit the end of what we iterate over. Performance note: the
function pointer `method' used here turns out to be faster than
using a sequence of if-statements. */
- int success_p = (*it->method) (it);
+ int success_p;
+
+ get_next:
+ success_p = (*it->method) (it);
if (it->what == IT_CHARACTER)
{
it->dpvec = v->contents;
it->dpend = v->contents + v->size;
it->current.dpvec_index = 0;
+ it->saved_face_id = it->face_id;
it->method = next_element_from_display_vector;
- success_p = get_next_display_element (it);
+ it->ellipsis_p = 0;
}
else
{
set_iterator_to_next (it, 0);
- success_p = get_next_display_element (it);
}
+ goto get_next;
}
/* Translate control characters into `\003' or `^C' form.
|| (it->multibyte_p
? ((it->c >= 127
&& it->len == 1)
- || !CHAR_PRINTABLE_P (it->c))
+ || !CHAR_PRINTABLE_P (it->c)
+ || it->c == 0x8ad
+ || it->c == 0x8a0)
: (it->c >= 127
&& (!unibyte_display_via_language_environment
|| it->c == unibyte_char_to_multibyte (it->c)))))
IT->ctl_chars with glyphs for what we have to
display. Then, set IT->dpvec to these glyphs. */
GLYPH g;
+ int ctl_len;
+ int face_id = escape_glyph_face;
+
+ /* Find the face id if `escape-glyph' unless we recently did. */
+ if (face_id < 0)
+ {
+ Lisp_Object tem = Fget (Qescape_glyph, Qface);
+ if (INTEGERP (tem))
+ face_id = XINT (tem);
+ else
+ face_id = 0;
+ /* If there's overflow, use 0 instead. */
+ if (FAST_GLYPH_FACE (FAST_MAKE_GLYPH (0, face_id)) != face_id)
+ face_id = 0;
+ escape_glyph_face = face_id;
+ }
if (it->c < 128 && it->ctl_arrow_p)
{
&& GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
g = XINT (DISP_CTRL_GLYPH (it->dp));
else
- g = FAST_MAKE_GLYPH ('^', 0);
+ g = FAST_MAKE_GLYPH ('^', face_id);
XSETINT (it->ctl_chars[0], g);
- g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
+ g = FAST_MAKE_GLYPH (it->c ^ 0100, face_id);
XSETINT (it->ctl_chars[1], g);
+ ctl_len = 2;
+ }
+ else if (it->c == 0x8a0 || it->c == 0x8ad)
+ {
+ /* Set IT->ctl_chars[0] to the glyph for `\\'. */
+ if (it->dp
+ && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
+ && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (it->dp))))
+ g = XINT (DISP_ESCAPE_GLYPH (it->dp));
+ else
+ g = FAST_MAKE_GLYPH ('\\', face_id);
+ XSETINT (it->ctl_chars[0], g);
- /* Set up IT->dpvec and return first character from it. */
- it->dpvec_char_len = it->len;
- it->dpvec = it->ctl_chars;
- it->dpend = it->dpvec + 2;
- it->current.dpvec_index = 0;
- it->method = next_element_from_display_vector;
- get_next_display_element (it);
+ g = FAST_MAKE_GLYPH (it->c == 0x8ad ? '-' : ' ', face_id);
+ XSETINT (it->ctl_chars[1], g);
+ ctl_len = 2;
}
else
{
&& GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
else
- escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
+ escape_glyph = FAST_MAKE_GLYPH ('\\', face_id);
if (SINGLE_BYTE_CHAR_P (it->c))
str[0] = it->c, len = 1;
XSETINT (it->ctl_chars[i * 4], escape_glyph);
/* Insert three more glyphs into IT->ctl_chars for
the octal display of the character. */
- g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
+ g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0',
+ face_id);
XSETINT (it->ctl_chars[i * 4 + 1], g);
- g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
+ g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0',
+ face_id);
XSETINT (it->ctl_chars[i * 4 + 2], g);
- g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
+ g = FAST_MAKE_GLYPH ((str[i] & 7) + '0',
+ face_id);
XSETINT (it->ctl_chars[i * 4 + 3], g);
}
-
- /* Set up IT->dpvec and return the first character
- from it. */
- it->dpvec_char_len = it->len;
- it->dpvec = it->ctl_chars;
- it->dpend = it->dpvec + len * 4;
- it->current.dpvec_index = 0;
- it->method = next_element_from_display_vector;
- get_next_display_element (it);
+ ctl_len = len * 4;
}
+
+ /* Set up IT->dpvec and return first character from it. */
+ it->dpvec_char_len = it->len;
+ it->dpvec = it->ctl_chars;
+ it->dpend = it->dpvec + ctl_len;
+ it->current.dpvec_index = 0;
+ it->saved_face_id = it->face_id;
+ it->method = next_element_from_display_vector;
+ it->ellipsis_p = 0;
+ goto get_next;
}
}
it->dpvec = NULL;
it->current.dpvec_index = -1;
+ /* Recheck faces after display vector */
+ it->stop_charpos = 0;
+
/* Skip over characters which were displayed via IT->dpvec. */
if (it->dpvec_char_len < 0)
reseat_at_next_visible_line_start (it, 1);
&& IT_STRING_CHARPOS (*it) >= 0));
}
-
/* Load IT's display element fields with information about the next
display element which comes from a display table entry or from the
result of translating a control character to one of the forms `^C'
- or `\003'. IT->dpvec holds the glyphs to return as characters. */
+ or `\003'.
+
+ IT->dpvec holds the glyphs to return as characters.
+ IT->saved_face_id holds the face id before the display vector--
+ it is restored into IT->face_idin set_iterator_to_next. */
static int
next_element_from_display_vector (it)
/* Precondition. */
xassert (it->dpvec && it->current.dpvec_index >= 0);
- /* Remember the current face id in case glyphs specify faces.
- IT's face is restored in set_iterator_to_next. */
- it->saved_face_id = it->face_id;
-
if (INTEGERP (*it->dpvec)
&& GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
{
struct it *it;
{
if (it->selective_display_ellipsis_p)
- {
- if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
- {
- /* Use the display table definition for `...'. Invalid glyphs
- will be handled by the method returning elements from dpvec. */
- struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
- it->dpvec_char_len = it->len;
- it->dpvec = v->contents;
- it->dpend = v->contents + v->size;
- it->current.dpvec_index = 0;
- it->method = next_element_from_display_vector;
- }
- else
- {
- /* Use default `...' which is stored in default_invis_vector. */
- it->dpvec_char_len = it->len;
- it->dpvec = default_invis_vector;
- it->dpend = default_invis_vector + 3;
- it->current.dpvec_index = 0;
- it->method = next_element_from_display_vector;
- }
- }
+ setup_for_ellipsis (it, it->len);
else
{
/* The face at the current position may be different from the
saved_glyph_row = it->glyph_row;
it->glyph_row = NULL;
-#define BUFFER_POS_REACHED_P() \
- ((op & MOVE_TO_POS) != 0 \
- && BUFFERP (it->object) \
- && IT_CHARPOS (*it) >= to_charpos)
+#define BUFFER_POS_REACHED_P() \
+ ((op & MOVE_TO_POS) != 0 \
+ && BUFFERP (it->object) \
+ && IT_CHARPOS (*it) >= to_charpos \
+ && it->method == next_element_from_buffer)
while (1)
{
}
return 0;
}
-
+\f
/* Display an echo area message M with a specified length of NBYTES
bytes. The string may include null characters. If M is 0, clear
struct gcpro gcpro1;
GCPRO1 (m);
+ clear_message (1,1);
/* First flush out any partial line written with print. */
message_log_maybe_newline ();
glyph = cursor;
x = cursor_x;
}
+ else if (row->ends_in_ellipsis_p && glyph == end)
+ {
+ /* Scan back over the ellipsis glyphs, decrementing positions. */
+ while (glyph > row->glyphs[TEXT_AREA]
+ && (glyph - 1)->charpos == last_pos)
+ glyph--, x -= glyph->pixel_width;
+ /* That loop always goes one position too far,
+ including the glyph before the ellipsis.
+ So scan forward over that one. */
+ x += glyph->pixel_width;
+ glyph++;
+ }
else if (string_start
&& (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
{
*w->desired_matrix->method = 0;
#endif
+ /* Force this to be looked up again for each redisp of each window. */
+ escape_glyph_face = -1;
+
specbind (Qinhibit_point_motion_hooks, Qt);
reconsider_clip_changes (w, buffer);
&& glyph->u.ch == ' '))
&& trailing_whitespace_p (glyph->charpos))
{
- int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
+ int face_id = lookup_named_face (f, Qtrailing_whitespace, 0, 0);
+ if (face_id < 0)
+ return;
while (glyph >= start
&& BUFFERP (glyph->object)
/* If the row ends with a newline from a string, we don't want
the cursor there (if the row is continued it doesn't end in a
newline). */
- if (CHARPOS (row->end.string_pos) >= 0
- || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
+ if (CHARPOS (row->end.string_pos) >= 0)
cursor_row_p = row->continued_p;
-
+ else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
+ {
+ /* If the row ends in middle of a real character,
+ and the line is continued, we want the cursor here.
+ That's because MATRIX_ROW_END_CHARPOS would equal
+ PT if PT is before the character. */
+ if (!row->ends_in_ellipsis_p)
+ cursor_row_p = row->continued_p;
+ else
+ /* If the row ends in an ellipsis, then
+ MATRIX_ROW_END_CHARPOS will equal point after the invisible text.
+ We want that position to be displayed after the ellipsis. */
+ cursor_row_p = 0;
+ }
/* If the row ends at ZV, display the cursor at the end of that
row instead of at the start of the row below. */
else if (row->ends_at_zv_p)
hscrolled. This may stop at an x-position < IT->first_visible_x
if the first glyph is partially visible or if we hit a line end. */
if (it->current_x < it->first_visible_x)
- move_it_in_display_line_to (it, ZV, it->first_visible_x,
- MOVE_TO_POS | MOVE_TO_X);
+ {
+ move_it_in_display_line_to (it, ZV, it->first_visible_x,
+ MOVE_TO_POS | MOVE_TO_X);
+ }
/* Get the initial row height. This is either the height of the
text hscrolled, if there is any, or zero. */
{
if (!get_next_display_element (it))
{
-#ifdef HAVE_WINDOW_SYSTEM
it->continuation_lines_width = 0;
row->ends_at_zv_p = 1;
row->exact_window_width_line_p = 1;
break;
-#endif /* HAVE_WINDOW_SYSTEM */
}
if (ITERATOR_AT_END_OF_LINE_P (it))
{
/* Remember the position at which this line ends. */
row->end = it->current;
+ /* Record whether this row ends inside an ellipsis. */
+ row->ends_in_ellipsis_p
+ = (it->method == next_element_from_display_vector
+ && it->ellipsis_p);
+
/* Save fringe bitmaps in this row. */
row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
row->left_user_fringe_face_id = it->left_user_fringe_face_id;
DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
- 0, 4, 0,
+ 1, 4, 0,
doc: /* Return the mode-line of selected window as a string.
-First optional arg FORMAT specifies a different format string (see
-`mode-line-format' for details) to use. If FORMAT is t, return
-the buffer's header-line. Second optional arg WINDOW specifies a
-different window to use as the context for the formatting.
-If third optional arg NO-PROPS is non-nil, string is not propertized.
-Fourth optional arg BUFFER specifies which buffer to use. */)
+First arg FORMAT specifies the mode line format (see `mode-line-format' for
+details) to use. Second optional arg WINDOW specifies a different window to
+use as the context for the formatting. If third optional arg NO-PROPS is
+non-nil, string is not propertized. Fourth optional arg BUFFER specifies
+which buffer to use. */)
(format, window, no_props, buffer)
Lisp_Object format, window, no_props, buffer;
{
set_buffer_internal_1 (XBUFFER (buffer));
}
- if (NILP (format) || EQ (format, Qt))
- {
- face_id = (NILP (format)
- ? CURRENT_MODE_LINE_FACE_ID (w)
- : HEADER_LINE_FACE_ID);
- format = (NILP (format)
- ? current_buffer->mode_line_format
- : current_buffer->header_line_format);
- }
-
init_iterator (&it, w, -1, -1, NULL, face_id);
if (NILP (no_props))
s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
/* Display the internal border below the tool-bar window. */
- if (s->w == XWINDOW (s->f->tool_bar_window))
+ if (WINDOWP (s->f->tool_bar_window)
+ && s->w == XWINDOW (s->f->tool_bar_window))
s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
s->ybase = s->y + row->ascent;
return x_reached;
}
+/* Expand row matrix if too narrow. Don't expand if area
+ is not present. */
+
+#define IT_EXPAND_MATRIX_WIDTH(it, area) \
+ { \
+ if (!fonts_changed_p \
+ && (it->glyph_row->glyphs[area] \
+ < it->glyph_row->glyphs[area + 1])) \
+ { \
+ it->w->ncols_scale_factor++; \
+ fonts_changed_p = 1; \
+ } \
+ }
/* Store one glyph for IT->char_to_display in IT->glyph_row.
Called from x_produce_glyphs when IT->glyph_row is non-null. */
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
- else if (!fonts_changed_p)
- {
- it->w->ncols_scale_factor++;
- fonts_changed_p = 1;
- }
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
- else if (!fonts_changed_p)
- {
- it->w->ncols_scale_factor++;
- fonts_changed_p = 1;
- }
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
- else if (!fonts_changed_p)
- {
- it->w->ncols_scale_factor++;
- fonts_changed_p = 1;
- }
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
}
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
- else if (!fonts_changed_p)
- {
- it->w->ncols_scale_factor++;
- fonts_changed_p = 1;
- }
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
take_vertical_position_into_account (it);
}
-/* Calculate line-height and line-spacing properties.
- An integer value specifies explicit pixel value.
- A float value specifies relative value to current face height.
- A cons (float . face-name) specifies relative value to
- height of specified face font.
-
- Returns height in pixels, or nil. */
+/* Get line-height and line-spacing property at point.
+ If line-height has format (HEIGHT TOTAL), return TOTAL
+ in TOTAL_HEIGHT. */
static Lisp_Object
-calc_line_height_property (it, prop, font, boff, total)
+get_line_height_property (it, prop)
struct it *it;
Lisp_Object prop;
- XFontStruct *font;
- int boff, *total;
{
Lisp_Object position, val;
- Lisp_Object face_name = Qnil;
- int ascent, descent, height, override;
if (STRINGP (it->object))
position = make_number (IT_STRING_CHARPOS (*it));
else
return Qnil;
- val = Fget_char_property (position, prop, it->object);
+ return Fget_char_property (position, prop, it->object);
+}
- if (NILP (val))
- return val;
+/* Calculate line-height and line-spacing properties.
+ An integer value specifies explicit pixel value.
+ A float value specifies relative value to current face height.
+ A cons (float . face-name) specifies relative value to
+ height of specified face font.
+
+ Returns height in pixels, or nil. */
- if (total && CONSP (val) && EQ (XCAR (val), Qtotal))
- {
- *total = 1;
- val = XCDR (val);
- }
- if (INTEGERP (val))
+static Lisp_Object
+calc_line_height_property (it, val, font, boff, override)
+ struct it *it;
+ Lisp_Object val;
+ XFontStruct *font;
+ int boff, override;
+{
+ Lisp_Object face_name = Qnil;
+ int ascent, descent, height;
+
+ if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
return val;
if (CONSP (val))
{
- face_name = XCDR (val);
- val = XCAR (val);
- }
- else if (SYMBOLP (val))
- {
- face_name = val;
- val = Qnil;
+ face_name = XCAR (val);
+ val = XCDR (val);
+ if (!NUMBERP (val))
+ val = make_number (1);
+ if (NILP (face_name))
+ {
+ height = it->ascent + it->descent;
+ goto scale;
+ }
}
- override = EQ (prop, Qline_height);
-
if (NILP (face_name))
{
font = FRAME_FONT (it->f);
struct face *face;
struct font_info *font_info;
- face_id = lookup_named_face (it->f, face_name, ' ');
+ face_id = lookup_named_face (it->f, face_name, ' ', 0);
if (face_id < 0)
return make_number (-1);
}
height = ascent + descent;
+
+ scale:
if (FLOATP (val))
height = (int)(XFLOAT_DATA (val) * height);
else if (INTEGERP (val))
increase that height */
Lisp_Object height;
+ Lisp_Object total_height = Qnil;
it->override_ascent = -1;
it->pixel_width = 0;
it->nglyphs = 0;
- height = calc_line_height_property(it, Qline_height, font, boff, 0);
+ height = get_line_height_property(it, Qline_height);
+ /* Split (line-height total-height) list */
+ if (CONSP (height)
+ && CONSP (XCDR (height))
+ && NILP (XCDR (XCDR (height))))
+ {
+ total_height = XCAR (XCDR (height));
+ height = XCAR (height);
+ }
+ height = calc_line_height_property(it, height, font, boff, 1);
if (it->override_ascent >= 0)
{
it->descent = FONT_DESCENT (font) - boff;
}
- if (EQ (height, make_number(0)))
+ if (EQ (height, Qt))
{
if (it->descent > it->max_descent)
{
&& XINT (height) > it->ascent + it->descent)
it->ascent = XINT (height) - it->descent;
- spacing = calc_line_height_property(it, Qline_spacing, font, boff, &total);
+ if (!NILP (total_height))
+ spacing = calc_line_height_property(it, total_height, font, boff, 0);
+ else
+ {
+ spacing = get_line_height_property(it, Qline_spacing);
+ spacing = calc_line_height_property(it, spacing, font, boff, 0);
+ }
if (INTEGERP (spacing))
{
extra_line_spacing = XINT (spacing);
- if (total)
+ if (!NILP (total_height))
extra_line_spacing -= (it->phys_ascent + it->phys_descent);
}
}
}
else if (it->char_to_display == '\t')
{
- int tab_width = it->tab_width * FRAME_COLUMN_WIDTH (it->f);
+ int tab_width = it->tab_width * FRAME_SPACE_WIDTH (it->f);
int x = it->current_x + it->continuation_lines_width;
int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
/* If the distance from the current position to the next tab
- stop is less than a canonical character width, use the
+ stop is less than a space character width, use the
tab stop after that. */
- if (next_tab_x - x < FRAME_COLUMN_WIDTH (it->f))
+ if (next_tab_x - x < FRAME_SPACE_WIDTH (it->f))
next_tab_x += tab_width;
it->pixel_width = next_tab_x - x;
if (!cursor_row->enabled_p)
goto mark_cursor_off;
+ /* If line spacing is > 0, old cursor may only be partially visible in
+ window after split-window. So adjust visible height. */
+ cursor_row->visible_height = min (cursor_row->visible_height,
+ window_text_bottom_y (w) - cursor_row->y);
+
/* If row is completely invisible, don't attempt to delete a cursor which
isn't there. This can happen if cursor is at top of a window, and
we switch to a buffer with a header line in that window. */
{
int x, y;
int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+ int width;
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph == NULL)
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
+ width = min (cursor_glyph->pixel_width,
+ window_box_width (w, TEXT_AREA) - w->phys_cursor.x);
- rif->clear_frame_area (f, x, y,
- cursor_glyph->pixel_width, cursor_row->visible_height);
+ rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
}
/* Erase the cursor by redrawing the character underneath it. */
/* If we're on a string with `help-echo' text property, arrange
for the help to be displayed. This is done by setting the
global variable help_echo_string to the help string. */
- help = Fget_text_property (pos, Qhelp_echo, string);
- if (!NILP (help))
+ if (NILP (help))
{
- help_echo_string = help;
- XSETWINDOW (help_echo_window, w);
- help_echo_object = string;
- help_echo_pos = charpos;
+ help = Fget_text_property (pos, Qhelp_echo, string);
+ if (!NILP (help))
+ {
+ help_echo_string = help;
+ XSETWINDOW (help_echo_window, w);
+ help_echo_object = string;
+ help_echo_pos = charpos;
+ }
}
if (NILP (pointer))
}
}
-#ifdef HAVE_CARBON
- /* Display scroll bar for this window. */
- if (!NILP (w->vertical_scroll_bar))
- {
- /* ++KFS:
- If this doesn't work here (maybe some header files are missing),
- make a function in macterm.c and call it to do the job! */
- ControlHandle ch
- = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
-
- Draw1Control (ch);
- }
-#endif
-
return mouse_face_overwritten_p;
}
return;
}
-#ifdef HAVE_CARBON
- /* MAC_TODO: this is a kludge, but if scroll bars are not activated
- or deactivated here, for unknown reasons, activated scroll bars
- are shown in deactivated frames in some instances. */
- if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
- activate_scroll_bars (f);
- else
- deactivate_scroll_bars (f);
-#endif
-
/* If basic faces haven't been realized yet, there is no point in
trying to redraw anything. This can happen when we get an expose
event while Emacs is starting, e.g. by moving another window. */
staticpro (&Qcenter);
Qline_height = intern ("line-height");
staticpro (&Qline_height);
- Qtotal = intern ("total");
- staticpro (&Qtotal);
QCalign_to = intern (":align-to");
staticpro (&QCalign_to);
QCrelative_width = intern (":relative-width");
staticpro (&Qfontification_functions);
Qtrailing_whitespace = intern ("trailing-whitespace");
staticpro (&Qtrailing_whitespace);
+ Qescape_glyph = intern ("escape-glyph");
+ staticpro (&Qescape_glyph);
Qimage = intern ("image");
staticpro (&Qimage);
QCmap = intern (":map");