summaryrefslogtreecommitdiff
path: root/src/xdisp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xdisp.c')
-rw-r--r--src/xdisp.c396
1 files changed, 264 insertions, 132 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 1815f986781..e853c8c2232 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -869,6 +869,19 @@ bset_update_mode_line (struct buffer *b)
b->text->redisplay = true;
}
+void
+wset_update_mode_line (struct window *w)
+{
+ w->update_mode_line = true;
+ /* When a window's mode line needs to be updated, the window's frame's
+ title may also need to be updated, but we don't need to worry about it
+ here. Instead, `gui_consider_frame_title' is automatically called
+ whenever w->update_mode_line is set for that frame's selected window.
+ But for this to work reliably, we have to make sure the window
+ is considered, so we have to mark it for redisplay. */
+ wset_redisplay (w);
+}
+
DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
Sset_buffer_redisplay, 4, 4, 0,
doc: /* Mark the current buffer for redisplay.
@@ -4459,7 +4472,13 @@ face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
static enum prop_handled
handle_face_prop (struct it *it)
{
+ ptrdiff_t count = SPECPDL_INDEX ();
+ /* Don't allow the user to quit out of face-merging code, in case
+ this is called when redisplaying a non-selected window, with
+ point temporarily moved to window-point. */
+ specbind (Qinhibit_quit, Qt);
const int new_face_id = face_at_pos (it, 0);
+ unbind_to (count, Qnil);
/* Is this a start of a run of characters with box face?
@@ -4544,11 +4563,13 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
ptrdiff_t bufpos, charpos;
int base_face_id;
- /* No face change past the end of the string (for the case
- we are padding with spaces). No face change before the
- string start. */
+ /* No face change past the end of the string (for the case we
+ are padding with spaces). No face change before the string
+ start. Ignore face changes before the first visible
+ character on this display line. */
if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
- || (IT_STRING_CHARPOS (*it) == 0 && before_p))
+ || (IT_STRING_CHARPOS (*it) == 0 && before_p)
+ || it->current_x <= it->first_visible_x)
return it->face_id;
if (!it->bidi_p)
@@ -4567,51 +4588,48 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
}
else
{
- if (before_p)
- {
- /* With bidi iteration, the character before the current
- in the visual order cannot be found by simple
- iteration, because "reverse" reordering is not
- supported. Instead, we need to start from the string
- beginning and go all the way to the current string
- position, remembering the previous position. */
- /* Ignore face changes before the first visible
- character on this display line. */
- if (it->current_x <= it->first_visible_x)
- return it->face_id;
- SAVE_IT (it_copy, *it, it_copy_data);
- IT_STRING_CHARPOS (it_copy) = 0;
- bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
+ /* With bidi iteration, the character before the current in
+ the visual order cannot be found by simple iteration,
+ because "reverse" reordering is not supported. Instead,
+ we need to start from the string beginning and go all the
+ way to the current string position, remembering the
+ visually-previous position. We need to start from the
+ string beginning for the character after the current as
+ well, since the iterator state in IT may have been
+ pushed, and the bidi cache is no longer coherent with the
+ string's text. */
+ SAVE_IT (it_copy, *it, it_copy_data);
+ IT_STRING_CHARPOS (it_copy) = 0;
+ bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
+ it_copy.bidi_it.scan_dir = 0;
- do
- {
- charpos = IT_STRING_CHARPOS (it_copy);
- if (charpos >= SCHARS (it->string))
- break;
- bidi_move_to_visually_next (&it_copy.bidi_it);
- }
- while (IT_STRING_CHARPOS (it_copy) != IT_STRING_CHARPOS (*it));
-
- RESTORE_IT (it, it, it_copy_data);
+ do
+ {
+ charpos = it_copy.bidi_it.charpos;
+ if (charpos >= SCHARS (it->string))
+ break;
+ bidi_move_to_visually_next (&it_copy.bidi_it);
}
- else
+ while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
+
+ if (!before_p)
{
/* Set charpos to the string position of the character
that comes after IT's current position in the visual
order. */
int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
-
- it_copy = *it;
- /* If this is the first display element,
+ /* If this is the first string character,
bidi_move_to_visually_next will deliver character at
current position without moving, so we need to enlarge N. */
- if (it->bidi_it.first_elt)
+ if (it_copy.bidi_it.first_elt)
n++;
while (n--)
bidi_move_to_visually_next (&it_copy.bidi_it);
charpos = it_copy.bidi_it.charpos;
}
+
+ RESTORE_IT (it, it, it_copy_data);
}
eassert (0 <= charpos && charpos <= SCHARS (it->string));
@@ -5770,8 +5788,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
#ifdef HAVE_WINDOW_SYSTEM
else
{
+ ptrdiff_t count = SPECPDL_INDEX ();
+
it->what = IT_IMAGE;
+ /* Don't allow quitting from lookup_image, for when we are
+ displaying a non-selected window, and the buffer's point
+ was temporarily moved to the window-point. */
+ specbind (Qinhibit_quit, Qt);
it->image_id = lookup_image (it->f, value, it->face_id);
+ unbind_to (count, Qnil);
it->position = start_pos;
it->object = NILP (object) ? it->w->contents : object;
it->method = GET_FROM_IMAGE;
@@ -9227,10 +9252,10 @@ move_it_in_display_line_to (struct it *it,
|| prev_method == GET_FROM_STRING)
/* Passed TO_CHARPOS from left to right. */
&& ((prev_pos < to_charpos
- && IT_CHARPOS (*it) > to_charpos)
+ && IT_CHARPOS (*it) >= to_charpos)
/* Passed TO_CHARPOS from right to left. */
|| (prev_pos > to_charpos
- && IT_CHARPOS (*it) < to_charpos)))))
+ && IT_CHARPOS (*it) <= to_charpos)))))
{
if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
{
@@ -10049,7 +10074,22 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
it->continuation_lines_width = 0;
reseat_at_next_visible_line_start (it, false);
if ((op & MOVE_TO_POS) != 0
- && IT_CHARPOS (*it) > to_charpos)
+ && (IT_CHARPOS (*it) > to_charpos
+ || (IT_CHARPOS (*it) == to_charpos
+ /* Consider TO_CHARPOS as REACHED if we are at
+ EOB that ends in something other than a newline. */
+ && to_charpos == ZV
+ && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
+ /* But if we have a display or an overlay string
+ at EOB, keep going until we exhaust all the
+ characters of the string(s). */
+ && (it->sp == 0
+ || (STRINGP (it->string)
+ && (it->current.overlay_string_index < 0
+ || (it->current.overlay_string_index >= 0
+ && it->current.overlay_string_index
+ >= it->n_overlay_strings - 1))
+ && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
{
reached = 9;
goto out;
@@ -10767,6 +10807,9 @@ include the height of both, if present, in the return value. */)
it.max_descent = max (it.max_descent, it.descent);
}
}
+ else
+ bidi_unshelve_cache (it2data, true);
+
if (!NILP (x_limit))
{
/* Don't return more than X-LIMIT. */
@@ -10810,6 +10853,47 @@ include the height of both, if present, in the return value. */)
return Fcons (make_fixnum (x - start_x), make_fixnum (y));
}
+
+DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
+ Sdisplay__line_is_continued_p, 0, 0, 0,
+ doc: /* Return non-nil if the current screen line is continued on display. */)
+ (void)
+{
+ struct buffer *oldb = current_buffer;
+ struct window *w = XWINDOW (selected_window);
+ enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
+
+ set_buffer_internal_1 (XBUFFER (w->contents));
+
+ if (PT < ZV)
+ {
+ struct text_pos startpos;
+ struct it it;
+ void *itdata;
+ /* Use a marker, since vertical-motion enters redisplay, which can
+ trigger fontifications, which in turn could modify buffer text. */
+ Lisp_Object opoint = Fpoint_marker ();
+
+ /* Make sure to start from the beginning of the current screen
+ line, so that move_it_in_display_line_to counts pixels correctly. */
+ Fvertical_motion (make_fixnum (0), selected_window, Qnil);
+ SET_TEXT_POS (startpos, PT, PT_BYTE);
+ itdata = bidi_shelve_cache ();
+ start_display (&it, w, startpos);
+ /* If lines are truncated, no line is continued. */
+ if (it.line_wrap != TRUNCATE)
+ {
+ it.glyph_row = NULL;
+ rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
+ }
+ SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
+ bidi_unshelve_cache (itdata, false);
+ }
+ set_buffer_internal_1 (oldb);
+
+ return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
+}
+
/***********************************************************************
Messages
@@ -11687,7 +11771,7 @@ display_echo_area (struct window *w)
/* If there is no message, we must call display_echo_area_1
nevertheless because it resizes the window. But we will have to
reset the echo_area_buffer in question to nil at the end because
- with_echo_area_buffer will sets it to an empty buffer. */
+ with_echo_area_buffer will set it to an empty buffer. */
bool i = display_last_displayed_message_p;
/* According to the C99, C11 and C++11 standards, the integral value
of a "bool" is always 0 or 1, so this array access is safe here,
@@ -11832,7 +11916,7 @@ resize_mini_window (struct window *w, bool exact_p)
int height, max_height;
struct text_pos start;
struct buffer *old_current_buffer = NULL;
- int windows_height = FRAME_WINDOWS_HEIGHT (f);
+ int windows_height = FRAME_INNER_HEIGHT (f);
if (current_buffer != XBUFFER (w->contents))
{
@@ -11854,18 +11938,27 @@ resize_mini_window (struct window *w, bool exact_p)
max_height = clip_to_bounds (unit, max_height, windows_height);
/* Find out the height of the text in the window. */
- if (it.line_wrap == TRUNCATE)
- height = unit;
- else
- {
- last_height = 0;
- move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
- if (it.max_ascent == 0 && it.max_descent == 0)
- height = it.current_y + last_height;
- else
- height = it.current_y + it.max_ascent + it.max_descent;
- height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
+ last_height = 0;
+ move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
+ /* If move_it_to moved to the next visible line after EOB,
+ account for the height of the last full line. */
+ if (it.max_ascent == 0 && it.max_descent == 0)
+ {
+ height = it.current_y;
+ /* Don't add the last line's height if lines are truncated
+ and the text doesn't end in a newline.
+ FIXME: if the text ends in a newline from a display
+ property or an overlay string, they lose: the mini-window
+ might not show the last empty line. */
+ if (!(it.line_wrap == TRUNCATE
+ && it.current_x <= it.first_visible_x
+ && ZV_BYTE > 1
+ && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
+ height += last_height;
}
+ else
+ height = it.current_y + it.max_ascent + it.max_descent;
+ height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
/* Compute a suitable window start. */
if (height > max_height)
@@ -12638,9 +12731,8 @@ gui_consider_frame_title (Lisp_Object frame)
mode_line_noprop_buf; then display the title. */
record_unwind_protect (unwind_format_mode_line,
format_mode_line_unwind_data
- (f, current_buffer, selected_window, false));
+ (NULL, current_buffer, Qnil, false));
- Fselect_window (f->selected_window, Qt);
set_buffer_internal_1
(XBUFFER (XWINDOW (f->selected_window)->contents));
fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
@@ -13441,8 +13533,6 @@ PIXELWISE non-nil means return the height of the tab bar in pixels. */)
static bool
redisplay_tab_bar (struct frame *f)
{
- f->tab_bar_redisplayed = true;
-
struct window *w;
struct it it;
struct glyph_row *row;
@@ -13456,6 +13546,8 @@ redisplay_tab_bar (struct frame *f)
WINDOW_TOTAL_LINES (w) == 0))
return false;
+ f->tab_bar_redisplayed = true;
+
/* Set up an iterator for the tab-bar window. */
init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
it.first_visible_x = 0;
@@ -13596,8 +13688,9 @@ redisplay_tab_bar (struct frame *f)
/* Get information about the tab-bar item which is displayed in GLYPH
on frame F. Return in *PROP_IDX the index where tab-bar item
- properties start in F->tab_bar_items. Value is false if
- GLYPH doesn't display a tab-bar item. */
+ properties start in F->tab_bar_items. Return in CLOSE_P an
+ indication whether the click was on the close-tab icon of the tab.
+ Value is false if GLYPH doesn't display a tab-bar item. */
static bool
tab_bar_item_info (struct frame *f, struct glyph *glyph,
@@ -13643,7 +13736,6 @@ static int
get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
int *hpos, int *vpos, int *prop_idx, bool *close_p)
{
- Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
struct window *w = XWINDOW (f->tab_bar_window);
int area;
@@ -13657,18 +13749,7 @@ get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
return -1;
- /* Is mouse on the highlighted item? */
- if (EQ (f->tab_bar_window, hlinfo->mouse_face_window)
- && *vpos >= hlinfo->mouse_face_beg_row
- && *vpos <= hlinfo->mouse_face_end_row
- && (*vpos > hlinfo->mouse_face_beg_row
- || *hpos >= hlinfo->mouse_face_beg_col)
- && (*vpos < hlinfo->mouse_face_end_row
- || *hpos < hlinfo->mouse_face_end_col
- || hlinfo->mouse_face_past_end))
- return 0;
-
- return 1;
+ return *prop_idx == f->last_tab_bar_item ? 0 : 1;
}
@@ -13690,25 +13771,14 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
Lisp_Object enabled_p;
int ts;
- /* If not on the highlighted tab-bar item, and mouse-highlight is
- non-nil, return. This is so we generate the tab-bar button
- click only when the mouse button is released on the same item as
- where it was pressed. However, when mouse-highlight is disabled,
- generate the click when the button is released regardless of the
- highlight, since tab-bar items are not highlighted in that
- case. */
frame_to_window_pixel_xy (w, &x, &y);
ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
if (ts == -1
- || (ts != 0 && !NILP (Vmouse_highlight)))
+ /* If the button is released on a tab other than the one where
+ it was pressed, don't generate the tab-bar button click event. */
+ || (ts != 0 && !down_p))
return;
- /* When mouse-highlight is off, generate the click for the item
- where the button was pressed, disregarding where it was
- released. */
- if (NILP (Vmouse_highlight) && !down_p)
- prop_idx = f->last_tab_bar_item;
-
/* If item is disabled, do nothing. */
enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
if (NILP (enabled_p))
@@ -13716,10 +13786,10 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
if (down_p)
{
- /* Show item in pressed state. */
+ /* Show the clicked button in pressed state. */
if (!NILP (Vmouse_highlight))
show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
- f->last_tab_bar_item = prop_idx;
+ f->last_tab_bar_item = prop_idx; /* record the pressed tab */
}
else
{
@@ -14388,21 +14458,13 @@ PIXELWISE non-nil means return the height of the tool bar in pixels. */)
return make_fixnum (height);
}
+#ifndef HAVE_EXT_TOOL_BAR
-/* Display the tool-bar of frame F. Value is true if tool-bar's
- height should be changed. */
+/* Display the internal tool-bar of frame F. Value is true if
+ tool-bar's height should be changed. */
static bool
redisplay_tool_bar (struct frame *f)
{
- f->tool_bar_redisplayed = true;
-#ifdef HAVE_EXT_TOOL_BAR
-
- if (FRAME_EXTERNAL_TOOL_BAR (f))
- update_frame_tool_bar (f);
- return false;
-
-#else /* ! (HAVE_EXT_TOOL_BAR) */
-
struct window *w;
struct it it;
struct glyph_row *row;
@@ -14416,6 +14478,8 @@ redisplay_tool_bar (struct frame *f)
WINDOW_TOTAL_LINES (w) == 0))
return false;
+ f->tool_bar_redisplayed = true;
+
/* Set up an iterator for the tool-bar window. */
init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
it.first_visible_x = 0;
@@ -14551,13 +14615,10 @@ redisplay_tool_bar (struct frame *f)
}
f->minimize_tool_bar_window_p = false;
- return false;
-#endif /* HAVE_EXT_TOOL_BAR */
+ return false;
}
-#ifndef HAVE_EXT_TOOL_BAR
-
/* Get information about the tool-bar item which is displayed in GLYPH
on frame F. Return in *PROP_IDX the index where tool-bar item
properties start in F->tool_bar_items. Value is false if
@@ -14837,7 +14898,15 @@ hscroll_window_tree (Lisp_Object window)
if (WINDOWP (w->contents))
hscrolled_p |= hscroll_window_tree (w->contents);
- else if (w->cursor.vpos >= 0)
+ else if (w->cursor.vpos >= 0
+ /* Don't allow hscroll in mini-windows that display
+ echo-area messages. This is because desired_matrix
+ of such windows was prepared while momentarily
+ switched to an echo-area buffer, which is different
+ from w->contents, and we simply cannot hscroll such
+ windows safely. */
+ && !(w == XWINDOW (echo_area_window)
+ && !NILP (echo_area_buffer[0])))
{
int h_margin;
int text_area_width;
@@ -15035,11 +15104,12 @@ hscroll_window_tree (Lisp_Object window)
else
{
if (hscroll_relative_p)
- wanted_x = text_area_width * hscroll_step_rel
- + h_margin;
+ wanted_x =
+ text_area_width * hscroll_step_rel + h_margin + x_offset;
else
- wanted_x = hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
- + h_margin;
+ wanted_x =
+ hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
+ + h_margin + x_offset;
hscroll
= max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
}
@@ -17227,8 +17297,11 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
if (!NILP (Vwindow_scroll_functions))
{
+ ptrdiff_t count = SPECPDL_INDEX ();
+ specbind (Qinhibit_quit, Qt);
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_fixnum (CHARPOS (startp)));
+ unbind_to (count, Qnil);
SET_TEXT_POS_FROM_MARKER (startp, w->start);
/* In case the hook functions switch buffers. */
set_buffer_internal (XBUFFER (w->contents));
@@ -19221,7 +19294,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
w->start_at_line_beg = (CHARPOS (startp) == BEGV
|| FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
- /* Display the mode line, if we must. */
+ /* Display the mode line, header line, and tab-line, if we must. */
if ((update_mode_line
/* If window not full width, must redo its mode line
if (a) the window to its side is being redone and
@@ -19240,8 +19313,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
|| window_wants_header_line (w)
|| window_wants_tab_line (w)))
{
+ ptrdiff_t count1 = SPECPDL_INDEX ();
+ specbind (Qinhibit_quit, Qt);
display_mode_lines (w);
+ unbind_to (count1, Qnil);
/* If mode line height has changed, arrange for a thorough
immediate redisplay using the correct mode line height. */
@@ -19289,7 +19365,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
finish_menu_bars:
/* When we reach a frame's selected window, redo the frame's menu
- bar and the frame's title. */
+ bar, tool bar, tab-bar, and the frame's title. */
if (update_mode_line
&& EQ (FRAME_SELECTED_WINDOW (f), window))
{
@@ -19320,7 +19396,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
#ifdef HAVE_EXT_TOOL_BAR
if (FRAME_EXTERNAL_TOOL_BAR (f))
- redisplay_tool_bar (f);
+ update_frame_tool_bar (f);
#else
if (WINDOWP (f->tool_bar_window)
&& (FRAME_TOOL_BAR_LINES (f) > 0
@@ -19452,8 +19528,11 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
'start_display' again. */
ptrdiff_t it_charpos = IT_CHARPOS (it);
- /* Don't let the cursor end in the scroll margins. */
+ /* Don't let the cursor end in the scroll margins. However, when
+ the window is vscrolled, we leave it to vscroll to handle the
+ margins, see window_scroll_pixel_based. */
if ((flags & TRY_WINDOW_CHECK_MARGINS)
+ && w->vscroll == 0
&& !MINI_WINDOW_P (w))
{
int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
@@ -19462,7 +19541,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
start_display (&it, w, pos);
- if ((w->cursor.y >= 0 /* not vscrolled */
+ if ((w->cursor.y >= 0
&& w->cursor.y < top_scroll_margin
&& CHARPOS (pos) > BEGV)
/* rms: considering make_cursor_line_fully_visible_p here
@@ -22054,10 +22133,17 @@ extend_face_to_end_of_line (struct it *it)
|| WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
return;
+ ptrdiff_t count = SPECPDL_INDEX ();
+
+ /* Don't allow the user to quit out of face-merging code, in case
+ this is called when redisplaying a non-selected window, with
+ point temporarily moved to window-point. */
+ specbind (Qinhibit_quit, Qt);
const int extend_face_id = (it->face_id == DEFAULT_FACE_ID
|| it->s != NULL)
? DEFAULT_FACE_ID
: face_at_pos (it, LFACE_EXTEND_INDEX);
+ unbind_to (count, Qnil);
/* Face extension extends the background and box of IT->extend_face_id
to the end of the line. If the background equals the background
@@ -22337,15 +22423,23 @@ extend_face_to_end_of_line (struct it *it)
it->face_id = (it->glyph_row->ends_at_zv_p ?
default_face->id : face->id);
- /* Display fill-column indicator if needed. */
- const int indicator_column = fill_column_indicator_column (it, 1);
-
/* Make sure our idea of current_x is in sync with the glyphs
actually in the glyph row. They might differ because
append_space_for_newline can insert one glyph without
updating current_x. */
it->current_x = it->glyph_row->used[TEXT_AREA];
+ /* The above assignment causes the code below to use a
+ non-standard semantics of it->current_x: it is measured
+ relative to the beginning of the text-area, thus disregarding
+ the window's hscroll. That is why we need to correct the
+ indicator column for the hscroll, otherwise the indicator
+ will not move together with the text as result of horizontal
+ scrolling. */
+ const int indicator_column =
+ fill_column_indicator_column (it, 1) - it->first_visible_x;
+
+ /* Display fill-column indicator if needed. */
while (it->current_x <= it->last_visible_x)
{
if (it->current_x != indicator_column)
@@ -22705,6 +22799,22 @@ get_it_property (struct it *it, Lisp_Object prop)
return Fget_char_property (position, prop, object);
}
+/* Return the line-prefix/wrap-prefix property, checking both the
+ current IT->OBJECT and the underlying buffer text. */
+
+static Lisp_Object
+get_line_prefix_it_property (struct it *it, Lisp_Object prop)
+{
+ Lisp_Object prefix = get_it_property (it, prop);
+
+ /* If we are looking at a display or overlay string, check also the
+ underlying buffer text. */
+ if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
+ return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
+ it->w->contents);
+ return prefix;
+}
+
/* See if there's a line- or wrap-prefix, and if so, push it on IT. */
static void
@@ -22714,13 +22824,13 @@ handle_line_prefix (struct it *it)
if (it->continuation_lines_width > 0)
{
- prefix = get_it_property (it, Qwrap_prefix);
+ prefix = get_line_prefix_it_property (it, Qwrap_prefix);
if (NILP (prefix))
prefix = Vwrap_prefix;
}
else
{
- prefix = get_it_property (it, Qline_prefix);
+ prefix = get_line_prefix_it_property (it, Qline_prefix);
if (NILP (prefix))
prefix = Vline_prefix;
}
@@ -24103,7 +24213,8 @@ display_line (struct it *it, int cursor_vpos)
the logical order. */
if (IT_BYTEPOS (*it) > BEG_BYTE)
row->ends_at_zv_p =
- IT_BYTEPOS (*it) >= ZV_BYTE && FETCH_BYTE (ZV_BYTE - 1) != '\n';
+ IT_BYTEPOS (*it) >= ZV_BYTE
+ && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
else
row->ends_at_zv_p = false;
break;
@@ -25352,8 +25463,9 @@ redisplay_mode_lines (Lisp_Object window, bool force)
}
-/* Display the mode and/or header line of window W. Value is the
- sum number of mode lines and header lines displayed. */
+/* Display the mode line, the header line, and the tab-line of window
+ W. Value is the sum number of mode lines, header lines, and tab
+ lines actually displayed. */
static int
display_mode_lines (struct window *w)
@@ -26933,7 +27045,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
Lisp_Object val = Qnil;
if (STRINGP (curdir))
- val = call1 (intern ("file-remote-p"), curdir);
+ val = safe_call1 (intern ("file-remote-p"), curdir);
val = unbind_to (count, val);
@@ -30240,7 +30352,7 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
/* +4 is for vertical bars of a box plus 1-pixel spaces at both side. */
width = max (metrics_upper.width, metrics_lower.width) + 4;
- upper_xoff = upper_yoff = 2; /* the typical case */
+ upper_xoff = lower_xoff = 2; /* the typical case */
if (base_width >= width)
{
/* Align the upper to the left, the lower to the right. */
@@ -30254,13 +30366,7 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
if (metrics_upper.width >= metrics_lower.width)
lower_xoff = (width - metrics_lower.width) / 2;
else
- {
- /* FIXME: This code doesn't look right. It formerly was
- missing the "lower_xoff = 0;", which couldn't have
- been right since it left lower_xoff uninitialized. */
- lower_xoff = 0;
- upper_xoff = (width - metrics_upper.width) / 2;
- }
+ upper_xoff = (width - metrics_upper.width) / 2;
}
/* +5 is for horizontal bars of a box plus 1-pixel spaces at
@@ -31968,6 +32074,11 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
static void
show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
{
+ /* Don't bother doing anything if the mouse-face window is not set
+ up. */
+ if (!WINDOWP (hlinfo->mouse_face_window))
+ return;
+
struct window *w = XWINDOW (hlinfo->mouse_face_window);
struct frame *f = XFRAME (WINDOW_FRAME (w));
@@ -33176,7 +33287,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
of the mode line without any text (e.g. past the right edge of
the mode line text), use that windows's mode line help echo if it
has been set. */
- if (STRINGP (string) || area == ON_MODE_LINE)
+ if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
+ || area == ON_TAB_LINE)
{
/* Arrange to display the help by setting the global variables
help_echo_string, help_echo_object, and help_echo_pos. */
@@ -33233,6 +33345,19 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
}
else if (draggable && area == ON_MODE_LINE)
cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
+ else if ((area == ON_MODE_LINE
+ && WINDOW_BOTTOMMOST_P (w)
+ && !FRAME_HAS_MINIBUF_P (f)
+ && !NILP (Fframe_parameter
+ (w->frame, Qdrag_with_mode_line)))
+ || (((area == ON_HEADER_LINE
+ && !NILP (Fframe_parameter
+ (w->frame, Qdrag_with_header_line)))
+ || (area == ON_TAB_LINE
+ && !NILP (Fframe_parameter
+ (w->frame, Qdrag_with_tab_line))))
+ && WINDOW_TOPMOST_P (w)))
+ cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
else
cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
}
@@ -34320,7 +34445,7 @@ gui_draw_bottom_divider (struct window *w)
&& !NILP (XWINDOW (p->parent)->next))))
x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
- FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
+ FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
}
}
@@ -34725,6 +34850,7 @@ be let-bound around code that needs to disable messages temporarily. */);
defsubr (&Swindow_text_pixel_size);
defsubr (&Smove_point_visually);
defsubr (&Sbidi_find_overridden_directionality);
+ defsubr (&Sdisplay__line_is_continued_p);
DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
@@ -34821,6 +34947,10 @@ be let-bound around code that needs to disable messages temporarily. */);
DEFSYM (Qdragging, "dragging");
DEFSYM (Qdropping, "dropping");
+ DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
+ DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
+ DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
+
DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
list_of_error = list1 (list2 (Qerror, Qvoid_variable));
@@ -35315,7 +35445,7 @@ and `scroll-right' overrides this variable's effect. */);
Vhscroll_step = make_fixnum (0);
DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
- doc: /* If non-nil, messages are truncated instead of resizing the echo area.
+ doc: /* If non-nil, messages are truncated when displaying the echo area.
Bind this around calls to `message' to let it take effect. */);
message_truncate_lines = false;
@@ -35589,8 +35719,10 @@ as usual. If the function returns a string, the returned string is
displayed in the echo area. If this function returns any other non-nil
value, this means that the message was already handled, and the original
message text will not be displayed in the echo area.
-See also `clear-message-function' that can be used to clear the
-message displayed by this function. */);
+
+Also see `clear-message-function' (which can be used to clear the
+message displayed by this function), and `command-error-function'
+(which controls how error messages are displayed). */);
Vset_message_function = Qnil;
DEFVAR_LISP ("clear-message-function", Vclear_message_function,