Lisp_Object limit, prop, pos;
int found = 0;
- pos = make_number (from);
+ pos = make_number (max (from, BEGV));
if (!back_p) /* looking forward */
{
{
/* DVPOS == 0 means move to the start of the screen line. */
move_it_vertically_backward (it, 0);
- xassert (it->current_x == 0 && it->hpos == 0);
/* Let next call to line_bottom_y calculate real line height */
last_height = 0;
}
{
move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
if (!IT_POS_VALID_AFTER_MOVE_P (it))
- move_it_to (it, IT_CHARPOS (*it) + 1, -1, -1, -1, MOVE_TO_POS);
+ {
+ /* Only move to the next buffer position if we ended up in a
+ string from display property, not in an overlay string
+ (before-string or after-string). That is because the
+ latter don't conceal the underlying buffer position, so
+ we can ask to move the iterator to the exact position we
+ are interested in. Note that, even if we are already at
+ IT_CHARPOS (*it), the call below is not a no-op, as it
+ will detect that we are at the end of the string, pop the
+ iterator, and compute it->current_x and it->hpos
+ correctly. */
+ move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
+ -1, -1, -1, MOVE_TO_POS);
+ }
}
else
{
comes from a text property, not from an overlay. */
int string_from_text_prop = 0;
+ /* Don't even try doing anything if called for a mode-line or
+ header-line row, since the rest of the code isn't prepared to
+ deal with such calamities. */
+ xassert (!row->mode_line_p);
+ if (row->mode_line_p)
+ return 0;
+
/* Skip over glyphs not having an object at the start and the end of
the row. These are special glyphs like truncation marks on
terminal frames. */
chprop = Fget_char_property (make_number (glyph_pos), Qcursor,
glyph->object);
+ if (!NILP (chprop))
+ {
+ /* If the string came from a `display' text property,
+ look up the buffer position of that property and
+ use that position to update bpos_max, as if we
+ actually saw such a position in one of the row's
+ glyphs. This helps with supporting integer values
+ of `cursor' property on the display string in
+ situations where most or all of the row's buffer
+ text is completely covered by display properties,
+ so that no glyph with valid buffer positions is
+ ever seen in the row. */
+ EMACS_INT prop_pos =
+ string_buffer_position_lim (glyph->object, pos_before,
+ pos_after, 0);
+
+ if (prop_pos >= pos_before)
+ bpos_max = prop_pos - 1;
+ }
if (INTEGERP (chprop))
{
bpos_covered = bpos_max + XINT (chprop);
/* If the `cursor' property covers buffer positions up
to and including point, we should display cursor on
- this glyph. Note that overlays and text properties
- with string values stop bidi reordering, so every
- buffer position to the left of the string is always
- smaller than any position to the right of the
- string. Therefore, if a `cursor' property on one
+ this glyph. Note that, if a `cursor' property on one
of the string's characters has an integer value, we
will break out of the loop below _before_ we get to
the position match above. IOW, integer values of
chprop = Fget_char_property (make_number (glyph_pos), Qcursor,
glyph->object);
+ if (!NILP (chprop))
+ {
+ EMACS_INT prop_pos =
+ string_buffer_position_lim (glyph->object, pos_before,
+ pos_after, 0);
+
+ if (prop_pos >= pos_before)
+ bpos_max = prop_pos - 1;
+ }
if (INTEGERP (chprop))
{
bpos_covered = bpos_max + XINT (chprop);
|| pos <= tem)
{
/* If the string from which this glyph came is
- found in the buffer at point, then we've
- found the glyph we've been looking for. If
- it comes from an overlay (tem == 0), and it
- has the `cursor' property on one of its
+ found in the buffer at point, or at position
+ that is closer to point than pos_after, then
+ we've found the glyph we've been looking for.
+ If it comes from an overlay (tem == 0), and
+ it has the `cursor' property on one of its
glyphs, record that glyph as a candidate for
displaying the cursor. (As in the
unidirectional version, we will display the
cursor on the last candidate we find.) */
- if (tem == 0 || tem == pt_old)
+ if (tem == 0
+ || tem == pt_old
+ || (tem - pt_old > 0 && tem < pos_after))
{
/* The glyphs from this string could have
been reordered. Find the one with the
}
}
- if (tem == pt_old)
+ if (tem == pt_old
+ || (tem - pt_old > 0 && tem < pos_after))
goto compute_x;
}
if (tem)
else if (rc != CURSOR_MOVEMENT_SUCCESS
&& !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
{
+ struct glyph_row *row1;
+
/* If rows are bidi-reordered and point moved, back up
until we find a row that does not belong to a
continuation line. This is because we must consider
/* FIXME: Revisit this when glyph ``spilling'' in
continuation lines' rows is implemented for
bidi-reordered rows. */
- while (MATRIX_ROW_CONTINUATION_LINE_P (row))
+ for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ MATRIX_ROW_CONTINUATION_LINE_P (row);
+ --row)
{
/* If we hit the beginning of the displayed portion
without finding the first row of a continued
line, give up. */
- if (row <= w->current_matrix->rows)
+ if (row <= row1)
{
rc = CURSOR_MOVEMENT_MUST_SCROLL;
break;
}
xassert (row->enabled_p);
- --row;
}
}
if (must_scroll)
;
else if (rc != CURSOR_MOVEMENT_SUCCESS
&& MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
+ /* Make sure this isn't a header line by any chance, since
+ then MATRIX_ROW_PARTIALLY_VISIBLE_P might yield non-zero. */
+ && !row->mode_line_p
&& make_cursor_line_fully_visible_p)
{
if (PT == MATRIX_ROW_END_CHARPOS (row)
continued. */
&& !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
&& (row->continued_p
- || row->exact_window_width_line_p)))
+ || row->exact_window_width_line_p))
+ /* If ROW->end is beyond ZV, then ROW->end is outdated and
+ needs to be recomputed, so don't consider this row as
+ unchanged. This happens when the last line was
+ bidi-reordered and was killed immediately before this
+ redisplay cycle. In that case, ROW->end stores the
+ buffer position of the first visual-order character of
+ the killed text, which is now beyond ZV. */
+ && CHARPOS (row->end.pos) <= ZV)
row_found = row;
/* Stop if last visible row. */
it->c = it->char_to_display = ' ';
it->len = 1;
+ /* If the default face was remapped, be sure to use the
+ remapped face for the appended newline. */
if (default_face_p)
- it->face_id = DEFAULT_FACE_ID;
+ it->face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
else if (it->face_before_selective_p)
it->face_id = it->saved_face_id;
face = FACE_FROM_ID (it->f, it->face_id);
static void
extend_face_to_end_of_line (struct it *it)
{
- struct face *face;
+ struct face *face, *default_face;
struct frame *f = it->f;
/* If line is already filled, do nothing. Non window-system frames
&& !it->glyph_row->continued_p))
return;
+ /* The default face, possibly remapped. */
+ default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
+
/* Face extension extends the background and box of IT->face_id
to the end of the line. If the background equals the background
of the frame, we don't have to do anything. */
if (it->glyph_row->used[TEXT_AREA] == 0)
{
it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
- it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
+ it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
it->glyph_row->used[TEXT_AREA] = 1;
}
#ifdef HAVE_WINDOW_SYSTEM
face, to avoid painting the rest of the window with
the region face, if the region ends at ZV. */
if (it->glyph_row->ends_at_zv_p)
- it->face_id = DEFAULT_FACE_ID;
+ it->face_id = default_face->id;
else
it->face_id = face->id;
append_stretch_glyph (it, make_number (0), stretch_width,
avoid painting the rest of the window with the region face,
if the region ends at ZV. */
if (it->glyph_row->ends_at_zv_p)
- it->face_id = DEFAULT_FACE_ID;
+ it->face_id = default_face->id;
else
it->face_id = face->id;
/* A row that displays right-to-left text must always have
its last face extended all the way to the end of line,
even if this row ends in ZV, because we still write to
- the screen left to right. */
- if (row->reversed_p)
+ the screen left to right. We also need to extend the
+ last face if the default face is remapped to some
+ different face, otherwise the functions that clear
+ portions of the screen will clear with the default face's
+ background color. */
+ if (row->reversed_p
+ || lookup_basic_face (it->f, DEFAULT_FACE_ID) != DEFAULT_FACE_ID)
extend_face_to_end_of_line (it);
break;
}
sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
str = buf;
}
- for (len = 0; str[len] && ASCII_BYTE_P (str[len]); len++)
+ for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++)
code[len] = font->driver->encode_char (font, str[len]);
upper_len = (len + 1) / 2;
font->driver->text_extents (font, code, upper_len,
#ifdef HAVE_WINDOW_SYSTEM
DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
- doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
+ doc: /* Non-nil means draw block cursor as wide as the glyph under it.
For example, if a block cursor is over a tab, it will be drawn as
wide as that tab on the display. */);
x_stretch_cursor_p = 0;
#endif
DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
- doc: /* *Non-nil means highlight trailing whitespace.
+ doc: /* Non-nil means highlight trailing whitespace.
The face used for trailing whitespace is `trailing-whitespace'. */);
Vshow_trailing_whitespace = Qnil;
Vnobreak_char_display = Qt;
DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
- doc: /* *The pointer shape to show in void text areas.
+ doc: /* The pointer shape to show in void text areas.
A value of nil means to show the text pointer. Other options are `arrow',
`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
Vvoid_text_area_pointer = Qarrow;
= Fcons (intern_c_string ("overlay-arrow-position"), Qnil);
DEFVAR_INT ("scroll-step", emacs_scroll_step,
- doc: /* *The number of lines to try scrolling a window by when point moves out.
+ doc: /* The number of lines to try scrolling a window by when point moves out.
If that fails to bring point back on frame, point is centered instead.
If this is zero, point is always centered after it moves off frame.
If you want scrolling to always be a line at a time, you should set
`scroll-conservatively' to a large value rather than set this to 1. */);
DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
- doc: /* *Scroll up to this many lines, to bring point back on screen.
+ doc: /* Scroll up to this many lines, to bring point back on screen.
If point moves off-screen, redisplay will scroll by up to
`scroll-conservatively' lines in order to bring point just barely
onto the screen again. If that cannot be done, then redisplay
scroll_conservatively = 0;
DEFVAR_INT ("scroll-margin", scroll_margin,
- doc: /* *Number of lines of margin at the top and bottom of a window.
+ doc: /* Number of lines of margin at the top and bottom of a window.
Recenter the window whenever point gets within this many lines
of the top or bottom of the window. */);
scroll_margin = 0;
mode_line_inverse_video = 1;
DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
- doc: /* *Maximum buffer size for which line number should be displayed.
+ doc: /* Maximum buffer size for which line number should be displayed.
If the buffer is bigger than this, the line number does not appear
in the mode line. A value of nil means no limit. */);
Vline_number_display_limit = Qnil;
DEFVAR_INT ("line-number-display-limit-width",
line_number_display_limit_width,
- doc: /* *Maximum line width (in characters) for line number display.
+ doc: /* Maximum line width (in characters) for line number display.
If the average length of the lines near point is bigger than this, then the
line number may be omitted from the mode line. */);
line_number_display_limit_width = 200;
DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
- doc: /* *Non-nil means highlight region even in nonselected windows. */);
+ doc: /* Non-nil means highlight region even in nonselected windows. */);
highlight_nonselected_windows = 0;
DEFVAR_BOOL ("multiple-frames", multiple_frames,
Vredisplay_end_trigger_functions = Qnil;
DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
- doc: /* *Non-nil means autoselect window with mouse pointer.
+ doc: /* Non-nil means autoselect window with mouse pointer.
If nil, do not autoselect windows.
A positive number means delay autoselection by that many seconds: a
window is autoselected only after the mouse has remained in that
Vmouse_autoselect_window = Qnil;
DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
- doc: /* *Non-nil means automatically resize tool-bars.
+ doc: /* Non-nil means automatically resize tool-bars.
This dynamically changes the tool-bar's height to the minimum height
that is needed to make all tool-bar items visible.
If value is `grow-only', the tool-bar's height is only increased
Vauto_resize_tool_bars = Qt;
DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
- doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
+ doc: /* Non-nil means raise tool-bar buttons when the mouse moves over them. */);
auto_raise_tool_bar_buttons_p = 1;
DEFVAR_BOOL ("make-cursor-line-fully-visible", make_cursor_line_fully_visible_p,
- doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible. */);
+ doc: /* Non-nil means to scroll (recenter) cursor line if it is not fully visible. */);
make_cursor_line_fully_visible_p = 1;
DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
- doc: /* *Border below tool-bar in pixels.
+ doc: /* Border below tool-bar in pixels.
If an integer, use it as the height of the border.
If it is one of `internal-border-width' or `border-width', use the
value of the corresponding frame parameter.
Vtool_bar_border = Qinternal_border_width;
DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
- doc: /* *Margin around tool-bar buttons in pixels.
+ doc: /* Margin around tool-bar buttons in pixels.
If an integer, use that for both horizontal and vertical margins.
Otherwise, value should be a pair of integers `(HORZ . VERT)' with
HORZ specifying the horizontal margin, and VERT specifying the
Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
- doc: /* *Relief thickness of tool-bar buttons. */);
+ doc: /* Relief thickness of tool-bar buttons. */);
tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
Vtool_bar_style = Qnil;
DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
- doc: /* *Maximum number of characters a label can have to be shown.
+ doc: /* Maximum number of characters a label can have to be shown.
The tool bar style must also show labels for this to have any effect, see
`tool-bar-style'. */);
tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
DEFVAR_BOOL ("unibyte-display-via-language-environment",
unibyte_display_via_language_environment,
- doc: /* *Non-nil means display unibyte text according to language environment.
+ doc: /* Non-nil means display unibyte text according to language environment.
Specifically, this means that raw bytes in the range 160-255 decimal
are displayed by converting them to the equivalent multibyte characters
according to the current language environment. As a result, they are
unibyte_display_via_language_environment = 0;
DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
- doc: /* *Maximum height for resizing mini-windows (the minibuffer and the echo area).
+ doc: /* Maximum height for resizing mini-windows (the minibuffer and the echo area).
If a float, it specifies a fraction of the mini-window frame's height.
If an integer, it specifies a number of lines. */);
Vmax_mini_window_height = make_float (0.25);
DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
DEFVAR_INT ("hscroll-margin", hscroll_margin,
- doc: /* *How many columns away from the window edge point is allowed to get
+ doc: /* How many columns away from the window edge point is allowed to get
before automatic hscrolling will horizontally scroll the window. */);
hscroll_margin = 5;
DEFVAR_LISP ("hscroll-step", Vhscroll_step,
- doc: /* *How many columns to scroll the window when point gets too close to the edge.
+ doc: /* How many columns to scroll the window when point gets too close to the edge.
When point is less than `hscroll-margin' columns from the window
edge, automatic hscrolling will scroll the window by the amount of columns
determined by this variable. If its value is a positive integer, scroll that
#endif /* GLYPH_DEBUG */
DEFVAR_INT ("overline-margin", overline_margin,
- doc: /* *Space between overline and text, in pixels.
+ doc: /* Space between overline and text, in pixels.
The default value is 2: the height of the overline (1 pixel) plus 1 pixel
margin to the character height. */);
overline_margin = 2;
display_hourglass_p = 1;
DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
- doc: /* *Seconds to wait before displaying an hourglass pointer when Emacs is busy. */);
+ doc: /* Seconds to wait before displaying an hourglass pointer when Emacs is busy. */);
Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
hourglass_atimer = NULL;