X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/ea6de9b1f867a49a1ad062ca54e461cd3b1e003f..2a14a4f13cdb22f5b6b0840081d977c8d38a91e6:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 4d359593c7..6b86fd076a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1,6 +1,7 @@ /* Display generation from window structure and buffer text. -Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc. +Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, +Inc. This file is part of GNU Emacs. @@ -366,28 +367,6 @@ Lisp_Object Qcenter; static Lisp_Object Qmargin, Qpointer; static Lisp_Object Qline_height; -/* These setters are used only in this file, so they can be private. */ -static void -wset_base_line_number (struct window *w, Lisp_Object val) -{ - w->base_line_number = val; -} -static void -wset_base_line_pos (struct window *w, Lisp_Object val) -{ - w->base_line_pos = val; -} -static void -wset_column_number_displayed (struct window *w, Lisp_Object val) -{ - w->column_number_displayed = val; -} -static void -wset_region_showing (struct window *w, Lisp_Object val) -{ - w->region_showing = val; -} - #ifdef HAVE_WINDOW_SYSTEM /* Test if overflow newline into fringe. Called with iterator IT @@ -515,11 +494,6 @@ Lisp_Object Qmenu_bar_update_hook; static int overlay_arrow_seen; -/* Number of windows showing the buffer of the selected - window (or another buffer with the same base buffer). */ - -int buffer_shared; - /* Vector containing glyphs for an ellipsis `...'. */ static Lisp_Object default_invis_vector[3]; @@ -844,17 +818,17 @@ static void ensure_echo_area_buffers (void); static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); static Lisp_Object with_echo_area_buffer_unwind_data (struct window *); static int with_echo_area_buffer (struct window *, int, - int (*) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t), - ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); + int (*) (ptrdiff_t, Lisp_Object), + ptrdiff_t, Lisp_Object); static void clear_garbaged_frames (void); -static int current_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); +static int current_message_1 (ptrdiff_t, Lisp_Object); static void pop_message (void); -static int truncate_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); -static void set_message (const char *, Lisp_Object, ptrdiff_t, int); -static int set_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); +static int truncate_message_1 (ptrdiff_t, Lisp_Object); +static void set_message (Lisp_Object); +static int set_message_1 (ptrdiff_t, Lisp_Object); static int display_echo_area (struct window *); -static int display_echo_area_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); -static int resize_mini_window_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); +static int display_echo_area_1 (ptrdiff_t, Lisp_Object); +static int resize_mini_window_1 (ptrdiff_t, Lisp_Object); static Lisp_Object unwind_redisplay (Lisp_Object); static int string_char_and_length (const unsigned char *, int *); static struct text_pos display_prop_end (struct it *, Lisp_Object, @@ -874,7 +848,6 @@ static void push_it (struct it *, struct text_pos *); static void iterate_out_of_display_property (struct it *); static void pop_it (struct it *); static void sync_frame_with_window_matrix_rows (struct window *); -static void select_frame_for_redisplay (Lisp_Object); static void redisplay_internal (void); static int echo_area_display (int); static void redisplay_windows (Lisp_Object); @@ -937,8 +910,8 @@ static int forward_to_next_line_start (struct it *, int *, struct bidi_it *); static struct text_pos string_pos_nchars_ahead (struct text_pos, Lisp_Object, ptrdiff_t); static struct text_pos string_pos (ptrdiff_t, Lisp_Object); -static struct text_pos c_string_pos (ptrdiff_t, const char *, int); -static ptrdiff_t number_of_chars (const char *, int); +static struct text_pos c_string_pos (ptrdiff_t, const char *, bool); +static ptrdiff_t number_of_chars (const char *, bool); static void compute_stop_pos (struct it *); static void compute_string_pos (struct text_pos *, struct text_pos, Lisp_Object); @@ -1335,7 +1308,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, BVAR (current_buffer, header_line_format)); start_display (&it, w, top); - move_it_to (&it, charpos, -1, it.last_visible_y-1, -1, + move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1, (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y); if (charpos >= 0 @@ -1343,7 +1316,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, && IT_CHARPOS (it) >= charpos) /* When scanning backwards under bidi iteration, move_it_to stops at or _before_ CHARPOS, because it stops at or to - the _right_ of the character at CHARPOS. */ + the _right_ of the character at CHARPOS. */ || (it.bidi_p && it.bidi_it.scan_dir == -1 && IT_CHARPOS (it) <= charpos))) { @@ -1419,21 +1392,9 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, Lisp_Object cpos = make_number (charpos); Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil); Lisp_Object string = string_from_display_spec (spec); - int newline_in_string = 0; - - if (STRINGP (string)) - { - const char *s = SSDATA (string); - const char *e = s + SBYTES (string); - while (s < e) - { - if (*s++ == '\n') - { - newline_in_string = 1; - break; - } - } - } + bool newline_in_string + = (STRINGP (string) + && memchr (SDATA (string), '\n', SBYTES (string))); /* The tricky code below is needed because there's a discrepancy between move_it_to and how we set cursor when the display line ends in a newline from a @@ -1689,7 +1650,7 @@ string_pos (ptrdiff_t charpos, Lisp_Object string) means recognize multibyte characters. */ static struct text_pos -c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p) +c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p) { struct text_pos pos; @@ -1720,7 +1681,7 @@ c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p) non-zero means recognize multibyte characters. */ static ptrdiff_t -number_of_chars (const char *s, int multibyte_p) +number_of_chars (const char *s, bool multibyte_p) { ptrdiff_t nchars; @@ -2544,8 +2505,7 @@ check_it (struct it *it) static void check_window_end (struct window *w) { - if (!MINI_WINDOW_P (w) - && !NILP (w->window_end_valid)) + if (!MINI_WINDOW_P (w) && w->window_end_valid) { struct glyph_row *row; eassert ((row = MATRIX_ROW (w->current_matrix, @@ -2564,8 +2524,24 @@ check_window_end (struct window *w) #endif /* GLYPH_DEBUG and ENABLE_CHECKING */ +/* Return mark position if current buffer has the region of non-zero length, + or -1 otherwise. */ + +static ptrdiff_t +markpos_of_region (void) +{ + if (!NILP (Vtransient_mark_mode) + && !NILP (BVAR (current_buffer, mark_active)) + && XMARKER (BVAR (current_buffer, mark))->buffer != NULL) + { + ptrdiff_t markpos = XMARKER (BVAR (current_buffer, mark))->charpos; + + if (markpos != PT) + return markpos; + } + return -1; +} - /*********************************************************************** Iterator initialization ***********************************************************************/ @@ -2594,7 +2570,7 @@ init_iterator (struct it *it, struct window *w, ptrdiff_t charpos, ptrdiff_t bytepos, struct glyph_row *row, enum face_id base_face_id) { - int highlight_region_p; + ptrdiff_t markpos; enum face_id remapped_base_face_id = base_face_id; /* Some precondition checks. */ @@ -2697,16 +2673,11 @@ init_iterator (struct it *it, struct window *w, /* Are multibyte characters enabled in current_buffer? */ it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); - /* Non-zero if we should highlight the region. */ - highlight_region_p - = (!NILP (Vtransient_mark_mode) - && !NILP (BVAR (current_buffer, mark_active)) - && XMARKER (BVAR (current_buffer, mark))->buffer != 0); - - /* Set IT->region_beg_charpos and IT->region_end_charpos to the - start and end of a visible region in window IT->w. Set both to - -1 to indicate no region. */ - if (highlight_region_p + /* If visible region is of non-zero length, set IT->region_beg_charpos + and IT->region_end_charpos to the start and end of a visible region + in window IT->w. Set both to -1 to indicate no region. */ + markpos = markpos_of_region (); + if (0 <= markpos /* Maybe highlight only in selected window. */ && (/* Either show region everywhere. */ highlight_nonselected_windows @@ -2718,7 +2689,6 @@ init_iterator (struct it *it, struct window *w, && WINDOWP (minibuf_selected_window) && w == XWINDOW (minibuf_selected_window)))) { - ptrdiff_t markpos = marker_position (BVAR (current_buffer, mark)); it->region_beg_charpos = min (PT, markpos); it->region_end_charpos = max (PT, markpos); } @@ -3760,18 +3730,26 @@ handle_face_prop (struct it *it) if (new_face_id != it->face_id) { 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. This will happen if this + is the initial call that gets the face. */ + struct face *old_face = FACE_FROM_ID (it->f, it->face_id); - /* If new face has a box but old face has not, this is - the start of a run of characters with box, i.e. it has - a shadow on the left side. The value of face_id of the - iterator will be -1 if this is the initial call that gets - the face. In this case, we have to look in front of IT's - position and see whether there is a face != new_face_id. */ - it->start_of_box_run_p - = (new_face->box != FACE_NO_BOX - && (it->face_id >= 0 - || IT_CHARPOS (*it) == BEG - || new_face_id != face_before_it_pos (it))); + /* 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 + face there that's different from new_face_id. */ + if (!old_face && IT_CHARPOS (*it) > BEG) + { + int prev_face_id = face_before_it_pos (it); + + old_face = FACE_FROM_ID (it->f, prev_face_id); + } + + /* If the new face has a box, but the old face does not, + this is the start of a run of characters with box face, + i.e. this character has a shadow on the left side. */ + it->start_of_box_run_p = (new_face->box != FACE_NO_BOX + && (old_face == NULL || !old_face->box)); it->face_box_p = new_face->box != FACE_NO_BOX; } } @@ -5927,8 +5905,9 @@ pop_it (struct it *it) static void back_to_previous_line_start (struct it *it) { - IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1); - IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it)); + IT_CHARPOS (*it) + = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, + -1, &IT_BYTEPOS (*it)); } @@ -5999,8 +5978,8 @@ forward_to_next_line_start (struct it *it, int *skipped_p, short-cut. */ if (!newline_found_p) { - ptrdiff_t start = IT_CHARPOS (*it); - ptrdiff_t limit = find_next_newline_no_quit (start, 1); + ptrdiff_t bytepos, start = IT_CHARPOS (*it); + ptrdiff_t limit = find_next_newline_no_quit (start, 1, &bytepos); Lisp_Object pos; eassert (!STRINGP (it->string)); @@ -6018,7 +5997,7 @@ forward_to_next_line_start (struct it *it, int *skipped_p, if (!it->bidi_p) { IT_CHARPOS (*it) = limit; - IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit); + IT_BYTEPOS (*it) = bytepos; } else { @@ -7454,11 +7433,9 @@ get_visually_first_element (struct it *it) if (string_p) it->bidi_it.charpos = it->bidi_it.bytepos = 0; else - { - it->bidi_it.charpos = find_next_newline_no_quit (IT_CHARPOS (*it), - -1); - it->bidi_it.bytepos = CHAR_TO_BYTE (it->bidi_it.charpos); - } + it->bidi_it.charpos + = find_next_newline_no_quit (IT_CHARPOS (*it), -1, + &it->bidi_it.bytepos); bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); do { @@ -9002,6 +8979,9 @@ move_it_vertically_backward (struct it *it, int dy) struct it it2, it3; void *it2data = NULL, *it3data = NULL; ptrdiff_t start_pos; + int nchars_per_row + = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); + ptrdiff_t pos_limit; move_further_back: eassert (dy >= 0); @@ -9010,9 +8990,15 @@ move_it_vertically_backward (struct it *it, int dy) /* Estimate how many newlines we must move back. */ nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f)); + if (it->line_wrap == TRUNCATE) + pos_limit = BEGV; + else + pos_limit = max (start_pos - nlines * nchars_per_row, BEGV); - /* Set the iterator's position that many lines back. */ - while (nlines-- && IT_CHARPOS (*it) > BEGV) + /* Set the iterator's position that many lines back. But don't go + back more than NLINES full screen lines -- this wins a day with + buffers which have very long lines. */ + while (nlines-- && IT_CHARPOS (*it) > pos_limit) back_to_previous_visible_line_start (it); /* Reseat the iterator here. When moving backward, we don't want @@ -9084,7 +9070,7 @@ move_it_vertically_backward (struct it *it, int dy) && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n') { ptrdiff_t nl_pos = - find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1); + find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1, NULL); move_it_to (it, nl_pos, -1, -1, -1, MOVE_TO_POS); } @@ -9243,6 +9229,9 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) struct it it2; void *it2data = NULL; ptrdiff_t start_charpos, i; + int nchars_per_row + = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); + ptrdiff_t pos_limit; /* Start at the beginning of the screen line containing IT's position. This may actually move vertically backwards, @@ -9251,9 +9240,14 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) move_it_vertically_backward (it, 0); dvpos -= it->vpos; - /* Go back -DVPOS visible lines and reseat the iterator there. */ + /* Go back -DVPOS buffer lines, but no farther than -DVPOS full + screen lines, and reseat the iterator there. */ start_charpos = IT_CHARPOS (*it); - for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > BEGV; --i) + if (it->line_wrap == TRUNCATE) + pos_limit = BEGV; + else + pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV); + for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i) back_to_previous_visible_line_start (it); reseat (it, it->current.pos, 1); @@ -9362,8 +9356,8 @@ message_log_maybe_newline (void) /* Add a string M of length NBYTES to the message log, optionally - terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if - nonzero, means interpret the contents of M as multibyte. This + terminated with a newline when NLFLAG is true. MULTIBYTE, if + true, means interpret the contents of M as multibyte. This function calls low-level routines in order to bypass text property hooks, etc. which might not be safe to run. @@ -9371,7 +9365,7 @@ message_log_maybe_newline (void) so the buffer M must NOT point to a Lisp string. */ void -message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) +message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte) { const unsigned char *msg = (const unsigned char *) m; @@ -9385,7 +9379,8 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t point_at_end = 0; ptrdiff_t zv_at_end = 0; - Lisp_Object old_deactivate_mark, tem; + Lisp_Object old_deactivate_mark; + bool shown; struct gcpro gcpro1; old_deactivate_mark = Vdeactivate_mark; @@ -9394,11 +9389,11 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) bset_undo_list (current_buffer, Qt); oldpoint = message_dolog_marker1; - set_marker_restricted (oldpoint, make_number (PT), Qnil); + set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE); oldbegv = message_dolog_marker2; - set_marker_restricted (oldbegv, make_number (BEGV), Qnil); + set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE); oldzv = message_dolog_marker3; - set_marker_restricted (oldzv, make_number (ZV), Qnil); + set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE); GCPRO1 (old_deactivate_mark); if (PT == Z) @@ -9449,13 +9444,14 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) } } else if (nbytes) - insert_1 (m, nbytes, 1, 0, 0); + insert_1_both (m, chars_in_text (msg, nbytes), nbytes, 1, 0, 0); if (nlflag) { ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte; printmax_t dups; - insert_1 ("\n", 1, 1, 0, 0); + + insert_1_both ("\n", 1, 1, 1, 0, 0); scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0); this_bol = PT; @@ -9484,7 +9480,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) change message_log_check_duplicate. */ int duplen = sprintf (dupstr, " [%"pMd" times]", dups); TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1); - insert_1 (dupstr, duplen, 1, 0, 1); + insert_1_both (dupstr, duplen, duplen, 1, 0, 1); } } } @@ -9500,7 +9496,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0); } } - BEGV = XMARKER (oldbegv)->charpos; + BEGV = marker_position (oldbegv); BEGV_BYTE = marker_byte_position (oldbegv); if (zv_at_end) @@ -9510,7 +9506,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) } else { - ZV = XMARKER (oldzv)->charpos; + ZV = marker_position (oldzv); ZV_BYTE = marker_byte_position (oldzv); } @@ -9519,17 +9515,17 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) else /* We can't do Fgoto_char (oldpoint) because it will run some Lisp code. */ - TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos, - XMARKER (oldpoint)->bytepos); + TEMP_SET_PT_BOTH (marker_position (oldpoint), + marker_byte_position (oldpoint)); UNGCPRO; unchain_marker (XMARKER (oldpoint)); unchain_marker (XMARKER (oldbegv)); unchain_marker (XMARKER (oldzv)); - tem = Fget_buffer_window (Fcurrent_buffer (), Qt); + shown = buffer_window_count (current_buffer) > 0; set_buffer_internal (oldbuf); - if (NILP (tem)) + if (!shown) windows_or_buffers_changed = old_windows_or_buffers_changed; message_log_need_newline = !nlflag; Vdeactivate_mark = old_deactivate_mark; @@ -9554,7 +9550,7 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte) for (i = 0; i < len; i++) { - if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.') + if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.') seen_dots = 1; if (p1[i] != p2[i]) return seen_dots; @@ -9567,87 +9563,12 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte) char *pend; intmax_t n = strtoimax ((char *) p1, &pend, 10); if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0) - return n+1; + return n + 1; } return 0; } -/* Display an echo area message M with a specified length of NBYTES - bytes. The string may include null characters. If M is 0, clear - out any existing message, and let the mini-buffer text show - through. - - This may GC, so the buffer M must NOT point to a Lisp string. */ - -void -message2 (const char *m, ptrdiff_t nbytes, int multibyte) -{ - /* First flush out any partial line written with print. */ - message_log_maybe_newline (); - if (m) - message_dolog (m, nbytes, 1, multibyte); - message2_nolog (m, nbytes, multibyte); -} - - -/* The non-logging counterpart of message2. */ - -void -message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte) -{ - struct frame *sf = SELECTED_FRAME (); - message_enable_multibyte = multibyte; - - if (FRAME_INITIAL_P (sf)) - { - if (noninteractive_need_newline) - putc ('\n', stderr); - noninteractive_need_newline = 0; - if (m) - fwrite (m, nbytes, 1, stderr); - if (cursor_in_echo_area == 0) - fprintf (stderr, "\n"); - fflush (stderr); - } - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ - else if (INTERACTIVE - && sf->glyphs_initialized_p - && FRAME_MESSAGE_BUF (sf)) - { - Lisp_Object mini_window; - struct frame *f; - - /* Get the frame containing the mini-buffer - that the selected frame is using. */ - mini_window = FRAME_MINIBUF_WINDOW (sf); - f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); - - FRAME_SAMPLE_VISIBILITY (f); - if (FRAME_VISIBLE_P (sf) - && ! FRAME_VISIBLE_P (f)) - Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window))); - - if (m) - { - set_message (m, Qnil, nbytes, multibyte); - if (minibuffer_auto_raise) - Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window))); - } - else - clear_message (1, 1); - - do_pending_window_change (0); - echo_area_display (1); - do_pending_window_change (0); - if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress) - (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f); - } -} - - /* Display an echo area message M with a specified length of NBYTES bytes. The string may include null characters. If M is not a string, clear out any existing message, and let the mini-buffer @@ -9656,7 +9577,7 @@ message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte) This function cancels echoing. */ void -message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte) +message3 (Lisp_Object m) { struct gcpro gcpro1; @@ -9668,13 +9589,15 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte) message_log_maybe_newline (); if (STRINGP (m)) { + ptrdiff_t nbytes = SBYTES (m); + bool multibyte = STRING_MULTIBYTE (m); USE_SAFE_ALLOCA; char *buffer = SAFE_ALLOCA (nbytes); memcpy (buffer, SDATA (m), nbytes); message_dolog (buffer, nbytes, 1, multibyte); SAFE_FREE (); } - message3_nolog (m, nbytes, multibyte); + message3_nolog (m); UNGCPRO; } @@ -9686,10 +9609,9 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte) and make this cancel echoing. */ void -message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) +message3_nolog (Lisp_Object m) { struct frame *sf = SELECTED_FRAME (); - message_enable_multibyte = multibyte; if (FRAME_INITIAL_P (sf)) { @@ -9697,36 +9619,28 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) putc ('\n', stderr); noninteractive_need_newline = 0; if (STRINGP (m)) - fwrite (SDATA (m), nbytes, 1, stderr); + fwrite (SDATA (m), SBYTES (m), 1, stderr); if (cursor_in_echo_area == 0) fprintf (stderr, "\n"); fflush (stderr); } - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ - else if (INTERACTIVE - && sf->glyphs_initialized_p - && FRAME_MESSAGE_BUF (sf)) + /* Error messages get reported properly by cmd_error, so this must be just an + informative message; if the frame hasn't really been initialized yet, just + toss it. */ + else if (INTERACTIVE && sf->glyphs_initialized_p) { - Lisp_Object mini_window; - Lisp_Object frame; - struct frame *f; - /* Get the frame containing the mini-buffer that the selected frame is using. */ - mini_window = FRAME_MINIBUF_WINDOW (sf); - frame = XWINDOW (mini_window)->frame; - f = XFRAME (frame); + Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf); + Lisp_Object frame = XWINDOW (mini_window)->frame; + struct frame *f = XFRAME (frame); - FRAME_SAMPLE_VISIBILITY (f); - if (FRAME_VISIBLE_P (sf) - && !FRAME_VISIBLE_P (f)) + if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f)) Fmake_frame_visible (frame); if (STRINGP (m) && SCHARS (m) > 0) { - set_message (NULL, m, nbytes, multibyte); + set_message (m); if (minibuffer_auto_raise) Fraise_frame (frame); /* Assume we are not echoing. @@ -9739,7 +9653,7 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) do_pending_window_change (0); echo_area_display (1); do_pending_window_change (0); - if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress) + if (FRAME_TERMINAL (f)->frame_up_to_date_hook) (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f); } } @@ -9756,7 +9670,7 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) void message1 (const char *m) { - message2 (m, (m ? strlen (m) : 0), 0); + message3 (m ? make_unibyte_string (m, strlen (m)) : Qnil); } @@ -9765,7 +9679,7 @@ message1 (const char *m) void message1_nolog (const char *m) { - message2_nolog (m, (m ? strlen (m) : 0), 0); + message3_nolog (m ? make_unibyte_string (m, strlen (m)) : Qnil); } /* Display a message M which contains a single %s @@ -9802,10 +9716,10 @@ message_with_string (const char *m, Lisp_Object string, int log) mini_window = FRAME_MINIBUF_WINDOW (sf); f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ - if (FRAME_MESSAGE_BUF (f)) + /* Error messages get reported properly by cmd_error, so this must be + just an informative message; if the frame hasn't really been + initialized yet, just toss it. */ + if (f->glyphs_initialized_p) { Lisp_Object args[2], msg; struct gcpro gcpro1, gcpro2; @@ -9818,9 +9732,9 @@ message_with_string (const char *m, Lisp_Object string, int log) msg = Fformat (2, args); if (log) - message3 (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); + message3 (msg); else - message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); + message3_nolog (msg); UNGCPRO; @@ -9864,20 +9778,20 @@ vmessage (const char *m, va_list ap) mini_window = FRAME_MINIBUF_WINDOW (sf); f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss - it. */ - if (FRAME_MESSAGE_BUF (f)) + /* Error messages get reported properly by cmd_error, so this must be + just an informative message; if the frame hasn't really been + initialized yet, just toss it. */ + if (f->glyphs_initialized_p) { if (m) { ptrdiff_t len; + ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f); + char *message_buf = alloca (maxsize + 1); - len = doprnt (FRAME_MESSAGE_BUF (f), - FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap); + len = doprnt (message_buf, maxsize, m, (char *)0, ap); - message2 (FRAME_MESSAGE_BUF (f), len, 1); + message3 (make_string (message_buf, len)); } else message1 (0); @@ -9928,8 +9842,7 @@ update_echo_area (void) { Lisp_Object string; string = Fcurrent_message (); - message3 (string, SBYTES (string), - !NILP (BVAR (current_buffer, enable_multibyte_characters))); + message3 (string); } } @@ -9965,7 +9878,7 @@ ensure_echo_area_buffers (void) } -/* Call FN with args A1..A4 with either the current or last displayed +/* Call FN with args A1..A2 with either the current or last displayed echo_area_buffer as current buffer. WHICH zero means use the current message buffer @@ -9983,8 +9896,8 @@ ensure_echo_area_buffers (void) static int with_echo_area_buffer (struct window *w, int which, - int (*fn) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t), - ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) + int (*fn) (ptrdiff_t, Lisp_Object), + ptrdiff_t a1, Lisp_Object a2) { Lisp_Object buffer; int this_one, the_other, clear_buffer_p, rc; @@ -10057,7 +9970,7 @@ with_echo_area_buffer (struct window *w, int which, eassert (BEGV >= BEG); eassert (ZV <= Z && ZV >= BEGV); - rc = fn (a1, a2, a3, a4); + rc = fn (a1, a2); eassert (BEGV >= BEG); eassert (ZV <= Z && ZV >= BEGV); @@ -10092,8 +10005,8 @@ with_echo_area_buffer_unwind_data (struct window *w) { XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i; ASET (vector, i, w->buffer); ++i; - ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i; - ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i; + ASET (vector, i, make_number (marker_position (w->pointm))); ++i; + ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i; } else { @@ -10236,7 +10149,7 @@ display_echo_area (struct window *w) window_height_changed_p = with_echo_area_buffer (w, display_last_displayed_message_p, display_echo_area_1, - (intptr_t) w, Qnil, 0, 0); + (intptr_t) w, Qnil); if (no_message_p) echo_area_buffer[i] = Qnil; @@ -10253,7 +10166,7 @@ display_echo_area (struct window *w) Value is non-zero if height of W was changed. */ static int -display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) +display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2) { intptr_t i1 = a1; struct window *w = (struct window *) i1; @@ -10298,8 +10211,7 @@ resize_echo_area_exactly (void) resize_exactly = Qnil; resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1, - (intptr_t) w, resize_exactly, - 0, 0); + (intptr_t) w, resize_exactly); if (resized_p) { ++windows_or_buffers_changed; @@ -10317,7 +10229,7 @@ resize_echo_area_exactly (void) resize_mini_window returns. */ static int -resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly, ptrdiff_t a3, ptrdiff_t a4) +resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly) { intptr_t i1 = a1; return resize_mini_window ((struct window *) i1, !NILP (exactly)); @@ -10390,8 +10302,7 @@ resize_mini_window (struct window *w, int exact_p) max_height = total_height / 4; /* Correct that max. height if it's bogus. */ - max_height = max (1, max_height); - max_height = min (total_height, max_height); + max_height = clip_to_bounds (1, max_height, total_height); /* Find out the height of the text in the window. */ if (it.line_wrap == TRUNCATE) @@ -10487,7 +10398,7 @@ current_message (void) else { with_echo_area_buffer (0, 0, current_message_1, - (intptr_t) &msg, Qnil, 0, 0); + (intptr_t) &msg, Qnil); if (NILP (msg)) echo_area_buffer[0] = Qnil; } @@ -10497,7 +10408,7 @@ current_message (void) static int -current_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) +current_message_1 (ptrdiff_t a1, Lisp_Object a2) { intptr_t i1 = a1; Lisp_Object *msg = (Lisp_Object *) i1; @@ -10529,14 +10440,8 @@ push_message (void) void restore_message (void) { - Lisp_Object msg; - eassert (CONSP (Vmessage_stack)); - msg = XCAR (Vmessage_stack); - if (STRINGP (msg)) - message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); - else - message3_nolog (msg, 0, 0); + message3_nolog (XCAR (Vmessage_stack)); } @@ -10579,16 +10484,16 @@ truncate_echo_area (ptrdiff_t nchars) { if (nchars == 0) echo_area_buffer[0] = Qnil; - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ else if (!noninteractive && INTERACTIVE && !NILP (echo_area_buffer[0])) { struct frame *sf = SELECTED_FRAME (); - if (FRAME_MESSAGE_BUF (sf)) - with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0); + /* Error messages get reported properly by cmd_error, so this must be + just an informative message; if the frame hasn't really been + initialized yet, just toss it. */ + if (sf->glyphs_initialized_p) + with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil); } } @@ -10597,7 +10502,7 @@ truncate_echo_area (ptrdiff_t nchars) message to at most NCHARS characters. */ static int -truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) +truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2) { if (BEG + nchars < Z) del_range (BEG + nchars, Z); @@ -10606,30 +10511,16 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4 return 0; } -/* Set the current message to a substring of S or STRING. - - If STRING is a Lisp string, set the message to the first NBYTES - bytes from STRING. NBYTES zero means use the whole string. If - STRING is multibyte, the message will be displayed multibyte. - - If S is not null, set the message to the first LEN bytes of S. LEN - zero means use the whole string. MULTIBYTE_P non-zero means S is - multibyte. Display the message multibyte in that case. - - Doesn't GC, as with_echo_area_buffer binds Qinhibit_modification_hooks - to t before calling set_message_1 (which calls insert). - */ +/* Set the current message to STRING. */ static void -set_message (const char *s, Lisp_Object string, - ptrdiff_t nbytes, int multibyte_p) +set_message (Lisp_Object string) { - message_enable_multibyte - = ((s && multibyte_p) - || (STRINGP (string) && STRING_MULTIBYTE (string))); + eassert (STRINGP (string)); + + message_enable_multibyte = STRING_MULTIBYTE (string); - with_echo_area_buffer (0, -1, set_message_1, - (intptr_t) s, string, nbytes, multibyte_p); + with_echo_area_buffer (0, -1, set_message_1, 0, string); message_buf_print = 0; help_echo_showing_p = 0; @@ -10639,18 +10530,14 @@ set_message (const char *s, Lisp_Object string, } -/* Helper function for set_message. Arguments have the same meaning - as there, with A1 corresponding to S and A2 corresponding to STRING - This function is called with the echo area buffer being - current. */ +/* Helper function for set_message. First argument is ignored and second + argument has the same meaning as for set_message. + This function is called with the echo area buffer being current. */ static int -set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multibyte_p) +set_message_1 (ptrdiff_t a1, Lisp_Object string) { - intptr_t i1 = a1; - const char *s = (const char *) i1; - const unsigned char *msg = (const unsigned char *) s; - Lisp_Object string = a2; + eassert (STRINGP (string)); /* Change multibyteness of the echo buffer appropriately. */ if (message_enable_multibyte @@ -10664,61 +10551,10 @@ set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multiby /* Insert new message at BEG. */ TEMP_SET_PT_BOTH (BEG, BEG_BYTE); - if (STRINGP (string)) - { - ptrdiff_t nchars; - - if (nbytes == 0) - nbytes = SBYTES (string); - nchars = string_byte_to_char (string, nbytes); - - /* This function takes care of single/multibyte conversion. We - just have to ensure that the echo area buffer has the right - setting of enable_multibyte_characters. */ - insert_from_string (string, 0, 0, nchars, nbytes, 1); - } - else if (s) - { - if (nbytes == 0) - nbytes = strlen (s); - - if (multibyte_p && NILP (BVAR (current_buffer, enable_multibyte_characters))) - { - /* Convert from multi-byte to single-byte. */ - ptrdiff_t i; - int c, n; - char work[1]; - - /* Convert a multibyte string to single-byte. */ - for (i = 0; i < nbytes; i += n) - { - c = string_char_and_length (msg + i, &n); - work[0] = (ASCII_CHAR_P (c) - ? c - : multibyte_char_to_unibyte (c)); - insert_1_both (work, 1, 1, 1, 0, 0); - } - } - else if (!multibyte_p - && !NILP (BVAR (current_buffer, enable_multibyte_characters))) - { - /* Convert from single-byte to multi-byte. */ - ptrdiff_t i; - int c, n; - unsigned char str[MAX_MULTIBYTE_LENGTH]; - - /* Convert a single-byte string to multibyte. */ - for (i = 0; i < nbytes; i++) - { - c = msg[i]; - MAKE_CHAR_MULTIBYTE (c); - n = CHAR_STRING (c, str); - insert_1_both ((char *) str, 1, n, 1, 0, 0); - } - } - else - insert_1 (s, nbytes, 1, 0, 0); - } + /* This function takes care of single/multibyte conversion. + We just have to ensure that the echo area buffer has the right + setting of enable_multibyte_characters. */ + insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), 1); return 0; } @@ -10888,26 +10724,52 @@ echo_area_display (int update_frame_p) return window_height_changed_p; } -/* Nonzero if the current buffer is shown in more than - one window and was modified since last display. */ +/* Nonzero if the current window's buffer is shown in more than one + window and was modified since last redisplay. */ static int buffer_shared_and_changed (void) { - return (buffer_shared > 1 && UNCHANGED_MODIFIED < MODIFF); + return (buffer_window_count (current_buffer) > 1 + && UNCHANGED_MODIFIED < MODIFF); } -/* Nonzero if W doesn't reflect the actual state of - current buffer due to its text or overlays change. */ +/* Nonzero if W doesn't reflect the actual state of current buffer due + to its text or overlays change. FIXME: this may be called when + XBUFFER (w->buffer) != current_buffer, which looks suspicious. */ static int window_outdated (struct window *w) { - eassert (XBUFFER (w->buffer) == current_buffer); - return (w->last_modified < MODIFF + return (w->last_modified < MODIFF || w->last_overlay_modified < OVERLAY_MODIFF); } +/* Nonzero if W's buffer was changed but not saved or Transient Mark mode + is enabled and mark of W's buffer was changed since last W's update. */ + +static int +window_buffer_changed (struct window *w) +{ + struct buffer *b = XBUFFER (w->buffer); + + eassert (BUFFER_LIVE_P (b)); + + return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star) + || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active))) + != (w->region_showing != 0))); +} + +/* Nonzero if W has %c in its mode line and mode line should be updated. */ + +static int +mode_line_update_needed (struct window *w) +{ + return (w->column_number_displayed != -1 + && !(PT == w->last_point && !window_outdated (w)) + && (w->column_number_displayed != current_column ())); +} + /*********************************************************************** Mode Lines and Frame Titles ***********************************************************************/ @@ -11327,12 +11189,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) /* This used to test w->update_mode_line, but we believe there is no need to recompute the menu in that case. */ || update_mode_lines - || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) - < BUF_MODIFF (XBUFFER (w->buffer))) - != w->last_had_star) - || ((!NILP (Vtransient_mark_mode) - && !NILP (BVAR (XBUFFER (w->buffer), mark_active))) - != !NILP (w->region_showing))) + || window_buffer_changed (w)) { struct buffer *prev = current_buffer; ptrdiff_t count = SPECPDL_INDEX (); @@ -11484,11 +11341,18 @@ FRAME_PTR last_mouse_frame; int last_tool_bar_item; - +/* Select `frame' temporarily without running all the code in + do_switch_frame. + FIXME: Maybe do_switch_frame should be trimmed down similarly + when `norecord' is set. */ static Lisp_Object -update_tool_bar_unwind (Lisp_Object frame) +fast_set_selected_frame (Lisp_Object frame) { - selected_frame = frame; + if (!EQ (selected_frame, frame)) + { + selected_frame = frame; + selected_window = XFRAME (frame)->selected_window; + } return Qnil; } @@ -11525,12 +11389,7 @@ update_tool_bar (struct frame *f, int save_match_data) if (windows_or_buffers_changed || w->update_mode_line || update_mode_lines - || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) - < BUF_MODIFF (XBUFFER (w->buffer))) - != w->last_had_star) - || ((!NILP (Vtransient_mark_mode) - && !NILP (BVAR (XBUFFER (w->buffer), mark_active))) - != !NILP (w->region_showing))) + || window_buffer_changed (w)) { struct buffer *prev = current_buffer; ptrdiff_t count = SPECPDL_INDEX (); @@ -11560,9 +11419,13 @@ update_tool_bar (struct frame *f, int save_match_data) before calling tool_bar_items, because the calculation of the tool-bar keymap uses the selected frame (see `tool-bar-make-keymap' in tool-bar.el). */ - record_unwind_protect (update_tool_bar_unwind, selected_frame); + eassert (EQ (selected_window, + /* Since we only explicitly preserve selected_frame, + check that selected_window would be redundant. */ + XFRAME (selected_frame)->selected_window)); + record_unwind_protect (fast_set_selected_frame, selected_frame); XSETFRAME (frame, f); - selected_frame = frame; + fast_set_selected_frame (frame); /* Build desired tool-bar items from keymaps. */ new_tool_bar @@ -12237,7 +12100,6 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, { /* Show item in pressed state. */ show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); - hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; last_tool_bar_item = prop_idx; } else @@ -12248,7 +12110,6 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, /* Show item in released state. */ show_mouse_face (hlinfo, DRAW_IMAGE_RAISED); - hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); @@ -12317,7 +12178,6 @@ note_tool_bar_highlight (struct frame *f, int x, int y) && last_tool_bar_item != prop_idx) return; - hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; /* If tool-bar item is not enabled, don't highlight it. */ @@ -12346,7 +12206,6 @@ note_tool_bar_highlight (struct frame *f, int x, int y) /* Display it as active. */ show_mouse_face (hlinfo, draw); - hlinfo->mouse_face_image_state = draw; } set_help_echo: @@ -12470,11 +12329,7 @@ hscroll_window_tree (Lisp_Object window) if (w == XWINDOW (selected_window)) pt = PT; else - { - pt = marker_position (w->pointm); - pt = max (BEGV, pt); - pt = min (ZV, pt); - } + pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV); /* Move iterator to pt starting at cursor_row->start in a line with infinite width. */ @@ -12890,10 +12745,10 @@ static void reconsider_clip_changes (struct window *w, struct buffer *b) { if (b->clip_changed - && !NILP (w->window_end_valid) - && w->current_matrix->buffer == b - && w->current_matrix->zv == BUF_ZV (b) - && w->current_matrix->begv == BUF_BEGV (b)) + && w->window_end_valid + && w->current_matrix->buffer == b + && w->current_matrix->zv == BUF_ZV (b) + && w->current_matrix->begv == BUF_BEGV (b)) b->clip_changed = 0; /* If display wasn't paused, and W is not a tool bar window, see if @@ -12901,8 +12756,7 @@ reconsider_clip_changes (struct window *w, struct buffer *b) we set b->clip_changed to 1 to force updating the screen. If b->clip_changed has already been set to 1, we can skip this check. */ - if (!b->clip_changed - && BUFFERP (w->buffer) && !NILP (w->window_end_valid)) + if (!b->clip_changed && BUFFERP (w->buffer) && w->window_end_valid) { ptrdiff_t pt; @@ -12921,37 +12775,6 @@ reconsider_clip_changes (struct window *w, struct buffer *b) } -/* Select FRAME to forward the values of frame-local variables into C - variables so that the redisplay routines can access those values - directly. */ - -static void -select_frame_for_redisplay (Lisp_Object frame) -{ - Lisp_Object tail, tem; - Lisp_Object old = selected_frame; - struct Lisp_Symbol *sym; - - eassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame))); - - selected_frame = frame; - - do { - for (tail = XFRAME (frame)->param_alist; - CONSP (tail); tail = XCDR (tail)) - if (CONSP (XCAR (tail)) - && (tem = XCAR (XCAR (tail)), - SYMBOLP (tem)) - && (sym = indirect_variable (XSYMBOL (tem)), - sym->redirect == SYMBOL_LOCALIZED) - && sym->val.blv->frame_local) - /* Use find_symbol_value rather than Fsymbol_value - to avoid an error if it is void. */ - find_symbol_value (tem); - } while (!EQ (frame, old) && (frame = old, 1)); -} - - #define STOP_POLLING \ do { if (! polling_stopped_here) stop_polling (); \ polling_stopped_here = 1; } while (0) @@ -12977,7 +12800,7 @@ redisplay_internal (void) ptrdiff_t count, count1; struct frame *sf; int polling_stopped_here = 0; - Lisp_Object old_frame = selected_frame; + Lisp_Object tail, frame; struct backtrace backtrace; /* Non-zero means redisplay has to consider all windows on all @@ -13029,28 +12852,13 @@ redisplay_internal (void) backtrace.debug_on_exit = 0; backtrace_list = &backtrace; - { - Lisp_Object tail, frame; - - FOR_EACH_FRAME (tail, frame) - { - struct frame *f = XFRAME (frame); - f->already_hscrolled_p = 0; - } - } + FOR_EACH_FRAME (tail, frame) + XFRAME (frame)->already_hscrolled_p = 0; retry: /* Remember the currently selected window. */ sw = w; - if (!EQ (old_frame, selected_frame) - && FRAME_LIVE_P (XFRAME (old_frame))) - /* When running redisplay, we play a bit fast-and-loose and allow e.g. - selected_frame and selected_window to be temporarily out-of-sync so - when we come back here via `goto retry', we need to resync because we - may need to run Elisp code (via prepare_menu_bars). */ - select_frame_for_redisplay (old_frame); - pending = 0; reconsider_clip_changes (w, current_buffer); last_escape_glyph_frame = NULL; @@ -13087,25 +12895,19 @@ redisplay_internal (void) FRAME_TTY (sf)->previous_frame = sf; } - /* Set the visible flags for all frames. Do this before checking - for resized or garbaged frames; they want to know if their frames - are visible. See the comment in frame.h for - FRAME_SAMPLE_VISIBILITY. */ - { - Lisp_Object tail, frame; - - number_of_visible_frames = 0; + /* Set the visible flags for all frames. Do this before checking for + resized or garbaged frames; they want to know if their frames are + visible. See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */ + number_of_visible_frames = 0; - FOR_EACH_FRAME (tail, frame) - { - struct frame *f = XFRAME (frame); + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); - FRAME_SAMPLE_VISIBILITY (f); - if (FRAME_VISIBLE_P (f)) - ++number_of_visible_frames; - clear_desired_matrices (f); - } - } + if (FRAME_VISIBLE_P (f)) + ++number_of_visible_frames; + clear_desired_matrices (f); + } /* Notice any pending interrupt request to change frame size. */ do_pending_window_change (1); @@ -13140,21 +12942,13 @@ redisplay_internal (void) count1 = SPECPDL_INDEX (); specbind (Qinhibit_point_motion_hooks, Qt); - /* If %c is in the mode line, update it if needed. */ - if (!NILP (w->column_number_displayed) - /* This alternative quickly identifies a common case - where no change is needed. */ - && !(PT == w->last_point && !window_outdated (w)) - && (XFASTINT (w->column_number_displayed) != current_column ())) + if (mode_line_update_needed (w)) w->update_mode_line = 1; unbind_to (count1, Qnil); FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1; - /* The variable buffer_shared is set in redisplay_window and - indicates that we redisplay a buffer in different windows. See - there. */ consider_all_windows_p = (update_mode_lines || buffer_shared_and_changed () || cursor_type_changed); @@ -13226,16 +13020,15 @@ redisplay_internal (void) clear_garbaged_frames (); } - /* If showing the region, and mark has changed, we must redisplay the whole window. The assignment to this_line_start_pos prevents the optimization directly below this if-statement. */ if (((!NILP (Vtransient_mark_mode) && !NILP (BVAR (XBUFFER (w->buffer), mark_active))) - != !NILP (w->region_showing)) - || (!NILP (w->region_showing) - && !EQ (w->region_showing, - Fmarker_position (BVAR (XBUFFER (w->buffer), mark))))) + != (w->region_showing > 0)) + || (w->region_showing + && w->region_showing + != XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark))))) CHARPOS (this_line_start_pos) = 0; /* Optimize the case that only the line containing the cursor in the @@ -13355,7 +13148,7 @@ redisplay_internal (void) else if (XFASTINT (w->window_end_vpos) == this_line_vpos && this_line_vpos > 0) wset_window_end_vpos (w, make_number (this_line_vpos - 1)); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; /* Update hint: No need to try to scroll in update_window. */ w->desired_matrix->no_scrolling_p = 1; @@ -13401,7 +13194,7 @@ redisplay_internal (void) && (EQ (selected_window, BVAR (current_buffer, last_selected_window)) || highlight_nonselected_windows) - && NILP (w->region_showing) + && !w->region_showing && NILP (Vshow_trailing_whitespace) && !cursor_in_echo_area) { @@ -13456,15 +13249,9 @@ redisplay_internal (void) if (consider_all_windows_p) { - Lisp_Object tail, frame; - FOR_EACH_FRAME (tail, frame) XFRAME (frame)->updated_p = 0; - /* Recompute # windows showing selected buffer. This will be - incremented each time such a window is displayed. */ - buffer_shared = 0; - FOR_EACH_FRAME (tail, frame) { struct frame *f = XFRAME (frame); @@ -13477,11 +13264,6 @@ redisplay_internal (void) if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf) { - if (! EQ (frame, selected_frame)) - /* Select the frame, for the sake of frame-local - variables. */ - select_frame_for_redisplay (frame); - /* Mark all the scroll bars to be removed; we'll redeem the ones we want when we redisplay their windows. */ if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook) @@ -13531,14 +13313,7 @@ redisplay_internal (void) } } - if (!EQ (old_frame, selected_frame) - && FRAME_LIVE_P (XFRAME (old_frame))) - /* We played a bit fast-and-loose above and allowed selected_frame - and selected_window to be temporarily out-of-sync but let's make - sure this stays contained. */ - select_frame_for_redisplay (old_frame); - eassert (EQ (XFRAME (selected_frame)->selected_window, - selected_window)); + eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window)); if (!pending) { @@ -13667,16 +13442,12 @@ redisplay_internal (void) frames here explicitly. */ if (!pending) { - Lisp_Object tail, frame; int new_count = 0; FOR_EACH_FRAME (tail, frame) { int this_is_visible = 0; - if (XFRAME (frame)->visible) - this_is_visible = 1; - FRAME_SAMPLE_VISIBILITY (XFRAME (frame)); if (XFRAME (frame)->visible) this_is_visible = 1; @@ -13758,65 +13529,53 @@ redisplay_preserve_echo_area (int from_where) /* Function registered with record_unwind_protect in redisplay_internal. - Clear redisplaying_p. Also, select the previously - selected frame, unless it has been deleted (by an X connection - failure during redisplay, for example). */ + Clear redisplaying_p. Also select the previously selected frame. */ static Lisp_Object unwind_redisplay (Lisp_Object old_frame) { redisplaying_p = 0; - if (! EQ (old_frame, selected_frame) - && FRAME_LIVE_P (XFRAME (old_frame))) - select_frame_for_redisplay (old_frame); return Qnil; } -/* Mark the display of window W as accurate or inaccurate. If - ACCURATE_P is non-zero mark display of W as accurate. If - ACCURATE_P is zero, arrange for W to be redisplayed the next time - redisplay_internal is called. */ +/* Mark the display of leaf window W as accurate or inaccurate. + If ACCURATE_P is non-zero mark display of W as accurate. If + ACCURATE_P is zero, arrange for W to be redisplayed the next + time redisplay_internal is called. */ static void mark_window_display_accurate_1 (struct window *w, int accurate_p) { - if (BUFFERP (w->buffer)) - { - struct buffer *b = XBUFFER (w->buffer); + struct buffer *b = XBUFFER (w->buffer); - w->last_modified = accurate_p ? BUF_MODIFF(b) : 0; - w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF(b) : 0; - w->last_had_star - = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b); + w->last_modified = accurate_p ? BUF_MODIFF (b) : 0; + w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0; + w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b); - if (accurate_p) - { - b->clip_changed = 0; - b->prevent_redisplay_optimizations_p = 0; + if (accurate_p) + { + b->clip_changed = 0; + b->prevent_redisplay_optimizations_p = 0; - BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b); - BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b); - BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b); - BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b); + BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b); + BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b); + BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b); + BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b); - w->current_matrix->buffer = b; - w->current_matrix->begv = BUF_BEGV (b); - w->current_matrix->zv = BUF_ZV (b); + w->current_matrix->buffer = b; + w->current_matrix->begv = BUF_BEGV (b); + w->current_matrix->zv = BUF_ZV (b); - w->last_cursor = w->cursor; - w->last_cursor_off_p = w->cursor_off_p; + w->last_cursor = w->cursor; + w->last_cursor_off_p = w->cursor_off_p; - if (w == XWINDOW (selected_window)) - w->last_point = BUF_PT (b); - else - w->last_point = XMARKER (w->pointm)->charpos; - } - } + if (w == XWINDOW (selected_window)) + w->last_point = BUF_PT (b); + else + w->last_point = marker_position (w->pointm); - if (accurate_p) - { - wset_window_end_valid (w, w->buffer); + w->window_end_valid = 1; w->update_mode_line = 0; } } @@ -13835,25 +13594,21 @@ mark_window_display_accurate (Lisp_Object window, int accurate_p) for (; !NILP (window); window = w->next) { w = XWINDOW (window); - mark_window_display_accurate_1 (w, accurate_p); - if (!NILP (w->vchild)) mark_window_display_accurate (w->vchild, accurate_p); - if (!NILP (w->hchild)) + else if (!NILP (w->hchild)) mark_window_display_accurate (w->hchild, accurate_p); + else if (BUFFERP (w->buffer)) + mark_window_display_accurate_1 (w, accurate_p); } if (accurate_p) - { - update_overlay_arrows (1); - } + update_overlay_arrows (1); else - { - /* Force a thorough redisplay the next time by setting - last_arrow_position and last_arrow_string to t, which is - unequal to any useful value of Voverlay_arrow_... */ - update_overlay_arrows (-1); - } + /* Force a thorough redisplay the next time by setting + last_arrow_position and last_arrow_string to t, which is + unequal to any useful value of Voverlay_arrow_... */ + update_overlay_arrows (-1); } @@ -14232,7 +13987,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, GLYPH_BEFORE and GLYPH_AFTER. */ if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end) && BUFFERP (glyph->object) && glyph->charpos == pt_old) - && bpos_covered < pt_old) + && !(bpos_max < pt_old && pt_old <= bpos_covered)) { /* An empty line has a single glyph whose OBJECT is zero and whose CHARPOS is the position of a newline on that line. @@ -14241,7 +13996,12 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, CHARPOS is zero or negative. */ int empty_line_p = (row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end) - && INTEGERP (glyph->object) && glyph->charpos > 0; + && INTEGERP (glyph->object) && glyph->charpos > 0 + /* On a TTY, continued and truncated rows also have a glyph at + their end whose OBJECT is zero and whose CHARPOS is + positive (the continuation and truncation glyphs), but such + rows are obviously not "empty". */ + && !(row->continued_p || row->truncated_on_right_p); if (row->ends_in_ellipsis_p && pos_after == last_pos) { @@ -14843,14 +14603,24 @@ try_scrolling (Lisp_Object window, int just_this_one_p, else { struct text_pos scroll_margin_pos = startp; + int y_offset = 0; /* See if point is inside the scroll margin at the top of the window. */ if (this_scroll_margin) { + int y_start; + start_display (&it, w, startp); + y_start = it.current_y; move_it_vertically (&it, this_scroll_margin); scroll_margin_pos = it.current.pos; + /* If we didn't move enough before hitting ZV, request + additional amount of scroll, to move point out of the + scroll margin. */ + if (IT_CHARPOS (it) == ZV + && it.current_y - y_start < this_scroll_margin) + y_offset = this_scroll_margin - (it.current_y - y_start); } if (PT < CHARPOS (scroll_margin_pos)) @@ -14877,6 +14647,9 @@ try_scrolling (Lisp_Object window, int just_this_one_p, || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos)) return SCROLLING_FAILED; + /* Additional scroll for when ZV was too close to point. */ + dy += y_offset; + /* Compute new window start. */ start_display (&it, w, startp); @@ -14931,7 +14704,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p, if (!just_this_one_p || current_buffer->clip_changed || BEG_UNCHANGED < CHARPOS (startp)) - wset_base_line_number (w, Qnil); + w->base_line_number = 0; /* If cursor ends up on a partially visible line, treat that as being off the bottom of the screen. */ @@ -14984,7 +14757,7 @@ compute_window_start_on_continuation_line (struct window *w) SET_TEXT_POS (start_pos, ZV, ZV_BYTE); /* Find the start of the continued line. This should be fast - because scan_buffer is fast (newline cache). */ + because find_newline is fast (newline cache). */ row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0); init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), row, DEFAULT_FACE_ID); @@ -15079,9 +14852,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste /* Can't use this case if highlighting a region. When a region exists, cursor movement has to do more than just set the cursor. */ - && !(!NILP (Vtransient_mark_mode) - && !NILP (BVAR (current_buffer, mark_active))) - && NILP (w->region_showing) + && markpos_of_region () < 0 + && !w->region_showing && NILP (Vshow_trailing_whitespace) /* This code is not used for mini-buffer for the sake of the case of redisplaying to replace an echo area message; since in @@ -15518,7 +15290,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) set_buffer_internal_1 (XBUFFER (w->buffer)); current_matrix_up_to_date_p - = (!NILP (w->window_end_valid) + = (w->window_end_valid && !current_buffer->clip_changed && !current_buffer->prevent_redisplay_optimizations_p && !window_outdated (w)); @@ -15541,7 +15313,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) specbind (Qinhibit_point_motion_hooks, Qt); buffer_unchanged_p - = (!NILP (w->window_end_valid) + = (w->window_end_valid && !current_buffer->clip_changed && !window_outdated (w)); @@ -15554,7 +15326,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) if (XMARKER (w->start)->buffer == current_buffer) compute_window_start_on_continuation_line (w); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; } /* Some sanity checks. */ @@ -15564,34 +15336,14 @@ redisplay_window (Lisp_Object window, int just_this_one_p) if (BYTEPOS (opoint) < CHARPOS (opoint)) emacs_abort (); - /* If %c is in mode line, update it if needed. */ - if (!NILP (w->column_number_displayed) - /* This alternative quickly identifies a common case - where no change is needed. */ - && !(PT == w->last_point && !window_outdated (w)) - && (XFASTINT (w->column_number_displayed) != current_column ())) + if (mode_line_update_needed (w)) update_mode_line = 1; - /* Count number of windows showing the selected buffer. An indirect - buffer counts as its base buffer. */ - if (!just_this_one_p) - { - struct buffer *current_base, *window_base; - current_base = current_buffer; - window_base = XBUFFER (XWINDOW (selected_window)->buffer); - if (current_base->base_buffer) - current_base = current_base->base_buffer; - if (window_base->base_buffer) - window_base = window_base->base_buffer; - if (current_base == window_base) - buffer_shared++; - } - /* Point refers normally to the selected window. For any other window, set up appropriate value. */ if (!EQ (window, selected_window)) { - ptrdiff_t new_pt = XMARKER (w->pointm)->charpos; + ptrdiff_t new_pt = marker_position (w->pointm); ptrdiff_t new_pt_byte = marker_byte_position (w->pointm); if (new_pt < BEGV) { @@ -15663,11 +15415,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p) w->force_start = 0; w->vscroll = 0; - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; /* Forget any recorded base line for line number display. */ if (!buffer_unchanged_p) - wset_base_line_number (w, Qnil); + w->base_line_number = 0; /* Redisplay the mode line. Select the buffer properly for that. Also, run the hook window-scroll-functions @@ -15717,6 +15469,34 @@ redisplay_window (Lisp_Object window, int just_this_one_p) Move it back to a fully-visible line. */ new_vpos = window_box_height (w); } + else if (w->cursor.vpos >=0) + { + /* Some people insist on not letting point enter the scroll + margin, even though this part handles windows that didn't + scroll at all. */ + int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4); + int pixel_margin = margin * FRAME_LINE_HEIGHT (f); + bool header_line = WINDOW_WANTS_HEADER_LINE_P (w); + + /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop + below, which finds the row to move point to, advances by + the Y coordinate of the _next_ row, see the definition of + MATRIX_ROW_BOTTOM_Y. */ + if (w->cursor.vpos < margin + header_line) + new_vpos + = pixel_margin + (header_line + ? CURRENT_HEADER_LINE_HEIGHT (w) + : 0) + FRAME_LINE_HEIGHT (f); + else + { + int window_height = window_box_height (w); + + if (header_line) + window_height += CURRENT_HEADER_LINE_HEIGHT (w); + if (w->cursor.y >= window_height - pixel_margin) + new_vpos = window_height - pixel_margin; + } + } /* If we need to move point for either of the above reasons, now actually do it. */ @@ -15740,8 +15520,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) /* If we are highlighting the region, then we just changed the region, so redisplay to show it. */ - if (!NILP (Vtransient_mark_mode) - && !NILP (BVAR (current_buffer, mark_active))) + if (0 <= markpos_of_region ()) { clear_glyph_matrix (w->desired_matrix); if (!try_window (window, startp, 0)) @@ -15880,7 +15659,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) || current_buffer->clip_changed || BEG_UNCHANGED < CHARPOS (startp)) /* Forget any recorded base line for line number display. */ - wset_base_line_number (w, Qnil); + w->base_line_number = 0; if (!cursor_row_fully_visible_p (w, 1, 0)) { @@ -15947,11 +15726,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p) debug_method_add (w, "recenter"); #endif - /* w->vscroll = 0; */ - /* Forget any previously recorded base line for line number display. */ if (!buffer_unchanged_p) - wset_base_line_number (w, Qnil); + w->base_line_number = 0; /* Determine the window start relative to point. */ init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); @@ -16085,8 +15862,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) line.) */ if (w->cursor.vpos < 0) { - if (!NILP (w->window_end_valid) - && PT >= Z - XFASTINT (w->window_end_pos)) + if (w->window_end_valid && PT >= Z - XFASTINT (w->window_end_pos)) { clear_glyph_matrix (w->desired_matrix); move_it_by_lines (&it, 1); @@ -16172,10 +15948,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) && !FRAME_WINDOW_P (f) && !WINDOW_FULL_WIDTH_P (w)) /* Line number to display. */ - || INTEGERP (w->base_line_pos) + || w->base_line_pos > 0 /* Column number is displayed and different from the one displayed. */ - || (!NILP (w->column_number_displayed) - && (XFASTINT (w->column_number_displayed) != current_column ()))) + || (w->column_number_displayed != -1 + && (w->column_number_displayed != current_column ()))) /* This means that the window has a mode line. */ && (WINDOW_WANTS_MODELINE_P (w) || WINDOW_WANTS_HEADER_LINE_P (w))) @@ -16206,11 +15982,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) goto need_larger_matrices; } - if (!line_number_displayed - && !BUFFERP (w->base_line_pos)) + if (!line_number_displayed && w->base_line_pos != -1) { - wset_base_line_pos (w, Qnil); - wset_base_line_number (w, Qnil); + w->base_line_pos = 0; + w->base_line_number = 0; } finish_menu_bars: @@ -16403,7 +16178,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) } /* But that is not valid info until redisplay finishes. */ - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; return 1; } @@ -16446,9 +16221,8 @@ try_window_reusing_current_matrix (struct window *w) return 0; /* Can't do this if region may have changed. */ - if ((!NILP (Vtransient_mark_mode) - && !NILP (BVAR (current_buffer, mark_active))) - || !NILP (w->region_showing) + if (0 <= markpos_of_region () + || w->region_showing || !NILP (Vshow_trailing_whitespace)) return 0; @@ -16651,7 +16425,7 @@ try_window_reusing_current_matrix (struct window *w) wset_window_end_pos (w, make_number (Z - ZV)); wset_window_end_vpos (w, make_number (0)); } - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; /* Update hint: don't try scrolling again in update_window. */ w->desired_matrix->no_scrolling_p = 1; @@ -16849,7 +16623,7 @@ try_window_reusing_current_matrix (struct window *w) (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled)); } - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; w->desired_matrix->no_scrolling_p = 1; #ifdef GLYPH_DEBUG @@ -16982,7 +16756,7 @@ find_first_unchanged_at_end_row (struct window *w, /* Display must not have been paused, otherwise the current matrix is not up to date. */ - eassert (!NILP (w->window_end_valid)); + eassert (w->window_end_valid); /* A value of window_end_pos >= END_UNCHANGED means that the window end is in the range of changed text. If so, there is no @@ -17166,7 +16940,7 @@ row_containing_pos (struct window *w, ptrdiff_t charpos, /* Try to redisplay window W by reusing its existing display. W's current matrix must be up to date when this function is called, - i.e. window_end_valid must not be nil. + i.e. window_end_valid must be nonzero. Value is @@ -17274,13 +17048,12 @@ try_window_id (struct window *w) GIVE_UP (7); /* Verify that display wasn't paused. */ - if (NILP (w->window_end_valid)) + if (!w->window_end_valid) GIVE_UP (8); /* Can't use this if highlighting a region because a cursor movement will do more than just set the cursor. */ - if (!NILP (Vtransient_mark_mode) - && !NILP (BVAR (current_buffer, mark_active))) + if (0 <= markpos_of_region ()) GIVE_UP (9); /* Likewise if highlighting trailing whitespace. */ @@ -17288,7 +17061,7 @@ try_window_id (struct window *w) GIVE_UP (11); /* Likewise if showing a region. */ - if (!NILP (w->region_showing)) + if (w->region_showing) GIVE_UP (10); /* Can't use this if overlay arrow position and/or string have @@ -17926,7 +17699,7 @@ try_window_id (struct window *w) debug_end_vpos = XFASTINT (w->window_end_vpos)); /* Record that display has not been completed. */ - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; w->desired_matrix->no_scrolling_p = 1; return 3; @@ -17967,18 +17740,23 @@ dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs) void dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) { - if (glyph->type == CHAR_GLYPH) + if (glyph->type == CHAR_GLYPH + || glyph->type == GLYPHLESS_GLYPH) { fprintf (stderr, - " %5td %4c %6"pI"d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", + " %5"pD"d %c %9"pI"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n", glyph - row->glyphs[TEXT_AREA], - 'C', + (glyph->type == CHAR_GLYPH + ? 'C' + : 'G'), glyph->charpos, (BUFFERP (glyph->object) ? 'B' : (STRINGP (glyph->object) ? 'S' - : '-')), + : (INTEGERP (glyph->object) + ? '0' + : '-'))), glyph->pixel_width, glyph->u.ch, (glyph->u.ch < 0x80 && glyph->u.ch >= ' ' @@ -17991,7 +17769,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) else if (glyph->type == STRETCH_GLYPH) { fprintf (stderr, - " %5td %4c %6"pI"d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", + " %5"pD"d %c %9"pI"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n", glyph - row->glyphs[TEXT_AREA], 'S', glyph->charpos, @@ -17999,10 +17777,12 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) ? 'B' : (STRINGP (glyph->object) ? 'S' - : '-')), + : (INTEGERP (glyph->object) + ? '0' + : '-'))), glyph->pixel_width, 0, - '.', + ' ', glyph->face_id, glyph->left_box_line_p, glyph->right_box_line_p); @@ -18010,7 +17790,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) else if (glyph->type == IMAGE_GLYPH) { fprintf (stderr, - " %5td %4c %6"pI"d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", + " %5"pD"d %c %9"pI"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n", glyph - row->glyphs[TEXT_AREA], 'I', glyph->charpos, @@ -18018,7 +17798,9 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) ? 'B' : (STRINGP (glyph->object) ? 'S' - : '-')), + : (INTEGERP (glyph->object) + ? '0' + : '-'))), glyph->pixel_width, glyph->u.img_id, '.', @@ -18029,7 +17811,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) else if (glyph->type == COMPOSITE_GLYPH) { fprintf (stderr, - " %5td %4c %6"pI"d %c %3d 0x%05x", + " %5"pD"d %c %9"pI"d %c %3d 0x%06x", glyph - row->glyphs[TEXT_AREA], '+', glyph->charpos, @@ -18037,7 +17819,9 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) ? 'B' : (STRINGP (glyph->object) ? 'S' - : '-')), + : (INTEGERP (glyph->object) + ? '0' + : '-'))), glyph->pixel_width, glyph->u.cmp.id); if (glyph->u.cmp.automatic) @@ -18062,10 +17846,10 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs) { if (glyphs != 1) { - fprintf (stderr, "Row Start End Used oE><\\CTZFesm X Y W H V A P\n"); - fprintf (stderr, "======================================================================\n"); + fprintf (stderr, "Row Start End Used oE><\\CTZFesm X Y W H V A P\n"); + fprintf (stderr, "==============================================================================\n"); - fprintf (stderr, "%3d %5"pI"d %5"pI"d %4d %1.1d%1.1d%1.1d%1.1d\ + fprintf (stderr, "%3d %9"pI"d %9"pI"d %4d %1.1d%1.1d%1.1d%1.1d\ %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n", vpos, MATRIX_ROW_START_CHARPOS (row), @@ -18090,13 +17874,14 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs) row->visible_height, row->ascent, row->phys_ascent); - fprintf (stderr, "%9"pD"d %5"pD"d\t%5d\n", row->start.overlay_string_index, + /* The next 3 lines should align to "Start" in the header. */ + fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index, row->end.overlay_string_index, row->continuation_lines_width); - fprintf (stderr, "%9"pI"d %5"pI"d\n", + fprintf (stderr, " %9"pI"d %9"pI"d\n", CHARPOS (row->start.string_pos), CHARPOS (row->end.string_pos)); - fprintf (stderr, "%9d %5d\n", row->start.dpvec_index, + fprintf (stderr, " %9d %9d\n", row->start.dpvec_index, row->end.dpvec_index); } @@ -18114,7 +17899,7 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs) ++glyph_end; if (glyph < glyph_end) - fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n"); + fprintf (stderr, " Glyph# Type Pos O W Code C Face LR\n"); for (; glyph < glyph_end; ++glyph) dump_glyph (row, glyph, area); @@ -18126,15 +17911,24 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs) for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) { - char *s = alloca (row->used[area] + 1); + char *s = alloca (row->used[area] + 4); int i; for (i = 0; i < row->used[area]; ++i) { struct glyph *glyph = row->glyphs[area] + i; - if (glyph->type == CHAR_GLYPH - && glyph->u.ch < 0x80 - && glyph->u.ch >= ' ') + if (i == row->used[area] - 1 + && area == TEXT_AREA + && INTEGERP (glyph->object) + && glyph->type == CHAR_GLYPH + && glyph->u.ch == ' ') + { + strcpy (&s[i], "[\\n]"); + i += 4; + } + else if (glyph->type == CHAR_GLYPH + && glyph->u.ch < 0x80 + && glyph->u.ch >= ' ') s[i] = glyph->u.ch; else s[i] = '.'; @@ -18269,7 +18063,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) const unsigned char *arrow_end = arrow_string + arrow_len; const unsigned char *p; struct it it; - int multibyte_p; + bool multibyte_p; int n_glyphs_before; set_buffer_temp (buffer); @@ -18613,6 +18407,7 @@ append_space_for_newline (struct it *it, int default_face_p) int saved_char_to_display = it->char_to_display; int saved_x = it->current_x; int saved_face_id = it->face_id; + int saved_box_end = it->end_of_box_run_p; struct text_pos saved_pos; Lisp_Object saved_object; struct face *face; @@ -18634,6 +18429,16 @@ append_space_for_newline (struct it *it, int default_face_p) it->face_id = it->saved_face_id; face = FACE_FROM_ID (it->f, it->face_id); it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil); + /* In R2L rows, we will prepend a stretch glyph that will + have the end_of_box_run_p flag set for it, so there's no + need for the appended newline glyph to have that flag + set. */ + if (it->glyph_row->reversed_p + /* But if the appended newline glyph goes all the way to + the end of the row, there will be no stretch glyph, + so leave the box flag set. */ + && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x) + it->end_of_box_run_p = 0; PRODUCE_GLYPHS (it); @@ -18647,6 +18452,7 @@ append_space_for_newline (struct it *it, int default_face_p) it->len = saved_len; it->c = saved_c; it->char_to_display = saved_char_to_display; + it->end_of_box_run_p = saved_box_end; return 1; } } @@ -18736,7 +18542,7 @@ extend_face_to_end_of_line (struct it *it) struct glyph *g; int row_width, stretch_ascent, stretch_width; struct text_pos saved_pos; - int saved_face_id, saved_avoid_cursor; + int saved_face_id, saved_avoid_cursor, saved_box_start; for (row_width = 0, g = row_start; g < row_end; g++) row_width += g->pixel_width; @@ -18751,6 +18557,7 @@ extend_face_to_end_of_line (struct it *it) saved_avoid_cursor = it->avoid_cursor_p; it->avoid_cursor_p = 1; saved_face_id = it->face_id; + saved_box_start = it->start_of_box_run_p; /* The last row's stretch glyph should get the default face, to avoid painting the rest of the window with the region face, if the region ends at ZV. */ @@ -18758,11 +18565,13 @@ extend_face_to_end_of_line (struct it *it) it->face_id = default_face->id; else it->face_id = face->id; + it->start_of_box_run_p = 0; append_stretch_glyph (it, make_number (0), stretch_width, it->ascent + it->descent, stretch_ascent); it->position = saved_pos; it->avoid_cursor_p = saved_avoid_cursor; it->face_id = saved_face_id; + it->start_of_box_run_p = saved_box_start; } } #endif /* HAVE_WINDOW_SYSTEM */ @@ -19339,7 +19148,7 @@ display_line (struct it *it) } /* Is IT->w showing the region? */ - wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil); + it->w->region_showing = it->region_beg_charpos > 0 ? it->region_beg_charpos : 0; /* Clear the result glyph row and enable it. */ prepare_desired_row (row); @@ -20329,17 +20138,21 @@ redisplay_mode_lines (Lisp_Object window, int force) static int display_mode_lines (struct window *w) { - Lisp_Object old_selected_window, old_selected_frame; + Lisp_Object old_selected_window = selected_window; + Lisp_Object old_selected_frame = selected_frame; + Lisp_Object new_frame = w->frame; + Lisp_Object old_frame_selected_window = XFRAME (new_frame)->selected_window; int n = 0; - old_selected_frame = selected_frame; - selected_frame = w->frame; - old_selected_window = selected_window; + selected_frame = new_frame; + /* FIXME: If we were to allow the mode-line's computation changing the buffer + or window's point, then we'd need select_window_1 here as well. */ XSETWINDOW (selected_window, w); + XFRAME (new_frame)->selected_window = selected_window; /* These will be set while the mode line specs are processed. */ line_number_displayed = 0; - wset_column_number_displayed (w, Qnil); + w->column_number_displayed = -1; if (WINDOW_WANTS_MODELINE_P (w)) { @@ -20358,6 +20171,7 @@ display_mode_lines (struct window *w) ++n; } + XFRAME (new_frame)->selected_window = old_frame_selected_window; selected_frame = old_selected_frame; selected_window = old_selected_window; return n; @@ -20680,7 +20494,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision, risky); else if (c != 0) { - int multibyte; + bool multibyte; ptrdiff_t bytepos, charpos; const char *spec; Lisp_Object string; @@ -21285,7 +21099,7 @@ static char * decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_flag) { Lisp_Object val; - int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); + bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); const unsigned char *eol_str; int eol_str_len; /* The EOL conversion we are using. */ @@ -21361,8 +21175,7 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_ returned with spaces to that value. Return a Lisp string in *STRING if the resulting string is taken from that Lisp string. - Note we operate on the current buffer for most purposes, - the exception being w->base_line_pos. */ + Note we operate on the current buffer for most purposes. */ static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; @@ -21443,8 +21256,8 @@ decode_mode_spec (struct window *w, register int c, int field_width, register int i; /* Let lots_of_dashes be a string of infinite length. */ - if (mode_line_target == MODE_LINE_NOPROP || - mode_line_target == MODE_LINE_STRING) + if (mode_line_target == MODE_LINE_NOPROP + || mode_line_target == MODE_LINE_STRING) return "--"; if (field_width <= 0 || field_width > sizeof (lots_of_dashes)) @@ -21473,7 +21286,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, else { ptrdiff_t col = current_column (); - wset_column_number_displayed (w, make_number (col)); + w->column_number_displayed = col; pint2str (decode_mode_spec_buf, width, col); return decode_mode_spec_buf; } @@ -21526,33 +21339,30 @@ decode_mode_spec (struct window *w, register int c, int field_width, if (mode_line_target == MODE_LINE_TITLE) return ""; - startpos = XMARKER (w->start)->charpos; + startpos = marker_position (w->start); startpos_byte = marker_byte_position (w->start); height = WINDOW_TOTAL_LINES (w); /* If we decided that this buffer isn't suitable for line numbers, don't forget that too fast. */ - if (EQ (w->base_line_pos, w->buffer)) + if (w->base_line_pos == -1) goto no_value; - /* But do forget it, if the window shows a different buffer now. */ - else if (BUFFERP (w->base_line_pos)) - wset_base_line_pos (w, Qnil); /* If the buffer is very big, don't waste time. */ if (INTEGERP (Vline_number_display_limit) && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit)) { - wset_base_line_pos (w, Qnil); - wset_base_line_number (w, Qnil); + w->base_line_pos = 0; + w->base_line_number = 0; goto no_value; } - if (INTEGERP (w->base_line_number) - && INTEGERP (w->base_line_pos) - && XFASTINT (w->base_line_pos) <= startpos) + if (w->base_line_number > 0 + && w->base_line_pos > 0 + && w->base_line_pos <= startpos) { - line = XFASTINT (w->base_line_number); - linepos = XFASTINT (w->base_line_pos); + line = w->base_line_number; + linepos = w->base_line_pos; linepos_byte = buf_charpos_to_bytepos (b, linepos); } else @@ -21575,8 +21385,8 @@ decode_mode_spec (struct window *w, register int c, int field_width, go back past it. */ if (startpos == BUF_BEGV (b)) { - wset_base_line_number (w, make_number (topline)); - wset_base_line_pos (w, make_number (BUF_BEGV (b))); + w->base_line_number = topline; + w->base_line_pos = BUF_BEGV (b); } else if (nlines < height + 25 || nlines > height * 3 + 50 || linepos == BUF_BEGV (b)) @@ -21602,13 +21412,13 @@ decode_mode_spec (struct window *w, register int c, int field_width, give up on line numbers for this window. */ if (position == limit_byte && limit == startpos - distance) { - wset_base_line_pos (w, w->buffer); - wset_base_line_number (w, Qnil); + w->base_line_pos = -1; + w->base_line_number = 0; goto no_value; } - wset_base_line_number (w, make_number (topline - nlines)); - wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position))); + w->base_line_number = topline - nlines; + w->base_line_pos = BYTE_TO_CHAR (position); } /* Now count lines from the start pos to point. */ @@ -21730,9 +21540,6 @@ decode_mode_spec (struct window *w, register int c, int field_width, return "@"; } - case 't': /* indicate TEXT or BINARY */ - return "T"; - case 'z': /* coding-system (not including end-of-line format) */ case 'Z': @@ -21782,11 +21589,15 @@ decode_mode_spec (struct window *w, register int c, int field_width, } -/* Count up to COUNT lines starting from START_BYTE. - But don't go beyond LIMIT_BYTE. - Return the number of lines thus found (always nonnegative). +/* Count up to COUNT lines starting from START_BYTE. COUNT negative + means count lines back from START_BYTE. But don't go beyond + LIMIT_BYTE. Return the number of lines thus found (always + nonnegative). - Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */ + Set *BYTE_POS_PTR to the byte position where we stopped. This is + either the position COUNT lines after/before START_BYTE, if we + found COUNT lines, or LIMIT_BYTE if we hit the limit before finding + COUNT lines. */ static ptrdiff_t display_count_lines (ptrdiff_t start_byte, @@ -21813,31 +21624,36 @@ display_count_lines (ptrdiff_t start_byte, ceiling = min (limit_byte - 1, ceiling); ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; base = (cursor = BYTE_POS_ADDR (start_byte)); - while (1) + + do { if (selective_display) - while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr) - ; + { + while (*cursor != '\n' && *cursor != 015 + && ++cursor != ceiling_addr) + continue; + if (cursor == ceiling_addr) + break; + } else - while (*cursor != '\n' && ++cursor != ceiling_addr) - ; + { + cursor = memchr (cursor, '\n', ceiling_addr - cursor); + if (! cursor) + break; + } + + cursor++; - if (cursor != ceiling_addr) + if (--count == 0) { - if (--count == 0) - { - start_byte += cursor - base + 1; - *byte_pos_ptr = start_byte; - return orig_count; - } - else - if (++cursor == ceiling_addr) - break; + start_byte += cursor - base; + *byte_pos_ptr = start_byte; + return orig_count; } - else - break; } - start_byte += cursor - base; + while (cursor < ceiling_addr); + + start_byte += ceiling_addr - base; } } else @@ -21846,35 +21662,35 @@ display_count_lines (ptrdiff_t start_byte, { ceiling = BUFFER_FLOOR_OF (start_byte - 1); ceiling = max (limit_byte, ceiling); - ceiling_addr = BYTE_POS_ADDR (ceiling) - 1; + ceiling_addr = BYTE_POS_ADDR (ceiling); base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); while (1) { if (selective_display) - while (--cursor != ceiling_addr - && *cursor != '\n' && *cursor != 015) - ; + { + while (--cursor >= ceiling_addr + && *cursor != '\n' && *cursor != 015) + continue; + if (cursor < ceiling_addr) + break; + } else - while (--cursor != ceiling_addr && *cursor != '\n') - ; + { + cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr); + if (! cursor) + break; + } - if (cursor != ceiling_addr) + if (++count == 0) { - if (++count == 0) - { - start_byte += cursor - base + 1; - *byte_pos_ptr = start_byte; - /* When scanning backwards, we should - not count the newline posterior to which we stop. */ - return - orig_count - 1; - } + start_byte += cursor - base + 1; + *byte_pos_ptr = start_byte; + /* When scanning backwards, we should + not count the newline posterior to which we stop. */ + return - orig_count - 1; } - else - break; } - /* Here we add 1 to compensate for the last decrement - of CURSOR, which took it past the valid range. */ - start_byte += cursor - base + 1; + start_byte += ceiling_addr - base; } } @@ -23462,8 +23278,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, /* Let's rather be paranoid than getting a SEGV. */ end = min (end, row->used[area]); - start = max (0, start); - start = min (end, start); + start = clip_to_bounds (0, start, end); /* Translate X to frame coordinates. Set last_x to the right end of the drawing area. */ @@ -23505,7 +23320,9 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, /* If mouse highlighting is on, we may need to draw adjacent glyphs using mouse-face highlighting. */ - if (area == TEXT_AREA && row->mouse_face_p) + if (area == TEXT_AREA && row->mouse_face_p + && hlinfo->mouse_face_beg_row >= 0 + && hlinfo->mouse_face_end_row >= 0) { struct glyph_row *mouse_beg_row, *mouse_end_row; @@ -23740,8 +23557,18 @@ append_glyph (struct it *it) glyph->type = CHAR_GLYPH; glyph->avoid_cursor_p = it->avoid_cursor_p; glyph->multibyte_p = it->multibyte_p; - glyph->left_box_line_p = it->start_of_box_run_p; - glyph->right_box_line_p = it->end_of_box_run_p; + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + /* In R2L rows, the left and the right box edges need to be + drawn in reverse direction. */ + glyph->right_box_line_p = it->start_of_box_run_p; + glyph->left_box_line_p = it->end_of_box_run_p; + } + else + { + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + } glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent || it->phys_descent > it->descent); glyph->glyph_not_available_p = it->glyph_not_available_p; @@ -23815,8 +23642,18 @@ append_composite_glyph (struct it *it) } glyph->avoid_cursor_p = it->avoid_cursor_p; glyph->multibyte_p = it->multibyte_p; - glyph->left_box_line_p = it->start_of_box_run_p; - glyph->right_box_line_p = it->end_of_box_run_p; + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + /* In R2L rows, the left and the right box edges need to be + drawn in reverse direction. */ + glyph->right_box_line_p = it->start_of_box_run_p; + glyph->left_box_line_p = it->end_of_box_run_p; + } + else + { + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + } glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent || it->phys_descent > it->descent); glyph->padding_p = 0; @@ -23993,8 +23830,18 @@ produce_image_glyph (struct it *it) glyph->type = IMAGE_GLYPH; glyph->avoid_cursor_p = it->avoid_cursor_p; glyph->multibyte_p = it->multibyte_p; - glyph->left_box_line_p = it->start_of_box_run_p; - glyph->right_box_line_p = it->end_of_box_run_p; + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + /* In R2L rows, the left and the right box edges need to be + drawn in reverse direction. */ + glyph->right_box_line_p = it->start_of_box_run_p; + glyph->left_box_line_p = it->end_of_box_run_p; + } + else + { + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + } glyph->overlaps_vertically_p = 0; glyph->padding_p = 0; glyph->glyph_not_available_p = 0; @@ -24053,8 +23900,18 @@ append_stretch_glyph (struct it *it, Lisp_Object object, glyph->type = STRETCH_GLYPH; glyph->avoid_cursor_p = it->avoid_cursor_p; glyph->multibyte_p = it->multibyte_p; - glyph->left_box_line_p = it->start_of_box_run_p; - glyph->right_box_line_p = it->end_of_box_run_p; + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + /* In R2L rows, the left and the right box edges need to be + drawn in reverse direction. */ + glyph->right_box_line_p = it->start_of_box_run_p; + glyph->left_box_line_p = it->end_of_box_run_p; + } + else + { + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + } glyph->overlaps_vertically_p = 0; glyph->padding_p = 0; glyph->glyph_not_available_p = 0; @@ -24506,8 +24363,18 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len, glyph->slice.glyphless.lower_yoff = lower_yoff; glyph->avoid_cursor_p = it->avoid_cursor_p; glyph->multibyte_p = it->multibyte_p; - glyph->left_box_line_p = it->start_of_box_run_p; - glyph->right_box_line_p = it->end_of_box_run_p; + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + /* In R2L rows, the left and the right box edges need to be + drawn in reverse direction. */ + glyph->right_box_line_p = it->start_of_box_run_p; + glyph->left_box_line_p = it->end_of_box_run_p; + } + else + { + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + } glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent || it->phys_descent > it->descent); glyph->padding_p = 0; @@ -27684,12 +27551,6 @@ note_mouse_highlight (struct frame *f, int x, int y) if (hlinfo->mouse_face_defer) return; - if (gc_in_progress) - { - hlinfo->mouse_face_deferred_gc = 1; - return; - } - /* Which window is that in? */ window = window_from_coordinates (f, x, y, &part, 1); @@ -27749,7 +27610,7 @@ note_mouse_highlight (struct frame *f, int x, int y) And verify the buffer's text has not changed. */ b = XBUFFER (w->buffer); if (part == ON_TEXT - && EQ (w->window_end_valid, w->buffer) + && w->window_end_valid && w->last_modified == BUF_MODIFF (b) && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b)) { @@ -28382,6 +28243,9 @@ x_draw_vertical_border (struct window *w) if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame))) return; + /* Note: It is necessary to redraw both the left and the right + borders, for when only this single window W is being + redisplayed. */ if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)) { @@ -28395,8 +28259,8 @@ x_draw_vertical_border (struct window *w) FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1); } - else if (!WINDOW_LEFTMOST_P (w) - && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) + if (!WINDOW_LEFTMOST_P (w) + && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) { int x0, x1, y0, y1;